diff --git a/router/broker.py b/router/broker.py index 7241143..85ea14a 100644 --- a/router/broker.py +++ b/router/broker.py @@ -19,7 +19,7 @@ class Broker: """Вызов метода """ for route in self.routes: - print(route) + log.debug(route) comparator = route.comparator output = comparator(route.rule, query) if output: @@ -52,9 +52,9 @@ class Broker: def wrap(function): _route = Route( - rule = rule, - comparator = comparator, - endpoint = function + rule=rule, + comparator=comparator, + endpoint=function ) self.routes.append(_route) return function diff --git a/router/compiler.py b/router/compiler.py new file mode 100644 index 0000000..b0b957f --- /dev/null +++ b/router/compiler.py @@ -0,0 +1,37 @@ +__author__ = 'RemiZOffAlex' +__email__ = 'remizoffalex@mail.ru' + +import logging + +from .dsl.common import And, Equal, Or, Regex + +log = logging.getLogger(__name__) + + +class Compiler: + def __call__(self, rule): + if isinstance(rule, list): + val = [] + for item in rule: + val.append(self(item)) + return val + elif isinstance(rule, dict): + assert 'operator' in rule, \ + 'Not operator in rule: {rule}'.format(rule=rule) + if rule['operator'] == 'and': + val = self(rule['rules']) + result = And(val) + return result + elif rule['operator'] == 'or': + val = self(rule['rules']) + return Or(val) + elif rule['operator'] == 'equal': + return Equal( + key=rule['key'], + value=rule['value'] + ) + elif rule['operator'] == 'regex': + return Regex( + key=rule['key'], + value=rule['value'] + ) diff --git a/router/dsl/__init__.py b/router/dsl/__init__.py new file mode 100644 index 0000000..18c55bb --- /dev/null +++ b/router/dsl/__init__.py @@ -0,0 +1,2 @@ +__author__ = 'RemiZOffAlex' +__email__ = 'remizoffalex@mail.ru' diff --git a/router/dsl/common.py b/router/dsl/common.py new file mode 100644 index 0000000..29e2d8c --- /dev/null +++ b/router/dsl/common.py @@ -0,0 +1,78 @@ +__author__ = 'RemiZOffAlex' +__email__ = 'remizoffalex@mail.ru' + +import re +import logging + +log = logging.getLogger(__name__) + + +class And: + def __init__(self, rules): + self.rules = rules + + def __json__(self): + result = [] + for item in self.rules: + result.append(item.__json__()) + return { + 'operator': 'and', + 'rules': result + } + + def __call__(self, query): + log.debug('And.__call__') + return all(map(lambda x: x(query), self.rules)) + + +class Equal: + def __init__(self, key, value): + self.key = key + self.value = value + + def __json__(self): + return { + 'operator': 'equal', + 'key': self.key, + 'value': self.value + } + + def __call__(self, query): + log.debug('Equal.__call__') + return query[self.key] == self.value + + +class Or: + def __init__(self, rules): + self.rules = rules + + def __json__(self): + result = [] + for item in self.rules: + result.append(item.__json__()) + return { + 'operator': 'or', + 'rules': result + } + + def __call__(self, query): + print('Or.__call__') + return any(map(lambda x: x(query), self.rules)) + + +class Regex: + def __init__(self, key, value): + self.key = key + self.value = re.compile(value) + + def __json__(self): + return { + 'operator': 'regex', + 'key': self.key, + 'value': self.value.pattern + } + + def __call__(self, query): + print('Regex.__call__') + result = self.value.match(query[self.key]) + return result diff --git a/router/endpoint.py b/router/endpoint.py index fab90aa..2f72454 100644 --- a/router/endpoint.py +++ b/router/endpoint.py @@ -1,6 +1,7 @@ __author__ = 'RemiZOffAlex' __email__ = 'remizoffalex@mail.ru' + class Endpoint: def __init__(self, function): self.function = function diff --git a/router/route.py b/router/route.py index 55f5d09..634f07c 100644 --- a/router/route.py +++ b/router/route.py @@ -1,8 +1,6 @@ __author__ = 'RemiZOffAlex' __email__ = 'remizoffalex@mail.ru' -from collections.abc import Callable - class Route: def __init__(self, rule, comparator, endpoint): @@ -11,6 +9,7 @@ class Route: :param : Как сравнивать :param : Куда отправить """ + print('Route.__init__') self.rule = rule self.comparator = comparator self.endpoint = endpoint