hypern 0.1.0__cp310-cp310-manylinux_2_34_x86_64.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 (65) hide show
  1. hypern/__init__.py +4 -0
  2. hypern/application.py +234 -0
  3. hypern/auth/__init__.py +0 -0
  4. hypern/auth/authorization.py +2 -0
  5. hypern/background.py +4 -0
  6. hypern/caching/__init__.py +0 -0
  7. hypern/caching/base/__init__.py +8 -0
  8. hypern/caching/base/backend.py +3 -0
  9. hypern/caching/base/key_maker.py +8 -0
  10. hypern/caching/cache_manager.py +56 -0
  11. hypern/caching/cache_tag.py +10 -0
  12. hypern/caching/custom_key_maker.py +11 -0
  13. hypern/caching/redis_backend.py +3 -0
  14. hypern/cli/__init__.py +0 -0
  15. hypern/cli/commands.py +0 -0
  16. hypern/config.py +149 -0
  17. hypern/datastructures.py +27 -0
  18. hypern/db/__init__.py +0 -0
  19. hypern/db/nosql/__init__.py +25 -0
  20. hypern/db/nosql/addons/__init__.py +4 -0
  21. hypern/db/nosql/addons/color.py +16 -0
  22. hypern/db/nosql/addons/daterange.py +30 -0
  23. hypern/db/nosql/addons/encrypted.py +53 -0
  24. hypern/db/nosql/addons/password.py +134 -0
  25. hypern/db/nosql/addons/unicode.py +10 -0
  26. hypern/db/sql/__init__.py +176 -0
  27. hypern/db/sql/addons/__init__.py +14 -0
  28. hypern/db/sql/addons/color.py +15 -0
  29. hypern/db/sql/addons/daterange.py +22 -0
  30. hypern/db/sql/addons/datetime.py +22 -0
  31. hypern/db/sql/addons/encrypted.py +58 -0
  32. hypern/db/sql/addons/password.py +170 -0
  33. hypern/db/sql/addons/ts_vector.py +46 -0
  34. hypern/db/sql/addons/unicode.py +15 -0
  35. hypern/db/sql/repository.py +289 -0
  36. hypern/enum.py +13 -0
  37. hypern/exceptions.py +93 -0
  38. hypern/hypern.cpython-310-x86_64-linux-gnu.so +0 -0
  39. hypern/hypern.pyi +172 -0
  40. hypern/i18n/__init__.py +0 -0
  41. hypern/logging/__init__.py +3 -0
  42. hypern/logging/logger.py +91 -0
  43. hypern/middleware/__init__.py +5 -0
  44. hypern/middleware/base.py +16 -0
  45. hypern/middleware/cors.py +38 -0
  46. hypern/middleware/i18n.py +1 -0
  47. hypern/middleware/limit.py +174 -0
  48. hypern/openapi/__init__.py +5 -0
  49. hypern/openapi/schemas.py +64 -0
  50. hypern/openapi/swagger.py +3 -0
  51. hypern/py.typed +0 -0
  52. hypern/response/__init__.py +3 -0
  53. hypern/response/response.py +134 -0
  54. hypern/routing/__init__.py +4 -0
  55. hypern/routing/dispatcher.py +65 -0
  56. hypern/routing/endpoint.py +27 -0
  57. hypern/routing/parser.py +101 -0
  58. hypern/routing/router.py +279 -0
  59. hypern/scheduler.py +5 -0
  60. hypern/security.py +44 -0
  61. hypern/worker.py +30 -0
  62. hypern-0.1.0.dist-info/METADATA +121 -0
  63. hypern-0.1.0.dist-info/RECORD +65 -0
  64. hypern-0.1.0.dist-info/WHEEL +4 -0
  65. hypern-0.1.0.dist-info/licenses/LICENSE +24 -0
