springbootAI 1.8.0__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 (175) hide show
  1. spring/__init__.py +66 -0
  2. spring/ai/__init__.py +78 -0
  3. spring/ai/advisors.py +139 -0
  4. spring/ai/annotations.py +74 -0
  5. spring/ai/autoconfig.py +481 -0
  6. spring/ai/core.py +391 -0
  7. spring/ai/etl.py +188 -0
  8. spring/ai/memory.py +109 -0
  9. spring/ai/observability.py +129 -0
  10. spring/ai/providers.py +789 -0
  11. spring/ai/resilience.py +258 -0
  12. spring/ai/tools.py +106 -0
  13. spring/ai/vectorstore.py +303 -0
  14. spring/annotations/__init__.py +188 -0
  15. spring/annotations/cache.py +126 -0
  16. spring/annotations/cloud.py +207 -0
  17. spring/annotations/conditional.py +272 -0
  18. spring/annotations/core.py +864 -0
  19. spring/annotations/messaging.py +107 -0
  20. spring/aop/__init__.py +4 -0
  21. spring/aop/cloud_aop.py +404 -0
  22. spring/aop/comprehensive_aop.py +1015 -0
  23. spring/aop/method_interceptor.py +19 -0
  24. spring/aop/proxy_factory.py +55 -0
  25. spring/cloud/__init__.py +76 -0
  26. spring/cloud/discovery.py +364 -0
  27. spring/cloud/feign.py +469 -0
  28. spring/cloud/gateway.py +452 -0
  29. spring/cloud/load_balancer.py +149 -0
  30. spring/cloud/seata.py +557 -0
  31. spring/cloud/sentinel.py +525 -0
  32. spring/cloud/tracer.py +337 -0
  33. spring/config/__init__.py +21 -0
  34. spring/config/binding.py +206 -0
  35. spring/config/config_loader.py +405 -0
  36. spring/context/__init__.py +13 -0
  37. spring/context/application_context.py +589 -0
  38. spring/context/bean_definition.py +70 -0
  39. spring/context/bean_factory.py +1052 -0
  40. spring/context/registry.py +58 -0
  41. spring/context/scanner.py +106 -0
  42. spring/core/__init__.py +3 -0
  43. spring/core/graceful_shutdown.py +196 -0
  44. spring/core/typing_utils.py +50 -0
  45. spring/csv/__init__.py +52 -0
  46. spring/csv/annotations.py +402 -0
  47. spring/csv/converters.py +69 -0
  48. spring/csv/easy_csv.py +95 -0
  49. spring/csv/exceptions.py +27 -0
  50. spring/csv/reader.py +195 -0
  51. spring/csv/writer.py +155 -0
  52. spring/data/__init__.py +54 -0
  53. spring/data/page.py +181 -0
  54. spring/data/repository.py +274 -0
  55. spring/data/specification.py +228 -0
  56. spring/datasource/__init__.py +66 -0
  57. spring/datasource/annotations.py +133 -0
  58. spring/datasource/context.py +69 -0
  59. spring/datasource/dynamic.py +148 -0
  60. spring/event/__init__.py +7 -0
  61. spring/event/publisher.py +69 -0
  62. spring/excel/__init__.py +51 -0
  63. spring/excel/annotations.py +405 -0
  64. spring/excel/converters.py +231 -0
  65. spring/excel/easy_excel.py +94 -0
  66. spring/excel/exceptions.py +31 -0
  67. spring/excel/reader.py +254 -0
  68. spring/excel/style.py +95 -0
  69. spring/excel/writer.py +197 -0
  70. spring/i18n/__init__.py +97 -0
  71. spring/i18n/accessor.py +94 -0
  72. spring/i18n/auto_config.py +177 -0
  73. spring/i18n/holder.py +106 -0
  74. spring/i18n/locale.py +152 -0
  75. spring/i18n/locale_resolver.py +367 -0
  76. spring/i18n/message_source.py +250 -0
  77. spring/i18n/middleware.py +79 -0
  78. spring/i18n/properties.py +168 -0
  79. spring/i18n/sources.py +255 -0
  80. spring/logging/__init__.py +1 -0
  81. spring/logging/loguru_logger.py +228 -0
  82. spring/main.py +378 -0
  83. spring/messaging/__init__.py +1 -0
  84. spring/messaging/rabbitmq.py +302 -0
  85. spring/monitoring/__init__.py +1 -0
  86. spring/monitoring/prometheus.py +199 -0
  87. spring/orm/__init__.py +258 -0
  88. spring/orm/database.py +222 -0
  89. spring/orm/ddl_auto.py +1217 -0
  90. spring/orm/migration.py +419 -0
  91. spring/orm/mybatis_integration.py +400 -0
  92. spring/orm/pymybatis/__init__.py +86 -0
  93. spring/orm/pymybatis/annotations/__init__.py +30 -0
  94. spring/orm/pymybatis/annotations/annotations.py +332 -0
  95. spring/orm/pymybatis/cache/__init__.py +47 -0
  96. spring/orm/pymybatis/cache/cache.py +371 -0
  97. spring/orm/pymybatis/cache/redis_cache.py +434 -0
  98. spring/orm/pymybatis/circuit_breaker/__init__.py +21 -0
  99. spring/orm/pymybatis/circuit_breaker/circuit_breaker.py +424 -0
  100. spring/orm/pymybatis/configuration.py +525 -0
  101. spring/orm/pymybatis/core/__init__.py +10 -0
  102. spring/orm/pymybatis/core/sql_session.py +1382 -0
  103. spring/orm/pymybatis/core/sql_session_factory.py +76 -0
  104. spring/orm/pymybatis/dialect/__init__.py +9 -0
  105. spring/orm/pymybatis/dialect/dialect.py +445 -0
  106. spring/orm/pymybatis/dynamic_sql/__init__.py +9 -0
  107. spring/orm/pymybatis/dynamic_sql/dynamic_sql.py +900 -0
  108. spring/orm/pymybatis/interceptor/__init__.py +31 -0
  109. spring/orm/pymybatis/interceptor/interceptor.py +427 -0
  110. spring/orm/pymybatis/mapper/__init__.py +9 -0
  111. spring/orm/pymybatis/mapper/mapper.py +540 -0
  112. spring/orm/pymybatis/metrics/__init__.py +41 -0
  113. spring/orm/pymybatis/metrics/metrics.py +595 -0
  114. spring/orm/pymybatis/pool/__init__.py +9 -0
  115. spring/orm/pymybatis/pool/connection_pool.py +711 -0
  116. spring/orm/pymybatis/security/__init__.py +19 -0
  117. spring/orm/pymybatis/security/access_control.py +415 -0
  118. spring/orm/pymybatis/security/password_encoder.py +293 -0
  119. spring/orm/pymybatis/security/sensitive_data_masker.py +326 -0
  120. spring/orm/pymybatis/security/sql_injection_detector.py +675 -0
  121. spring/orm/pymybatis/transaction/__init__.py +9 -0
  122. spring/orm/pymybatis/transaction/transaction.py +288 -0
  123. spring/orm/pymybatis/type_handler/__init__.py +37 -0
  124. spring/orm/pymybatis/type_handler/type_handler.py +473 -0
  125. spring/orm/pymybatis/version.py +9 -0
  126. spring/orm/pymybatis/xml_parser/__init__.py +9 -0
  127. spring/orm/pymybatis/xml_parser/xml_parser.py +761 -0
  128. spring/retry/__init__.py +12 -0
  129. spring/retry/retry_annotations.py +71 -0
  130. spring/retry/retry_decorator.py +155 -0
  131. spring/scheduling/__init__.py +3 -0
  132. spring/scheduling/scheduler.py +389 -0
  133. spring/security/__init__.py +39 -0
  134. spring/security/jwt_utils.py +281 -0
  135. spring/security/replay_protection.py +206 -0
  136. spring/security/secret_manager.py +226 -0
  137. spring/security/security_aop.py +248 -0
  138. spring/security/security_context.py +172 -0
  139. spring/test/__init__.py +45 -0
  140. spring/test/slicing.py +341 -0
  141. spring/tracing/__init__.py +11 -0
  142. spring/tracing/skywalking.py +229 -0
  143. spring/tx/__init__.py +52 -0
  144. spring/tx/events.py +172 -0
  145. spring/tx/synchronization.py +143 -0
  146. spring/utils/__init__.py +5 -0
  147. spring/utils/banner.py +32 -0
  148. spring/utils/logger.py +73 -0
  149. spring/utils/redis_client.py +526 -0
  150. spring/validation/__init__.py +55 -0
  151. spring/validation/aop.py +141 -0
  152. spring/validation/constraints.py +357 -0
  153. spring/validation/exceptions.py +55 -0
  154. spring/validation/validator.py +139 -0
  155. spring/web/__init__.py +12 -0
  156. spring/web/actuator.py +319 -0
  157. spring/web/exception_handler.py +61 -0
  158. spring/web/health.py +399 -0
  159. spring/web/interceptor.py +91 -0
  160. spring/web/result.py +44 -0
  161. spring/web/swagger.py +601 -0
  162. spring/web/web_context.py +755 -0
  163. spring/websocket/__init__.py +86 -0
  164. spring/websocket/annotations.py +169 -0
  165. spring/websocket/broker.py +238 -0
  166. spring/websocket/exceptions.py +26 -0
  167. spring/websocket/handler.py +243 -0
  168. spring/websocket/router.py +526 -0
  169. spring/websocket/session.py +216 -0
  170. springbootai-1.8.0.dist-info/METADATA +2796 -0
  171. springbootai-1.8.0.dist-info/RECORD +175 -0
  172. springbootai-1.8.0.dist-info/WHEEL +5 -0
  173. springbootai-1.8.0.dist-info/entry_points.txt +2 -0
  174. springbootai-1.8.0.dist-info/licenses/LICENSE +7 -0
  175. springbootai-1.8.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,216 @@
