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.
Files changed (67) hide show
  1. nexom/__init__.py +2 -2
  2. nexom/__main__.py +111 -17
  3. nexom/app/__init__.py +62 -0
  4. nexom/app/auth.py +322 -0
  5. nexom/{web → app}/cookie.py +4 -2
  6. nexom/app/db.py +88 -0
  7. nexom/app/path.py +195 -0
  8. nexom/app/request.py +267 -0
  9. nexom/{web → app}/response.py +13 -3
  10. nexom/{web → app}/template.py +1 -1
  11. nexom/app/user.py +31 -0
  12. nexom/assets/app/__init__.py +0 -0
  13. nexom/assets/app/__pycache__/__init__.cpython-313.pyc +0 -0
  14. nexom/assets/app/config.py +28 -0
  15. nexom/assets/app/gunicorn.conf.py +5 -0
  16. nexom/assets/app/pages/__pycache__/__init__.cpython-313.pyc +0 -0
  17. nexom/assets/app/pages/_templates.py +7 -0
  18. nexom/assets/{server → app}/pages/default.py +2 -2
  19. nexom/assets/{server → app}/pages/document.py +2 -2
  20. nexom/assets/app/router.py +12 -0
  21. nexom/assets/app/wsgi.py +64 -0
  22. nexom/assets/auth/__init__.py +0 -0
  23. nexom/assets/auth/__pycache__/__init__.cpython-313.pyc +0 -0
  24. nexom/assets/auth/config.py +27 -0
  25. nexom/assets/auth/gunicorn.conf.py +5 -0
  26. nexom/assets/auth/wsgi.py +62 -0
  27. nexom/assets/auth_page/login.html +95 -0
  28. nexom/assets/auth_page/signup.html +106 -0
  29. nexom/assets/error_page/error.html +3 -3
  30. nexom/assets/gateway/apache_app.conf +16 -0
  31. nexom/assets/gateway/nginx_app.conf +21 -0
  32. nexom/buildTools/__init__.py +1 -0
  33. nexom/buildTools/build.py +274 -54
  34. nexom/buildTools/run.py +185 -0
  35. nexom/core/__init__.py +2 -1
  36. nexom/core/error.py +81 -3
  37. nexom/core/log.py +111 -0
  38. nexom/{engine → core}/object_html_render.py +4 -1
  39. nexom/templates/__init__.py +0 -0
  40. nexom/templates/auth.py +72 -0
  41. {nexom-0.1.4.dist-info → nexom-1.0.2.dist-info}/METADATA +76 -50
  42. nexom-1.0.2.dist-info/RECORD +56 -0
  43. {nexom-0.1.4.dist-info → nexom-1.0.2.dist-info}/WHEEL +1 -1
  44. nexom/assets/server/config.py +0 -27
  45. nexom/assets/server/gunicorn.conf.py +0 -16
  46. nexom/assets/server/pages/__pycache__/__init__.cpython-313.pyc +0 -0
  47. nexom/assets/server/pages/_templates.py +0 -11
  48. nexom/assets/server/router.py +0 -18
  49. nexom/assets/server/wsgi.py +0 -30
  50. nexom/engine/__init__.py +0 -1
  51. nexom/web/__init__.py +0 -5
  52. nexom/web/path.py +0 -125
  53. nexom/web/request.py +0 -62
  54. nexom-0.1.4.dist-info/RECORD +0 -39
  55. /nexom/{web → app}/http_status_codes.py +0 -0
  56. /nexom/{web → app}/middleware.py +0 -0
  57. /nexom/assets/{server → app}/pages/__init__.py +0 -0
  58. /nexom/assets/{server → app}/static/dog.jpeg +0 -0
  59. /nexom/assets/{server → app}/static/style.css +0 -0
  60. /nexom/assets/{server → app}/templates/base.html +0 -0
  61. /nexom/assets/{server → app}/templates/default.html +0 -0
  62. /nexom/assets/{server → app}/templates/document.html +0 -0
  63. /nexom/assets/{server → app}/templates/footer.html +0 -0
  64. /nexom/assets/{server → app}/templates/header.html +0 -0
  65. {nexom-0.1.4.dist-info → nexom-1.0.2.dist-info}/entry_points.txt +0 -0
  66. {nexom-0.1.4.dist-info → nexom-1.0.2.dist-info}/licenses/LICENSE +0 -0
  67. {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
@@ -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
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