@@ -0,0 +1,279 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Callable, Any, Dict, List, Union, Type, get_origin, get_args
3
+ from robyn.router import Router as RobynRouter
4
+ from robyn import HttpMethod, Request
5
+ from pydantic import BaseModel
6
+ from pydantic.fields import FieldInfo
7
+ from enum import Enum
8
+
9
+ import inspect
10
+ import yaml # type: ignore
11
+
12
+ from hypern.auth.authorization import Authorization
13
+ from .dispatcher import dispatch
14
+
15
+
16
+ def get_field_type(field):
17
+ return field.outer_type_
18
+
19
+
20
+ def pydantic_to_swagger(model: type[BaseModel] | dict):
21
+ if isinstance(model, dict):
22
+ # Handle the case when a dict is passed instead of a Pydantic model
23
+ schema = {}
24
+ for name, field_type in model.items():
25
+ schema[name] = _process_field(name, field_type)
26
+ return schema
27
+
28
+ schema = {
29
+ model.__name__: {
30
+ "type": "object",
31
+ "properties": {},
32
+ }
33
+ }
34
+
35
+ for name, field in model.model_fields.items():
36
+ schema[model.__name__]["properties"][name] = _process_field(name, field)
37
+
38
+ return schema
39
+
40
+
41
+ class SchemaProcessor:
42
+ @staticmethod
43
+ def process_union(args: tuple) -> Dict[str, Any]:
44
+ """Process Union types"""
45
+ if type(None) in args:
46
+ inner_type = next(arg for arg in args if arg is not type(None))
47
+ schema = SchemaProcessor._process_field("", inner_type)
48
+ schema["nullable"] = True
49
+ return schema
50
+ return {"oneOf": [SchemaProcessor._process_field("", arg) for arg in args]}
51
+
52
+ @staticmethod
53
+ def process_enum(annotation: Type[Enum]) -> Dict[str, Any]:
54
+ """Process Enum types"""
55
+ return {"type": "string", "enum": [e.value for e in annotation]}
56
+
57
+ @staticmethod
58
+ def process_primitive(annotation: type) -> Dict[str, str]:
59
+ """Process primitive types"""
60
+ type_mapping = {int: "integer", float: "number", str: "string", bool: "boolean"}
61
+ return {"type": type_mapping.get(annotation, "object")}
62
+
63
+ @staticmethod
64
+ def process_list(annotation: type) -> Dict[str, Any]:
65
+ """Process list types"""
66
+ schema = {"type": "array"}
67
+
68
+ args = get_args(annotation)
69
+ if args:
70
+ item_type = args[0]
71
+ schema["items"] = SchemaProcessor._process_field("item", item_type)
72
+ else:
73
+ schema["items"] = {}
74
+ return schema
75
+
76
+ @staticmethod
77
+ def process_dict(annotation: type) -> Dict[str, Any]:
78
+ """Process dict types"""
79
+ schema = {"type": "object"}
80
+
81
+ args = get_args(annotation)
82
+ if args:
83
+ key_type, value_type = args
84
+ if key_type == str: # noqa: E721
85
+ schema["additionalProperties"] = SchemaProcessor._process_field("value", value_type)
86
+ return schema
87
+
88
+ @classmethod
89
+ def _process_field(cls, name: str, field: Any) -> Dict[str, Any]:
90
+ """Process a single field"""
91
+ if isinstance(field, FieldInfo):
92
+ annotation = field.annotation
93
+ else:
94
+ annotation = field
95
+
96
+ # Process Union types
97
+ origin = get_origin(annotation)
98
+ if origin is Union:
99
+ return cls.process_union(get_args(annotation))
100
+
101
+ # Process Enum types
102
+ if isinstance(annotation, type) and issubclass(annotation, Enum):
103
+ return cls.process_enum(annotation)
104
+
105
+ # Process primitive types
106
+ if annotation in {int, float, str, bool}:
107
+ return cls.process_primitive(annotation)
108
+
109
+ # Process list types
110
+ if annotation == list or origin is list: # noqa: E721
111
+ return cls.process_list(annotation)
112
+
113
+ # Process dict types
114
+ if annotation == dict or origin is dict: # noqa: E721
115
+ return cls.process_dict(annotation)
116
+
117
+ # Process Pydantic models
118
+ if isinstance(annotation, type) and issubclass(annotation, BaseModel):
119
+ return pydantic_to_swagger(annotation)
120
+
121
+ # Fallback for complex types
122
+ return {"type": "object"}
123
+
124
+
125
+ def _process_field(name: str, field: Any) -> Dict[str, Any]:
126
+ """
127
+ Process a field and return its schema representation
128
+
129
+ Args:
130
+ name: Field name
131
+ field: Field type or FieldInfo object
132
+
133
+ Returns:
134
+ Dictionary representing the JSON schema for the field
135
+ """
136
+ return SchemaProcessor._process_field(name, field)
137
+
138
+
139
+ class Route:
140
+ def __init__(
141
+ self,
142
+ path: str,
143
+ endpoint: Callable[..., Any] | None = None,
144
+ *,
145
+ name: str | None = None,
146
+ tags: List[str] | None = None,
147
+ ) -> None:
148
+ self.path = path
149
+ self.endpoint = endpoint
150
+ self.tags = tags or ["Default"]
151
+ self.name = name
152
+
153
+ self.http_methods = {
154
+ "GET": HttpMethod.GET,
155
+ "POST": HttpMethod.POST,
156
+ "PUT": HttpMethod.PUT,
157
+ "DELETE": HttpMethod.DELETE,
158
+ "PATCH": HttpMethod.PATCH,
159
+ "HEAD": HttpMethod.HEAD,
160
+ "OPTIONS": HttpMethod.OPTIONS,
161
+ }
162
+ self.functional_handlers = []
163
+
164
+ def swagger_generate(self, signature: inspect.Signature, summary: str = "Document API") -> str:
165
+ _inputs = signature.parameters.values()
166
+ _inputs_dict = {_input.name: _input.annotation for _input in _inputs}
167
+ _docs: Dict = {"summary": summary, "tags": self.tags, "responses": [], "name": self.name}
168
+ _response_type = signature.return_annotation
169
+
170
+ for key, item in _inputs_dict.items():
171
+ if isinstance(item, type) and issubclass(item, Authorization):
172
+ auth_obj = item()
173
+ _docs["security"] = [{auth_obj.name: []}]
174
+
175
+ if isinstance(item, type) and issubclass(item, BaseModel):
176
+ if key == "form_data":
177
+ _docs["requestBody"] = {"content": {"application/json": {"schema": pydantic_to_swagger(item).get(item.__name__)}}}
178
+
179
+ if key == "query_params":
180
+ _docs["parameters"] = [{"name": param, "in": "query", "schema": _process_field(param, field)} for param, field in item.model_fields.items()]
181
+
182
+ if key == "path_params":
183
+ path_params = [
184
+ {"name": param, "in": "path", "required": True, "schema": _process_field(param, field)} for param, field in item.model_fields.items()
185
+ ]
186
+ _docs.setdefault("parameters", []).extend(path_params)
187
+
188
+ if isinstance(_response_type, type) and issubclass(_response_type, BaseModel):
189
+ _docs["responses"] = {
190
+ "200": {
191
+ "description": "Successful response",
192
+ # type: ignore
193
+ "content": {"application/json": {"schema": _response_type.model_json_schema()}},
194
+ }
195
+ }
196
+
197
+ return yaml.dump(_docs)
198
+
199
+ def _combine_path(self, path1: str, path2: str) -> str:
200
+ if path1.endswith("/") and path2.startswith("/"):
201
+ return path1 + path2[1:]
202
+ if not path1.endswith("/") and not path2.startswith("/"):
203
+ return path1 + "/" + path2
204
+ return path1 + path2
205
+
206
+ def __call__(self, app, *args: Any, **kwds: Any) -> Any:
207
+ router = RobynRouter()
208
+
209
+ # Validate handlers
210
+ if not self.endpoint and not self.functional_handlers:
211
+ raise ValueError(f"No handler found for route: {self.path}")
212
+
213
+ default_params = {"is_const": False, "injected_dependencies": app.dependencies.get_dependency_map(app), "exception_handler": app.exception_handler}
214
+
215
+ # Handle functional routes
216
+ for h in self.functional_handlers:
217
+ router.add_route(
218
+ route_type=self.http_methods[h["method"].upper()], endpoint=self._combine_path(self.path, h["path"]), handler=h["func"], **default_params
219
+ )
220
+
221
+ if not self.endpoint:
222
+ return router
223
+
224
+ # Handle class-based routes
225
+ for name, func in self.endpoint.__dict__.items():
226
+ if name.upper() in self.http_methods:
227
+ sig = inspect.signature(func)
228
+ doc = self.swagger_generate(sig, func.__doc__)
229
+ self.endpoint.dispatch.__doc__ = doc
230
+ endpoint_obj = self.endpoint()
231
+ router.add_route(route_type=self.http_methods[name.upper()], endpoint=self.path, handler=endpoint_obj.dispatch, **default_params)
232
+ del endpoint_obj # free up memory
233
+
234
+ return router
235
+
236
+ def route(
237
+ self,
238
+ path: str,
239
+ method: str,
240
+ *args: Any,
241
+ **kwds: Any,
242
+ ) -> Callable:
243
+ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
244
+ async def functional_wrapper(request: Request, global_dependencies, router_dependencies) -> Any:
245
+ return await dispatch(func, request, global_dependencies, router_dependencies)
246
+
247
+ sig = inspect.signature(func)
248
+ functional_wrapper.__doc__ = self.swagger_generate(sig, func.__doc__)
249
+
250
+ self.functional_handlers.append(
251
+ {
252
+ "path": path,
253
+ "method": method,
254
+ "func": functional_wrapper,
255
+ }
256
+ )
257
+
258
+ return decorator
259
+
260
+ def get(self, path: str) -> Callable:
261
+ return self.route(path, "GET")
262
+
263
+ def post(self, path: str) -> Callable:
264
+ return self.route(path, "POST")
265
+
266
+ def put(self, path: str) -> Callable:
267
+ return self.route(path, "PUT")
268
+
269
+ def delete(self, path: str) -> Callable:
270
+ return self.route(path, "DELETE")
271
+
272
+ def patch(self, path: str) -> Callable:
273
+ return self.route(path, "PATCH")
274
+
275
+ def head(self, path: str) -> Callable:
276
+ return self.route(path, "HEAD")
277
+
278
+ def options(self, path: str) -> Callable:
279
+ return self.route(path, "OPTIONS")
hypern/scheduler.py ADDED
@@ -0,0 +1,5 @@
1
+ from .hypern import Scheduler
2
+
3
+ __all__ = [
4
+ "Scheduler",
5
+ ]
hypern/security.py ADDED
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ from abc import ABC, abstractmethod
3
+ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
4
+ from cryptography.hazmat.backends import default_backend
5
+ from base64 import b64encode, b64decode
6
+
7
+ import typing
8
+
9
+
10
+ class EDEngine(ABC):
11
+ @abstractmethod
12
+ def encrypt(self, data: str) -> str:
13
+ raise NotImplementedError("Method not implemented")
14
+
15
+ @abstractmethod
16
+ def decrypt(self, data: str) -> str:
17
+ raise NotImplementedError("Method not implemented")
18
+
19
+
20
+ class AESEngine(EDEngine):
21
+ def __init__(self, secret_key: bytes, iv: bytes, padding_class: typing.Type) -> None:
22
+ super().__init__()
23
+ self.secret_key = secret_key
24
+ self.iv = iv
25
+ self.padding = padding_class(128)
26
+
27
+ def encrypt(self, data: str) -> bytes:
28
+ bytes_data = data.encode("utf-8")
29
+ encryptor = Cipher(algorithms.AES(self.secret_key), modes.GCM(self.iv), backend=default_backend()).encryptor()
30
+ padder = self.padding.padder()
31
+ padded_data = padder.update(bytes_data) + padder.finalize()
32
+ enctyped_data = encryptor.update(padded_data) + encryptor.finalize()
33
+ tag = encryptor.tag
34
+ return b64encode(tag + enctyped_data)
35
+
36
+ def decrypt(self, data: bytes) -> str:
37
+ data = b64decode(data)
38
+ tag = data[:16]
39
+ encrypted_data = data[16:]
40
+ decryptor = Cipher(algorithms.AES(self.secret_key), modes.GCM(self.iv, tag), backend=default_backend()).decryptor()
41
+ unpadder = self.padding.unpadder()
42
+ decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()
43
+ unpadded_data = unpadder.update(decrypted_data) + unpadder.finalize()
44
+ return unpadded_data.decode("utf-8")
hypern/worker.py ADDED
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+ from typing import Any
3
+ from celery import Celery
4
+ from asgiref.sync import async_to_sync
5
+
6
+
7
+ class AsyncCelery(Celery):
8
+ def __new__(cls, *args, **kwargs) -> Any:
9
+ if not hasattr(cls, "instance") or not cls.instance: # type: ignore
10
+ cls.instance = super().__new__(cls)
11
+ return cls.instance
12
+
13
+ def __init__(self, *args, **kwargs) -> None:
14
+ super().__init__(*args, **kwargs)
15
+ self.patch_task()
16
+
17
+ def patch_task(self) -> None:
18
+ TaskBase = self.Task
19
+
20
+ class ContextTask(TaskBase): # type: ignore
21
+ abstract = True
22
+
23
+ def _run(self, *args, **kwargs):
24
+ result = async_to_sync(TaskBase.__call__)(self, *args, **kwargs)
25
+ return result
26
+
27
+ def __call__(self, *args, **kwargs):
28
+ return self._run(*args, **kwargs)
29
+
30
+ self.Task = ContextTask
@@ -0,0 +1,121 @@
1
+ Metadata-Version: 2.3
2
+ Name: hypern
3
+ Version: 0.1.0
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
7
+ Requires-Dist: robyn ==0.58.0
8
+ Requires-Dist: sqlalchemy[asyncio] ==2.0.31
9
+ Requires-Dist: pydantic[email] ==2.8.2
10
+ Requires-Dist: passlib ==1.7.4
11
+ Requires-Dist: pyjwt ==2.8.0
12
+ Requires-Dist: pydash ==8.0.3
13
+ Requires-Dist: sentry-sdk ==2.11.0
14
+ Requires-Dist: pydantic-settings ==2.3.4
15
+ Requires-Dist: celery ==5.4.0
16
+ Requires-Dist: asgiref ==3.8.1
17
+ Requires-Dist: psycopg ==3.2.3
18
+ Requires-Dist: pyyaml ==6.0.2
19
+ Requires-Dist: mongoengine ==0.29.1
20
+ Requires-Dist: argon2-cffi ==23.1.0
21
+ Requires-Dist: bcrypt ==4.2.0
22
+ License-File: LICENSE
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
25
+
26
+
27
+ # Hypern
28
+
29
+ Hypern: A Versatile Python and Rust Framework
30
+
31
+ Hypern is a flexible, open-source framework built on the [Robyn](https://github.com/sparckles/Robyn/), designed to jumpstart your high-performance web development endeavors. By providing a pre-configured structure and essential components, Hypern empowers you to rapidly develop custom web applications that leverage the combined power of Python and Rust.
32
+
33
+ With Hypern, you can seamlessly integrate asynchronous features and build scalable solutions for RESTful APIs and dynamic web applications. Its intuitive design and robust tooling allow developers to focus on creating high-quality code while maximizing performance. Embrace the synergy of Python and Rust to elevate your web development experience.
34
+
35
+
36
+ ### 🏁 Get started
37
+
38
+ ### ⚙️ To Develop Locally
39
+
40
+ - Setup a virtual environment:
41
+ ```
42
+ python3 -m venv venv
43
+ source venv/bin/activate
44
+ ```
45
+ - Install required packages
46
+
47
+ ```
48
+ pip install pre-commit poetry maturin
49
+ ```
50
+ - Install development dependencies
51
+ ```
52
+ poetry install --with dev --with test
53
+ ```
54
+ - Install pre-commit git hooks
55
+ ```
56
+ pre-commit install
57
+ ```
58
+ - Build & install Robyn Rust package
59
+ ```
60
+ maturin develop
61
+ ```
62
+
63
+ ## 🤔 Usage
64
+
65
+ ### 🏃 Run your code
66
+
67
+ This using default CLI Robyn, you can see bellow. You will then have access to a server on the `localhost:5005`,
68
+ ```python
69
+ # main.py
70
+ from hypern import Hypern
71
+ from hypern.routing import Route, HTTPEndpoint
72
+
73
+ class MyEndpoint(HTTPEndpoint):
74
+
75
+ async def get(self, global_dependencies):
76
+ return {"data": "Hello World"}
77
+
78
+ routing = [
79
+ Route("/hello", MyEndpoint)
80
+ ]
81
+
82
+ app = Hypern(routing)
83
+
84
+ if __name__ == "__main__":
85
+ app.start(host='localhost', port=5005)
86
+ ```
87
+
88
+ ```
89
+ $ python3 main.py
90
+ ```
91
+
92
+ To see the usage
93
+
94
+ ```
95
+ usage: main.py [-h] [--processes PROCESSES] [--workers WORKERS] [--dev] [--log-level LOG_LEVEL]
96
+
97
+ options:
98
+ -h, --help show this help message and exit
99
+ --processes PROCESSES Choose the number of processes. [Default: 1]
100
+ --workers WORKERS Choose the number of workers. [Default: 1]
101
+ --dev Development mode. It restarts the server based on file changes.
102
+ --log-level LOG_LEVEL Set the log level name
103
+ --create Create a new project template.
104
+ --docs Open the Robyn documentation.
105
+ --open-browser Open the browser on successful start.
106
+ ```
107
+
108
+ Log level can be `DEBUG`, `INFO`, `WARNING`, or `ERROR`.
109
+
110
+ You can open swagger UI at path `/docs`
111
+
112
+
113
+ ## 💡 Features
114
+
115
+ Comming Soon !
116
+
117
+
118
+ ## ✨ Special thanks
119
+
120
+ Special thanks to the [PyO3](https://pyo3.rs/v0.13.2/) community and [Robyn](https://github.com/sparckles/Robyn) for their amazing libraries 💖
121
+
@@ -0,0 +1,65 @@
1
+ hypern-0.1.0.dist-info/METADATA,sha256=NidC7S9N8WeFH-YSl2_KK9bhXkkFQVLHYBTMWvpxKi4,3540
2
+ hypern-0.1.0.dist-info/WHEEL,sha256=Eon-X1H-_QAARJHJrle01PrnTNoTi49kSjaP6kGdlhU,108
3
+ hypern-0.1.0.dist-info/licenses/LICENSE,sha256=VdbaK2hSaaD-LUjtDIlEbeZVmvLGK7BEQvltP3mv-cY,1304
4
+ hypern/middleware/cors.py,sha256=SfG-3vAS-4MPXqsIsegNwDx9mqC9lvgUc3RuYzN6HNg,1643
5
+ hypern/middleware/base.py,sha256=zqUU85jkPNXOXC4JPXGwkJ7BwjafqI8dq3aajoCUQV0,345
6
+ hypern/middleware/__init__.py,sha256=YpgxL7GQkzZM91VCNxHT2xmTa1R1b_BUS8n3tZ2b1Ys,268
7
+ hypern/middleware/i18n.py,sha256=s82nQo6kKClZ0s3G3jsy87VRfwxpBDbASB_ErjRL3O0,15
8
+ hypern/middleware/limit.py,sha256=3Kp1amDd3s27shHQPPgRMtYM5LFmSGccEWVzT9ajXI4,7962
9
+ hypern/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ hypern/hypern.pyi,sha256=buOBdrrDel8PpkS6Fz0idBoOYuK8FYy2eo0nTlIyWL0,4191
11
+ hypern/scheduler.py,sha256=nQoWIYMRmKd30g4XwdB072hWTNHvJlLd9S6rLlTFKS0,62
12
+ hypern/application.py,sha256=KcINmggRIPmKUfbpRA7_dQ_8RG7qRA83VvyfrDmcXgc,7731
13
+ hypern/openapi/swagger.py,sha256=E5fHYUfFa77zQsCyQGf_vnqJVpl4_KI5qsKFHdgJEdw,61
14
+ hypern/openapi/__init__.py,sha256=oJ0HM9yAgSN00mBC_fRgV2irlGugrhvIpiveuDMv8PM,136
15
+ hypern/openapi/schemas.py,sha256=d4AQUkDdw9AO4vUfUU0bckDh6KMCyGJYGW_u_PIOtew,2083
16
+ hypern/background.py,sha256=fN38UlJG6wZf1gOGcvdY-INoD8zJKvGZZOdVYTMjDwg,120
17
+ hypern/datastructures.py,sha256=MitMRsvoWz3_SJvtbkcaJ-FovaLrRhmkp5MqSMfZPjs,631
18
+ hypern/response/__init__.py,sha256=9z99BDgASpG404GK8LGkOsXgac0wFwH_cQOTI5Ju-1U,223
19
+ hypern/response/response.py,sha256=akOqPDOi4J0g9jxsoZ1Za2ErcSA9eZFy2Fg5Wn38sIU,4436
20
+ hypern/logging/__init__.py,sha256=2K5q9ECE8HYVLnYbrzrzu6Bg2C5MiROD9KH835ujMUU,79
21
+ hypern/logging/logger.py,sha256=1XVzlNoYEVDWQ20csClCkweEdKcNZWk-o63qfcVTLFI,3235
22
+ hypern/db/sql/addons/unicode.py,sha256=gvsWvt0gTEwy62U4l6yDQjEXfc982QAaVay3YfxD3do,396
23
+ hypern/db/sql/addons/datetime.py,sha256=vZEV0s8M6VlsV9DDcEsCFIwoEAi_vNGY5HGFGULc0H0,621
24
+ hypern/db/sql/addons/color.py,sha256=1fHRVrqekip5u9nc7yv53niYnePmCdeYOr2gGVrXVzE,463
25
+ hypern/db/sql/addons/daterange.py,sha256=MUgAFHBt-iqY0sTU4sJYzvVFANlD1WFokCabhuodFCg,829
26
+ hypern/db/sql/addons/encrypted.py,sha256=hAzGaN_dXwlgYbC2_OsiHOxKh7PRX8gbM1_nnIF7M-w,1872
27
+ hypern/db/sql/addons/ts_vector.py,sha256=xmh-iLLGG5uW4QL_cnONdQd5rEfYZpNXaX_rW2kBrZU,1315
28
+ hypern/db/sql/addons/__init__.py,sha256=gZpp75nCNZHx9VDw5aNEmJzlpvVKv7Tulp40-Z7-ULM,345
29
+ hypern/db/sql/addons/password.py,sha256=mPwD17_0Fk0l378wdNP_BGojbC9EGPoZE94nCPTNy80,5617
30
+ hypern/db/sql/__init__.py,sha256=WnUiXBO2YV5f8q4gtu23opuu6vf4ZuMw-Inv2pqaE8Y,6314
31
+ hypern/db/sql/repository.py,sha256=SeSHKfO2cdd65dKBB5tP9-ORPsjGHbPEDWH3GYhdERY,9225
32
+ hypern/db/nosql/addons/unicode.py,sha256=vKyqfzrS9SKFo4eKlvu6klST0FrjM0wTx5N3ocvSSO8,258
33
+ hypern/db/nosql/addons/color.py,sha256=8zUBFjR19J1zy_WaOCXlS14GjgdOaHAcuSb__zFp_II,430
34
+ hypern/db/nosql/addons/daterange.py,sha256=YJBVfiX13Wx8DZociajWLBm20L_c0ZxTUbgCYMNk10Q,1162
35
+ hypern/db/nosql/addons/encrypted.py,sha256=bbJozZfcsWvumqHYOrN1Y8XrwRZqaR-z__u11GEmIv4,1688
36
+ hypern/db/nosql/addons/__init__.py,sha256=h6wJKPvCqyvivD52L7qsbFKnqqUnAdU1RQ30spnki98,121
37
+ hypern/db/nosql/addons/password.py,sha256=kbqQRzT5uq9IQ4Z_eE69cVo1rHTiovhtG3I0l5AZmMk,4901
38
+ hypern/db/nosql/__init__.py,sha256=LCVBhcJCQmFt5dCLiSf7C_TsjsEILeZe8JqiFEKuD2s,619
39
+ hypern/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
+ hypern/i18n/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
+ hypern/routing/parser.py,sha256=tRGxlkLDAvavtf3sWNEbezkZki2yxtDlOuuR-6pmptU,3691
42
+ hypern/routing/endpoint.py,sha256=bT8Dl0kaWIGOKzt-3J_gkBykZ2TDBefJq9dUt1yIGK8,1009
43
+ hypern/routing/router.py,sha256=pf1oBvCjLP10kWwUv_EBz1D8X6HncJcm8FGu9OfG-l0,9776
44
+ hypern/routing/dispatcher.py,sha256=o5H2qa_8iOui98gs1J9G6ZhJdHgB6kqvypa0iSZUho0,2329
45
+ hypern/routing/__init__.py,sha256=inI2G6oZTnf8__0avz2f47M5_Cf-4oWN1sbyaARtcEg,98
46
+ hypern/enum.py,sha256=-StRU0cWboP-y5fNuhB4Q7yMk8Zm_h1Eua9KzOtIyI8,347
47
+ hypern/security.py,sha256=dOWdNHA8SoUhlbu6Z2MapOwT9tAhlsierrTBBiEV5-A,1729
48
+ hypern/__init__.py,sha256=3fOyAFU6K9AusoP7UXeUGnHP3jPde5p6CZjtwJi3xHI,133
49
+ hypern/caching/cache_tag.py,sha256=DpkhFeKvcPT0zJlIWq5ywkYM8zRWGJ_grYIVZmHj-Js,257
50
+ hypern/caching/custom_key_maker.py,sha256=DxJv1RV--5IdFCCFYawVExwMQ097hZ5V6_nHDYIQIZI,383
51
+ hypern/caching/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ hypern/caching/base/backend.py,sha256=RHOq9Y_FzTlYHKpTqAPxUYdJDOSYBXx-mxaDitYtP70,65
53
+ hypern/caching/base/key_maker.py,sha256=FPW9L-N8NSPPgRngqMUCOdLurm1qmqe-KTe4UctoBp8,224
54
+ hypern/caching/base/__init__.py,sha256=8S6QSax1FVGzfve_fYIzPmhrpvxXG8WYoc7M9v25b6Q,147
55
+ hypern/caching/redis_backend.py,sha256=3FYzKCW0_OvoIMl-e9pARRGOUvRYGG7hGlaXEB18vnY,67
56
+ hypern/caching/cache_manager.py,sha256=EBx89xNj38bYpQ9jf4MoQ3zNkfoCGYInxvvPtzsW5Xo,1997
57
+ hypern/worker.py,sha256=kN93QGx4bst0inHRO_fsTzMmhDA0N3pdzaqNXwyu3N0,894
58
+ hypern/config.py,sha256=v9KLL6snReAETKiVb8x3KOFrXpYd8-Io5tM7eruR85U,4781
59
+ hypern/auth/authorization.py,sha256=b8N_MiBmSJBVR45SsOI2iMGmXYOlNKbsMsrMwXApxtk,30
60
+ hypern/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ hypern/exceptions.py,sha256=NJ19MXix0g9ueSkYA-ImghDiva7oAdmbtNEaiSCVLZo,2284
62
+ hypern/cli/commands.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
+ hypern/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
+ hypern/hypern.cpython-310-x86_64-linux-gnu.so,sha256=44C4si9vfQfpf6rF4OtotP-8MvcMCt9AgAf7tzPliLQ,4911472
65
+ hypern-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.7.4)
3
+ Root-Is-Purelib: false
4
+ Tag: cp310-cp310-manylinux_2_34_x86_64
@@ -0,0 +1,24 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2024, Dang Van Nghiem
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.