1
+ """``WebSocketSession`` 会话抽象与全局注册表(对齐 Spring ``WebSocketSession`` +
2
+ ``WebSocketHandlerRegistry``)。
3
+
4
+ ``WebSocketSession`` 包装 Starlette ``WebSocket``,提供:
5
+ - 唯一 ``id``(uuid4)
6
+ - ``attributes`` 字典(用户态附加数据,对齐 Spring ``attributes``)
7
+ - ``send_text`` / ``send_json`` / ``send_bytes`` / ``receive_text`` / ``receive_json`` / ``close``
8
+ - ``is_open`` / ``is_closed`` 状态
9
+ - ``user`` 属性(可选,关联鉴权用户)
10
+
11
+ ``WebSocketSessionRegistry`` 线程安全注册表,支持:
12
+ - ``register`` / ``unregister`` / ``get`` / ``all``
13
+ - ``send_to_user(user, message)`` 定向推送
14
+ - ``broadcast(message)`` 广播
15
+ - ``close_all(code, reason)`` 关闭所有会话(优雅退出)
16
+ """
17
+ from __future__ import annotations
18
+
19
+ import asyncio
20
+ import logging
21
+ import threading
22
+ import uuid
23
+ from typing import Any, Dict, Iterable, List, Optional
24
+
25
+ logger = logging.getLogger("Spring.WebSocket.Session")
26
+
27
+
28
+ class WebSocketSession:
29
+ """WebSocket 会话抽象,包装 Starlette ``WebSocket``。
30
+
31
+ 每个会话有唯一 ``id``;``attributes`` 用于在生命周期钩子间传递用户态数据。
32
+ """
33
+
34
+ def __init__(self, websocket, user: Optional[str] = None):
35
+ # 延迟导入以避免顶层依赖 FastAPI/Starlette(仅类型注解需要)
36
+ self._ws = websocket
37
+ self._id: str = uuid.uuid4().hex
38
+ self._attributes: Dict[str, Any] = {}
39
+ self._user: Optional[str] = user
40
+ self._closed: bool = False
41
+ self._lock = threading.Lock()
42
+
43
+ # ==================== 属性 ====================
44
+
45
+ @property
46
+ def id(self) -> str:
47
+ return self._id
48
+
49
+ @property
50
+ def attributes(self) -> Dict[str, Any]:
51
+ return self._attributes
52
+
53
+ @property
54
+ def user(self) -> Optional[str]:
55
+ return self._user
56
+
57
+ @user.setter
58
+ def user(self, value: Optional[str]) -> None:
59
+ self._user = value
60
+
61
+ @property
62
+ def is_open(self) -> bool:
63
+ return not self._closed and self._ws is not None
64
+
65
+ @property
66
+ def is_closed(self) -> bool:
67
+ return self._closed
68
+
69
+ # ==================== 接收 ====================
70
+
71
+ async def receive_text(self) -> str:
72
+ return await self._ws.receive_text()
73
+
74
+ async def receive_bytes(self) -> bytes:
75
+ return await self._ws.receive_bytes()
76
+
77
+ async def receive_json(self) -> Any:
78
+ return await self._ws.receive_json()
79
+
80
+ # ==================== 发送 ====================
81
+
82
+ async def send_text(self, message: str) -> None:
83
+ if self._closed:
84
+ logger.debug("send_text on closed session %s, ignored", self._id)
85
+ return
86
+ await self._ws.send_text(message)
87
+
88
+ async def send_bytes(self, data: bytes) -> None:
89
+ if self._closed:
90
+ return
91
+ await self._ws.send_bytes(data)
92
+
93
+ async def send_json(self, data: Any) -> None:
94
+ """发送 JSON 消息。Starlette ``send_json`` 内部用 ``json.dumps``。"""
95
+ if self._closed:
96
+ return
97
+ await self._ws.send_json(data)
98
+
99
+ # ==================== 关闭 ====================
100
+
101
+ async def close(self, code: int = 1000, reason: str = "") -> None:
102
+ with self._lock:
103
+ if self._closed:
104
+ return
105
+ self._closed = True
106
+ try:
107
+ await self._ws.close(code=code, reason=reason)
108
+ except Exception as exc:
109
+ logger.debug("close session %s failed: %s", self._id, exc)
110
+
111
+ def mark_closed(self) -> None:
112
+ """标记会话已关闭(不主动发 close 帧,用于异常分支)。"""
113
+ with self._lock:
114
+ self._closed = True
115
+
116
+ def __repr__(self) -> str:
117
+ return f"WebSocketSession(id={self._id!r}, user={self._user!r}, open={self.is_open})"
118
+
119
+
120
+ # ==================== 全局会话注册表 ====================
121
+
122
+ class WebSocketSessionRegistry:
123
+ """线程安全的 WebSocket 会话注册表。
124
+
125
+ - ``register(session)`` 注册会话
126
+ - ``unregister(session_id)`` 注销会话
127
+ - ``get(session_id)`` 按 id 取会话
128
+ - ``all()`` 返回所有会话列表(拷贝)
129
+ - ``send_to_user(user, ...)`` 定向推送
130
+ - ``broadcast(...)`` 广播
131
+ - ``close_all(...)`` 关闭所有会话
132
+
133
+ 推送方法自动跳过已关闭的会话;推送是 ``async`` 的,需要事件循环驱动。
134
+ """
135
+
136
+ def __init__(self):
137
+ self._sessions: Dict[str, WebSocketSession] = {}
138
+ self._lock = threading.RLock()
139
+
140
+ def register(self, session: WebSocketSession) -> None:
141
+ with self._lock:
142
+ self._sessions[session.id] = session
143
+
144
+ def unregister(self, session_id: str) -> Optional[WebSocketSession]:
145
+ with self._lock:
146
+ return self._sessions.pop(session_id, None)
147
+
148
+ def get(self, session_id: str) -> Optional[WebSocketSession]:
149
+ with self._lock:
150
+ return self._sessions.get(session_id)
151
+
152
+ def all(self) -> List[WebSocketSession]:
153
+ with self._lock:
154
+ return list(self._sessions.values())
155
+
156
+ def count(self) -> int:
157
+ with self._lock:
158
+ return len(self._sessions)
159
+
160
+ def clear(self) -> None:
161
+ with self._lock:
162
+ self._sessions.clear()
163
+
164
+ async def send_to_user(self, user: str, message: Any, as_json: bool = True) -> int:
165
+ """向指定用户的所有会话推送消息;返回成功推送的会话数。"""
166
+ sent = 0
167
+ for session in self.all():
168
+ if session.user != user or not session.is_open:
169
+ continue
170
+ try:
171
+ if as_json:
172
+ await session.send_json(message)
173
+ else:
174
+ await session.send_text(message if isinstance(message, str) else str(message))
175
+ sent += 1
176
+ except Exception as exc:
177
+ logger.warning("send_to_user failed for session %s: %s", session.id, exc)
178
+ return sent
179
+
180
+ async def broadcast(self, message: Any, as_json: bool = True,
181
+ exclude: Optional[Iterable[str]] = None) -> int:
182
+ """向所有会话广播;``exclude`` 是要排除的 session_id 列表。返回推送数。"""
183
+ excluded = set(exclude or [])
184
+ sent = 0
185
+ for session in self.all():
186
+ if session.id in excluded or not session.is_open:
187
+ continue
188
+ try:
189
+ if as_json:
190
+ await session.send_json(message)
191
+ else:
192
+ await session.send_text(message if isinstance(message, str) else str(message))
193
+ sent += 1
194
+ except Exception as exc:
195
+ logger.warning("broadcast failed for session %s: %s", session.id, exc)
196
+ return sent
197
+
198
+ async def close_all(self, code: int = 1001, reason: str = "server shutdown") -> None:
199
+ """关闭所有会话(优雅退出)。"""
200
+ for session in self.all():
201
+ try:
202
+ await session.close(code=code, reason=reason)
203
+ except Exception as exc:
204
+ logger.debug("close_all session %s failed: %s", session.id, exc)
205
+ self.clear()
206
+
207
+
208
+ # 全局单例(对齐 Spring ``WebSocketHandlerRegistry`` 默认实现)
209
+ global_session_registry = WebSocketSessionRegistry()
210
+
211
+
212
+ __all__ = [
213
+ "WebSocketSession",
214
+ "WebSocketSessionRegistry",
215
+ "global_session_registry",
216
+ ]