JiuwenMemory 0.1.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 (247) hide show
  1. jiuwen_memory/__init__.py +23 -0
  2. jiuwen_memory/common/__init__.py +13 -0
  3. jiuwen_memory/common/clients/__init__.py +6 -0
  4. jiuwen_memory/common/clients/client_registry.py +238 -0
  5. jiuwen_memory/common/exception/__init__.py +0 -0
  6. jiuwen_memory/common/exception/codes.py +968 -0
  7. jiuwen_memory/common/exception/errors.py +332 -0
  8. jiuwen_memory/common/exception/status_mapping.py +133 -0
  9. jiuwen_memory/common/logging/__init__.py +243 -0
  10. jiuwen_memory/common/logging/base_impl.py +164 -0
  11. jiuwen_memory/common/logging/default/__init__.py +29 -0
  12. jiuwen_memory/common/logging/default/config_provider.py +209 -0
  13. jiuwen_memory/common/logging/default/constant.py +26 -0
  14. jiuwen_memory/common/logging/default/default_impl.py +532 -0
  15. jiuwen_memory/common/logging/events.py +953 -0
  16. jiuwen_memory/common/logging/log_config.py +166 -0
  17. jiuwen_memory/common/logging/log_levels.py +65 -0
  18. jiuwen_memory/common/logging/loguru/__init__.py +8 -0
  19. jiuwen_memory/common/logging/loguru/config_provider.py +326 -0
  20. jiuwen_memory/common/logging/loguru/constant.py +68 -0
  21. jiuwen_memory/common/logging/loguru/loguru_impl.py +501 -0
  22. jiuwen_memory/common/logging/manager.py +214 -0
  23. jiuwen_memory/common/logging/protocol.py +75 -0
  24. jiuwen_memory/common/logging/utils.py +127 -0
  25. jiuwen_memory/common/schema/__init__.py +8 -0
  26. jiuwen_memory/common/schema/card.py +25 -0
  27. jiuwen_memory/common/schema/param.py +248 -0
  28. jiuwen_memory/common/security/__init__.py +0 -0
  29. jiuwen_memory/common/security/crypt_utils.py +114 -0
  30. jiuwen_memory/common/security/path_checker.py +68 -0
  31. jiuwen_memory/common/security/ssl_utils.py +128 -0
  32. jiuwen_memory/common/security/url_utils.py +148 -0
  33. jiuwen_memory/common/security/user_config.py +105 -0
  34. jiuwen_memory/common/utils/__init__.py +0 -0
  35. jiuwen_memory/common/utils/header_utils.py +32 -0
  36. jiuwen_memory/common/utils/schema_utils.py +526 -0
  37. jiuwen_memory/common/utils/singleton.py +16 -0
  38. jiuwen_memory/foundation/llm/__init__.py +93 -0
  39. jiuwen_memory/foundation/llm/headers_helper.py +46 -0
  40. jiuwen_memory/foundation/llm/model.py +368 -0
  41. jiuwen_memory/foundation/llm/model_clients/__init__.py +81 -0
  42. jiuwen_memory/foundation/llm/model_clients/base_model_client.py +518 -0
  43. jiuwen_memory/foundation/llm/model_clients/dashscope_model_client.py +579 -0
  44. jiuwen_memory/foundation/llm/model_clients/deepseek_model_client.py +83 -0
  45. jiuwen_memory/foundation/llm/model_clients/inference_affinity_model_client.py +846 -0
  46. jiuwen_memory/foundation/llm/model_clients/intelli_router_model_client.py +482 -0
  47. jiuwen_memory/foundation/llm/model_clients/openai_model_client.py +714 -0
  48. jiuwen_memory/foundation/llm/model_clients/openrouter_model_client.py +46 -0
  49. jiuwen_memory/foundation/llm/model_clients/siliconflow_model_client.py +662 -0
  50. jiuwen_memory/foundation/llm/output_parsers/__init__.py +11 -0
  51. jiuwen_memory/foundation/llm/output_parsers/json_output_parser.py +239 -0
  52. jiuwen_memory/foundation/llm/output_parsers/markdown_output_parser.py +481 -0
  53. jiuwen_memory/foundation/llm/output_parsers/output_parser.py +33 -0
  54. jiuwen_memory/foundation/llm/schema/__init__.py +20 -0
  55. jiuwen_memory/foundation/llm/schema/config.py +87 -0
  56. jiuwen_memory/foundation/llm/schema/generation_response.py +45 -0
  57. jiuwen_memory/foundation/llm/schema/message.py +126 -0
  58. jiuwen_memory/foundation/llm/schema/message_chunk.py +274 -0
  59. jiuwen_memory/foundation/llm/schema/mode_info.py +33 -0
  60. jiuwen_memory/foundation/llm/schema/tool_call.py +22 -0
  61. jiuwen_memory/foundation/prompt/__init__.py +13 -0
  62. jiuwen_memory/foundation/prompt/assemble/__init__.py +0 -0
  63. jiuwen_memory/foundation/prompt/assemble/assembler.py +149 -0
  64. jiuwen_memory/foundation/prompt/assemble/variables/__init__.py +0 -0
  65. jiuwen_memory/foundation/prompt/assemble/variables/dictable.py +100 -0
  66. jiuwen_memory/foundation/prompt/assemble/variables/textable.py +74 -0
  67. jiuwen_memory/foundation/prompt/assemble/variables/variable.py +37 -0
  68. jiuwen_memory/foundation/prompt/template.py +80 -0
  69. jiuwen_memory/foundation/store/__init__.py +210 -0
  70. jiuwen_memory/foundation/store/base_db_store.py +28 -0
  71. jiuwen_memory/foundation/store/base_embedding.py +45 -0
  72. jiuwen_memory/foundation/store/base_kv_store.py +214 -0
  73. jiuwen_memory/foundation/store/base_memory_index.py +273 -0
  74. jiuwen_memory/foundation/store/base_message_store.py +172 -0
  75. jiuwen_memory/foundation/store/base_reranker.py +71 -0
  76. jiuwen_memory/foundation/store/base_vector_store.py +601 -0
  77. jiuwen_memory/foundation/store/db/__init__.py +0 -0
  78. jiuwen_memory/foundation/store/db/default_db_store.py +13 -0
  79. jiuwen_memory/foundation/store/db/gauss_db_store.py +30 -0
  80. jiuwen_memory/foundation/store/db/gauss_dialect.py +117 -0
  81. jiuwen_memory/foundation/store/graph/__init__.py +31 -0
  82. jiuwen_memory/foundation/store/graph/base.py +95 -0
  83. jiuwen_memory/foundation/store/graph/base_graph_store.py +202 -0
  84. jiuwen_memory/foundation/store/graph/config.py +80 -0
  85. jiuwen_memory/foundation/store/graph/constants.py +19 -0
  86. jiuwen_memory/foundation/store/graph/database_config.py +52 -0
  87. jiuwen_memory/foundation/store/graph/graph_object.py +134 -0
  88. jiuwen_memory/foundation/store/graph/index_field.py +480 -0
  89. jiuwen_memory/foundation/store/graph/milvus/__init__.py +35 -0
  90. jiuwen_memory/foundation/store/graph/milvus/generate_milvus_schema.py +156 -0
  91. jiuwen_memory/foundation/store/graph/milvus/milvus_support.py +696 -0
  92. jiuwen_memory/foundation/store/graph/result_ranking.py +107 -0
  93. jiuwen_memory/foundation/store/graph/utils.py +242 -0
  94. jiuwen_memory/foundation/store/index/simple_memory_index.py +488 -0
  95. jiuwen_memory/foundation/store/kv/__init__.py +8 -0
  96. jiuwen_memory/foundation/store/kv/db_based_kv_store.py +348 -0
  97. jiuwen_memory/foundation/store/kv/in_memory_kv_store.py +161 -0
  98. jiuwen_memory/foundation/store/kv/shelve_store.py +235 -0
  99. jiuwen_memory/foundation/store/query/__init__.py +72 -0
  100. jiuwen_memory/foundation/store/query/base.py +270 -0
  101. jiuwen_memory/foundation/store/query/chroma_query_func.py +198 -0
  102. jiuwen_memory/foundation/store/query/milvus_query_func.py +131 -0
  103. jiuwen_memory/foundation/store/query/registry.py +21 -0
  104. jiuwen_memory/foundation/store/vector/__init__.py +0 -0
  105. jiuwen_memory/foundation/store/vector/chroma_vector_store.py +798 -0
  106. jiuwen_memory/foundation/store/vector/es_vector_store.py +614 -0
  107. jiuwen_memory/foundation/store/vector/gauss_vector_store.py +832 -0
  108. jiuwen_memory/foundation/store/vector/milvus_vector_store.py +1067 -0
  109. jiuwen_memory/foundation/store/vector/utils.py +369 -0
  110. jiuwen_memory/foundation/tool/__init__.py +3 -0
  111. jiuwen_memory/foundation/tool/schema.py +14 -0
  112. jiuwen_memory/memory_core/__init__.py +18 -0
  113. jiuwen_memory/memory_core/codec/__init__.py +0 -0
  114. jiuwen_memory/memory_core/codec/aes_storage_codec.py +57 -0
  115. jiuwen_memory/memory_core/common/__init__.py +1 -0
  116. jiuwen_memory/memory_core/common/base.py +24 -0
  117. jiuwen_memory/memory_core/common/distributed_lock.py +45 -0
  118. jiuwen_memory/memory_core/common/kv_prefix_registry.py +86 -0
  119. jiuwen_memory/memory_core/config/__init__.py +8 -0
  120. jiuwen_memory/memory_core/config/config.py +74 -0
  121. jiuwen_memory/memory_core/config/graph.py +94 -0
  122. jiuwen_memory/memory_core/external/__init__.py +15 -0
  123. jiuwen_memory/memory_core/external/agentarts_memory_provider.py +321 -0
  124. jiuwen_memory/memory_core/external/mem0_provider.py +303 -0
  125. jiuwen_memory/memory_core/external/openjiuwen_memory_provider.py +351 -0
  126. jiuwen_memory/memory_core/external/provider.py +53 -0
  127. jiuwen_memory/memory_core/graph/__init__.py +11 -0
  128. jiuwen_memory/memory_core/graph/extraction/__init__.py +7 -0
  129. jiuwen_memory/memory_core/graph/extraction/base.py +113 -0
  130. jiuwen_memory/memory_core/graph/extraction/custom_types.py +11 -0
  131. jiuwen_memory/memory_core/graph/extraction/entity_type_definition.py +56 -0
  132. jiuwen_memory/memory_core/graph/extraction/extraction_models.py +108 -0
  133. jiuwen_memory/memory_core/graph/extraction/extraction_prompts.py +290 -0
  134. jiuwen_memory/memory_core/graph/extraction/parse_response.py +93 -0
  135. jiuwen_memory/memory_core/graph/extraction/prompts/__init__.py +10 -0
  136. jiuwen_memory/memory_core/graph/extraction/prompts/cn/__init__.py +7 -0
  137. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_check_missing_cn.pr.md +12 -0
  138. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_conversation_cn.pr.md +37 -0
  139. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_dedupe_entity_cn.pr.md +23 -0
  140. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_dedupe_relation_cn.pr.md +33 -0
  141. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_document_cn.pr.md +38 -0
  142. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_entity_merge_cn.pr.md +40 -0
  143. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_json_cn.pr.md +30 -0
  144. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_relation_cn.pr.md +49 -0
  145. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_relation_filter_cn.pr.md +26 -0
  146. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_summary_create_cn.pr.md +39 -0
  147. jiuwen_memory/memory_core/graph/extraction/prompts/cn/entity_extraction_timezone_cn.pr.md +14 -0
  148. jiuwen_memory/memory_core/graph/extraction/prompts/cn/prompts.yaml +32 -0
  149. jiuwen_memory/memory_core/graph/extraction/prompts/en/__init__.py +7 -0
  150. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_check_missing_en.pr.md +12 -0
  151. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_conversation_en.pr.md +37 -0
  152. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_dedupe_entity_en.pr.md +23 -0
  153. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_dedupe_relation_en.pr.md +35 -0
  154. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_document_en.pr.md +38 -0
  155. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_entity_merge_en.pr.md +40 -0
  156. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_json_en.pr.md +30 -0
  157. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_relation_en.pr.md +49 -0
  158. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_relation_filter_en.pr.md +26 -0
  159. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_summary_create_en.pr.md +39 -0
  160. jiuwen_memory/memory_core/graph/extraction/prompts/en/entity_extraction_timezone_en.pr.md +14 -0
  161. jiuwen_memory/memory_core/graph/extraction/prompts/en/prompts.yaml +32 -0
  162. jiuwen_memory/memory_core/graph/extraction/prompts/entity_extraction/__init__.py +15 -0
  163. jiuwen_memory/memory_core/graph/extraction/prompts/entity_extraction/base.py +142 -0
  164. jiuwen_memory/memory_core/graph/extraction/prompts/entity_extraction/cn.py +91 -0
  165. jiuwen_memory/memory_core/graph/extraction/prompts/entity_extraction/en.py +96 -0
  166. jiuwen_memory/memory_core/graph/extraction/prompts/manager.py +109 -0
  167. jiuwen_memory/memory_core/graph/graph_memory/__init__.py +0 -0
  168. jiuwen_memory/memory_core/graph/graph_memory/base.py +1139 -0
  169. jiuwen_memory/memory_core/graph/graph_memory/local_storage/__init__.py +10 -0
  170. jiuwen_memory/memory_core/graph/graph_memory/parse_llm_response.py +282 -0
  171. jiuwen_memory/memory_core/graph/graph_memory/postprocess_graph_objects.py +190 -0
  172. jiuwen_memory/memory_core/graph/graph_memory/states.py +338 -0
  173. jiuwen_memory/memory_core/graph/graph_memory/utils.py +86 -0
  174. jiuwen_memory/memory_core/graph/graph_memory/validate_input.py +82 -0
  175. jiuwen_memory/memory_core/long_term_memory.py +2339 -0
  176. jiuwen_memory/memory_core/manage/__init__.py +0 -0
  177. jiuwen_memory/memory_core/manage/index/__init__.py +0 -0
  178. jiuwen_memory/memory_core/manage/index/base_memory_manager.py +155 -0
  179. jiuwen_memory/memory_core/manage/index/fragment_memory_manager.py +449 -0
  180. jiuwen_memory/memory_core/manage/index/middle_mem_manager.py +199 -0
  181. jiuwen_memory/memory_core/manage/index/summary_manager.py +230 -0
  182. jiuwen_memory/memory_core/manage/index/variable_manager.py +246 -0
  183. jiuwen_memory/memory_core/manage/index/write_manager.py +94 -0
  184. jiuwen_memory/memory_core/manage/mem_model/__init__.py +0 -0
  185. jiuwen_memory/memory_core/manage/mem_model/data_id_manager.py +17 -0
  186. jiuwen_memory/memory_core/manage/mem_model/db_model.py +110 -0
  187. jiuwen_memory/memory_core/manage/mem_model/memory_unit.py +66 -0
  188. jiuwen_memory/memory_core/manage/mem_model/message_manager.py +105 -0
  189. jiuwen_memory/memory_core/manage/mem_model/scope_user_mapping_manager.py +41 -0
  190. jiuwen_memory/memory_core/manage/mem_model/semantic_store.py +310 -0
  191. jiuwen_memory/memory_core/manage/mem_model/sql_db_store.py +226 -0
  192. jiuwen_memory/memory_core/manage/mem_model/sql_message_store.py +306 -0
  193. jiuwen_memory/memory_core/manage/mem_model/user_mem_store.py +260 -0
  194. jiuwen_memory/memory_core/manage/search/__init__.py +0 -0
  195. jiuwen_memory/memory_core/manage/search/search_manager.py +232 -0
  196. jiuwen_memory/memory_core/manage/update/__init__.py +0 -0
  197. jiuwen_memory/memory_core/manage/update/mem_update_checker.py +297 -0
  198. jiuwen_memory/memory_core/migration/__init__.py +0 -0
  199. jiuwen_memory/memory_core/migration/migration_plan.py +136 -0
  200. jiuwen_memory/memory_core/migration/migrator/__init__.py +0 -0
  201. jiuwen_memory/memory_core/migration/migrator/index_version_migrator.py +209 -0
  202. jiuwen_memory/memory_core/migration/migrator/kv_migrator.py +291 -0
  203. jiuwen_memory/memory_core/migration/migrator/memory_meta_manager.py +43 -0
  204. jiuwen_memory/memory_core/migration/migrator/message_migrator.py +233 -0
  205. jiuwen_memory/memory_core/migration/migrator/sql_migrator.py +338 -0
  206. jiuwen_memory/memory_core/migration/migrator/vector_migrator.py +98 -0
  207. jiuwen_memory/memory_core/migration/operation/__init__.py +0 -0
  208. jiuwen_memory/memory_core/migration/operation/base_operation.py +35 -0
  209. jiuwen_memory/memory_core/migration/operation/operation_registry.py +152 -0
  210. jiuwen_memory/memory_core/migration/operation/operations.py +206 -0
  211. jiuwen_memory/memory_core/migration/run_migrations.py +162 -0
  212. jiuwen_memory/memory_core/process/__init__.py +0 -0
  213. jiuwen_memory/memory_core/process/dreaming/__init__.py +27 -0
  214. jiuwen_memory/memory_core/process/dreaming/orchestrator.py +100 -0
  215. jiuwen_memory/memory_core/process/dreaming/source.py +108 -0
  216. jiuwen_memory/memory_core/process/dreaming/store.py +127 -0
  217. jiuwen_memory/memory_core/process/dreaming/sweeper.py +159 -0
  218. jiuwen_memory/memory_core/process/extract/__init__.py +0 -0
  219. jiuwen_memory/memory_core/process/extract/common.py +25 -0
  220. jiuwen_memory/memory_core/process/extract/generation.py +447 -0
  221. jiuwen_memory/memory_core/process/extract/long_term_memory_extractor.py +122 -0
  222. jiuwen_memory/memory_core/process/extract/memory_analyzer.py +139 -0
  223. jiuwen_memory/memory_core/process/refine/__init__.py +0 -0
  224. jiuwen_memory/memory_core/prompts/__init__.py +0 -0
  225. jiuwen_memory/memory_core/prompts/continuity_check_system_prompt.md +16 -0
  226. jiuwen_memory/memory_core/prompts/dreaming_extraction.md +23 -0
  227. jiuwen_memory/memory_core/prompts/fragment_memory_prompt.md +109 -0
  228. jiuwen_memory/memory_core/prompts/memory_analysis_prompt.md +61 -0
  229. jiuwen_memory/memory_core/prompts/memory_update_check.md +53 -0
  230. jiuwen_memory/memory_core/prompts/prompt_applier.py +131 -0
  231. jiuwen_memory/memory_core/prompts/semantic_validation.md +43 -0
  232. jiuwen_memory/retrieval/__init__.py +0 -0
  233. jiuwen_memory/retrieval/common/__init__.py +0 -0
  234. jiuwen_memory/retrieval/common/callbacks.py +61 -0
  235. jiuwen_memory/retrieval/common/config.py +81 -0
  236. jiuwen_memory/retrieval/embedding/__init__.py +0 -0
  237. jiuwen_memory/retrieval/embedding/api_embedding.py +358 -0
  238. jiuwen_memory/retrieval/embedding/base.py +11 -0
  239. jiuwen_memory/server/__init__.py +0 -0
  240. jiuwen_memory/server/memory_server.py +459 -0
  241. jiuwen_memory/server/store_factory.py +144 -0
  242. jiuwenmemory-0.1.0.dist-info/METADATA +545 -0
  243. jiuwenmemory-0.1.0.dist-info/RECORD +247 -0
  244. jiuwenmemory-0.1.0.dist-info/WHEEL +5 -0
  245. jiuwenmemory-0.1.0.dist-info/entry_points.txt +2 -0
  246. jiuwenmemory-0.1.0.dist-info/licenses/LICENSE +202 -0
  247. jiuwenmemory-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ # Copyright (c) Huawei Technologies Co., Ltd. 2025-2026. All rights reserved.
