Nexom 0.1.4__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nexom/__init__.py +2 -2
- nexom/__main__.py +111 -17
- nexom/app/__init__.py +62 -0
- nexom/app/auth.py +322 -0
- nexom/{web → app}/cookie.py +4 -2
- nexom/app/db.py +88 -0
- nexom/app/path.py +195 -0
- nexom/app/request.py +267 -0
- nexom/{web → app}/response.py +13 -3
- nexom/{web → app}/template.py +1 -1
- nexom/app/user.py +31 -0
- nexom/assets/app/__init__.py +0 -0
- nexom/assets/app/__pycache__/__init__.cpython-313.pyc +0 -0
- nexom/assets/app/config.py +28 -0
- nexom/assets/app/gunicorn.conf.py +5 -0
- nexom/assets/app/pages/__pycache__/__init__.cpython-313.pyc +0 -0
- nexom/assets/app/pages/_templates.py +7 -0
- nexom/assets/{server → app}/pages/default.py +2 -2
- nexom/assets/{server → app}/pages/document.py +2 -2
- nexom/assets/app/router.py +12 -0
- nexom/assets/app/wsgi.py +64 -0
- nexom/assets/auth/__init__.py +0 -0
- nexom/assets/auth/__pycache__/__init__.cpython-313.pyc +0 -0
- nexom/assets/auth/config.py +27 -0
- nexom/assets/auth/gunicorn.conf.py +5 -0
- nexom/assets/auth/wsgi.py +62 -0
- nexom/assets/auth_page/login.html +95 -0
- nexom/assets/auth_page/signup.html +106 -0
- nexom/assets/error_page/error.html +3 -3
- nexom/assets/gateway/apache_app.conf +16 -0
- nexom/assets/gateway/nginx_app.conf +21 -0
- nexom/buildTools/__init__.py +1 -0
- nexom/buildTools/build.py +274 -54
- nexom/buildTools/run.py +185 -0
- nexom/core/__init__.py +2 -1
- nexom/core/error.py +81 -3
- nexom/core/log.py +111 -0
- nexom/{engine → core}/object_html_render.py +4 -1
- nexom/templates/__init__.py +0 -0
- nexom/templates/auth.py +72 -0
- {nexom-0.1.4.dist-info → nexom-1.0.2.dist-info}/METADATA +76 -50
- nexom-1.0.2.dist-info/RECORD +56 -0
- {nexom-0.1.4.dist-info → nexom-1.0.2.dist-info}/WHEEL +1 -1
- nexom/assets/server/config.py +0 -27
- nexom/assets/server/gunicorn.conf.py +0 -16
- nexom/assets/server/pages/__pycache__/__init__.cpython-313.pyc +0 -0
- nexom/assets/server/pages/_templates.py +0 -11
- nexom/assets/server/router.py +0 -18
- nexom/assets/server/wsgi.py +0 -30
- nexom/engine/__init__.py +0 -1
- nexom/web/__init__.py +0 -5
- nexom/web/path.py +0 -125
- nexom/web/request.py +0 -62
- nexom-0.1.4.dist-info/RECORD +0 -39
- /nexom/{web → app}/http_status_codes.py +0 -0
- /nexom/{web → app}/middleware.py +0 -0
- /nexom/assets/{server → app}/pages/__init__.py +0 -0
- /nexom/assets/{server → app}/static/dog.jpeg +0 -0
- /nexom/assets/{server → app}/static/style.css +0 -0
- /nexom/assets/{server → app}/templates/base.html +0 -0
- /nexom/assets/{server → app}/templates/default.html +0 -0
- /nexom/assets/{server → app}/templates/document.html +0 -0
- /nexom/assets/{server → app}/templates/footer.html +0 -0
- /nexom/assets/{server → app}/templates/header.html +0 -0
- {nexom-0.1.4.dist-info → nexom-1.0.2.dist-info}/entry_points.txt +0 -0
- {nexom-0.1.4.dist-info → nexom-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {nexom-0.1.4.dist-info → nexom-1.0.2.dist-info}/top_level.txt +0 -0
nexom/web/path.py
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
import os
|
|
3
|
-
import re
|
|
4
|
-
import json
|
|
5
|
-
from mimetypes import guess_type
|
|
6
|
-
from typing import Callable, Any, Optional, Iterable
|
|
7
|
-
|
|
8
|
-
from ..core.error import (
|
|
9
|
-
PathNotFoundError,
|
|
10
|
-
PathlibTypeError,
|
|
11
|
-
PathInvalidHandlerTypeError,
|
|
12
|
-
PathHandlerMissingArgError,
|
|
13
|
-
)
|
|
14
|
-
from .request import Request
|
|
15
|
-
from .response import Response, JsonResponse
|
|
16
|
-
from .middleware import Middleware, MiddlewareChain, Handler
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class Path:
|
|
20
|
-
"""
|
|
21
|
-
Represents a route with optional path arguments and its handler.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
def __init__(self, path: str, handler: Handler, name: str):
|
|
25
|
-
self.handler = handler
|
|
26
|
-
self.name: str = name
|
|
27
|
-
|
|
28
|
-
path_segments = path.strip("/").split("/")
|
|
29
|
-
self.path_args: dict[int, str] = {}
|
|
30
|
-
detection_index = 0
|
|
31
|
-
|
|
32
|
-
for idx, segment in enumerate(path_segments):
|
|
33
|
-
m = re.match(r"{(.*?)}", segment)
|
|
34
|
-
if m:
|
|
35
|
-
if detection_index == 0:
|
|
36
|
-
detection_index = idx
|
|
37
|
-
self.path_args[idx] = m.group(1)
|
|
38
|
-
if idx == len(path_segments) - 1 and detection_index == 0:
|
|
39
|
-
detection_index = idx + 1
|
|
40
|
-
|
|
41
|
-
self.path: str = "/".join(path_segments[:detection_index])
|
|
42
|
-
self.detection_range: int = detection_index
|
|
43
|
-
self.args: dict[str, Optional[str]] = {}
|
|
44
|
-
|
|
45
|
-
def _read_args(self, request_path: str) -> None:
|
|
46
|
-
segments = request_path.strip("/").split("/")
|
|
47
|
-
for idx, arg_name in self.path_args.items():
|
|
48
|
-
self.args[arg_name] = segments[idx] if idx < len(segments) else None
|
|
49
|
-
|
|
50
|
-
def call_handler(self, request: Request, middlewares: tuple[Middleware, ...] = ()) -> Response:
|
|
51
|
-
try:
|
|
52
|
-
self._read_args(request.path)
|
|
53
|
-
|
|
54
|
-
handler = self.handler
|
|
55
|
-
if middlewares:
|
|
56
|
-
handler = MiddlewareChain(middlewares).wrap(handler)
|
|
57
|
-
|
|
58
|
-
res = handler(request, self.args)
|
|
59
|
-
if isinstance(res, dict):
|
|
60
|
-
return JsonResponse(res)
|
|
61
|
-
if not isinstance(res, Response):
|
|
62
|
-
raise PathInvalidHandlerTypeError(self.handler)
|
|
63
|
-
return res
|
|
64
|
-
except TypeError as e:
|
|
65
|
-
if re.search(r"takes \d+ positional arguments? but \d+ were given", str(e)):
|
|
66
|
-
raise PathHandlerMissingArgError()
|
|
67
|
-
raise
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class Static(Path):
|
|
71
|
-
"""
|
|
72
|
-
Represents a static file route.
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
def __init__(self, path: str, static_directory: str, name: str) -> None:
|
|
76
|
-
self.static_directory = os.path.abspath(static_directory.rstrip("/"))
|
|
77
|
-
super().__init__(path, self._access, name)
|
|
78
|
-
|
|
79
|
-
def _access(self, request: Request, args: dict[str, Optional[str]]) -> Response:
|
|
80
|
-
segments = request.path.strip("/").split("/")
|
|
81
|
-
relative_path = os.path.join(*segments[self.detection_range :]) if len(segments) > self.detection_range else ""
|
|
82
|
-
abs_path = os.path.abspath(os.path.join(self.static_directory, relative_path))
|
|
83
|
-
|
|
84
|
-
if os.path.isdir(abs_path):
|
|
85
|
-
abs_path = os.path.join(abs_path, "index.html")
|
|
86
|
-
|
|
87
|
-
if not abs_path.startswith(self.static_directory) or not os.path.exists(abs_path):
|
|
88
|
-
raise PathNotFoundError(request.path)
|
|
89
|
-
|
|
90
|
-
with open(abs_path, "rb") as f:
|
|
91
|
-
content = f.read()
|
|
92
|
-
|
|
93
|
-
mime_type, _ = guess_type(abs_path)
|
|
94
|
-
return Response(content, headers=[("Content-Type", mime_type or "application/octet-stream")])
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
class Pathlib(list[Path]):
|
|
98
|
-
"""
|
|
99
|
-
Collection of Path objects with middleware support.
|
|
100
|
-
"""
|
|
101
|
-
|
|
102
|
-
def __init__(self, *paths: Path) -> None:
|
|
103
|
-
for p in paths:
|
|
104
|
-
self._check(p)
|
|
105
|
-
super().__init__(paths)
|
|
106
|
-
self.raise_if_not_exist: bool = True
|
|
107
|
-
self.middlewares: list[Middleware] = []
|
|
108
|
-
|
|
109
|
-
def _check(self, arg: object) -> None:
|
|
110
|
-
if not isinstance(arg, Path):
|
|
111
|
-
raise PathlibTypeError
|
|
112
|
-
|
|
113
|
-
def add_middleware(self, *middlewares: Middleware) -> None:
|
|
114
|
-
self.middlewares.extend(middlewares)
|
|
115
|
-
|
|
116
|
-
def get(self, request_path: str) -> Path | None:
|
|
117
|
-
segments = request_path.rstrip("/").split("/")
|
|
118
|
-
for p in self:
|
|
119
|
-
detection_path = "/".join(segments[: p.detection_range])
|
|
120
|
-
if detection_path == p.path:
|
|
121
|
-
return p
|
|
122
|
-
|
|
123
|
-
if self.raise_if_not_exist:
|
|
124
|
-
raise PathNotFoundError(request_path)
|
|
125
|
-
return None
|
nexom/web/request.py
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Any, Mapping
|
|
4
|
-
from http.cookies import SimpleCookie
|
|
5
|
-
|
|
6
|
-
from .cookie import RequestCookies
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
WSGIEnviron = Mapping[str, Any]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class Request:
|
|
13
|
-
"""
|
|
14
|
-
Represents an HTTP request constructed from a WSGI environ.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
def __init__(self, environ: WSGIEnviron) -> None:
|
|
18
|
-
self.environ: WSGIEnviron = environ
|
|
19
|
-
|
|
20
|
-
self.method: str = environ.get("REQUEST_METHOD", "GET")
|
|
21
|
-
self.path: str = environ.get("PATH_INFO", "").lstrip("/")
|
|
22
|
-
self.query: str = environ.get("QUERY_STRING", "")
|
|
23
|
-
self.headers: dict[str, str] = {
|
|
24
|
-
k[5:].replace("_", "-"): v
|
|
25
|
-
for k, v in environ.items()
|
|
26
|
-
if k.startswith("HTTP_")
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
self.cookie: RequestCookies | None = self._parse_cookies()
|
|
30
|
-
self._body: bytes | None = None
|
|
31
|
-
|
|
32
|
-
def _parse_cookies(self) -> RequestCookies | None:
|
|
33
|
-
cookie_header = self.environ.get("HTTP_COOKIE")
|
|
34
|
-
if not cookie_header:
|
|
35
|
-
return None
|
|
36
|
-
|
|
37
|
-
simple_cookie = SimpleCookie()
|
|
38
|
-
simple_cookie.load(cookie_header)
|
|
39
|
-
|
|
40
|
-
cookies = {
|
|
41
|
-
key: morsel.value
|
|
42
|
-
for key, morsel in simple_cookie.items()
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
rc = RequestCookies(**cookies)
|
|
46
|
-
rc.default = None
|
|
47
|
-
return rc
|
|
48
|
-
|
|
49
|
-
def read_body(self) -> bytes:
|
|
50
|
-
"""
|
|
51
|
-
Read and cache the request body.
|
|
52
|
-
"""
|
|
53
|
-
if self._body is not None:
|
|
54
|
-
return self._body
|
|
55
|
-
|
|
56
|
-
length = int(self.environ.get("CONTENT_LENGTH") or 0)
|
|
57
|
-
if length <= 0:
|
|
58
|
-
self._body = b""
|
|
59
|
-
return self._body
|
|
60
|
-
|
|
61
|
-
self._body = self.environ["wsgi.input"].read(length)
|
|
62
|
-
return self._body
|
nexom-0.1.4.dist-info/RECORD
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
nexom/__init__.py,sha256=tkqlHy7lHeCM4OuTb0GJZO3zopx6RcnpdMZE9E6g0_4,367
|
|
2
|
-
nexom/__main__.py,sha256=3W07j3zeXDxh8nmsAN0THLb9tVEB3Gjc2CNA1uYSB4Y,1949
|
|
3
|
-
nexom/assets/error_page/error.html,sha256=KlNyr-57wCEkp9ICSHTAmq4-6mQ0idbI2zgsmBx3MRw,1224
|
|
4
|
-
nexom/assets/server/config.py,sha256=3bWgwlS394JwFSDHfuZasgXPdtJVzSvT99kqCMT_2Zs,509
|
|
5
|
-
nexom/assets/server/gunicorn.conf.py,sha256=NedfqQFONa_p53zevgfRHrypu7aBCc6nCMeiEN1_BtM,377
|
|
6
|
-
nexom/assets/server/router.py,sha256=AxkoOJRE1lRmsA8Xve8RbvCZs6UleEQ4cbP2DzimGrQ,416
|
|
7
|
-
nexom/assets/server/wsgi.py,sha256=CiJJDWibh73a1wkCSuALoWDJ3u8fDDbbrR1bkurNgWE,743
|
|
8
|
-
nexom/assets/server/pages/__init__.py,sha256=DlX9iwM39JaMKfzK4mbgjE2uVMX3ax0wd2mCVnpg0b4,61
|
|
9
|
-
nexom/assets/server/pages/_templates.py,sha256=g77QjqMS9--Pw1P4mNCC2KMyiQI0kKo02ENwgIdE8dU,320
|
|
10
|
-
nexom/assets/server/pages/default.py,sha256=_XCNtj7Z57volVIS4KBhps9TQPYiflPBTv8v3GH2SYM,257
|
|
11
|
-
nexom/assets/server/pages/document.py,sha256=R7r8zBDBfv0vtr82TFcGb60MesKVqDihdGFt03eppVc,245
|
|
12
|
-
nexom/assets/server/pages/__pycache__/__init__.cpython-313.pyc,sha256=O03yzGGSKHVUeAqQVULe0-He2mBqkcVb_UwFF_esNUw,276
|
|
13
|
-
nexom/assets/server/static/dog.jpeg,sha256=qGEhcg48FxRLRISzbmXvw1qvfbdluC_ukM8ZrHg7_XE,6559
|
|
14
|
-
nexom/assets/server/static/style.css,sha256=mDKNWue0uRLdWB0w1RsMSn6h3tHsuTVLuk3xOOJl7X8,566
|
|
15
|
-
nexom/assets/server/templates/base.html,sha256=RVW_63gA1sr7pqNkfB6Djk5an_VFpowahDIHGjfV-Wk,349
|
|
16
|
-
nexom/assets/server/templates/default.html,sha256=EKG9NTYkXngdCiDodSI1Kuic_ZwVwdeRc3VLq6fX5UI,167
|
|
17
|
-
nexom/assets/server/templates/document.html,sha256=16ClimpeqhLnXFNa8nMdMOlXUu8JOw7XxfpjU9DdIFs,6243
|
|
18
|
-
nexom/assets/server/templates/footer.html,sha256=1NZbbarU-CQhs1OPs2MTzhnWu0h7YYiEKDIP_cgIl9I,98
|
|
19
|
-
nexom/assets/server/templates/header.html,sha256=VgkCtCVE1J-eGEYvbBgWSUU-QauEf6xuvweOE-84U9c,75
|
|
20
|
-
nexom/buildTools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
nexom/buildTools/build.py,sha256=q4_4seJSH8fmRruDb1LkKAaQTBDtBKqInIJk46i_LMg,3317
|
|
22
|
-
nexom/core/__init__.py,sha256=EsfVI7jSjLWUhwMIWasUDIOdlSHtOsFSJ6WfzkrtY5o,19
|
|
23
|
-
nexom/core/error.py,sha256=YXMYQ-rgMXpId_d7_uxRVNFm-YMu99LjQBImTSTftTY,4148
|
|
24
|
-
nexom/engine/__init__.py,sha256=yorquMUk_CF949j-Tw2hkavz5VpbeQhAQ1pYZbMLIcw,32
|
|
25
|
-
nexom/engine/object_html_render.py,sha256=-99gxYv2m2emv7JvTVuKJCx9V8UpKRpFjmx8Qw5e_8A,6928
|
|
26
|
-
nexom/web/__init__.py,sha256=5Ox2txlSe4M4y353Xi7PymC_bCsFtgP0tjEI6wQfai8,107
|
|
27
|
-
nexom/web/cookie.py,sha256=Ad7TamzkUOGR7VMq4LTSAKATS43ycP7o6KRKOSLhyu4,1940
|
|
28
|
-
nexom/web/http_status_codes.py,sha256=R4ka3n4rijqvfahF5n5kS-Qrg8bZSsrvF8lGnpKWAgY,1934
|
|
29
|
-
nexom/web/middleware.py,sha256=7bHGtEem92QhgULOvTFDFlZ4K719CQgu9RKj1g7XOW8,1429
|
|
30
|
-
nexom/web/path.py,sha256=VcNhPOpVURn5G26iNgI_qU30RnpxUSXceYGLj-yASwA,4299
|
|
31
|
-
nexom/web/request.py,sha256=jNYdEbYCOKmgm_2iPVmB_IwCSCyLWgODBIl1974hSVY,1680
|
|
32
|
-
nexom/web/response.py,sha256=Z94-qXq2mlzhY1QkHPTTNlewac79gBOoV0ClP3h-YRE,3854
|
|
33
|
-
nexom/web/template.py,sha256=qPH0bGSzwn8tNIsPdxVoFZDL5NSO2Yxd6gPXShL2mXg,3589
|
|
34
|
-
nexom-0.1.4.dist-info/licenses/LICENSE,sha256=YbcHyxYLJ5jePeMS_NXpR9yiZjP5skhn32LvcKeknJw,1066
|
|
35
|
-
nexom-0.1.4.dist-info/METADATA,sha256=YZt9pP4sqWKjcynH6OBKHnb25ReT7OZoy84aSIfhn4M,5406
|
|
36
|
-
nexom-0.1.4.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
37
|
-
nexom-0.1.4.dist-info/entry_points.txt,sha256=0r1egKZmF1MUo25AKPt-2d55sk5Q_EIBOQwD3JC8RgI,46
|
|
38
|
-
nexom-0.1.4.dist-info/top_level.txt,sha256=mTyUruscL3rqXvYJRo8KGwDM6PWXRzgf4CamLr8LSX4,6
|
|
39
|
-
nexom-0.1.4.dist-info/RECORD,,
|
|
File without changes
|
/nexom/{web → app}/middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|