hypern 0.3.6__cp312-cp312-win32.whl → 0.3.8__cp312-cp312-win32.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.
- hypern/__init__.py +21 -1
- hypern/application.py +26 -36
- hypern/args_parser.py +0 -26
- hypern/database/sql/__init__.py +24 -1
- hypern/database/sql/field.py +130 -491
- hypern/database/sql/migrate.py +263 -0
- hypern/database/sql/model.py +4 -3
- hypern/database/sql/query.py +2 -2
- hypern/datastructures.py +2 -2
- hypern/hypern.cp312-win32.pyd +0 -0
- hypern/hypern.pyi +4 -9
- hypern/openapi/schemas.py +5 -7
- hypern/routing/route.py +8 -12
- hypern/worker.py +265 -21
- {hypern-0.3.6.dist-info → hypern-0.3.8.dist-info}/METADATA +16 -6
- {hypern-0.3.6.dist-info → hypern-0.3.8.dist-info}/RECORD +18 -18
- {hypern-0.3.6.dist-info → hypern-0.3.8.dist-info}/WHEEL +1 -1
- hypern/ws.py +0 -16
- {hypern-0.3.6.dist-info → hypern-0.3.8.dist-info}/licenses/LICENSE +0 -0
hypern/worker.py
CHANGED
@@ -1,30 +1,274 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
import asyncio
|
2
|
+
import logging
|
3
|
+
import os
|
4
|
+
import time
|
5
|
+
import traceback
|
6
|
+
from concurrent.futures import ThreadPoolExecutor
|
7
|
+
from functools import partial, wraps
|
8
|
+
from typing import Callable, Dict, List
|
9
|
+
|
3
10
|
from celery import Celery
|
4
|
-
from
|
11
|
+
from celery.result import AsyncResult
|
12
|
+
from celery.signals import (
|
13
|
+
after_setup_logger,
|
14
|
+
after_setup_task_logger,
|
15
|
+
task_failure,
|
16
|
+
task_postrun,
|
17
|
+
task_prerun,
|
18
|
+
worker_ready,
|
19
|
+
worker_shutdown,
|
20
|
+
)
|
21
|
+
from kombu import Exchange, Queue
|
22
|
+
|
23
|
+
|
24
|
+
class Worker(Celery):
|
25
|
+
def __init__(
|
26
|
+
self,
|
27
|
+
main: str = None,
|
28
|
+
broker_url: str = None,
|
29
|
+
result_backend: str = "rpc://",
|
30
|
+
queues: Dict[str, Dict] = None,
|
31
|
+
task_routes: Dict[str, str] = None,
|
32
|
+
imports: List[str] = None,
|
33
|
+
**kwargs,
|
34
|
+
):
|
35
|
+
super().__init__(main, **kwargs)
|
36
|
+
|
37
|
+
self._executor = ThreadPoolExecutor()
|
38
|
+
self._task_timings = {}
|
39
|
+
|
40
|
+
self.default_exchange = Exchange("default", type="direct")
|
41
|
+
self.priority_exchange = Exchange("priority", type="direct")
|
42
|
+
|
43
|
+
default_queues = {
|
44
|
+
"default": {"exchange": self.default_exchange, "routing_key": "default"},
|
45
|
+
"high_priority": {"exchange": self.priority_exchange, "routing_key": "high"},
|
46
|
+
"low_priority": {"exchange": self.priority_exchange, "routing_key": "low"},
|
47
|
+
}
|
48
|
+
if queues:
|
49
|
+
default_queues.update(queues)
|
50
|
+
|
51
|
+
self._queues = {
|
52
|
+
name: Queue(
|
53
|
+
name,
|
54
|
+
exchange=config.get("exchange", self.default_exchange),
|
55
|
+
routing_key=config.get("routing_key", name),
|
56
|
+
queue_arguments=config.get("arguments", {}),
|
57
|
+
)
|
58
|
+
for name, config in default_queues.items()
|
59
|
+
}
|
60
|
+
|
61
|
+
self.conf.update(
|
62
|
+
broker_url=broker_url,
|
63
|
+
result_backend=result_backend,
|
64
|
+
# Worker Pool Configuration
|
65
|
+
worker_pool="solo",
|
66
|
+
worker_pool_restarts=True,
|
67
|
+
broker_connection_retry_on_startup=True,
|
68
|
+
# Worker Configuration
|
69
|
+
worker_prefetch_multiplier=1,
|
70
|
+
worker_max_tasks_per_child=1000,
|
71
|
+
worker_concurrency=os.cpu_count(),
|
72
|
+
# Task Settings
|
73
|
+
task_acks_late=True,
|
74
|
+
task_reject_on_worker_lost=True,
|
75
|
+
task_time_limit=3600,
|
76
|
+
task_soft_time_limit=3000,
|
77
|
+
task_default_retry_delay=300,
|
78
|
+
task_max_retries=3,
|
79
|
+
# Memory Management
|
80
|
+
worker_max_memory_per_child=200000, # 200MB
|
81
|
+
# Task Routing
|
82
|
+
task_routes=task_routes,
|
83
|
+
task_queues=list(self._queues.values()),
|
84
|
+
# Performance Settings
|
85
|
+
task_compression="gzip",
|
86
|
+
result_compression="gzip",
|
87
|
+
task_serializer="json",
|
88
|
+
result_serializer="json",
|
89
|
+
accept_content=["json"],
|
90
|
+
imports=imports,
|
91
|
+
task_default_exchange=self.default_exchange.name,
|
92
|
+
task_default_routing_key="default",
|
93
|
+
)
|
94
|
+
|
95
|
+
self._setup_signals()
|
96
|
+
|
97
|
+
def _setup_signals(self):
|
98
|
+
@worker_ready.connect
|
99
|
+
def on_worker_ready(sender, **kwargs):
|
100
|
+
self.logger.info(f"Worker {sender.hostname} is ready")
|
101
|
+
|
102
|
+
@worker_shutdown.connect
|
103
|
+
def on_worker_shutdown(sender, **kwargs):
|
104
|
+
self.logger.info(f"Worker {sender.hostname} is shutting down")
|
105
|
+
self._executor.shutdown(wait=True)
|
106
|
+
|
107
|
+
@task_prerun.connect
|
108
|
+
def task_prerun_handler(task_id, task, *args, **kwargs):
|
109
|
+
self._task_timings[task_id] = {"start": time.time()}
|
110
|
+
self.logger.info(f"Task {task.name}[{task_id}] started")
|
111
|
+
|
112
|
+
@task_postrun.connect
|
113
|
+
def task_postrun_handler(task_id, task, *args, retval=None, **kwargs):
|
114
|
+
if task_id in self._task_timings:
|
115
|
+
start_time = self._task_timings[task_id]["start"]
|
116
|
+
duration = time.time() - start_time
|
117
|
+
self.logger.info(f"Task {task.name}[{task_id}] completed in {duration:.2f}s")
|
118
|
+
del self._task_timings[task_id]
|
119
|
+
|
120
|
+
@task_failure.connect
|
121
|
+
def task_failure_handler(task_id, exc, task, *args, **kwargs):
|
122
|
+
self.logger.error(f"Task {task.name}[{task_id}] failed: {exc}\n{traceback.format_exc()}")
|
123
|
+
|
124
|
+
@after_setup_logger.connect
|
125
|
+
def setup_celery_logger(logger, *args, **kwargs):
|
126
|
+
existing_logger = logging.getLogger("hypern")
|
127
|
+
logger.handlers = existing_logger.handlers
|
128
|
+
logger.filters = existing_logger.filters
|
129
|
+
logger.level = existing_logger.level
|
130
|
+
|
131
|
+
@after_setup_task_logger.connect
|
132
|
+
def setup_task_logger(logger, *args, **kwargs):
|
133
|
+
existing_logger = logging.getLogger("hypern")
|
134
|
+
logger.handlers = existing_logger.handlers
|
135
|
+
logger.filters = existing_logger.filters
|
136
|
+
logger.level = existing_logger.level
|
137
|
+
|
138
|
+
def add_task_routes(self, routes: Dict[str, str]) -> None:
|
139
|
+
"""
|
140
|
+
Example:
|
141
|
+
app.add_task_routes({
|
142
|
+
'tasks.email.*': 'email_queue',
|
143
|
+
'tasks.payment.process': 'payment_queue',
|
144
|
+
'tasks.high_priority.*': 'high_priority'
|
145
|
+
})
|
146
|
+
"""
|
147
|
+
for task_pattern, queue in routes.items():
|
148
|
+
self.add_task_route(task_pattern, queue)
|
149
|
+
|
150
|
+
def add_task_route(self, task_pattern: str, queue: str) -> None:
|
151
|
+
"""
|
152
|
+
Add a task route to the Celery app
|
153
|
+
|
154
|
+
Example:
|
155
|
+
app.add_task_route('tasks.email.send', 'email_queue')
|
156
|
+
app.add_task_route('tasks.payment.*', 'payment_queue')
|
157
|
+
"""
|
158
|
+
if queue not in self._queues:
|
159
|
+
raise ValueError(f"Queue '{queue}' does not exist. Create it first using create_queue()")
|
160
|
+
|
161
|
+
self._task_route_mapping[task_pattern] = queue
|
162
|
+
|
163
|
+
# Update Celery task routes
|
164
|
+
routes = self.conf.task_routes or {}
|
165
|
+
routes[task_pattern] = {"queue": queue}
|
166
|
+
self.conf.task_routes = routes
|
167
|
+
|
168
|
+
self.logger.info(f"Added route: {task_pattern} -> {queue}")
|
169
|
+
|
170
|
+
def task(self, *args, **opts):
|
171
|
+
"""
|
172
|
+
Decorator modified to support sync and async functions
|
173
|
+
"""
|
174
|
+
base_task = Celery.task.__get__(self)
|
175
|
+
|
176
|
+
def decorator(func):
|
177
|
+
is_async = asyncio.iscoroutinefunction(func)
|
178
|
+
|
179
|
+
if is_async:
|
180
|
+
|
181
|
+
@wraps(func)
|
182
|
+
async def async_wrapper(*fargs, **fkwargs):
|
183
|
+
return await func(*fargs, **fkwargs)
|
184
|
+
|
185
|
+
@base_task(*args, **opts)
|
186
|
+
def wrapped(*fargs, **fkwargs):
|
187
|
+
loop = asyncio.new_event_loop()
|
188
|
+
asyncio.set_event_loop(loop)
|
189
|
+
try:
|
190
|
+
return loop.run_until_complete(async_wrapper(*fargs, **fkwargs))
|
191
|
+
finally:
|
192
|
+
loop.close()
|
193
|
+
|
194
|
+
return wrapped
|
195
|
+
else:
|
196
|
+
return base_task(*args, **opts)(func)
|
197
|
+
|
198
|
+
return decorator
|
199
|
+
|
200
|
+
async def async_send_task(self, task_name: str, *args, **kwargs) -> AsyncResult:
|
201
|
+
"""
|
202
|
+
Version of send_task() that is async
|
203
|
+
"""
|
204
|
+
loop = asyncio.get_event_loop()
|
205
|
+
return await loop.run_in_executor(self._executor, partial(self.send_task, task_name, args=args, kwargs=kwargs))
|
206
|
+
|
207
|
+
async def async_result(self, task_id: str) -> Dict:
|
208
|
+
"""
|
209
|
+
Get the result of a task asynchronously
|
210
|
+
"""
|
211
|
+
async_result = self.AsyncResult(task_id)
|
212
|
+
loop = asyncio.get_event_loop()
|
213
|
+
|
214
|
+
result = await loop.run_in_executor(
|
215
|
+
self._executor,
|
216
|
+
lambda: {
|
217
|
+
"task_id": task_id,
|
218
|
+
"status": async_result.status,
|
219
|
+
"result": async_result.result,
|
220
|
+
"traceback": async_result.traceback,
|
221
|
+
"date_done": async_result.date_done,
|
222
|
+
},
|
223
|
+
)
|
224
|
+
return result
|
225
|
+
|
226
|
+
def get_queue_length(self, queue_name: str) -> int:
|
227
|
+
"""
|
228
|
+
Get the number of messages in a queue
|
229
|
+
"""
|
230
|
+
with self.connection_or_acquire() as conn:
|
231
|
+
channel = conn.channel()
|
232
|
+
queue = Queue(queue_name, channel=channel)
|
233
|
+
return queue.queue_declare(passive=True).message_count
|
5
234
|
|
235
|
+
async def chain_tasks(self, tasks: list) -> AsyncResult:
|
236
|
+
"""
|
237
|
+
Function to chain multiple tasks together
|
238
|
+
"""
|
239
|
+
chain = tasks[0]
|
240
|
+
for task in tasks[1:]:
|
241
|
+
chain = chain | task
|
242
|
+
return await self.adelay_task(chain)
|
6
243
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
return cls.instance
|
244
|
+
def register_task_middleware(self, middleware: Callable):
|
245
|
+
"""
|
246
|
+
Register a middleware function to be called before each task
|
247
|
+
"""
|
12
248
|
|
13
|
-
|
14
|
-
|
15
|
-
|
249
|
+
def task_middleware(task):
|
250
|
+
@wraps(task)
|
251
|
+
def _wrapped(*args, **kwargs):
|
252
|
+
return middleware(task, *args, **kwargs)
|
16
253
|
|
17
|
-
|
18
|
-
TaskBase = self.Task
|
254
|
+
return _wrapped
|
19
255
|
|
20
|
-
|
21
|
-
abstract = True
|
256
|
+
self.task = task_middleware(self.task)
|
22
257
|
|
23
|
-
|
24
|
-
|
25
|
-
|
258
|
+
def monitor_task(self, task_id: str) -> dict:
|
259
|
+
"""
|
260
|
+
Get monitoring data for a task
|
261
|
+
"""
|
262
|
+
result = self.AsyncResult(task_id)
|
263
|
+
timing_info = self._task_timings.get(task_id, {})
|
26
264
|
|
27
|
-
|
28
|
-
|
265
|
+
monitoring_data = {
|
266
|
+
"task_id": task_id,
|
267
|
+
"status": result.status,
|
268
|
+
"start_time": timing_info.get("start"),
|
269
|
+
"duration": time.time() - timing_info["start"] if timing_info.get("start") else None,
|
270
|
+
"result": result.result if result.ready() else None,
|
271
|
+
"traceback": result.traceback,
|
272
|
+
}
|
29
273
|
|
30
|
-
|
274
|
+
return monitoring_data
|
@@ -1,11 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: hypern
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.8
|
4
4
|
Classifier: Programming Language :: Rust
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
7
7
|
Requires-Dist: sqlalchemy[asyncio] ==2.0.31
|
8
|
-
Requires-Dist: pydantic[email] ==2.8.2
|
9
8
|
Requires-Dist: passlib ==1.7.4
|
10
9
|
Requires-Dist: pyjwt ==2.8.0
|
11
10
|
Requires-Dist: pydash ==8.0.3
|
@@ -26,6 +25,7 @@ Requires-Dist: watchdog ==6.0.0
|
|
26
25
|
Requires-Dist: jsonschema ==4.23.0
|
27
26
|
Requires-Dist: psutil ==6.1.0
|
28
27
|
Requires-Dist: msgpack ==1.1.0
|
28
|
+
Requires-Dist: redis ==5.2.1
|
29
29
|
License-File: LICENSE
|
30
30
|
Summary: A Fast Async Python backend with a Rust runtime.
|
31
31
|
Author-email: Martin Dang <vannghiem848@gmail.com>
|
@@ -37,7 +37,7 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
37
37
|
|
38
38
|
Hypern: A Versatile Python and Rust Framework
|
39
39
|
|
40
|
-
Hypern is a flexible, open-source framework built on the [
|
40
|
+
Hypern is a flexible, open-source framework built on the [Rust](https://github.com/rust-lang/rust), 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.
|
41
41
|
|
42
42
|
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.
|
43
43
|
|
@@ -91,7 +91,7 @@ routing = [
|
|
91
91
|
app = Hypern(routing)
|
92
92
|
|
93
93
|
if __name__ == "__main__":
|
94
|
-
app.start(
|
94
|
+
app.start()
|
95
95
|
```
|
96
96
|
|
97
97
|
```
|
@@ -99,6 +99,16 @@ $ python3 main.py
|
|
99
99
|
```
|
100
100
|
You can open swagger UI at path `/docs`
|
101
101
|
|
102
|
+
## CLI
|
103
|
+
|
104
|
+
- host (str): The host address to bind to. Defaults to '127.0.0.1'.
|
105
|
+
- port (int): The port number to bind to. Defaults to 5000.
|
106
|
+
- processes (int): The number of processes to use. Defaults to 1.
|
107
|
+
- workers (int): The number of worker threads to use. Defaults to 1.
|
108
|
+
- max_blocking_threads (int): The maximum number of blocking threads. Defaults to 32.
|
109
|
+
- reload (bool): If True, the server will restart on file changes.
|
110
|
+
- auto_workers (bool): If True, sets the number of workers and max-blocking-threads automatically.
|
111
|
+
|
102
112
|
|
103
113
|
## 💡 Features
|
104
114
|
|
@@ -106,7 +116,7 @@ You can open swagger UI at path `/docs`
|
|
106
116
|
- Rust-powered core with Python flexibility
|
107
117
|
- Multi-process architecture for optimal CPU utilization
|
108
118
|
- Async/await support for non-blocking operations
|
109
|
-
- Built on top of production-ready
|
119
|
+
- Built on top of production-ready Rust language
|
110
120
|
|
111
121
|
### 🛠 Development Experience
|
112
122
|
- Type hints and IDE support
|
@@ -117,7 +127,7 @@ You can open swagger UI at path `/docs`
|
|
117
127
|
### 🔌 Integration & Extensions
|
118
128
|
- Easy dependency injection
|
119
129
|
- Middleware support (before/after request hooks)
|
120
|
-
- WebSocket support
|
130
|
+
- WebSocket support
|
121
131
|
- Background task scheduling
|
122
132
|
- File upload handling
|
123
133
|
|
@@ -1,8 +1,8 @@
|
|
1
|
-
hypern-0.3.
|
2
|
-
hypern-0.3.
|
3
|
-
hypern-0.3.
|
4
|
-
hypern/application.py,sha256=
|
5
|
-
hypern/args_parser.py,sha256=
|
1
|
+
hypern-0.3.8.dist-info/METADATA,sha256=0bMLw-pA0VeoGBbQxXr4cqCO8dS6esga5NjluEeV5MY,4356
|
2
|
+
hypern-0.3.8.dist-info/WHEEL,sha256=19xj5Waw2omQTyAh5Pnrm7rXeZkfzX1OuBYghlKYN-I,92
|
3
|
+
hypern-0.3.8.dist-info/licenses/LICENSE,sha256=qbYKAIJLS6jYg5hYncKE7OtWmqOtpVTvKNkwOa0Iwwg,1328
|
4
|
+
hypern/application.py,sha256=07QGDd3w7tQRL8njfbNVinG6l8W7O0V-rN_SkO5O3B4,18002
|
5
|
+
hypern/args_parser.py,sha256=BjGCooHdZjOpyN-AGL9PCKCKdzROVThE3dzQgC97rng,2035
|
6
6
|
hypern/auth/authorization.py,sha256=-NprZsI0np889ZN1fp-MiVFrPoMNzUtatBJaCMtkllM,32
|
7
7
|
hypern/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
hypern/background.py,sha256=xy38nQZSJsYFRXr3-uFJeNW9E1GiXXOC7lSe5pC0eyE,124
|
@@ -31,12 +31,13 @@ hypern/database/nosql/addons/password.py,sha256=jfZxvWFm6nV9EWpXq5Mj-jpqnl9QbokZ
|
|
31
31
|
hypern/database/nosql/addons/unicode.py,sha256=LaDpLfdoTcJuASPE-8fqOVD05H_uOx8gOdnyDn5Iu0c,268
|
32
32
|
hypern/database/nosql/addons/__init__.py,sha256=WEtPM8sPHilvga7zxwqvINeTkF0hdcfgPcAnHc4MASE,125
|
33
33
|
hypern/database/nosql/__init__.py,sha256=MH9YvlbRlbBCrQVNOdfTaK-hINwJxbJLmxwY9Mei7I8,644
|
34
|
-
hypern/database/sql/field.py,sha256=
|
35
|
-
hypern/database/sql/
|
36
|
-
hypern/database/sql/
|
37
|
-
hypern/database/sql/
|
34
|
+
hypern/database/sql/field.py,sha256=gV9u_BvMIoxoDT3_J7sL5XJNa5XFsAO9w324ThwHbNs,9121
|
35
|
+
hypern/database/sql/migrate.py,sha256=BTtAs3-iMyMDzIWl6B3rM9sj7XGggLDRjD0h_WgGPtc,9742
|
36
|
+
hypern/database/sql/model.py,sha256=C8_rJA1Adw1yPWthjmAGh26hjTBuwwlEdtH45ADxvL0,4044
|
37
|
+
hypern/database/sql/query.py,sha256=En19t27zt6iUDQbFgO_wLEWPQCkPeBuH3s37fzlhMVc,33345
|
38
|
+
hypern/database/sql/__init__.py,sha256=dbSAz2nP0DPKK4Bb_jJdObSaSYQfgZ8D4U1TJdc4e7c,645
|
38
39
|
hypern/database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
|
-
hypern/datastructures.py,sha256=
|
40
|
+
hypern/datastructures.py,sha256=Pxr9KsZZTFfp0KC1-A4v5AkQfmrUyvVwxKuToQUOLoE,882
|
40
41
|
hypern/enum.py,sha256=KcVziJj7vWvyie0r2rtxhrLzdtkZAsf0DY58oJ4tQl4,360
|
41
42
|
hypern/exceptions/base.py,sha256=5AgfyEea79JjKk5MeAIJ-wy44FG5XEU0Jn3KXKScPiI,2017
|
42
43
|
hypern/exceptions/common.py,sha256=0E8wHRRTWjYOmtOCkTDvZ5NMwL6vRW6aiDD9X1eYA30,227
|
@@ -49,7 +50,7 @@ hypern/gateway/gateway.py,sha256=26K2qvJUR-0JnN4IlhwvSSt7EYcpYrBVDuzZ1ivQQ34,147
|
|
49
50
|
hypern/gateway/proxy.py,sha256=w1wcTplDnVrfjn7hb0M0yBVth5TGl88irF-MUYHysQQ,2463
|
50
51
|
hypern/gateway/service.py,sha256=PkRaM08olqM_j_4wRjEJCR8X8ZysAF2WOcfhWjaX2eo,1701
|
51
52
|
hypern/gateway/__init__.py,sha256=TpFWtqnJerW1-jCWq5fjypJcw9Y6ytyrkvkzby1Eg0E,235
|
52
|
-
hypern/hypern.pyi,sha256=
|
53
|
+
hypern/hypern.pyi,sha256=Urc3uHhPupsN-RRYluyWiw8B_xYWzE91Og3Zft40NgU,9010
|
53
54
|
hypern/i18n/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
54
55
|
hypern/logging/logger.py,sha256=WACam_IJiCMXX0hGVKMGSxUQpY4DgAXy7M1dD3q-Z9s,3256
|
55
56
|
hypern/logging/__init__.py,sha256=6eVriyncsJ4J73fGYhoejv9MX7aGTkRezTpPxO4DX1I,52
|
@@ -61,7 +62,7 @@ hypern/middleware/i18n.py,sha256=jHzVzjTx1nnjbraZtIVOprrnSaeKMxZB8RuSqRp2I4s,16
|
|
61
62
|
hypern/middleware/limit.py,sha256=eAYARPjqxq8Ue0TCpnxlVRB5hv7hwBF0PxeD-bG6Sl0,8252
|
62
63
|
hypern/middleware/security.py,sha256=fGBSF7n2iKBtDHE2QW4q_sQE4awYgaYxVUFKsDHkMXg,7675
|
63
64
|
hypern/middleware/__init__.py,sha256=V-Gnv-Jf-14BVuA28z7PN7GBVQ9BBiBdab6-QnTPCfY,493
|
64
|
-
hypern/openapi/schemas.py,sha256=
|
65
|
+
hypern/openapi/schemas.py,sha256=hsqSPpwsOETQ5NoGiR9Ay0qEp6GxJ2xhh69rzwxx0CY,1598
|
65
66
|
hypern/openapi/swagger.py,sha256=naqUY3rFAEYA1ZLIlmDsMYaol0yIm6TVebdkFa5cMTc,64
|
66
67
|
hypern/openapi/__init__.py,sha256=4rEVD8pa0kdSpsy7ZkJ5JY0Z2XF0NGSKDMwYAd7YZpE,141
|
67
68
|
hypern/processpool.py,sha256=qEsu9WXWc3_Cl0Frn1jGs7jUJho45zck5L5Ww81Vm70,3883
|
@@ -73,17 +74,16 @@ hypern/routing/dispatcher.py,sha256=NAVjILlEJjYrixJZ4CO4N1CKkuqbk4TGZOjnQNTTEu4,
|
|
73
74
|
hypern/routing/endpoint.py,sha256=RKVhvqOEGL9IKBXQ3KJgPi9bgJj9gfWC5BdZc5U_atc,1026
|
74
75
|
hypern/routing/parser.py,sha256=0tJVVNwHC3pWDsehwH6SwJv8_gEuDjltVXrNQWbHyrU,3426
|
75
76
|
hypern/routing/queue.py,sha256=NtFBbogU22ddyyX-CuQMip1XFDPZdMCVMIeUCQ-CR6Y,7176
|
76
|
-
hypern/routing/route.py,sha256=
|
77
|
+
hypern/routing/route.py,sha256=kan47-UeL-OPwcpp0rEhmBaaum6hN7FUj13Y8pZDEYA,10256
|
77
78
|
hypern/routing/__init__.py,sha256=U4xW5fDRsn03z4cVLT4dJHHGGU6SVxyv2DL86LXodeE,162
|
78
79
|
hypern/scheduler.py,sha256=-k3tW2AGCnHYSthKXk-FOs_SCtWp3yIxQzwzUJMJsbo,67
|
79
80
|
hypern/security.py,sha256=3E86Yp_eOSVa1emUvBrDgoF0Sn6eNX0CfLnt87w5CPI,1773
|
80
|
-
hypern/worker.py,sha256=
|
81
|
+
hypern/worker.py,sha256=ksJW8jWQg3HbIYnIZ5qdAmO-yh5hLpwvTT3dKkHR4Eo,9761
|
81
82
|
hypern/ws/channel.py,sha256=0ns2qmeoFJOpGLXS_hqldhywDQm_DxHwj6KloQx4Q3I,3183
|
82
83
|
hypern/ws/heartbeat.py,sha256=sWMXzQm6cbDHHA2NHc-gFjv7G_E56XtxswHQ93_BueM,2861
|
83
84
|
hypern/ws/room.py,sha256=0_L6Nun0n007F0rfNY8yX5x_A8EuXuI67JqpMkJ4RNI,2598
|
84
85
|
hypern/ws/route.py,sha256=fGQ2RC708MPOiiIHPUo8aZ-oK379TTAyQYm4htNA5jM,803
|
85
86
|
hypern/ws/__init__.py,sha256=dhRoRY683_rfPfSPM5qUczfTuyYDeuLOCFxY4hIdKt8,131
|
86
|
-
hypern/
|
87
|
-
hypern/
|
88
|
-
hypern
|
89
|
-
hypern-0.3.6.dist-info/RECORD,,
|
87
|
+
hypern/__init__.py,sha256=p3AtJQbsPs1RYEiN1thxH-k5UP8FfLeiJSoP0Vt3MDg,639
|
88
|
+
hypern/hypern.cp312-win32.pyd,sha256=rvh5yYWRidA1p4JK6cneYi7yjaJ8okvTNHUIpwn6c9k,7591936
|
89
|
+
hypern-0.3.8.dist-info/RECORD,,
|
hypern/ws.py
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
from .hypern import WebsocketRoute as WebsocketRouteInternal, WebSocketSession
|
2
|
-
|
3
|
-
|
4
|
-
class WebsocketRoute:
|
5
|
-
def __init__(self) -> None:
|
6
|
-
self.routes = []
|
7
|
-
|
8
|
-
def on(self, path):
|
9
|
-
def wrapper(func):
|
10
|
-
self.routes.append(WebsocketRouteInternal(path, func))
|
11
|
-
return func
|
12
|
-
|
13
|
-
return wrapper
|
14
|
-
|
15
|
-
|
16
|
-
__all__ = ["WebsocketRoute", "WebSocketSession"]
|
File without changes
|