mcp-proxy-adapter 2.0.1__py3-none-any.whl → 6.9.50__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.

Potentially problematic release.


This version of mcp-proxy-adapter might be problematic. Click here for more details.

Files changed (269) hide show
  1. mcp_proxy_adapter/__init__.py +47 -0
  2. mcp_proxy_adapter/__main__.py +13 -0
  3. mcp_proxy_adapter/api/__init__.py +0 -0
  4. mcp_proxy_adapter/api/app.py +66 -0
  5. mcp_proxy_adapter/api/core/__init__.py +18 -0
  6. mcp_proxy_adapter/api/core/app_factory.py +400 -0
  7. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  8. mcp_proxy_adapter/api/core/registration_context.py +356 -0
  9. mcp_proxy_adapter/api/core/registration_manager.py +307 -0
  10. mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
  11. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  12. mcp_proxy_adapter/api/handlers.py +181 -0
  13. mcp_proxy_adapter/api/middleware/__init__.py +21 -0
  14. mcp_proxy_adapter/api/middleware/base.py +54 -0
  15. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
  16. mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
  17. mcp_proxy_adapter/api/middleware/factory.py +147 -0
  18. mcp_proxy_adapter/api/middleware/logging.py +31 -0
  19. mcp_proxy_adapter/api/middleware/performance.py +51 -0
  20. mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
  21. mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
  22. mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
  23. mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
  24. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  25. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  26. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  27. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  28. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  29. mcp_proxy_adapter/api/schemas.py +270 -0
  30. mcp_proxy_adapter/api/tool_integration.py +131 -0
  31. mcp_proxy_adapter/api/tools.py +163 -0
  32. mcp_proxy_adapter/cli/__init__.py +12 -0
  33. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  34. mcp_proxy_adapter/cli/commands/client.py +100 -0
  35. mcp_proxy_adapter/cli/commands/config_generate.py +105 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +94 -0
  37. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  38. mcp_proxy_adapter/cli/commands/server.py +174 -0
  39. mcp_proxy_adapter/cli/commands/sets.py +132 -0
  40. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  41. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  42. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  43. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  44. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  45. mcp_proxy_adapter/cli/main.py +63 -0
  46. mcp_proxy_adapter/cli/parser.py +338 -0
  47. mcp_proxy_adapter/cli/validators.py +231 -0
  48. mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
  49. mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
  50. mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
  51. mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
  52. mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
  53. mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
  54. mcp_proxy_adapter/client/proxy.py +123 -0
  55. mcp_proxy_adapter/commands/__init__.py +66 -0
  56. mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
  57. mcp_proxy_adapter/commands/base.py +389 -0
  58. mcp_proxy_adapter/commands/builtin_commands.py +30 -0
  59. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  60. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  61. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  62. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  63. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  64. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  65. mcp_proxy_adapter/commands/catalog_manager.py +97 -0
  66. mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
  67. mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
  68. mcp_proxy_adapter/commands/command_registry.py +298 -0
  69. mcp_proxy_adapter/commands/config_command.py +102 -0
  70. mcp_proxy_adapter/commands/dependency_container.py +40 -0
  71. mcp_proxy_adapter/commands/dependency_manager.py +143 -0
  72. mcp_proxy_adapter/commands/echo_command.py +48 -0
  73. mcp_proxy_adapter/commands/health_command.py +142 -0
  74. mcp_proxy_adapter/commands/help_command.py +175 -0
  75. mcp_proxy_adapter/commands/hooks.py +172 -0
  76. mcp_proxy_adapter/commands/key_management_command.py +484 -0
  77. mcp_proxy_adapter/commands/load_command.py +123 -0
  78. mcp_proxy_adapter/commands/plugins_command.py +246 -0
  79. mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
  80. mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
  81. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  82. mcp_proxy_adapter/commands/registration_status_command.py +76 -0
  83. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  84. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  85. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  86. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  87. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  88. mcp_proxy_adapter/commands/reload_command.py +136 -0
  89. mcp_proxy_adapter/commands/result.py +157 -0
  90. mcp_proxy_adapter/commands/role_test_command.py +99 -0
  91. mcp_proxy_adapter/commands/roles_management_command.py +502 -0
  92. mcp_proxy_adapter/commands/security_command.py +472 -0
  93. mcp_proxy_adapter/commands/settings_command.py +113 -0
  94. mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
  95. mcp_proxy_adapter/commands/token_management_command.py +500 -0
  96. mcp_proxy_adapter/commands/transport_management_command.py +129 -0
  97. mcp_proxy_adapter/commands/unload_command.py +92 -0
  98. mcp_proxy_adapter/config.py +32 -0
  99. mcp_proxy_adapter/core/__init__.py +8 -0
  100. mcp_proxy_adapter/core/app_factory.py +560 -0
  101. mcp_proxy_adapter/core/app_runner.py +318 -0
  102. mcp_proxy_adapter/core/auth_validator.py +508 -0
  103. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  104. mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
  105. mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
  106. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  107. mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
  108. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
  109. mcp_proxy_adapter/core/certificate_utils.py +249 -0
  110. mcp_proxy_adapter/core/client.py +608 -0
  111. mcp_proxy_adapter/core/client_manager.py +271 -0
  112. mcp_proxy_adapter/core/client_security.py +411 -0
  113. mcp_proxy_adapter/core/config/__init__.py +18 -0
  114. mcp_proxy_adapter/core/config/config.py +237 -0
  115. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  116. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  117. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  118. mcp_proxy_adapter/core/config/simple_config.py +204 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
  121. mcp_proxy_adapter/core/config_converter.py +252 -0
  122. mcp_proxy_adapter/core/config_validator.py +211 -0
  123. mcp_proxy_adapter/core/crl_utils.py +362 -0
  124. mcp_proxy_adapter/core/errors.py +276 -0
  125. mcp_proxy_adapter/core/job_manager.py +54 -0
  126. mcp_proxy_adapter/core/logging.py +250 -0
  127. mcp_proxy_adapter/core/mtls_asgi.py +140 -0
  128. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  129. mcp_proxy_adapter/core/mtls_proxy.py +229 -0
  130. mcp_proxy_adapter/core/mtls_server.py +154 -0
  131. mcp_proxy_adapter/core/protocol_manager.py +232 -0
  132. mcp_proxy_adapter/core/proxy/__init__.py +19 -0
  133. mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
  134. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
  135. mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
  136. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  137. mcp_proxy_adapter/core/proxy_client.py +184 -0
  138. mcp_proxy_adapter/core/proxy_registration.py +80 -0
  139. mcp_proxy_adapter/core/role_utils.py +103 -0
  140. mcp_proxy_adapter/core/security_adapter.py +343 -0
  141. mcp_proxy_adapter/core/security_factory.py +96 -0
  142. mcp_proxy_adapter/core/security_integration.py +342 -0
  143. mcp_proxy_adapter/core/server_adapter.py +251 -0
  144. mcp_proxy_adapter/core/server_engine.py +217 -0
  145. mcp_proxy_adapter/core/settings.py +260 -0
  146. mcp_proxy_adapter/core/signal_handler.py +107 -0
  147. mcp_proxy_adapter/core/ssl_utils.py +161 -0
  148. mcp_proxy_adapter/core/transport_manager.py +153 -0
  149. mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
  150. mcp_proxy_adapter/core/utils.py +101 -0
  151. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  152. mcp_proxy_adapter/core/validation/config_validator.py +219 -0
  153. mcp_proxy_adapter/core/validation/file_validator.py +131 -0
  154. mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
  155. mcp_proxy_adapter/core/validation/security_validator.py +140 -0
  156. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  157. mcp_proxy_adapter/custom_openapi.py +58 -0
  158. mcp_proxy_adapter/examples/__init__.py +16 -0
  159. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  160. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  161. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  162. mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
  163. mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
  164. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  165. mcp_proxy_adapter/examples/check_config.py +413 -0
  166. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  167. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  168. mcp_proxy_adapter/examples/config_builder.py +234 -0
  169. mcp_proxy_adapter/examples/config_cli.py +282 -0
  170. mcp_proxy_adapter/examples/create_test_configs.py +174 -0
  171. mcp_proxy_adapter/examples/debug_request_state.py +130 -0
  172. mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
  173. mcp_proxy_adapter/examples/demo_client.py +287 -0
  174. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  175. mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
  176. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
  177. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
  178. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
  179. mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
  180. mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
  181. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
  182. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
  183. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
  184. mcp_proxy_adapter/examples/full_application/main.py +311 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
  186. mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
  187. mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
  188. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
  189. mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
  190. mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
  191. mcp_proxy_adapter/examples/generate_config.py +502 -0
  192. mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
  193. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  194. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  195. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  196. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  197. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  198. mcp_proxy_adapter/examples/required_certificates.py +208 -0
  199. mcp_proxy_adapter/examples/run_example.py +77 -0
  200. mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
  201. mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
  202. mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
  203. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  204. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  205. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  206. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  207. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  208. mcp_proxy_adapter/examples/security_test_client.py +72 -0
  209. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  210. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  211. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  212. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  213. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  214. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  215. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  216. mcp_proxy_adapter/examples/setup_test_environment.py +235 -0
  217. mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
  218. mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
  219. mcp_proxy_adapter/examples/test_config.py +205 -0
  220. mcp_proxy_adapter/examples/test_config_builder.py +110 -0
  221. mcp_proxy_adapter/examples/test_examples.py +308 -0
  222. mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
  223. mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
  224. mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
  225. mcp_proxy_adapter/examples/universal_client.py +674 -0
  226. mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
  227. mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
  228. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
  229. mcp_proxy_adapter/integrations/__init__.py +25 -0
  230. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  231. mcp_proxy_adapter/main.py +311 -0
  232. mcp_proxy_adapter/openapi.py +375 -0
  233. mcp_proxy_adapter/schemas/base_schema.json +114 -0
  234. mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
  235. mcp_proxy_adapter/schemas/roles.json +37 -0
  236. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  237. mcp_proxy_adapter/version.py +5 -0
  238. mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
  239. mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
  240. {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
  241. mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
  242. mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
  243. adapters/__init__.py +0 -16
  244. analyzers/__init__.py +0 -14
  245. analyzers/docstring_analyzer.py +0 -199
  246. analyzers/type_analyzer.py +0 -151
  247. cli/__init__.py +0 -12
  248. cli/__main__.py +0 -79
  249. cli/command_runner.py +0 -233
  250. dispatchers/__init__.py +0 -14
  251. dispatchers/base_dispatcher.py +0 -85
  252. dispatchers/json_rpc_dispatcher.py +0 -198
  253. generators/__init__.py +0 -14
  254. generators/endpoint_generator.py +0 -172
  255. generators/openapi_generator.py +0 -254
  256. generators/rest_api_generator.py +0 -207
  257. mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
  258. mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
  259. mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
  260. mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
  261. openapi_schema/__init__.py +0 -38
  262. openapi_schema/command_registry.py +0 -312
  263. openapi_schema/rest_schema.py +0 -510
  264. openapi_schema/rpc_generator.py +0 -307
  265. openapi_schema/rpc_schema.py +0 -416
  266. validators/__init__.py +0 -14
  267. validators/base_validator.py +0 -23
  268. validators/docstring_validator.py +0 -75
  269. validators/metadata_validator.py +0 -76
@@ -1,151 +0,0 @@
1
- """
2
- Type analyzer for extracting information from function type annotations.
3
- """
4
- import inspect
5
- from typing import Dict, Any, List, Optional, Callable, Union, get_origin, get_args, get_type_hints
6
-
7
- class TypeAnalyzer:
8
- """
9
- Type analyzer for extracting information from function type annotations.
10
-
11
- This class is responsible for analyzing type annotations of command handler functions
12
- and converting them to JSON Schema/OpenAPI type format.
13
- """
14
-
15
- def __init__(self):
16
- # Mapping Python types to OpenAPI types
17
- self.type_map = {
18
- str: "string",
19
- int: "integer",
20
- float: "number",
21
- bool: "boolean",
22
- list: "array",
23
- dict: "object",
24
- Any: "object",
25
- None: "null",
26
- }
27
-
28
- def analyze(self, handler: Callable) -> Dict[str, Any]:
29
- """
30
- Analyzes function type annotations and returns metadata.
31
-
32
- Args:
33
- handler: Handler function to analyze
34
-
35
- Returns:
36
- Dict[str, Any]: Metadata about parameter types and return value
37
- """
38
- result = {
39
- "parameters": {},
40
- "returns": None
41
- }
42
-
43
- # Get function signature
44
- sig = inspect.signature(handler)
45
-
46
- # Get type annotations
47
- type_hints = self._get_type_hints(handler)
48
-
49
- # Analyze parameters
50
- for param_name, param in sig.parameters.items():
51
- # Skip self for methods
52
- if param_name == 'self':
53
- continue
54
-
55
- # If parameter is named params, assume it's a dictionary of all parameters
56
- if param_name == 'params':
57
- continue
58
-
59
- # Determine if parameter is required
60
- required = param.default == inspect.Parameter.empty
61
-
62
- # Determine parameter type
63
- param_type = "object" # Default type
64
-
65
- if param_name in type_hints:
66
- param_type = self._map_type_to_openapi(type_hints[param_name])
67
-
68
- # Create parameter metadata
69
- param_metadata = {
70
- "type": param_type,
71
- "required": required
72
- }
73
-
74
- # Add default value if exists
75
- if param.default != inspect.Parameter.empty:
76
- # Some default values cannot be serialized to JSON
77
- # So we convert them to string representation for such cases
78
- if param.default is None or isinstance(param.default, (str, int, float, bool, list, dict)):
79
- param_metadata["default"] = param.default
80
-
81
- # Add parameter to metadata
82
- result["parameters"][param_name] = param_metadata
83
-
84
- # Analyze return value
85
- if 'return' in type_hints:
86
- result["returns"] = self._map_type_to_openapi(type_hints['return'])
87
-
88
- return result
89
-
90
- def _get_type_hints(self, handler: Callable) -> Dict[str, Any]:
91
- """
92
- Gets type annotations of a function.
93
-
94
- Args:
95
- handler: Handler function
96
-
97
- Returns:
98
- Dict[str, Any]: Type annotations
99
- """
100
- try:
101
- return get_type_hints(handler)
102
- except Exception:
103
- # If failed to get annotations via get_type_hints,
104
- # extract them manually from __annotations__
105
- return getattr(handler, "__annotations__", {})
106
-
107
- def _map_type_to_openapi(self, type_hint: Any) -> Union[str, Dict[str, Any]]:
108
- """
109
- Converts Python type to OpenAPI type.
110
-
111
- Args:
112
- type_hint: Python type
113
-
114
- Returns:
115
- Union[str, Dict[str, Any]]: OpenAPI type string representation or schema
116
- """
117
- # Check for None
118
- if type_hint is None:
119
- return "null"
120
-
121
- # Handle primitive types
122
- if type_hint in self.type_map:
123
- return self.type_map[type_hint]
124
-
125
- # Check for generic types
126
- origin = get_origin(type_hint)
127
- if origin is not None:
128
- # Handle List[X], Dict[X, Y], etc.
129
- if origin in (list, List):
130
- args = get_args(type_hint)
131
- if args:
132
- item_type = self._map_type_to_openapi(args[0])
133
- return {
134
- "type": "array",
135
- "items": item_type if isinstance(item_type, dict) else {"type": item_type}
136
- }
137
- return "array"
138
- elif origin in (dict, Dict):
139
- # For dict we just return object, as OpenAPI
140
- # doesn't have a direct equivalent for Dict[X, Y]
141
- return "object"
142
- elif origin is Union:
143
- # For Union we take the first type that is not None
144
- args = get_args(type_hint)
145
- for arg in args:
146
- if arg is not type(None):
147
- return self._map_type_to_openapi(arg)
148
- return "object"
149
-
150
- # Default to object
151
- return "object"
cli/__init__.py DELETED
@@ -1,12 +0,0 @@
1
- """
2
- Командный интерфейс для запуска команд из командной строки.
3
-
4
- Этот модуль предоставляет инструменты для создания командной строки
5
- на основе зарегистрированных команд.
6
- """
7
-
8
- from command_registry.cli.command_runner import CommandRunner
9
-
10
- __all__ = [
11
- 'CommandRunner',
12
- ]
cli/__main__.py DELETED
@@ -1,79 +0,0 @@
1
- #!/usr/bin/env python
2
- """
3
- Entry point for the command registry CLI interface.
4
-
5
- This module allows running commands from the command line
6
- using the command dispatcher.
7
-
8
- Usage:
9
- python -m command_registry.cli [command] [args...]
10
- """
11
-
12
- import os
13
- import sys
14
- import importlib.util
15
- from typing import Optional
16
-
17
- from command_registry.cli.command_runner import CommandRunner
18
- from command_registry.dispatchers.base_dispatcher import BaseDispatcher
19
- from command_registry.dispatchers.command_dispatcher import CommandDispatcher
20
-
21
-
22
- def find_dispatcher() -> BaseDispatcher:
23
- """
24
- Finds and creates command dispatcher.
25
-
26
- Search order:
27
- 1. Checks DISPATCHER_MODULE environment variable
28
- 2. Looks for app.py in current directory
29
- 3. Creates new CommandDispatcher
30
-
31
- Returns:
32
- BaseDispatcher: Command dispatcher
33
- """
34
- # Check environment variable
35
- dispatcher_module = os.environ.get("DISPATCHER_MODULE")
36
- if dispatcher_module:
37
- try:
38
- module_path, attr_name = dispatcher_module.rsplit(":", 1)
39
- module = importlib.import_module(module_path)
40
- return getattr(module, attr_name)
41
- except (ValueError, ImportError, AttributeError) as e:
42
- print(f"Failed to load dispatcher from {dispatcher_module}: {e}",
43
- file=sys.stderr)
44
-
45
- # Check app.py file
46
- app_path = os.path.join(os.getcwd(), "app.py")
47
- if os.path.exists(app_path):
48
- try:
49
- spec = importlib.util.spec_from_file_location("app", app_path)
50
- if spec and spec.loader:
51
- app = importlib.util.module_from_spec(spec)
52
- spec.loader.exec_module(app)
53
-
54
- # Look for dispatcher in module
55
- dispatcher = getattr(app, "dispatcher", None)
56
- if dispatcher and isinstance(dispatcher, BaseDispatcher):
57
- return dispatcher
58
- except Exception as e:
59
- print(f"Failed to load dispatcher from app.py: {e}",
60
- file=sys.stderr)
61
-
62
- # Create new dispatcher if not found
63
- return CommandDispatcher()
64
-
65
-
66
- def main() -> None:
67
- """
68
- Main function for running CLI interface.
69
- """
70
- # Get dispatcher
71
- dispatcher = find_dispatcher()
72
-
73
- # Create and run CommandRunner
74
- runner = CommandRunner(dispatcher)
75
- runner.run(sys.argv[1:])
76
-
77
-
78
- if __name__ == "__main__":
79
- main()
cli/command_runner.py DELETED
@@ -1,233 +0,0 @@
1
- """
2
- Command line utility for executing commands.
3
-
4
- Provides a command line interface for the command dispatcher,
5
- allowing execution of registered commands and getting help information.
6
- """
7
-
8
- import argparse
9
- import json
10
- import sys
11
- from typing import Any, Dict, List, Optional, Sequence
12
-
13
- from command_registry.dispatchers.base_dispatcher import BaseDispatcher
14
-
15
-
16
- class CommandRunner:
17
- """
18
- Command line utility for executing commands.
19
-
20
- Converts command line arguments into dispatcher command calls.
21
- Provides ability to get help information about commands.
22
- """
23
-
24
- def __init__(self, dispatcher: BaseDispatcher):
25
- """
26
- Initializes CommandRunner.
27
-
28
- Args:
29
- dispatcher: Command dispatcher for executing commands
30
- """
31
- self.dispatcher = dispatcher
32
-
33
- def build_parser(self) -> argparse.ArgumentParser:
34
- """
35
- Creates argument parser based on registered commands.
36
-
37
- Returns:
38
- Command line argument parser
39
- """
40
- parser = argparse.ArgumentParser(
41
- description="Execute commands from command registry",
42
- add_help=False, # Disable standard help
43
- )
44
-
45
- # Add main arguments
46
- parser.add_argument(
47
- "command",
48
- help="Command name to execute or 'help' to get list of commands",
49
- nargs="?",
50
- default="help",
51
- )
52
-
53
- parser.add_argument(
54
- "--help", "-h",
55
- action="store_true",
56
- help="Show help for specified command",
57
- dest="show_help",
58
- )
59
-
60
- parser.add_argument(
61
- "--json",
62
- action="store_true",
63
- help="Output result in JSON format",
64
- )
65
-
66
- return parser
67
-
68
- def _handle_help_command(self, args: Optional[List[str]] = None) -> None:
69
- """
70
- Outputs help information about available commands.
71
-
72
- Args:
73
- args: List of arguments, if first argument is command name,
74
- outputs help for that command
75
- """
76
- if args and len(args) > 0 and args[0] != "help":
77
- # Help for specific command
78
- command_name = args[0]
79
- if command_name not in self.dispatcher.get_valid_commands():
80
- print(f"Unknown command: {command_name}", file=sys.stderr)
81
- return
82
-
83
- info = self.dispatcher.get_command_info(command_name)
84
-
85
- print(f"\nCommand: {command_name}\n")
86
-
87
- if info.get("description"):
88
- print(f"Description: {info['description']}\n")
89
-
90
- if "parameters" in info and info["parameters"]:
91
- print("Parameters:")
92
- for name, param_info in info["parameters"].items():
93
- param_type = param_info.get("type", "any")
94
- required = param_info.get("required", False)
95
- description = param_info.get("description", "")
96
-
97
- req_str = " (required)" if required else ""
98
- print(f" {name} ({param_type}){req_str}")
99
- if description:
100
- print(f" {description}")
101
- print()
102
-
103
- if "returns" in info and info["returns"]:
104
- print(f"Returns: {info['returns']}")
105
-
106
- print("\nUsage:")
107
- params_str = " ".join(
108
- f"--{name}=<value>" for name in info.get("parameters", {})
109
- )
110
- print(f" python -m command_registry.cli {command_name} {params_str}")
111
- else:
112
- # General help
113
- commands = self.dispatcher.get_commands_info()
114
-
115
- print("\nAvailable commands:\n")
116
- for name, info in commands.items():
117
- description = info.get("description", "No description")
118
- # Show only first line of description for brevity
119
- short_desc = description.split("\n")[0]
120
- print(f" {name:<20} {short_desc}")
121
-
122
- print("\nTo get detailed information about a command use:")
123
- print(" python -m command_registry.cli help <command>")
124
- print(" python -m command_registry.cli <command> --help")
125
-
126
- def run(self, args: Sequence[str]) -> None:
127
- """
128
- Runs command based on provided arguments.
129
-
130
- Args:
131
- args: Command line arguments (without program name)
132
- """
133
- parser = self.build_parser()
134
-
135
- # Parse arguments
136
- parsed_args, remaining = parser.parse_known_args(args)
137
-
138
- # Handle help command or --help flag
139
- if parsed_args.command == "help" or parsed_args.show_help:
140
- if parsed_args.command == "help":
141
- self._handle_help_command(remaining)
142
- else:
143
- self._handle_help_command([parsed_args.command])
144
- return
145
-
146
- # Check command existence
147
- if parsed_args.command not in self.dispatcher.get_valid_commands():
148
- print(f"Unknown command: {parsed_args.command}", file=sys.stderr)
149
- print("Use 'help' to get list of available commands", file=sys.stderr)
150
- sys.exit(1)
151
-
152
- # Convert remaining arguments to command parameters
153
- command_params = {}
154
- command_info = self.dispatcher.get_command_info(parsed_args.command)
155
- expected_params = command_info.get("parameters", {})
156
-
157
- # Parse parameters from remaining arguments
158
- i = 0
159
- while i < len(remaining):
160
- arg = remaining[i]
161
-
162
- # Support --param=value format
163
- if arg.startswith("--") and "=" in arg:
164
- param_name, value = arg[2:].split("=", 1)
165
- command_params[param_name] = self._parse_value(value)
166
- i += 1
167
- # Support --param value format
168
- elif arg.startswith("--"):
169
- param_name = arg[2:]
170
- if i + 1 < len(remaining) and not remaining[i + 1].startswith("--"):
171
- command_params[param_name] = self._parse_value(remaining[i + 1])
172
- i += 2
173
- else:
174
- # Boolean flag
175
- command_params[param_name] = True
176
- i += 1
177
- else:
178
- print(f"Unknown argument: {arg}", file=sys.stderr)
179
- i += 1
180
-
181
- # Check required parameters
182
- for param_name, param_info in expected_params.items():
183
- if param_info.get("required", False) and param_name not in command_params:
184
- print(f"Missing required parameter: {param_name}", file=sys.stderr)
185
- sys.exit(1)
186
-
187
- try:
188
- # Execute command
189
- result = self.dispatcher.execute(parsed_args.command, **command_params)
190
-
191
- # Output result
192
- if parsed_args.json:
193
- print(json.dumps(result, ensure_ascii=False, indent=2))
194
- elif result is not None:
195
- print(result)
196
- except Exception as e:
197
- print(f"Error executing command: {e}", file=sys.stderr)
198
- sys.exit(1)
199
-
200
- def _parse_value(self, value_str: str) -> Any:
201
- """
202
- Parses string value into corresponding type.
203
-
204
- Args:
205
- value_str: String representation of value
206
-
207
- Returns:
208
- Parsed value of corresponding type
209
- """
210
- # Boolean values
211
- if value_str.lower() in ("true", "yes", "y", "1"):
212
- return True
213
- if value_str.lower() in ("false", "no", "n", "0"):
214
- return False
215
-
216
- # Numbers
217
- try:
218
- if "." in value_str:
219
- return float(value_str)
220
- return int(value_str)
221
- except ValueError:
222
- pass
223
-
224
- # JSON
225
- if (value_str.startswith("{") and value_str.endswith("}")) or \
226
- (value_str.startswith("[") and value_str.endswith("]")):
227
- try:
228
- return json.loads(value_str)
229
- except json.JSONDecodeError:
230
- pass
231
-
232
- # Default - string
233
- return value_str
dispatchers/__init__.py DELETED
@@ -1,14 +0,0 @@
1
- """
2
- Command dispatchers for registering and executing commands.
3
-
4
- This module contains base classes and implementations of command dispatchers
5
- that are responsible for registering and executing commands.
6
- """
7
-
8
- from .base_dispatcher import BaseDispatcher
9
- from .json_rpc_dispatcher import JsonRpcDispatcher
10
-
11
- __all__ = [
12
- 'BaseDispatcher',
13
- 'JsonRpcDispatcher',
14
- ]
@@ -1,85 +0,0 @@
1
- """
2
- Base command dispatcher class.
3
- """
4
- from abc import ABC, abstractmethod
5
- from typing import Dict, Any, Callable, List, Optional
6
-
7
- class BaseDispatcher(ABC):
8
- """
9
- Abstract base class for command dispatchers.
10
-
11
- Defines the interface that all command dispatchers must implement.
12
- Dispatchers are responsible for registering and executing commands.
13
- """
14
-
15
- @abstractmethod
16
- def register_handler(
17
- self,
18
- command: str,
19
- handler: Callable,
20
- description: str = "",
21
- summary: str = "",
22
- params: Dict[str, Any] = None
23
- ) -> None:
24
- """
25
- Registers a command handler.
26
-
27
- Args:
28
- command: Command name
29
- handler: Command handler function
30
- description: Command description
31
- summary: Brief command summary
32
- params: Command parameters description
33
- """
34
- pass
35
-
36
- @abstractmethod
37
- def execute(self, command: str, **kwargs) -> Any:
38
- """
39
- Executes a command with the specified parameters.
40
-
41
- Args:
42
- command: Command name
43
- **kwargs: Command parameters
44
-
45
- Returns:
46
- Any: Command execution result
47
-
48
- Raises:
49
- CommandNotFoundError: If command is not found
50
- CommandExecutionError: On command execution error
51
- """
52
- pass
53
-
54
- @abstractmethod
55
- def get_valid_commands(self) -> List[str]:
56
- """
57
- Returns a list of all registered command names.
58
-
59
- Returns:
60
- List[str]: List of command names
61
- """
62
- pass
63
-
64
- @abstractmethod
65
- def get_command_info(self, command: str) -> Optional[Dict[str, Any]]:
66
- """
67
- Returns information about a command.
68
-
69
- Args:
70
- command: Command name
71
-
72
- Returns:
73
- Optional[Dict[str, Any]]: Command information or None if command not found
74
- """
75
- pass
76
-
77
- @abstractmethod
78
- def get_commands_info(self) -> Dict[str, Dict[str, Any]]:
79
- """
80
- Returns information about all registered commands.
81
-
82
- Returns:
83
- Dict[str, Dict[str, Any]]: Dictionary {command_name: information}
84
- """
85
- pass