hypern 0.3.11__cp312-cp312-macosx_11_0_arm64.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 (73) hide show
  1. hypern/__init__.py +24 -0
  2. hypern/application.py +495 -0
  3. hypern/args_parser.py +73 -0
  4. hypern/auth/__init__.py +0 -0
  5. hypern/auth/authorization.py +2 -0
  6. hypern/background.py +4 -0
  7. hypern/caching/__init__.py +6 -0
  8. hypern/caching/backend.py +31 -0
  9. hypern/caching/redis_backend.py +201 -0
  10. hypern/caching/strategies.py +208 -0
  11. hypern/cli/__init__.py +0 -0
  12. hypern/cli/commands.py +0 -0
  13. hypern/config.py +246 -0
  14. hypern/database/__init__.py +0 -0
  15. hypern/database/sqlalchemy/__init__.py +4 -0
  16. hypern/database/sqlalchemy/config.py +66 -0
  17. hypern/database/sqlalchemy/repository.py +290 -0
  18. hypern/database/sqlx/__init__.py +36 -0
  19. hypern/database/sqlx/field.py +246 -0
  20. hypern/database/sqlx/migrate.py +263 -0
  21. hypern/database/sqlx/model.py +117 -0
  22. hypern/database/sqlx/query.py +904 -0
  23. hypern/datastructures.py +40 -0
  24. hypern/enum.py +13 -0
  25. hypern/exceptions/__init__.py +34 -0
  26. hypern/exceptions/base.py +62 -0
  27. hypern/exceptions/common.py +12 -0
  28. hypern/exceptions/errors.py +15 -0
  29. hypern/exceptions/formatters.py +56 -0
  30. hypern/exceptions/http.py +76 -0
  31. hypern/gateway/__init__.py +6 -0
  32. hypern/gateway/aggregator.py +32 -0
  33. hypern/gateway/gateway.py +41 -0
  34. hypern/gateway/proxy.py +60 -0
  35. hypern/gateway/service.py +52 -0
  36. hypern/hypern.cpython-312-darwin.so +0 -0
  37. hypern/hypern.pyi +333 -0
  38. hypern/i18n/__init__.py +0 -0
  39. hypern/logging/__init__.py +3 -0
  40. hypern/logging/logger.py +82 -0
  41. hypern/middleware/__init__.py +17 -0
  42. hypern/middleware/base.py +13 -0
  43. hypern/middleware/cache.py +177 -0
  44. hypern/middleware/compress.py +78 -0
  45. hypern/middleware/cors.py +41 -0
  46. hypern/middleware/i18n.py +1 -0
  47. hypern/middleware/limit.py +177 -0
  48. hypern/middleware/security.py +184 -0
  49. hypern/openapi/__init__.py +5 -0
  50. hypern/openapi/schemas.py +51 -0
  51. hypern/openapi/swagger.py +3 -0
  52. hypern/processpool.py +139 -0
  53. hypern/py.typed +0 -0
  54. hypern/reload.py +46 -0
  55. hypern/response/__init__.py +3 -0
  56. hypern/response/response.py +142 -0
  57. hypern/routing/__init__.py +5 -0
  58. hypern/routing/dispatcher.py +70 -0
  59. hypern/routing/endpoint.py +30 -0
  60. hypern/routing/parser.py +98 -0
  61. hypern/routing/queue.py +175 -0
  62. hypern/routing/route.py +280 -0
  63. hypern/scheduler.py +5 -0
  64. hypern/worker.py +274 -0
  65. hypern/ws/__init__.py +4 -0
  66. hypern/ws/channel.py +80 -0
  67. hypern/ws/heartbeat.py +74 -0
  68. hypern/ws/room.py +76 -0
  69. hypern/ws/route.py +26 -0
  70. hypern-0.3.11.dist-info/METADATA +134 -0
  71. hypern-0.3.11.dist-info/RECORD +73 -0
  72. hypern-0.3.11.dist-info/WHEEL +4 -0
  73. hypern-0.3.11.dist-info/licenses/LICENSE +24 -0
hypern/ws/heartbeat.py ADDED
@@ -0,0 +1,74 @@
1
+ import asyncio
2
+ from dataclasses import dataclass
3
+ from time import time
4
+ from typing import Dict
5
+
6
+ from hypern.hypern import WebSocketSession
7
+
8
+
9
+ @dataclass
10
+ class HeartbeatConfig:
11
+ ping_interval: float = 30.0 # Send ping every 30 seconds
12
+ ping_timeout: float = 10.0 # Wait 10 seconds for pong response
13
+ max_missed_pings: int = 2 # Disconnect after 2 missed pings
14
+
15
+
16
+ class HeartbeatManager:
17
+ def __init__(self, config: HeartbeatConfig = None):
18
+ self.config = config or HeartbeatConfig()
19
+ self.active_sessions: Dict[WebSocketSession, float] = {}
20
+ self.ping_tasks: Dict[WebSocketSession, asyncio.Task] = {}
21
+ self.missed_pings: Dict[WebSocketSession, int] = {}
22
+
23
+ async def start_heartbeat(self, session: WebSocketSession):
24
+ """Start heartbeat monitoring for a session"""
25
+ self.active_sessions[session] = time()
26
+ self.missed_pings[session] = 0
27
+ self.ping_tasks[session] = asyncio.create_task(self._heartbeat_loop(session))
28
+
29
+ async def stop_heartbeat(self, session: WebSocketSession):
30
+ """Stop heartbeat monitoring for a session"""
31
+ if session in self.ping_tasks:
32
+ self.ping_tasks[session].cancel()
33
+ del self.ping_tasks[session]
34
+ self.active_sessions.pop(session, None)
35
+ self.missed_pings.pop(session, None)
36
+
37
+ async def handle_pong(self, session: WebSocketSession):
38
+ """Handle pong response from client"""
39
+ if session in self.active_sessions:
40
+ self.active_sessions[session] = time()
41
+ self.missed_pings[session] = 0
42
+
43
+ async def _heartbeat_loop(self, session: WebSocketSession):
44
+ """Main heartbeat loop for a session"""
45
+ try:
46
+ while True:
47
+ await asyncio.sleep(self.config.ping_interval)
48
+
49
+ if session not in self.active_sessions:
50
+ break
51
+
52
+ # Send ping frame
53
+ try:
54
+ await session.ping()
55
+ last_pong = self.active_sessions[session]
56
+
57
+ # Wait for pong timeout
58
+ await asyncio.sleep(self.config.ping_timeout)
59
+
60
+ # Check if we received a pong
61
+ if self.active_sessions[session] == last_pong:
62
+ self.missed_pings[session] += 1
63
+
64
+ # Check if we exceeded max missed pings
65
+ if self.missed_pings[session] >= self.config.max_missed_pings:
66
+ await session.close(1001, "Connection timeout")
67
+ break
68
+
69
+ except Exception as e:
70
+ await session.close(1001, f"Heartbeat failed: {str(e)}")
71
+ break
72
+
73
+ finally:
74
+ await self.stop_heartbeat(session)
hypern/ws/room.py ADDED
@@ -0,0 +1,76 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Dict, Set
3
+
4
+ from hypern.hypern import WebSocketSession
5
+
6
+
7
+ @dataclass
8
+ class Room:
9
+ name: str
10
+ clients: Set[WebSocketSession] = field(default_factory=set)
11
+
12
+ def broadcast(self, message: str, exclude: WebSocketSession = None):
13
+ """Broadcast message to all clients in the room except excluded one"""
14
+ for client in self.clients:
15
+ if client != exclude:
16
+ client.send(message)
17
+
18
+ def add_client(self, client: WebSocketSession):
19
+ """Add a client to the room"""
20
+ self.clients.add(client)
21
+
22
+ def remove_client(self, client: WebSocketSession):
23
+ """Remove a client from the room"""
24
+ self.clients.discard(client)
25
+
26
+ @property
27
+ def client_count(self) -> int:
28
+ return len(self.clients)
29
+
30
+
31
+ class RoomManager:
32
+ def __init__(self):
33
+ self.rooms: Dict[str, Room] = {}
34
+ self.client_rooms: Dict[WebSocketSession, Set[str]] = {}
35
+
36
+ def create_room(self, room_name: str) -> Room:
37
+ """Create a new room if it doesn't exist"""
38
+ if room_name not in self.rooms:
39
+ self.rooms[room_name] = Room(room_name)
40
+ return self.rooms[room_name]
41
+
42
+ def get_room(self, room_name: str) -> Room:
43
+ """Get a room by name"""
44
+ return self.rooms.get(room_name)
45
+
46
+ def join_room(self, client: WebSocketSession, room_name: str):
47
+ """Add a client to a room"""
48
+ room = self.create_room(room_name)
49
+ room.add_client(client)
50
+
51
+ if client not in self.client_rooms:
52
+ self.client_rooms[client] = set()
53
+ self.client_rooms[client].add(room_name)
54
+
55
+ room.broadcast(f"Client joined room: {room_name}", exclude=client)
56
+
57
+ def leave_room(self, client: WebSocketSession, room_name: str):
58
+ """Remove a client from a room"""
59
+ room = self.get_room(room_name)
60
+ if room:
61
+ room.remove_client(client)
62
+ if client in self.client_rooms:
63
+ self.client_rooms[client].discard(room_name)
64
+
65
+ room.broadcast(f"Client left room: {room_name}", exclude=client)
66
+
67
+ if room.client_count == 0:
68
+ del self.rooms[room_name]
69
+
70
+ def leave_all_rooms(self, client: WebSocketSession):
71
+ """Remove a client from all rooms"""
72
+ if client in self.client_rooms:
73
+ rooms = self.client_rooms[client].copy()
74
+ for room_name in rooms:
75
+ self.leave_room(client, room_name)
76
+ del self.client_rooms[client]
hypern/ws/route.py ADDED
@@ -0,0 +1,26 @@
1
+ from typing import Callable, Optional
2
+
3
+ from hypern.hypern import WebsocketRoute as WebsocketRouteInternal, WebSocketSession
4
+
5
+
6
+ class WebsocketRoute:
7
+ def __init__(self) -> None:
8
+ self.routes = []
9
+ self._disconnect_handler: Optional[Callable] = None
10
+
11
+ def on(self, path):
12
+ def wrapper(func):
13
+ self.routes.append(WebsocketRouteInternal(path, func))
14
+ return func
15
+
16
+ return wrapper
17
+
18
+ def on_disconnect(self, func):
19
+ """Register a disconnect handler"""
20
+ self._disconnect_handler = func
21
+ return func
22
+
23
+ def handle_disconnect(self, session: WebSocketSession):
24
+ """Internal method to handle disconnection"""
25
+ if self._disconnect_handler:
26
+ return self._disconnect_handler(session)
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.4
2
+ Name: hypern
3
+ Version: 0.3.11
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
7
+ Requires-Dist: sqlalchemy[asyncio] ==2.0.31
8
+ Requires-Dist: pyjwt ==2.8.0
9
+ Requires-Dist: pydash ==8.0.3
10
+ Requires-Dist: sentry-sdk ==2.11.0
11
+ Requires-Dist: celery ==5.4.0
12
+ Requires-Dist: psycopg ==3.2.3
13
+ Requires-Dist: pyyaml ==6.0.2
14
+ Requires-Dist: orjson ==3.10.11
15
+ Requires-Dist: multiprocess ==0.70.17
16
+ Requires-Dist: uvloop ==0.21.0 ; sys_platform != 'win32' and platform_python_implementation == 'CPython' and platform_machine != 'armv7l'
17
+ Requires-Dist: watchdog ==6.0.0
18
+ Requires-Dist: psutil ==6.1.0
19
+ Requires-Dist: msgpack ==1.1.0
20
+ Requires-Dist: redis ==5.2.1
21
+ Requires-Dist: pydantic ==2.10.4
22
+ License-File: LICENSE
23
+ Summary: A Fast Async Python backend with a Rust runtime.
24
+ Author-email: Martin Dang <vannghiem848@gmail.com>
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
27
+
28
+
29
+ # Hypern
30
+
31
+ Hypern: A Versatile Python and Rust Framework
32
+
33
+ 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.
34
+
35
+ 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.
36
+
37
+
38
+ ### 🏁 Get started
39
+
40
+ ### ⚙️ To Develop Locally
41
+
42
+ - Setup a virtual environment:
43
+ ```
44
+ python3 -m venv venv
45
+ source venv/bin/activate
46
+ ```
47
+ - Install required packages
48
+
49
+ ```
50
+ pip install pre-commit poetry maturin
51
+ ```
52
+ - Install development dependencies
53
+ ```
54
+ poetry install --with dev --with test
55
+ ```
56
+ - Install pre-commit git hooks
57
+ ```
58
+ pre-commit install
59
+ ```
60
+ - Build & install Rust package
61
+ ```
62
+ maturin develop
63
+ ```
64
+
65
+ ## 🤔 Usage
66
+
67
+ ### 🏃 Run your code
68
+
69
+ You will then have access to a server on the `localhost:5005`,
70
+ ```python
71
+ # main.py
72
+ from hypern import Hypern
73
+ from hypern.routing import Route, HTTPEndpoint
74
+
75
+ class MyEndpoint(HTTPEndpoint):
76
+
77
+ async def get(self, request):
78
+ return {"data": "Hello World"}
79
+
80
+ routing = [
81
+ Route("/hello", MyEndpoint)
82
+ ]
83
+
84
+ app = Hypern(routing)
85
+
86
+ if __name__ == "__main__":
87
+ app.start()
88
+ ```
89
+
90
+ ```
91
+ $ python3 main.py
92
+ ```
93
+ You can open swagger UI at path `/docs`
94
+
95
+ ## CLI
96
+
97
+ - host (str): The host address to bind to. Defaults to '127.0.0.1'.
98
+ - port (int): The port number to bind to. Defaults to 5000.
99
+ - processes (int): The number of processes to use. Defaults to 1.
100
+ - workers (int): The number of worker threads to use. Defaults to 1.
101
+ - max_blocking_threads (int): The maximum number of blocking threads. Defaults to 32.
102
+ - reload (bool): If True, the server will restart on file changes.
103
+ - auto_workers (bool): If True, sets the number of workers and max-blocking-threads automatically.
104
+
105
+
106
+ ## 💡 Features
107
+
108
+ ### ⚡ High Performance
109
+ - Rust-powered core with Python flexibility
110
+ - Multi-process architecture for optimal CPU utilization
111
+ - Async/await support for non-blocking operations
112
+ - Built on top of production-ready Rust language
113
+
114
+ ### 🛠 Development Experience
115
+ - Type hints and IDE support
116
+ - Built-in Swagger/OpenAPI documentation
117
+ - Hot reload during development
118
+ - Comprehensive error handling and logging
119
+
120
+ ### 🔌 Integration & Extensions
121
+ - Easy dependency injection
122
+ - Middleware support (before/after request hooks)
123
+ - WebSocket support
124
+ - Background task scheduling
125
+ - File upload handling
126
+
127
+ ### 🔒 Security
128
+ - Built-in authentication/authorization (Comming soon)
129
+ - CORS configuration
130
+ - Rate limiting
131
+ - Request validation
132
+
133
+
134
+
@@ -0,0 +1,73 @@
1
+ hypern-0.3.11.dist-info/METADATA,sha256=ITw8gsjB2mG8_N0MV--ZF2Fi2pVeFCzAZBGCR0cK80o,4007
2
+ hypern-0.3.11.dist-info/WHEEL,sha256=lWK3-Bgk0WnWBByE5b3Cq5VR1998HCQ2lZtuFHoBwss,104
3
+ hypern-0.3.11.dist-info/licenses/LICENSE,sha256=VdbaK2hSaaD-LUjtDIlEbeZVmvLGK7BEQvltP3mv-cY,1304
4
+ hypern/worker.py,sha256=_m0NV-Srn4NGi65UciOOg3t4Bk6wGm0PMG4_1EYi6Zk,9487
5
+ hypern/middleware/cors.py,sha256=q8Ts_znqApdUJYSJyLlRIbYKxxTQy6WNnJD6Kqbl32I,1759
6
+ hypern/middleware/security.py,sha256=hPYsilqhF9mRCX7DzOQw4AKh0y5k5FL0cM_zQdb9tiA,7491
7
+ hypern/middleware/cache.py,sha256=b4hRh1smFwhJE789hZ0p4TlkQ8ZjYR-7fXg9rI7uvbc,7406
8
+ hypern/middleware/__init__.py,sha256=sPmefKAy8-XeSg6BhkZBjqV8zgreeNLxikyyM6aDFT8,476
9
+ hypern/middleware/limit.py,sha256=oWNt-XqYdORJuJMgg8pLYoEpHVm1cZBOPatxk8g7Nao,8075
10
+ hypern/middleware/compress.py,sha256=2eyxkYMgmsL6klbcTqr7WK0rFTo0grU0ZKQF15pVUBI,3041
11
+ hypern/middleware/i18n.py,sha256=s82nQo6kKClZ0s3G3jsy87VRfwxpBDbASB_ErjRL3O0,15
12
+ hypern/middleware/base.py,sha256=IXmEe7x_X5YykBsxTpko6ApsvNmVqfZ7IHBgJSSEWnY,356
13
+ hypern/database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ hypern/database/sqlalchemy/config.py,sha256=AyeDJnWtq42NFLX65T0w04yhX7l9x8t6lXFq8U4WgfE,2580
15
+ hypern/database/sqlalchemy/__init__.py,sha256=U_9q6L3V7VIRN-neeN5mVb1z6wKf7_GjWptgUl8-xxI,150
16
+ hypern/database/sqlalchemy/repository.py,sha256=YShEl1DqRXtYwNnn1F3YVfXX-TEdoNRjDEWIO_3Lu2s,9226
17
+ hypern/database/sqlx/field.py,sha256=C7vxo6VvCeOWxG3-GFrwe23xC4AiZ3fGqOzZTDbkC8c,8875
18
+ hypern/database/sqlx/query.py,sha256=_SRoXXXdVZ_kRLcvrYCtxmIbpb1GE3BpBg4rseHhctc,32442
19
+ hypern/database/sqlx/__init__.py,sha256=1GJLdJfh1Dgy6o1tyl6Aus431rhrX4shhE53M9FLQl0,609
20
+ hypern/database/sqlx/model.py,sha256=5liN9IP6cKZhW2SZqQE5ynFNCPVkGL9_xoyPu5PAyjQ,3927
21
+ hypern/database/sqlx/migrate.py,sha256=gHoZFUPop7OGp_cVic8pKiVnnV1-j2oUAJ9lXVfBBAA,9479
22
+ hypern/config.py,sha256=Ksn2LnHU0yhtGUjnac9bNjqtxl7IcPKmMdbDfZYm7Jo,7911
23
+ hypern/response/__init__.py,sha256=9z99BDgASpG404GK8LGkOsXgac0wFwH_cQOTI5Ju-1U,223
24
+ hypern/response/response.py,sha256=_UbLlzEfDZvXKHDKOdXFdus-CJXgoNFPmV259cjQz2Q,4729
25
+ hypern/reload.py,sha256=Y2pjHHh8Zv0z-pRkBPLezKiowRblb1ZJ7yI_oE55D4U,1523
26
+ hypern/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ hypern/auth/authorization.py,sha256=b8N_MiBmSJBVR45SsOI2iMGmXYOlNKbsMsrMwXApxtk,30
28
+ hypern/background.py,sha256=fN38UlJG6wZf1gOGcvdY-INoD8zJKvGZZOdVYTMjDwg,120
29
+ hypern/__init__.py,sha256=IxXU3ev_2KFfceMvBlJBgHeF5_YGYoiDotWJOAiYjh4,615
30
+ hypern/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ hypern/cli/commands.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ hypern/openapi/swagger.py,sha256=E5fHYUfFa77zQsCyQGf_vnqJVpl4_KI5qsKFHdgJEdw,61
33
+ hypern/openapi/__init__.py,sha256=oJ0HM9yAgSN00mBC_fRgV2irlGugrhvIpiveuDMv8PM,136
34
+ hypern/openapi/schemas.py,sha256=Hg8G4aPZ1xXJTKFWhx8BgwRsDt2yw-v0N6LVjJ_qBHU,1547
35
+ hypern/exceptions/formatters.py,sha256=51krRQIUq3uvwvcQm81mYPifdp2r2ckwC98pXI5v_P8,2330
36
+ hypern/exceptions/__init__.py,sha256=t4GhxGHjOPgPQ34f0MycMjoRGw5u3TRb3OcTDYc4Orw,936
37
+ hypern/exceptions/common.py,sha256=p9cx3PC6Azn0WAz7jCH02DEoLRLCCvKqNrL-dGhMGSQ,215
38
+ hypern/exceptions/http.py,sha256=N98kHaQtH4x9EW6Gavrcr-Ll_-HDvsDSaRAX1sNuN4A,3150
39
+ hypern/exceptions/errors.py,sha256=mt6ZXUGHFZ_FfyP7sZFj4XT6amb5G-1Fa_26rH7BSWc,842
40
+ hypern/exceptions/base.py,sha256=_tt42Tuy_7oXR-THhJ00lZFsCJMKWbArJyTlF-kcgH4,1955
41
+ hypern/application.py,sha256=8dnaBB5zn5H-AccPHO38EWPMun1M3eRyxdF6zXFi1mg,17573
42
+ hypern/hypern.pyi,sha256=GSVs2lNIlIU6k8KL2VNOBO8jafEEqzmsmJF6PHNtwAA,8718
43
+ hypern/processpool.py,sha256=7DSUMKy0IL6D3822W-XseH6oAU2MCmb-wKRt_80RuZE,3744
44
+ hypern/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
+ hypern/scheduler.py,sha256=nQoWIYMRmKd30g4XwdB072hWTNHvJlLd9S6rLlTFKS0,62
46
+ hypern/args_parser.py,sha256=hRlZe6VOZUutynVPXzCS8Mpn_Qp36MDDV0hFLNjM5YM,2149
47
+ hypern/routing/dispatcher.py,sha256=8_JuxyyOMiCqY3WsqcjSzUTpYjIGbvzGtI8j9T-fIkA,2391
48
+ hypern/routing/queue.py,sha256=Yus-49N4xc7O5S3YYxqL0muFLypu_Zgd0u2SADFh-Uk,7001
49
+ hypern/routing/route.py,sha256=juK0eOjmTv1iYYhw3zyLt3uHCB3pT6au64tVcXqCEDc,9976
50
+ hypern/routing/__init__.py,sha256=FvmUQlSraZ91q9AFGkgj3ELIep1jiKZLBCDrXIVf5DI,157
51
+ hypern/routing/parser.py,sha256=VYdQtf9TPe-NSx3J2wCfOZIh1S-iFLf0jdqrY9UPVMQ,3328
52
+ hypern/routing/endpoint.py,sha256=AWLHLQNlSGR8IGU6xM0RP-1kP06OJQzqpbXKSiZEzEo,996
53
+ hypern/enum.py,sha256=-StRU0cWboP-y5fNuhB4Q7yMk8Zm_h1Eua9KzOtIyI8,347
54
+ hypern/datastructures.py,sha256=SqqYX0iwA0U7R42bYerUjL-gjaA4mu-RwrvVT9biELg,842
55
+ hypern/i18n/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
+ hypern/caching/backend.py,sha256=Tj66YSepGUvpXrwC04gSdJzs45IepHA2hNlMtnRVB6c,798
57
+ hypern/caching/strategies.py,sha256=VU0FpYmIK6rEjjJSwRXPrprYdo0d2u1s9OxB3OAvs3g,7080
58
+ hypern/caching/__init__.py,sha256=I7X3bmdEHeHs80kjAI1s0mMlVD7RKmw9I-QupaTAIWo,346
59
+ hypern/caching/redis_backend.py,sha256=nRkAq07B248iFljn9TxE4tadYUeM8RqqERZWzEpfk7E,5767
60
+ hypern/logging/__init__.py,sha256=lzYSz0382eIM3CvP0sZ6RbEEwYZwfeJEJh9cxQA6Rws,49
61
+ hypern/logging/logger.py,sha256=62Qg4YAi_JDGV72Rd6R58jixqZk7anRqHbtnuBlkrwA,3174
62
+ hypern/ws/channel.py,sha256=TWaqowshz3WZRdg7ApBdFtVAlZW0OsVqoOHoFtXaZrk,3103
63
+ hypern/ws/route.py,sha256=8YPTf1fsF46oCyqoXePC3mEbhjNVFDp8rqyWSsBHhBA,777
64
+ hypern/ws/__init__.py,sha256=iUYERiHxs7HCmHj7CS5iG2XewKAJgW7w8kqxSORu_N8,127
65
+ hypern/ws/heartbeat.py,sha256=PIrYWnQn8VxQjfDXDmtMymMl-wN5MQ_Q6oHfAjPWznU,2787
66
+ hypern/ws/room.py,sha256=9u6gLq1WY4hn9_yEniavaY0yetFbQzgya_g6VPN-cgg,2522
67
+ hypern/gateway/service.py,sha256=kxKTBZN0ZjuNEp8uwFldQWql-g1q1AECXUjKZsICdLg,1649
68
+ hypern/gateway/gateway.py,sha256=rAZrS9db55tQGUfEfVNIKw6EetBdHAcSXyrC7rLfCZ8,1434
69
+ hypern/gateway/aggregator.py,sha256=Z4LnsDlVDtlPlhsSKu8jCD0UsbztXOLu6UAVtkgJwQk,1100
70
+ hypern/gateway/proxy.py,sha256=cgMFJ6znUMWRDgPgnRz7HmPT6UUY6Z09-8HAxkCWGgk,2403
71
+ hypern/gateway/__init__.py,sha256=4wyCK49W_sTBCh0hkTdEli6kdRUFu9UBxncV6EXBxwA,229
72
+ hypern/hypern.cpython-312-darwin.so,sha256=KtgpTFJJVIuo7NEBfQgOt-iJG3DFvUQkhTUxe7r4R9E,8776624
73
+ hypern-0.3.11.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.8.1)
3
+ Root-Is-Purelib: false
4
+ Tag: cp312-cp312-macosx_11_0_arm64
@@ -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.