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,525 @@
1
+ """
2
+ PyMyBatis配置管理模块
3
+
4
+ 负责加载和管理框架的所有配置项,包括:
5
+ - 数据源配置(支持环境变量读取)
6
+ - 映射文件配置
7
+ - 缓存配置
8
+ - 事务配置
9
+ - 安全配置
10
+ - 连接池配置
11
+ """
12
+
13
+ import os
14
+ import json
15
+ import yaml
16
+ import re
17
+ from typing import Dict, List, Optional, Any
18
+
19
+
20
+ class ConfigurationError(ValueError):
21
+ """Raised when ORM configuration is missing or internally inconsistent."""
22
+
23
+
24
+ class Configuration:
25
+ """
26
+ 配置管理类
27
+
28
+ 核心职责:
29
+ 1. 加载配置文件(JSON/YAML)
30
+ 2. 管理多数据源配置
31
+ 3. 管理映射器配置
32
+ 4. 管理缓存配置
33
+ 5. 管理事务和安全配置
34
+ 6. 支持环境变量读取(${ENV_VAR}格式)
35
+ """
36
+
37
+ # 环境变量替换模式:${ENV_VAR} 或 ${ENV_VAR:default}
38
+ ENV_VAR_PATTERN = re.compile(r'\$\{([^}]+)\}')
39
+
40
+ def __init__(self):
41
+ # 数据源配置
42
+ self.datasources: Dict[str, Dict[str, Any]] = {}
43
+
44
+ # 默认数据源名称
45
+ self.default_datasource: str = 'default'
46
+
47
+ # 映射器配置
48
+ self.mappers: List[str] = []
49
+
50
+ # XML映射文件路径
51
+ self.mapper_locations: List[str] = []
52
+
53
+ # 缓存配置
54
+ self.cache_enabled: bool = True
55
+ self.cache_type: str = 'lru'
56
+ self.cache_size: int = 1024
57
+ self.cache_ttl: int = 3600
58
+
59
+ # Redis缓存配置(可选)
60
+ self.redis_cache_enabled: bool = False
61
+ self.redis_cache_config: Dict[str, Any] = {}
62
+
63
+ # 事务配置
64
+ self.default_transaction_isolation: str = 'READ_COMMITTED'
65
+ self.default_fetch_size: int = 100
66
+ self.default_timeout: int = 30
67
+
68
+ # 连接池配置
69
+ self.pool_min_size: int = 5
70
+ self.pool_max_size: int = 20
71
+ self.pool_max_idle: int = 10
72
+ self.pool_wait_timeout: int = 30
73
+ self.pool_validation_interval: int = 300
74
+ self.leak_detection_enabled: bool = True
75
+ self.leak_timeout: int = 300
76
+
77
+ # 熔断器配置
78
+ self.circuit_breaker_enabled: bool = False
79
+ self.circuit_breaker_failure_threshold: int = 3
80
+ self.circuit_breaker_recovery_timeout: int = 60
81
+ self.circuit_breaker_success_threshold: int = 3
82
+
83
+ # 安全配置
84
+ self.sql_injection_detection: bool = True
85
+ self.ast_validation_enabled: bool = False # AST验证(需要sqlglot)
86
+ self.sensitive_data_masking: bool = True
87
+ self.access_control_enabled: bool = False
88
+ self.log_masking_enabled: bool = True
89
+ self.block_ddl: bool = True
90
+ self.allow_raw_params: bool = False
91
+ self.allowed_tables: List[str] = [] # 允许的表名白名单
92
+ self.allowed_columns: List[str] = [] # 允许的字段名白名单
93
+
94
+ # 性能配置
95
+ self.sql_precompile_cache: bool = True
96
+ self.result_map_cache: bool = True
97
+ self.lazy_load_mappers: bool = True
98
+
99
+ # 批量操作配置
100
+ self.max_batch_size: int = 1000
101
+ self.batch_split_size: int = 100
102
+
103
+ # 类型处理器注册
104
+ self.type_handlers: Dict[str, Any] = {}
105
+
106
+ # 拦截器列表
107
+ self.interceptors: List[Any] = []
108
+
109
+ # 方言配置
110
+ self.dialect: str = 'mysql'
111
+
112
+ # 日志配置
113
+ self.log_level: str = 'INFO'
114
+ self.log_file: Optional[str] = None
115
+
116
+ # 分页配置
117
+ self.max_pagination_offset: int = 10000
118
+
119
+ # 监控指标配置
120
+ self.metrics_enabled: bool = False
121
+ self.metrics_endpoint: str = '/metrics'
122
+ self.metrics_port: int = 9090
123
+
124
+ def _resolve_env_var(self, value: str) -> Any:
125
+ """
126
+ 解析环境变量引用
127
+
128
+ 支持格式:
129
+ - ${ENV_VAR} - 直接读取环境变量
130
+ - ${ENV_VAR:default} - 读取环境变量,不存在使用默认值
131
+
132
+ Args:
133
+ value: 包含环境变量引用的字符串
134
+
135
+ Returns:
136
+ 解析后的字符串
137
+ """
138
+ if not isinstance(value, str):
139
+ return value
140
+
141
+ exact_placeholder = self.ENV_VAR_PATTERN.fullmatch(value)
142
+
143
+ def replace_env(match):
144
+ env_spec = match.group(1)
145
+
146
+ # 检查是否有默认值
147
+ if ':' in env_spec:
148
+ env_name, default_value = env_spec.split(':', 1)
149
+ else:
150
+ env_name = env_spec
151
+ default_value = None # 使用None表示没有默认值
152
+
153
+ # 从环境变量获取值
154
+ env_value = os.environ.get(env_name.strip())
155
+
156
+ # 如果环境变量不存在,使用默认值
157
+ if env_value is None:
158
+ if default_value is None:
159
+ raise ConfigurationError(f"必需的环境变量 {env_name.strip()} 未设置")
160
+ return default_value
161
+
162
+ return env_value
163
+
164
+ resolved = self.ENV_VAR_PATTERN.sub(replace_env, value)
165
+ if exact_placeholder:
166
+ parsed = yaml.safe_load(resolved)
167
+ if not isinstance(parsed, (dict, list)):
168
+ return parsed
169
+ return resolved
170
+
171
+ def _resolve_config_recursive(self, config: Any) -> Any:
172
+ """
173
+ 递归解析配置中的环境变量
174
+
175
+ Args:
176
+ config: 配置值(可能是字典、列表或字符串)
177
+
178
+ Returns:
179
+ 解析后的配置值
180
+ """
181
+ if isinstance(config, str):
182
+ return self._resolve_env_var(config)
183
+
184
+ if isinstance(config, dict):
185
+ resolved = {}
186
+ for key, value in config.items():
187
+ resolved[key] = self._resolve_config_recursive(value)
188
+ return resolved
189
+
190
+ if isinstance(config, list):
191
+ resolved = []
192
+ for item in config:
193
+ resolved.append(self._resolve_config_recursive(item))
194
+ return resolved
195
+
196
+ return config
197
+
198
+ def load_config(self, config: Dict[str, Any]) -> None:
199
+ """
200
+ 加载配置字典(支持环境变量解析)
201
+
202
+ Args:
203
+ config: 配置字典
204
+ """
205
+ # 递归解析环境变量
206
+ config = self._resolve_config_recursive(config)
207
+ if not isinstance(config, dict):
208
+ raise ConfigurationError("ORM配置根节点必须是对象")
209
+
210
+ # 加载数据源配置(支持单数据源和多数据源两种格式)
211
+ if 'datasource' in config:
212
+ # 单数据源格式
213
+ self.datasources = {'default': config['datasource']}
214
+ self.default_datasource = 'default'
215
+
216
+ # 根据驱动自动设置方言
217
+ driver = config['datasource'].get('driver', 'mysql').lower()
218
+ if driver == 'sqlite':
219
+ self.dialect = 'sqlite'
220
+ elif driver == 'postgresql':
221
+ self.dialect = 'postgresql'
222
+ elif driver == 'oracle':
223
+ self.dialect = 'oracle'
224
+ else:
225
+ self.dialect = 'mysql'
226
+
227
+ elif 'datasources' in config:
228
+ # 多数据源格式
229
+ self.datasources = config['datasources']
230
+ if 'default' in self.datasources:
231
+ self.default_datasource = 'default'
232
+
233
+ # 加载默认数据源
234
+ if 'default_datasource' in config:
235
+ self.default_datasource = config['default_datasource']
236
+
237
+ # 加载映射器配置
238
+ if 'mappers' in config:
239
+ self.mappers = config['mappers']
240
+
241
+ # 加载XML映射文件路径(支持mapper_paths和mapper_locations两种格式)
242
+ if 'mapper_paths' in config:
243
+ self.mapper_locations = config['mapper_paths']
244
+ elif 'mapper_locations' in config:
245
+ self.mapper_locations = config['mapper_locations']
246
+
247
+ # 加载缓存配置
248
+ if 'cache' in config:
249
+ cache_config = config['cache']
250
+ self.cache_enabled = cache_config.get('enabled', True)
251
+ self.cache_type = cache_config.get('type', 'lru')
252
+ self.cache_size = cache_config.get('size', 1024)
253
+ self.cache_ttl = cache_config.get('ttl', 3600)
254
+
255
+ # Redis缓存配置
256
+ if 'redis' in cache_config:
257
+ redis_config = cache_config['redis']
258
+ self.redis_cache_enabled = redis_config.get('enabled', False)
259
+ self.redis_cache_config = redis_config
260
+
261
+ # 加载事务配置
262
+ if 'transaction' in config:
263
+ tx_config = config['transaction']
264
+ self.default_transaction_isolation = tx_config.get('isolation', 'READ_COMMITTED')
265
+ self.default_fetch_size = tx_config.get('fetch_size', 100)
266
+ self.default_timeout = tx_config.get('timeout', 30)
267
+
268
+ # 加载连接池配置
269
+ if 'pool' in config:
270
+ pool_config = config['pool']
271
+ self.pool_min_size = int(pool_config.get('min_size', 5))
272
+ self.pool_max_size = int(pool_config.get('max_size', 20))
273
+ self.pool_max_idle = float(pool_config.get('max_idle', 10))
274
+ self.pool_wait_timeout = float(pool_config.get('wait_timeout', 30))
275
+ self.pool_validation_interval = float(pool_config.get('validation_interval', 300))
276
+ self.leak_detection_enabled = pool_config.get('leak_detection_enabled', True)
277
+ self.leak_timeout = float(pool_config.get('leak_timeout', 300))
278
+
279
+ # 熔断器配置
280
+ if 'circuit_breaker' in pool_config:
281
+ cb_config = pool_config['circuit_breaker']
282
+ self.circuit_breaker_enabled = cb_config.get('enabled', False)
283
+ self.circuit_breaker_failure_threshold = int(cb_config.get('failure_threshold', 3))
284
+ self.circuit_breaker_recovery_timeout = float(cb_config.get('recovery_timeout', 60))
285
+ self.circuit_breaker_success_threshold = int(cb_config.get('success_threshold', 3))
286
+
287
+ # 加载安全配置
288
+ if 'security' in config:
289
+ security_config = config['security']
290
+ self.sql_injection_detection = security_config.get('sql_injection_detection', True)
291
+ self.ast_validation_enabled = security_config.get('ast_validation_enabled', False)
292
+ self.sensitive_data_masking = security_config.get('sensitive_data_masking', True)
293
+ self.access_control_enabled = security_config.get('access_control_enabled', False)
294
+ self.log_masking_enabled = security_config.get('log_masking_enabled', True)
295
+ self.block_ddl = security_config.get('block_ddl', True)
296
+ self.allow_raw_params = security_config.get('allow_raw_params', False)
297
+ self.allowed_tables = security_config.get('allowed_tables', [])
298
+ self.allowed_columns = security_config.get('allowed_columns', [])
299
+
300
+ # 加载性能配置
301
+ if 'performance' in config:
302
+ perf_config = config['performance']
303
+ self.sql_precompile_cache = perf_config.get('sql_precompile_cache', True)
304
+ self.result_map_cache = perf_config.get('result_map_cache', True)
305
+ self.lazy_load_mappers = perf_config.get('lazy_load_mappers', True)
306
+
307
+ # 加载批量操作配置
308
+ if 'batch' in config:
309
+ batch_config = config['batch']
310
+ self.max_batch_size = batch_config.get('max_size', 1000)
311
+ self.batch_split_size = batch_config.get('split_size', 100)
312
+
313
+ # 加载方言配置
314
+ if 'dialect' in config:
315
+ self.dialect = config['dialect']
316
+
317
+ # 加载日志配置
318
+ if 'logging' in config:
319
+ logging_config = config['logging']
320
+ self.log_level = logging_config.get('level', 'INFO')
321
+ self.log_file = logging_config.get('file')
322
+
323
+ # 加载分页配置
324
+ if 'pagination' in config:
325
+ pagination_config = config['pagination']
326
+ self.max_pagination_offset = pagination_config.get('max_offset', 10000)
327
+
328
+ # 加载监控指标配置
329
+ if 'metrics' in config:
330
+ metrics_config = config['metrics']
331
+ self.metrics_enabled = metrics_config.get('enabled', False)
332
+ self.metrics_endpoint = metrics_config.get('endpoint', '/metrics')
333
+ self.metrics_port = metrics_config.get('port', 9090)
334
+
335
+ self._validate()
336
+
337
+ def _validate(self) -> None:
338
+ if self.datasources and self.default_datasource not in self.datasources:
339
+ raise ConfigurationError(f"默认数据源不存在: {self.default_datasource}")
340
+ if self.pool_min_size < 0 or self.pool_max_size < 1:
341
+ raise ConfigurationError("连接池大小必须为非负数,且 max_size 必须大于 0")
342
+ if self.pool_min_size > self.pool_max_size:
343
+ raise ConfigurationError("连接池 min_size 不能大于 max_size")
344
+ if self.pool_wait_timeout <= 0 or self.pool_validation_interval <= 0 or self.leak_timeout <= 0:
345
+ raise ConfigurationError("连接池超时配置必须大于 0")
346
+ valid_isolation_levels = {
347
+ 'READ_UNCOMMITTED', 'READ_COMMITTED', 'REPEATABLE_READ', 'SERIALIZABLE'
348
+ }
349
+ if self.default_transaction_isolation not in valid_isolation_levels:
350
+ raise ConfigurationError(
351
+ f"不支持的事务隔离级别: {self.default_transaction_isolation}"
352
+ )
353
+
354
+ def load_config_file(self, file_path: str) -> None:
355
+ """
356
+ 从配置文件加载配置(支持环境变量解析)
357
+
358
+ Args:
359
+ file_path: 配置文件路径,支持JSON和YAML格式
360
+ """
361
+ if not os.path.exists(file_path):
362
+ raise FileNotFoundError(f"配置文件不存在: {file_path}")
363
+
364
+ ext = os.path.splitext(file_path)[1].lower()
365
+ with open(file_path, 'r', encoding='utf-8') as f:
366
+ if ext == '.json':
367
+ config = json.load(f)
368
+ elif ext in ('.yaml', '.yml'):
369
+ config = yaml.safe_load(f)
370
+ else:
371
+ raise ValueError(f"不支持的配置文件格式: {ext}")
372
+
373
+ self.load_config(config)
374
+
375
+ def get_datasource(self, name: Optional[str] = None) -> Dict[str, Any]:
376
+ """
377
+ 获取数据源配置(已解析环境变量)
378
+
379
+ Args:
380
+ name: 数据源名称,默认为默认数据源
381
+
382
+ Returns:
383
+ 数据源配置字典
384
+ """
385
+ ds_name = name or self.default_datasource
386
+ if ds_name not in self.datasources:
387
+ raise ValueError(f"数据源不存在: {ds_name}")
388
+ return self.datasources[ds_name]
389
+
390
+ def register_type_handler(self, java_type: str, handler: Any) -> None:
391
+ """
392
+ 注册自定义类型处理器
393
+
394
+ Args:
395
+ java_type: Java类型全限定名
396
+ handler: 类型处理器实例
397
+ """
398
+ self.type_handlers[java_type] = handler
399
+
400
+ def register_interceptor(self, interceptor: Any) -> None:
401
+ """
402
+ 注册拦截器
403
+
404
+ Args:
405
+ interceptor: 拦截器实例
406
+ """
407
+ self.interceptors.append(interceptor)
408
+
409
+ def is_cache_enabled(self) -> bool:
410
+ """检查缓存是否启用"""
411
+ return self.cache_enabled
412
+
413
+ def is_sql_injection_detection_enabled(self) -> bool:
414
+ """检查SQL注入检测是否启用"""
415
+ return self.sql_injection_detection
416
+
417
+ def is_sensitive_data_masking_enabled(self) -> bool:
418
+ """检查敏感数据脱敏是否启用"""
419
+ return self.sensitive_data_masking
420
+
421
+ def is_access_control_enabled(self) -> bool:
422
+ """检查访问控制是否启用"""
423
+ return self.access_control_enabled
424
+
425
+ def is_log_masking_enabled(self) -> bool:
426
+ """检查日志脱敏是否启用"""
427
+ return self.log_masking_enabled
428
+
429
+ def is_sql_precompile_cache_enabled(self) -> bool:
430
+ """检查SQL预编译缓存是否启用"""
431
+ return self.sql_precompile_cache
432
+
433
+ def is_result_map_cache_enabled(self) -> bool:
434
+ """检查结果集映射缓存是否启用"""
435
+ return self.result_map_cache
436
+
437
+ def is_lazy_load_mappers_enabled(self) -> bool:
438
+ """检查映射器懒加载是否启用"""
439
+ return self.lazy_load_mappers
440
+
441
+ def is_ddl_blocked(self) -> bool:
442
+ """检查DDL语句是否被阻止"""
443
+ return self.block_ddl
444
+
445
+ def is_raw_params_allowed(self) -> bool:
446
+ """检查${}参数是否允许使用"""
447
+ return self.allow_raw_params
448
+
449
+ def to_dict(self) -> Dict[str, Any]:
450
+ """将配置转换为字典(不包含敏感信息)"""
451
+ return {
452
+ 'datasources': {name: {k: '******' if k.lower() in ('password', 'pwd') else v
453
+ for k, v in ds.items()}
454
+ for name, ds in self.datasources.items()},
455
+ 'default_datasource': self.default_datasource,
456
+ 'mappers': self.mappers,
457
+ 'mapper_locations': self.mapper_locations,
458
+ 'cache': {
459
+ 'enabled': self.cache_enabled,
460
+ 'type': self.cache_type,
461
+ 'size': self.cache_size,
462
+ 'ttl': self.cache_ttl,
463
+ 'redis': {
464
+ 'enabled': self.redis_cache_enabled,
465
+ **{k: '******' if k.lower() == 'password' else v
466
+ for k, v in self.redis_cache_config.items()}
467
+ }
468
+ },
469
+ 'transaction': {
470
+ 'isolation': self.default_transaction_isolation,
471
+ 'fetch_size': self.default_fetch_size,
472
+ 'timeout': self.default_timeout
473
+ },
474
+ 'pool': {
475
+ 'min_size': self.pool_min_size,
476
+ 'max_size': self.pool_max_size,
477
+ 'max_idle': self.pool_max_idle,
478
+ 'wait_timeout': self.pool_wait_timeout,
479
+ 'validation_interval': self.pool_validation_interval,
480
+ 'leak_detection_enabled': self.leak_detection_enabled,
481
+ 'leak_timeout': self.leak_timeout,
482
+ 'circuit_breaker': {
483
+ 'enabled': self.circuit_breaker_enabled,
484
+ 'failure_threshold': self.circuit_breaker_failure_threshold,
485
+ 'recovery_timeout': self.circuit_breaker_recovery_timeout,
486
+ 'success_threshold': self.circuit_breaker_success_threshold
487
+ }
488
+ },
489
+ 'security': {
490
+ 'sql_injection_detection': self.sql_injection_detection,
491
+ 'ast_validation_enabled': self.ast_validation_enabled,
492
+ 'sensitive_data_masking': self.sensitive_data_masking,
493
+ 'access_control_enabled': self.access_control_enabled,
494
+ 'log_masking_enabled': self.log_masking_enabled,
495
+ 'block_ddl': self.block_ddl,
496
+ 'allow_raw_params': self.allow_raw_params,
497
+ 'allowed_tables': self.allowed_tables,
498
+ 'allowed_columns': self.allowed_columns
499
+ },
500
+ 'performance': {
501
+ 'sql_precompile_cache': self.sql_precompile_cache,
502
+ 'result_map_cache': self.result_map_cache,
503
+ 'lazy_load_mappers': self.lazy_load_mappers
504
+ },
505
+ 'batch': {
506
+ 'max_size': self.max_batch_size,
507
+ 'split_size': self.batch_split_size
508
+ },
509
+ 'dialect': self.dialect,
510
+ 'logging': {
511
+ 'level': self.log_level,
512
+ 'file': self.log_file
513
+ },
514
+ 'pagination': {
515
+ 'max_offset': self.max_pagination_offset
516
+ },
517
+ 'metrics': {
518
+ 'enabled': self.metrics_enabled,
519
+ 'endpoint': self.metrics_endpoint,
520
+ 'port': self.metrics_port
521
+ }
522
+ }
523
+
524
+ def __repr__(self) -> str:
525
+ return f"<Configuration dialect={self.dialect}, datasources={list(self.datasources.keys())}>"
@@ -0,0 +1,10 @@
1
+ """
2
+ PyMyBatis核心模块
3
+
4
+ 包含SqlSession、SqlSessionFactory等核心组件
5
+ """
6
+
7
+ from .sql_session import SqlSession
8
+ from .sql_session_factory import SqlSessionFactory
9
+
10
+ __all__ = ['SqlSession', 'SqlSessionFactory']