Skip to content

Instantly share code, notes, and snippets.

@wmalarski
Created March 28, 2019 06:40
Show Gist options
  • Save wmalarski/ec8cdb3359f059ed0baccd3f1ac80687 to your computer and use it in GitHub Desktop.
Save wmalarski/ec8cdb3359f059ed0baccd3f1ac80687 to your computer and use it in GitHub Desktop.
import inspect
class Context:
def __init__(self):
self._filters = {}
self._parsers = {}
self._runnable_attr = '_runnable'
def filter(self, matching_cls):
class FilterCaller:
def __init__(selff, filter_cls):
selff._filter_cls = filter_cls
selff._matching_cls = matching_cls
runnable = [func for name, func in inspect.getmembers(filter_cls, inspect.isfunction)
if (self._runnable_attr, True) in inspect.getmembers(func)]
self._filters[selff] = (filter_cls, matching_cls, runnable)
def __call__(selff):
return None
def __hash__(selff):
return hash(str(selff._filter_cls) + str(matching_cls))
def __eq__(selff, other):
if isinstance(other, FilterCaller):
return selff._filter_cls == other._filter_cls and other._matching_cls == matching_cls
return False
return FilterCaller
def matcher(self, *parsers):
def matcher_inner(matcher):
self._parsers[matcher] = parsers
return matcher
return matcher_inner
def runnable(self, func):
func.__setattr__(self._runnable_attr, True)
return func
def run(self, filters_call, resource1, resource2):
matching_uniq = {}
for filter_call_cls in filters_call:
matching_cls = self._filters.get(filter_call_cls)[1]
if matching_cls is not None:
if matching_cls not in matching_uniq:
matching = matching_cls()
parsers = self._parsers[matching_cls]
for parser in parsers:
resource1 = parser.parse_resuorce1(resource1)
resource2 = parser.parse_resuorce2(resource2)
pairs = matching.pairs(resource1, resource2)
for parser in parsers:
pairs = parser.parse_pairs(resource1, resource2, pairs)
matching_uniq[matching_cls] = pairs
results = []
for filter_call_cls in filters_call:
if filter_call_cls in self._filters:
filter_cls, matching_cls, runnable = self._filters[filter_call_cls]
pairs = matching_uniq[matching_cls]
filter_obj = filter_cls()
for run in runnable:
result = run(filter_obj, pairs)
results.append(result)
return results
context = Context()
class MatcherParser:
def parse_pairs(self, resource1, resource2, pairs):
return pairs
def parse_resuorce1(self, resource1):
return resource1
def parse_resuorce2(self, resource2):
return resource2
class FirstLastParser(MatcherParser):
def parse_pairs(self, resource1, resource2, pairs):
return {'a': pairs}
class Matching:
def pairs(self, resource1, resource2):
pass
@context.matcher(FirstLastParser())
class ObjectsMatching(Matching):
def pairs(self, resource1, resource2):
return []
@context.filter(ObjectsMatching)
class CyclistsFilter:
def __init__(self):
print('CyclistsFilter.__init__')
@context.runnable
def run(self, pairs):
print('CyclistsFilter.run', pairs)
return [pairs]
@context.runnable
def run2(self, pairs):
print('CyclistsFilter.run2', pairs)
return ['dsd', pairs]
def main():
results = context.run([CyclistsFilter], 'a', 'b')
print(results)
# print('a', CyclistsFilter(), type(CyclistsFilter()))
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment