Skip to content

Commit 8e25c30

Browse files
committed
fix/feat: fix codestyle, bugs, docstrings, add PrefixTree and improve routing system
1 parent e244bff commit 8e25c30

File tree

15 files changed

+299
-100
lines changed

15 files changed

+299
-100
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
commit e244bff1db90fb0714a0c23f3ffdee3c0192a376
2+
Author: Alexeev Bronislav <alexeev.dev@mail.ru>
3+
Date: Sun Apr 27 00:31:31 2025 +0700
4+
5+
some changes
6+
17
commit 84c7a3d2b8b4f997c039e6e515f18bc48e8fb8e5
28
Author: Alexeev Bronislav <alexeev.dev@mail.ru>
39
Date: Sat Apr 26 23:34:40 2025 +0700

README.md

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
<img src="https://img.shields.io/github/stars/alexeev-prog/pyEchoNext?style=for-the-badge">
3232
<img src="https://img.shields.io/github/issues/alexeev-prog/pyEchoNext?style=for-the-badge">
3333
<img src="https://img.shields.io/github/last-commit/alexeev-prog/pyEchoNext?style=for-the-badge">
34-
<img src="https://img.shields.io/pypi/wheel/uvolution?style=for-the-badge">
35-
<img src="https://img.shields.io/badge/coverage-73%25-73%25?style=for-the-badge" alt="">
34+
<img src="https://img.shields.io/pypi/wheel/pyechonext?style=for-the-badge">
35+
<img src="https://img.shields.io/badge/coverage-73%25-73%25?style=for-the-badge" alt="Coverage">
3636
<img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/pyEchoNext?style=for-the-badge">
3737
<img alt="PyPI - Version" src="https://img.shields.io/pypi/v/pyEchoNext?style=for-the-badge">
3838
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/pyEchoNext?style=for-the-badge">
@@ -172,6 +172,35 @@ calculate(4) # Output: 16
172172
## 💻 Usage Examples
173173
You can view examples at [examples directory](./examples).
174174

175+
### Prefix Tree (Trie)
176+
Prefix Tree data structure (this structure also used in pyechonext routing system)
177+
178+
```python
179+
from pyechonext.utils.trie import PrefixTree
180+
181+
if __name__ == '__main__':
182+
trie = PrefixTree()
183+
trie.insert('apple')
184+
trie.insert('app')
185+
trie.insert('aposematic')
186+
trie.insert('appreciate')
187+
trie.insert('book')
188+
trie.insert('bad')
189+
trie.insert('bear')
190+
trie.insert('bat')
191+
print(trie.starts_with('app'))
192+
193+
router_tree = PrefixTree()
194+
router_tree.insert('index')
195+
router_tree.insert('users')
196+
router_tree.insert('transactions')
197+
router_tree.insert('wallets')
198+
router_tree.insert('wallets/create')
199+
200+
print(router_tree.starts_with('wa'))
201+
202+
```
203+
175204
### i18n with hermes-langlib
176205
Hermes LangLib - a fast and light python library for translating, localizing and internationalizing your applications. The library is aimed at high speed and stability; it can be used in highly loaded projects.
177206

pyechonext/app.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from pyechonext.logging import logger
1313
from pyechonext.middleware import BaseMiddleware
1414
from pyechonext.mvc.controllers import PageController
15-
from pyechonext.mvc.routes import Route, Router, RoutesTypes
15+
from pyechonext.mvc.routes import Route, Router, RoutesTypes, generate_page_route
1616
from pyechonext.request import Request
1717
from pyechonext.response import Response
1818
from pyechonext.static import StaticFile, StaticFilesManager
@@ -49,8 +49,8 @@ def _default_response(response: Response, error: WebError) -> None:
4949
"""Get default response (HTTP 404)
5050
5151
Args:
52-
response (Response): Response object
53-
error (WebError): web error
52+
response (Response): Response object
53+
error (WebError): web error
5454
"""
5555
response.status_code = str(error.code)
5656
response.body = str(error)
@@ -60,14 +60,14 @@ def _check_handler(request: Request, route: Route) -> Callable:
6060
"""Check handler
6161
6262
Args:
63-
request (Request): request object
64-
handler (Callable): handler
63+
request (Request): request object
64+
route (Route): route
6565
6666
Raises:
67-
MethodNotAllow: handler request method is None, method not allowed
67+
MethodNotAllow: handler request method is None, method not allowed
6868
6969
Returns:
70-
Callable: handler object
70+
Callable: handler object
7171
"""
7272
handler = route.handler
7373

@@ -188,34 +188,44 @@ def add_route(
188188
self,
189189
page_path: str,
190190
handler: Callable | PageController,
191-
methods: List[str] = ["GET"],
191+
methods: Optional[List[str]] = None,
192192
summary: Optional[str] = None,
193193
):
194194
"""Add page route without decorator
195195
196196
Args:
197197
page_path (str): page path url
198198
handler (Callable): handler of route
199+
methods (Optional[List[str]]): supported methods of handler. Defaults to None.
199200
summary (Optional[str], optional): summary documentation. Defaults to None.
200201
"""
202+
if methods is None:
203+
methods = ["GET"]
201204
if inspect.isclass(handler):
202205
self.router.add_url(URL(path=page_path, controller=handler))
203206
else:
204207
self.router.add_page_route(page_path, handler, methods, summary)
205208

206209
def route_page(
207-
self, page_path: str, methods: list = ["GET"], summary: Optional[str] = None
210+
self,
211+
page_path: str,
212+
methods: Optional[List[str]] = None,
213+
summary: Optional[str] = None,
208214
) -> Callable:
209215
"""Route page decorator
210216
211217
Args:
212218
page_path (str): page path url
219+
methods (Optional[List[str]]): supported methods of handler. Defaults to None.
213220
summary (Optional[str], optional): summary documentation. Defaults to None.
214221
215222
Returns:
216223
Callable: wrapper
217224
"""
218225

226+
if methods is None:
227+
methods = ["GET"]
228+
219229
def wrapper(handler: Callable | PageController):
220230
if inspect.isclass(handler):
221231
self.router.add_url(
@@ -321,8 +331,8 @@ def _find_handler(
321331

322332
if self.static_files_manager.serve_static_file(url):
323333
return (
324-
self.router.generate_page_route(
325-
url, self._serve_static_file, f"Serving static file: {url}"
334+
generate_page_route(
335+
url, self._serve_static_file, None, f"Serving static file: {url}"
326336
),
327337
{},
328338
)

pyechonext/config.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def dynamic_import(module: str):
2525
return importlib.import_module(str(module))
2626

2727

28-
@dataclass
28+
@dataclass(frozen=True)
2929
class Settings:
3030
"""
3131
This class describes settings.
@@ -59,6 +59,12 @@ class SettingsLoader:
5959
This class describes a settings loader.
6060
"""
6161

62+
__slots__ = (
63+
'config',
64+
'config_type',
65+
'filename'
66+
)
67+
6268
def __init__(self, config_type: SettingsConfigType, filename: str = None):
6369
"""Initialize a basic settings info
6470
@@ -71,9 +77,7 @@ def __init__(self, config_type: SettingsConfigType, filename: str = None):
7177
"""
7278
self.config = None
7379
self.config_type: SettingsConfigType = config_type
74-
self.filename: str = filename
75-
76-
self.filename: str = Path(self.filename)
80+
self.filename: Path = Path(self.filename)
7781

7882
if not self.filename.exists():
7983
raise FileNotFoundError(f'Config file "{self.filename}" don\'t exists.')

0 commit comments

Comments
 (0)