Рабочая версия

This commit is contained in:
2024-02-02 23:24:29 +03:00
commit ce86755d81
9 changed files with 303 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
*.pyc
*.pyo
prototypes
dist
build

25
README.md Normal file
View File

@@ -0,0 +1,25 @@
```
from router.broker import Broker
broker = Broker()
@broker.route(
rule = {
url:
}
)
def foo():
return 'foo'
request = {
url: ''
}
method = broker(request)
response = method()
print(response)
```

74
progon.py Executable file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/env python3
__author__ = 'RemiZOffAlex'
__email__ = 'remizoffalex@mail.ru'
from router.broker import Broker
from router.syntetic.url import rule_comparator
broker = Broker()
def comparator(rule, query):
print('comparator')
print(rule['url'])
print(query['url'])
if rule['url']['value'] == query['url']:
return {}
@broker.route(
rule = {
'domain': {
'value': '',
'isregex': True
},
'url': {
'value': '',
'isregex': True
}
},
comparator = comparator
)
def foo():
return 'foo'
def comparator_flask(rule, query):
print('comparator')
print(rule['url'])
print(query['url'])
if rule['url'] == query['url']:
result = rule_comparator(rule['url'], query['url'])
print(result)
return result
@broker.route(
rule = {
'url': '/'
},
comparator = comparator_flask
)
def foo():
return 'foo'
request = {
'url': '/'
}
broker_response = broker(request)
print('broker_response', broker_response)
if broker_response is not None:
method, params = broker_response
print('method', 'params')
print(method, params)
if method is None:
print('Маршрут не найден')
response = None
else:
response = method(**params)
print(response)

15
pyproject.toml Normal file
View File

@@ -0,0 +1,15 @@
[project]
name = "router"
version ="0.1.0"
authors = [
{ name="RemiZOffAlex", email="remizoffalex@gmail.com" },
]
description = "Маршрутизатор"
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12"
]
keywords = ["documentation"]
dependencies = []

2
router/__init__.py Normal file
View File

@@ -0,0 +1,2 @@
__author__ = 'RemiZOffAlex'
__email__ = 'remizoffalex@mail.ru'

61
router/broker.py Normal file
View File

@@ -0,0 +1,61 @@
__author__ = 'RemiZOffAlex'
__email__ = 'remizoffalex@mail.ru'
import logging
from collections.abc import Callable
from .route import Route
log = logging.getLogger(__name__)
class Broker:
def __init__(self):
self.routes = []
def __call__(self, query):
"""Вызов метода
"""
for route in self.routes:
print(route)
comparator = route.comparator
output = comparator(route.rule, query)
if output:
return (route.endpoint, output)
def __getitem__(self, key):
method = self.methods[key]
return method.function
def __iter__(self):
return iter(self.methods)
def __len__(self):
return len(self.methods)
def __setitem__(self, key, function, pre=None):
method = Method(function=function, pre=pre)
self.methods[key] = method
def __delitem__(self, key):
del self.methods[key]
def __repr__(self):
return repr(self.methods)
def route(self, rule: dict, comparator: Callable, *args):
"""Декоратор
"""
assert rule is not None, 'Не указано имя метода'
def wrap(function):
_route = Route(
rule = rule,
comparator = comparator,
endpoint = function
)
self.routes.append(_route)
return function
return wrap

9
router/endpoint.py Normal file
View File

@@ -0,0 +1,9 @@
__author__ = 'RemiZOffAlex'
__email__ = 'remizoffalex@mail.ru'
class Endpoint:
def __init__(self, function):
self.function = function
def __call__(self, *args, **kwargs):
result = self.function()

16
router/route.py Normal file
View File

@@ -0,0 +1,16 @@
__author__ = 'RemiZOffAlex'
__email__ = 'remizoffalex@mail.ru'
from collections.abc import Callable
class Route:
def __init__(self, rule, comparator, endpoint):
"""
:param rule: С чем сравнивать
:param : Как сравнивать
:param : Куда отправить
"""
self.rule = rule
self.comparator = comparator
self.endpoint = endpoint

95
router/syntetic/url.py Normal file
View File

@@ -0,0 +1,95 @@
__author__ = 'RemiZOffAlex'
__email__ = 'remizoffalex@mail.ru'
import re
_part_re = re.compile(
r"""
(?:
(?P<slash>/) # a slash
|
(?P<static>[^</]+) # static rule data
|
(?:
<
(?:
(?P<converter>[a-zA-Z_][a-zA-Z0-9_]*) # converter name
(?:\((?P<arguments>.*?)\))? # converter arguments
: # variable delimiter
)?
(?P<variable>[a-zA-Z_][a-zA-Z0-9_]*) # variable name
>
)
)
""",
re.VERBOSE,
)
def rule_parse(rule: str) -> list:
"""Парсим правило
"""
result = []
pos = 0
while pos < len(rule):
match = _part_re.match(rule, pos)
print('match:', match)
pos = match.end()
data = match.groupdict()
print('data:', data)
result.append(data)
return result
def rule_compile(rule: list):
"""Компилируем регулярку из правила
"""
result = []
params = {}
for item in rule:
if item['slash']:
result.append(item['slash'])
elif item['static']:
result.append(item['static'])
elif item['converter']:
params[item['variable']] = None
if item['converter']=='int':
result.append('(?P<{}>\d+)'.format(item['variable']))
print('item:', item)
regexp = ''.join(result)
print('regexp:', regexp)
return (re.compile(regexp), params)
def rule_extract(regexp, request):
pass
def rule_comparator(rule, request):
try:
rule_proto = rule_parse(rule)
print('rule_proto:', rule_proto)
rule_regex, params = rule_compile(rule_proto)
print('rule:', rule_regex)
result = rule_regex.match(url)
for key in params:
params[key] = result.group(key)
print(key, ':', params[key])
return params
except Exception as error:
return None
def main():
print('_part_re.groups:', _part_re.groups)
print('_part_re.groups:', _part_re.groups)
rule = '/v<int:major>.<int:minor>'
urls = [
'/v3451.5432',
'/v3sdfsdf451.5432'
]
for url in urls:
params = rule_comparator(rule, url)
if params:
print('route {} is valid:'.format(url), params)
else:
print('route {} invalid'.format(url))