3
+
4
+ from importlib.metadata import PackageNotFoundError, version
5
+
6
+ try:
7
+ # Wheel installation should include package metadata
8
+ __version__ = version("JiuwenMemory")
9
+ except PackageNotFoundError:
10
+ # Only developer working with source code directly may not have package metadata
11
+ import tomllib
12
+ from pathlib import Path
13
+
14
+ __version__ = "unknown"
15
+ pyproject = Path(__file__).parents[1] / "pyproject.toml"
16
+ if pyproject.exists():
17
+ project_metadata = tomllib.loads(pyproject.read_text(encoding="utf-8")).get("project", {})
18
+ package_name = project_metadata.get("name")
19
+ version_parsed = project_metadata.get("version")
20
+ if package_name == "JiuwenMemory" and version_parsed:
21
+ __version__ = version_parsed
22
+
23
+ __all__ = ["__version__"]
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+ # Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
3
+ from jiuwen_memory.common.schema import Param
4
+ from jiuwen_memory.common.schema.card import BaseCard
5
+
6
+ _SCHEMA_CLASSES = [
7
+ "BaseCard",
8
+ "Param"
9
+ ]
10
+
11
+ __all__ = (
12
+ _SCHEMA_CLASSES
13
+ )
@@ -0,0 +1,6 @@
1
+ from jiuwen_memory.common.clients.client_registry import BaseClient, get_client_registry
2
+
3
+ __all__ = [
4
+ "get_client_registry",
5
+ "BaseClient",
6
+ ]
@@ -0,0 +1,238 @@
1
+ # coding: utf-8
2
+ # Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
3
+ from typing import Dict, List, Optional, Any, Callable, Type
4
+ from jiuwen_memory.common.logging import logger
5
+
6
+
7
+ class ClientRegistry:
8
+ """Registry for managing client classes and factories.
9
+
10
+ This class provides a central registry for client classes, their factories.
11
+ It supports both decorator-based and class-based registration.
12
+ """
13
+
14
+ def __init__(self):
15
+ """Initialize an empty registry."""
16
+ self._factories: Dict[str, Callable] = {}
17
+ self._client_classes: Dict[str, Type] = {}
18
+
19
+ def register_client(self, name: str, client_type: Optional[str] = "common"):
20
+ """Decorator to register client factory functions.
21
+
22
+ Args:
23
+ name: Primary name of the client.
24
+ client_type: Type category of the client (e.g., 'database', 'cache').
25
+
26
+ Returns:
27
+ Decorator function that registers the factory.
28
+
29
+
30
+ Raises:
31
+ ValueError: If the client name is already registered.
32
+
33
+ Example:
34
+ @registry.register_client('redis', client_type='cache')
35
+ def create_redis_client(**kwargs):
36
+ return RedisClient(**kwargs)
37
+ """
38
+
39
+ def decorator(factory_func: Callable) -> Callable:
40
+ full_name = f'{client_type}_{name}' if client_type else name
41
+
42
+ if full_name in self._factories:
43
+ raise ValueError(f"Client type '{full_name}' already registered")
44
+
45
+ self._factories[full_name] = factory_func
46
+ return factory_func
47
+
48
+ return decorator
49
+
50
+ def register_class(self, client_class: Type['BaseClient']) -> None:
51
+ """Register a client class.
52
+
53
+ Args:
54
+ client_class: The client class to register. Must have __client_name__
55
+ and __client_type__ attributes.
56
+
57
+ Raises:
58
+ ValueError: If the class doesn't define required attributes or if
59
+ the client name is already registered.
60
+
61
+ Example:
62
+ class MySQLClient(BaseClient):
63
+ __client_name__ = 'mysql'
64
+ __client_type__ = 'database'
65
+ """
66
+ if not hasattr(client_class, '__client_name__'):
67
+ raise ValueError(f"Client class {client_class.__name__} must define __client_name__")
68
+
69
+ if not hasattr(client_class, '__client_type__'):
70
+ raise ValueError(f"Client class {client_class.__name__} must define __client_type__")
71
+
72
+ names = client_class.__client_name__ if isinstance(client_class.__client_name__, list) else [
73
+ client_class.__client_name__]
74
+ client_type = client_class.__client_type__
75
+
76
+ if not client_type:
77
+ raise ValueError(f"Client class {client_class.__name__} __client_type__ cannot be empty, register failed")
78
+ for name in names:
79
+ full_name = f'{client_type}_{name}'
80
+
81
+ if full_name in self._factories or full_name in self._client_classes:
82
+ logger.warning(f"Client type '{full_name}' already registered")
83
+ return
84
+
85
+ # Store the client class
86
+ self._client_classes[full_name] = client_class
87
+
88
+ # Create factory function
89
+ def factory(**kwargs):
90
+ return client_class(**kwargs)
91
+
92
+ self._factories[full_name] = factory
93
+
94
+ def get_client(self, name: str, client_type: Optional[str] = "common", **kwargs) -> Any:
95
+ """Get a client instance.
96
+
97
+ Args:
98
+ name: Name of the client.
99
+ client_type: Optional type category to narrow down the search.
100
+ **kwargs: Additional arguments to pass to the client constructor.
101
+
102
+ Returns:
103
+ An instance of the requested client.
104
+
105
+ Raises:
106
+ ValueError: If the client name is empty or unknown.
107
+ RuntimeError: If client creation fails.
108
+
109
+ Example:
110
+ client = registry.get_client('mysql', client_type='database', host='localhost')
111
+ """
112
+ if not name:
113
+ raise ValueError("Client name cannot be empty")
114
+
115
+ lookup_name = name
116
+ if client_type:
117
+ full_name = f'{client_type}_{name}'
118
+ if full_name in self._factories:
119
+ lookup_name = full_name
120
+
121
+ factory = self._factories.get(lookup_name)
122
+ if not factory:
123
+ available = list(self._factories.keys())
124
+ search_key = f'{client_type}_{name}' if client_type else name
125
+ raise ValueError(f"Unknown client type: '{search_key}'. Available: {available}")
126
+
127
+ try:
128
+ return factory(**kwargs)
129
+ except Exception as e:
130
+ raise RuntimeError(f"Failed to create client '{lookup_name}': {e}") from e
131
+
132
+ def unregister(self, name: str, client_type: Optional[str] = None) -> None:
133
+ """Unregister a client.
134
+
135
+ Args:
136
+ name: Name of the client to unregister.
137
+ client_type: Optional type category of the client.
138
+
139
+ Raises:
140
+ ValueError: If the client is not registered.
141
+ """
142
+ full_name = f'{client_type}_{name}' if client_type else name
143
+
144
+ if full_name not in self._factories:
145
+ raise ValueError(f"Client type '{full_name}' not registered")
146
+
147
+ del self._factories[full_name]
148
+ self._client_classes.pop(full_name, None)
149
+
150
+ def list_clients(self) -> List[str]:
151
+ """List all registered clients.
152
+
153
+ Returns:
154
+ List of registered client full names.
155
+ """
156
+ return list(self._factories.keys())
157
+
158
+
159
+ _client_registry = ClientRegistry()
160
+
161
+
162
+ def get_client_registry():
163
+ return _client_registry
164
+
165
+
166
+ class BaseClient:
167
+ """Abstract base class for asynchronous clients.
168
+
169
+ This class serves as a template for creating client classes. Subclasses
170
+ must define __client_name__ and __client_type__ class attributes, and
171
+ implement all abstract methods.
172
+
173
+ Attributes:
174
+ __client_name__: Primary name of the client type.
175
+ __client_type__: Type category (e.g., 'database', 'cache', 'api').
176
+ config: Configuration dictionary passed during initialization.
177
+ """
178
+
179
+ __client_name__: str = None
180
+ __client_type__: str = "common"
181
+
182
+ def __init_subclass__(cls, **kwargs):
183
+ """Initialize subclass and register it if it's a client class.
184
+
185
+ This method is called whenever a class inherits from BaseClient.
186
+ It automatically registers any class that defines __client_name__
187
+ and __client_type__ attributes with the global client registry.
188
+
189
+ Args:
190
+ **kwargs: Additional keyword arguments passed to the subclass.
191
+ """
192
+ super().__init_subclass__(**kwargs)
193
+
194
+ # Skip registration for BaseClient itself (though this method won't be called for BaseClient)
195
+ # Check if client name and type are defined
196
+ if hasattr(cls, '__client_name__') and hasattr(cls, '__client_type__'):
197
+ # Automatically register with the global registry
198
+ if cls.__client_name__ is not None: # Ensure it's actually set
199
+ get_client_registry().register_class(cls)
200
+
201
+ def __init__(self, **kwargs):
202
+ """Initialize the client with configuration.
203
+
204
+ Args:
205
+ **kwargs: Configuration parameters for the client.
206
+ """
207
+ self.config = kwargs
208
+
209
+ async def close(self) -> bool:
210
+ """Asynchronously close connection to the service.
211
+
212
+ Returns:
213
+ True if disconnection successful, False otherwise.
214
+ """
215
+ pass
216
+
217
+ async def __aenter__(self):
218
+ """Async context manager entry point.
219
+
220
+ Automatically connects when entering the context.
221
+
222
+ Returns:
223
+ The client instance.
224
+ """
225
+
226
+ return self
227
+
228
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
229
+ """Async context manager exit point.
230
+
231
+ Automatically disconnects when exiting the context.
232
+
233
+ Args:
234
+ exc_type: Exception type if an exception was raised.
235
+ exc_val: Exception value if an exception was raised.
236
+ exc_tb: Exception traceback if an exception was raised.
237
+ """
238
+ await self.close()
File without changes