mcp-proxy-adapter 2.1.0__py3-none-any.whl → 2.1.2__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.
- docs/README.md +172 -0
- docs/README_ru.md +172 -0
- docs/architecture.md +251 -0
- docs/architecture_ru.md +343 -0
- docs/command_development.md +250 -0
- docs/command_development_ru.md +593 -0
- docs/deployment.md +251 -0
- docs/deployment_ru.md +1298 -0
- docs/examples.md +254 -0
- docs/examples_ru.md +401 -0
- docs/mcp_proxy_adapter.md +251 -0
- docs/mcp_proxy_adapter_ru.md +405 -0
- docs/quickstart.md +251 -0
- docs/quickstart_ru.md +397 -0
- docs/testing.md +255 -0
- docs/testing_ru.md +469 -0
- docs/validation_ru.md +287 -0
- examples/analyze_config.py +141 -0
- examples/basic_integration.py +161 -0
- examples/docstring_and_schema_example.py +60 -0
- examples/extension_example.py +60 -0
- examples/help_best_practices.py +67 -0
- examples/help_usage.py +64 -0
- examples/mcp_proxy_client.py +131 -0
- examples/mcp_proxy_config.json +175 -0
- examples/openapi_server.py +369 -0
- examples/project_structure_example.py +47 -0
- examples/testing_example.py +53 -0
- mcp_proxy_adapter/__init__.py +17 -0
- mcp_proxy_adapter/adapter.py +697 -0
- mcp_proxy_adapter/models.py +47 -0
- mcp_proxy_adapter/registry.py +439 -0
- mcp_proxy_adapter/schema.py +257 -0
- {mcp_proxy_adapter-2.1.0.dist-info → mcp_proxy_adapter-2.1.2.dist-info}/METADATA +2 -2
- mcp_proxy_adapter-2.1.2.dist-info/RECORD +61 -0
- mcp_proxy_adapter-2.1.2.dist-info/top_level.txt +5 -0
- scripts/code_analyzer/code_analyzer.py +328 -0
- scripts/code_analyzer/register_commands.py +446 -0
- scripts/publish.py +85 -0
- tests/conftest.py +12 -0
- tests/test_adapter.py +529 -0
- tests/test_adapter_coverage.py +274 -0
- tests/test_basic_dispatcher.py +169 -0
- tests/test_command_registry.py +328 -0
- tests/test_examples.py +32 -0
- tests/test_mcp_proxy_adapter.py +568 -0
- tests/test_mcp_proxy_adapter_basic.py +262 -0
- tests/test_part1.py +348 -0
- tests/test_part2.py +524 -0
- tests/test_schema.py +358 -0
- tests/test_simple_adapter.py +251 -0
- adapters/__init__.py +0 -16
- cli/__init__.py +0 -12
- cli/__main__.py +0 -79
- cli/command_runner.py +0 -233
- generators/__init__.py +0 -14
- generators/endpoint_generator.py +0 -172
- generators/openapi_generator.py +0 -254
- generators/rest_api_generator.py +0 -207
- mcp_proxy_adapter-2.1.0.dist-info/RECORD +0 -28
- mcp_proxy_adapter-2.1.0.dist-info/top_level.txt +0 -7
- openapi_schema/__init__.py +0 -38
- openapi_schema/command_registry.py +0 -312
- openapi_schema/rest_schema.py +0 -510
- openapi_schema/rpc_generator.py +0 -307
- openapi_schema/rpc_schema.py +0 -416
- validators/__init__.py +0 -14
- validators/base_validator.py +0 -23
- {analyzers → mcp_proxy_adapter/analyzers}/__init__.py +0 -0
- {analyzers → mcp_proxy_adapter/analyzers}/docstring_analyzer.py +0 -0
- {analyzers → mcp_proxy_adapter/analyzers}/type_analyzer.py +0 -0
- {dispatchers → mcp_proxy_adapter/dispatchers}/__init__.py +0 -0
- {dispatchers → mcp_proxy_adapter/dispatchers}/base_dispatcher.py +0 -0
- {dispatchers → mcp_proxy_adapter/dispatchers}/json_rpc_dispatcher.py +0 -0
- {validators → mcp_proxy_adapter/validators}/docstring_validator.py +0 -0
- {validators → mcp_proxy_adapter/validators}/metadata_validator.py +0 -0
- {mcp_proxy_adapter-2.1.0.dist-info → mcp_proxy_adapter-2.1.2.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-2.1.0.dist-info → mcp_proxy_adapter-2.1.2.dist-info}/licenses/LICENSE +0 -0
docs/quickstart.md
ADDED
@@ -0,0 +1,251 @@
|
|
1
|
+
# Command Registry Quick Start
|
2
|
+
|
3
|
+
This guide will help you quickly get started with the Command Registry system and integrate it into your application.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install the package using pip:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
pip install command-registry
|
11
|
+
```
|
12
|
+
|
13
|
+
## Basic Usage
|
14
|
+
|
15
|
+
### 1. Defining a Command
|
16
|
+
|
17
|
+
Create a `commands.py` file with your commands:
|
18
|
+
|
19
|
+
```python
|
20
|
+
from typing import List, Dict, Any, Optional
|
21
|
+
|
22
|
+
def add_item(
|
23
|
+
item_name: str,
|
24
|
+
quantity: int = 1,
|
25
|
+
properties: Optional[Dict[str, Any]] = None
|
26
|
+
) -> Dict[str, Any]:
|
27
|
+
"""
|
28
|
+
Adds a new item to the system.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
item_name: Name of the item
|
32
|
+
quantity: Item quantity (default 1)
|
33
|
+
properties: Additional item properties
|
34
|
+
|
35
|
+
Returns:
|
36
|
+
Information about the created item
|
37
|
+
"""
|
38
|
+
# In a real application, this would be code for
|
39
|
+
# saving the item to a database
|
40
|
+
item_id = "item_" + str(hash(item_name))
|
41
|
+
item = {
|
42
|
+
"id": item_id,
|
43
|
+
"name": item_name,
|
44
|
+
"quantity": quantity,
|
45
|
+
"properties": properties or {}
|
46
|
+
}
|
47
|
+
return item
|
48
|
+
|
49
|
+
def get_items(
|
50
|
+
search_term: Optional[str] = None,
|
51
|
+
limit: int = 10,
|
52
|
+
offset: int = 0
|
53
|
+
) -> List[Dict[str, Any]]:
|
54
|
+
"""
|
55
|
+
Gets a list of items with search and pagination capabilities.
|
56
|
+
|
57
|
+
Args:
|
58
|
+
search_term: String to search by name (optional)
|
59
|
+
limit: Maximum number of items to return
|
60
|
+
offset: Offset for result pagination
|
61
|
+
|
62
|
+
Returns:
|
63
|
+
List of items matching search criteria
|
64
|
+
"""
|
65
|
+
# In a real application, this would be code for
|
66
|
+
# retrieving items from a database
|
67
|
+
items = [
|
68
|
+
{"id": f"item_{i}", "name": f"Item {i}", "quantity": i % 10}
|
69
|
+
for i in range(offset, offset + limit)
|
70
|
+
]
|
71
|
+
|
72
|
+
if search_term:
|
73
|
+
items = [item for item in items if search_term.lower() in item["name"].lower()]
|
74
|
+
|
75
|
+
return items
|
76
|
+
```
|
77
|
+
|
78
|
+
### 2. Creating Command Registry
|
79
|
+
|
80
|
+
Create an `app.py` file with Command Registry initialization:
|
81
|
+
|
82
|
+
```python
|
83
|
+
from command_registry import CommandRegistry
|
84
|
+
from command_registry.dispatchers import CommandDispatcher
|
85
|
+
import commands
|
86
|
+
|
87
|
+
# Create dispatcher instance
|
88
|
+
dispatcher = CommandDispatcher()
|
89
|
+
|
90
|
+
# Create command registry
|
91
|
+
registry = CommandRegistry(dispatcher)
|
92
|
+
|
93
|
+
# Register commands
|
94
|
+
registry.register_command("add_item", commands.add_item)
|
95
|
+
registry.register_command("get_items", commands.get_items)
|
96
|
+
|
97
|
+
# Automatic registration of all commands from module (alternative way)
|
98
|
+
# registry.scan_module(commands)
|
99
|
+
```
|
100
|
+
|
101
|
+
### 3. Executing Commands
|
102
|
+
|
103
|
+
Add code to `app.py` for executing commands:
|
104
|
+
|
105
|
+
```python
|
106
|
+
# Execute add_item command
|
107
|
+
result = registry.execute(
|
108
|
+
"add_item",
|
109
|
+
{
|
110
|
+
"item_name": "Laptop",
|
111
|
+
"quantity": 5,
|
112
|
+
"properties": {"brand": "SuperLaptop", "color": "silver"}
|
113
|
+
}
|
114
|
+
)
|
115
|
+
print("add_item result:", result)
|
116
|
+
|
117
|
+
# Execute get_items command
|
118
|
+
items = registry.execute(
|
119
|
+
"get_items",
|
120
|
+
{
|
121
|
+
"search_term": "Item",
|
122
|
+
"limit": 5
|
123
|
+
}
|
124
|
+
)
|
125
|
+
print(f"Found {len(items)} items:")
|
126
|
+
for item in items:
|
127
|
+
print(f"- {item['name']} (ID: {item['id']}, Quantity: {item['quantity']})")
|
128
|
+
```
|
129
|
+
|
130
|
+
### 4. Command Information
|
131
|
+
|
132
|
+
```python
|
133
|
+
# Get list of available commands
|
134
|
+
commands = registry.get_valid_commands()
|
135
|
+
print("Available commands:", commands)
|
136
|
+
|
137
|
+
# Get information about specific command
|
138
|
+
info = registry.get_command_info("add_item")
|
139
|
+
print("Information about add_item command:")
|
140
|
+
print(f"- Description: {info['description']}")
|
141
|
+
print(f"- Parameters: {list(info['params'].keys())}")
|
142
|
+
```
|
143
|
+
|
144
|
+
## Web Framework Integration
|
145
|
+
|
146
|
+
### FastAPI
|
147
|
+
|
148
|
+
```python
|
149
|
+
from fastapi import FastAPI
|
150
|
+
from command_registry.adapters import RESTAdapter
|
151
|
+
|
152
|
+
app = FastAPI(title="Command Registry API")
|
153
|
+
|
154
|
+
# Create REST adapter
|
155
|
+
rest_adapter = RESTAdapter(registry)
|
156
|
+
|
157
|
+
# Register endpoints in FastAPI
|
158
|
+
rest_adapter.register_endpoints(app)
|
159
|
+
|
160
|
+
# Run application
|
161
|
+
# uvicorn app:app --reload
|
162
|
+
```
|
163
|
+
|
164
|
+
### Flask
|
165
|
+
|
166
|
+
```python
|
167
|
+
from flask import Flask
|
168
|
+
from command_registry.adapters import FlaskRESTAdapter
|
169
|
+
|
170
|
+
app = Flask(__name__)
|
171
|
+
|
172
|
+
# Create REST adapter for Flask
|
173
|
+
flask_adapter = FlaskRESTAdapter(registry)
|
174
|
+
|
175
|
+
# Register endpoints in Flask
|
176
|
+
flask_adapter.register_endpoints(app)
|
177
|
+
|
178
|
+
# Run application
|
179
|
+
# app.run(debug=True)
|
180
|
+
```
|
181
|
+
|
182
|
+
### aiohttp
|
183
|
+
|
184
|
+
```python
|
185
|
+
from aiohttp import web
|
186
|
+
from command_registry.adapters import AioHttpAdapter
|
187
|
+
|
188
|
+
app = web.Application()
|
189
|
+
|
190
|
+
# Create aiohttp adapter
|
191
|
+
aiohttp_adapter = AioHttpAdapter(registry)
|
192
|
+
|
193
|
+
# Register endpoints
|
194
|
+
aiohttp_adapter.register_endpoints(app)
|
195
|
+
|
196
|
+
# Run application
|
197
|
+
# web.run_app(app)
|
198
|
+
```
|
199
|
+
|
200
|
+
## Using JSON-RPC
|
201
|
+
|
202
|
+
```python
|
203
|
+
from fastapi import FastAPI
|
204
|
+
from command_registry.adapters import JSONRPCAdapter
|
205
|
+
|
206
|
+
app = FastAPI(title="Command Registry JSON-RPC API")
|
207
|
+
|
208
|
+
# Create JSON-RPC adapter
|
209
|
+
jsonrpc_adapter = JSONRPCAdapter(registry)
|
210
|
+
|
211
|
+
# Register JSON-RPC endpoint
|
212
|
+
jsonrpc_adapter.register_endpoint(app, "/api/jsonrpc")
|
213
|
+
|
214
|
+
# Run application
|
215
|
+
# uvicorn app:app --reload
|
216
|
+
```
|
217
|
+
|
218
|
+
## Command Line Integration
|
219
|
+
|
220
|
+
```python
|
221
|
+
from command_registry.adapters import ClickAdapter
|
222
|
+
import click
|
223
|
+
|
224
|
+
# Create adapter for Click
|
225
|
+
cli_adapter = ClickAdapter(registry)
|
226
|
+
|
227
|
+
# Create CLI application
|
228
|
+
cli = click.Group()
|
229
|
+
|
230
|
+
# Register commands
|
231
|
+
cli_adapter.register_commands(cli)
|
232
|
+
|
233
|
+
# Run CLI
|
234
|
+
if __name__ == "__main__":
|
235
|
+
cli()
|
236
|
+
```
|
237
|
+
|
238
|
+
## Error Handling
|
239
|
+
|
240
|
+
```python
|
241
|
+
from command_registry.exceptions import (
|
242
|
+
CommandNotFoundError,
|
243
|
+
ValidationError,
|
244
|
+
CommandExecutionError
|
245
|
+
)
|
246
|
+
|
247
|
+
try:
|
248
|
+
result = registry.execute("non_existent_command", {})
|
249
|
+
except CommandNotFoundError as e:
|
250
|
+
print(f"Error: Command not found - {e}")
|
251
|
+
```
|
docs/quickstart_ru.md
ADDED
@@ -0,0 +1,397 @@
|
|
1
|
+
# Быстрый старт Command Registry
|
2
|
+
|
3
|
+
Это руководство поможет вам быстро начать работу с системой Command Registry и интегрировать её в ваше приложение.
|
4
|
+
|
5
|
+
## Установка
|
6
|
+
|
7
|
+
Установите пакет с помощью pip:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
pip install command-registry
|
11
|
+
```
|
12
|
+
|
13
|
+
## Базовое использование
|
14
|
+
|
15
|
+
### 1. Определение команды
|
16
|
+
|
17
|
+
Создайте файл `commands.py` с вашими командами:
|
18
|
+
|
19
|
+
```python
|
20
|
+
from typing import List, Dict, Any, Optional
|
21
|
+
|
22
|
+
def add_item(
|
23
|
+
item_name: str,
|
24
|
+
quantity: int = 1,
|
25
|
+
properties: Optional[Dict[str, Any]] = None
|
26
|
+
) -> Dict[str, Any]:
|
27
|
+
"""
|
28
|
+
Добавляет новый товар в систему.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
item_name: Название товара
|
32
|
+
quantity: Количество товара (по умолчанию 1)
|
33
|
+
properties: Дополнительные свойства товара
|
34
|
+
|
35
|
+
Returns:
|
36
|
+
Информация о созданном товаре
|
37
|
+
"""
|
38
|
+
# В реальном приложении здесь был бы код для
|
39
|
+
# сохранения товара в базе данных
|
40
|
+
item_id = "item_" + str(hash(item_name))
|
41
|
+
item = {
|
42
|
+
"id": item_id,
|
43
|
+
"name": item_name,
|
44
|
+
"quantity": quantity,
|
45
|
+
"properties": properties or {}
|
46
|
+
}
|
47
|
+
return item
|
48
|
+
|
49
|
+
def get_items(
|
50
|
+
search_term: Optional[str] = None,
|
51
|
+
limit: int = 10,
|
52
|
+
offset: int = 0
|
53
|
+
) -> List[Dict[str, Any]]:
|
54
|
+
"""
|
55
|
+
Получает список товаров с возможностью поиска и пагинации.
|
56
|
+
|
57
|
+
Args:
|
58
|
+
search_term: Строка для поиска по названию (опционально)
|
59
|
+
limit: Максимальное количество возвращаемых товаров
|
60
|
+
offset: Смещение для пагинации результатов
|
61
|
+
|
62
|
+
Returns:
|
63
|
+
Список товаров, соответствующих критериям поиска
|
64
|
+
"""
|
65
|
+
# В реальном приложении здесь был бы код для
|
66
|
+
# получения товаров из базы данных
|
67
|
+
items = [
|
68
|
+
{"id": f"item_{i}", "name": f"Товар {i}", "quantity": i % 10}
|
69
|
+
for i in range(offset, offset + limit)
|
70
|
+
]
|
71
|
+
|
72
|
+
if search_term:
|
73
|
+
items = [item for item in items if search_term.lower() in item["name"].lower()]
|
74
|
+
|
75
|
+
return items
|
76
|
+
```
|
77
|
+
|
78
|
+
### 2. Создание Command Registry
|
79
|
+
|
80
|
+
Создайте файл `app.py` с инициализацией Command Registry:
|
81
|
+
|
82
|
+
```python
|
83
|
+
from command_registry import CommandRegistry
|
84
|
+
from command_registry.dispatchers import CommandDispatcher
|
85
|
+
import commands
|
86
|
+
|
87
|
+
# Создание экземпляра диспетчера
|
88
|
+
dispatcher = CommandDispatcher()
|
89
|
+
|
90
|
+
# Создание реестра команд
|
91
|
+
registry = CommandRegistry(dispatcher)
|
92
|
+
|
93
|
+
# Регистрация команд
|
94
|
+
registry.register_command("add_item", commands.add_item)
|
95
|
+
registry.register_command("get_items", commands.get_items)
|
96
|
+
|
97
|
+
# Автоматическая регистрация всех команд из модуля (альтернативный способ)
|
98
|
+
# registry.scan_module(commands)
|
99
|
+
```
|
100
|
+
|
101
|
+
### 3. Выполнение команд
|
102
|
+
|
103
|
+
Добавьте в `app.py` код для выполнения команд:
|
104
|
+
|
105
|
+
```python
|
106
|
+
# Выполнение команды add_item
|
107
|
+
result = registry.execute(
|
108
|
+
"add_item",
|
109
|
+
{
|
110
|
+
"item_name": "Ноутбук",
|
111
|
+
"quantity": 5,
|
112
|
+
"properties": {"brand": "SuperLaptop", "color": "silver"}
|
113
|
+
}
|
114
|
+
)
|
115
|
+
print("Результат add_item:", result)
|
116
|
+
|
117
|
+
# Выполнение команды get_items
|
118
|
+
items = registry.execute(
|
119
|
+
"get_items",
|
120
|
+
{
|
121
|
+
"search_term": "Товар",
|
122
|
+
"limit": 5
|
123
|
+
}
|
124
|
+
)
|
125
|
+
print(f"Найдено {len(items)} товаров:")
|
126
|
+
for item in items:
|
127
|
+
print(f"- {item['name']} (ID: {item['id']}, Количество: {item['quantity']})")
|
128
|
+
```
|
129
|
+
|
130
|
+
### 4. Информация о командах
|
131
|
+
|
132
|
+
```python
|
133
|
+
# Получение списка доступных команд
|
134
|
+
commands = registry.get_valid_commands()
|
135
|
+
print("Доступные команды:", commands)
|
136
|
+
|
137
|
+
# Получение информации о конкретной команде
|
138
|
+
info = registry.get_command_info("add_item")
|
139
|
+
print("Информация о команде add_item:")
|
140
|
+
print(f"- Описание: {info['description']}")
|
141
|
+
print(f"- Параметры: {list(info['params'].keys())}")
|
142
|
+
```
|
143
|
+
|
144
|
+
## Интеграция с веб-фреймворками
|
145
|
+
|
146
|
+
### FastAPI
|
147
|
+
|
148
|
+
```python
|
149
|
+
from fastapi import FastAPI
|
150
|
+
from command_registry.adapters import RESTAdapter
|
151
|
+
|
152
|
+
app = FastAPI(title="Command Registry API")
|
153
|
+
|
154
|
+
# Создание адаптера REST
|
155
|
+
rest_adapter = RESTAdapter(registry)
|
156
|
+
|
157
|
+
# Регистрация эндпоинтов в FastAPI
|
158
|
+
rest_adapter.register_endpoints(app)
|
159
|
+
|
160
|
+
# Запуск приложения
|
161
|
+
# uvicorn app:app --reload
|
162
|
+
```
|
163
|
+
|
164
|
+
### Flask
|
165
|
+
|
166
|
+
```python
|
167
|
+
from flask import Flask
|
168
|
+
from command_registry.adapters import FlaskRESTAdapter
|
169
|
+
|
170
|
+
app = Flask(__name__)
|
171
|
+
|
172
|
+
# Создание адаптера REST для Flask
|
173
|
+
flask_adapter = FlaskRESTAdapter(registry)
|
174
|
+
|
175
|
+
# Регистрация эндпоинтов в Flask
|
176
|
+
flask_adapter.register_endpoints(app)
|
177
|
+
|
178
|
+
# Запуск приложения
|
179
|
+
# app.run(debug=True)
|
180
|
+
```
|
181
|
+
|
182
|
+
### aiohttp
|
183
|
+
|
184
|
+
```python
|
185
|
+
from aiohttp import web
|
186
|
+
from command_registry.adapters import AioHttpAdapter
|
187
|
+
|
188
|
+
app = web.Application()
|
189
|
+
|
190
|
+
# Создание адаптера aiohttp
|
191
|
+
aiohttp_adapter = AioHttpAdapter(registry)
|
192
|
+
|
193
|
+
# Регистрация эндпоинтов
|
194
|
+
aiohttp_adapter.register_endpoints(app)
|
195
|
+
|
196
|
+
# Запуск приложения
|
197
|
+
# web.run_app(app)
|
198
|
+
```
|
199
|
+
|
200
|
+
## Использование JSON-RPC
|
201
|
+
|
202
|
+
```python
|
203
|
+
from fastapi import FastAPI
|
204
|
+
from command_registry.adapters import JSONRPCAdapter
|
205
|
+
|
206
|
+
app = FastAPI(title="Command Registry JSON-RPC API")
|
207
|
+
|
208
|
+
# Создание адаптера JSON-RPC
|
209
|
+
jsonrpc_adapter = JSONRPCAdapter(registry)
|
210
|
+
|
211
|
+
# Регистрация эндпоинта JSON-RPC
|
212
|
+
jsonrpc_adapter.register_endpoint(app, "/api/jsonrpc")
|
213
|
+
|
214
|
+
# Запуск приложения
|
215
|
+
# uvicorn app:app --reload
|
216
|
+
```
|
217
|
+
|
218
|
+
## Интеграция с командной строкой
|
219
|
+
|
220
|
+
```python
|
221
|
+
from command_registry.adapters import ClickAdapter
|
222
|
+
import click
|
223
|
+
|
224
|
+
# Создание адаптера для Click
|
225
|
+
cli_adapter = ClickAdapter(registry)
|
226
|
+
|
227
|
+
# Создание CLI приложения
|
228
|
+
cli = click.Group()
|
229
|
+
|
230
|
+
# Регистрация команд
|
231
|
+
cli_adapter.register_commands(cli)
|
232
|
+
|
233
|
+
# Запуск CLI
|
234
|
+
if __name__ == "__main__":
|
235
|
+
cli()
|
236
|
+
```
|
237
|
+
|
238
|
+
## Обработка ошибок
|
239
|
+
|
240
|
+
```python
|
241
|
+
from command_registry.exceptions import (
|
242
|
+
CommandNotFoundError,
|
243
|
+
ValidationError,
|
244
|
+
CommandExecutionError
|
245
|
+
)
|
246
|
+
|
247
|
+
try:
|
248
|
+
result = registry.execute("non_existent_command", {})
|
249
|
+
except CommandNotFoundError as e:
|
250
|
+
print(f"Ошибка: Команда не найдена - {e}")
|
251
|
+
|
252
|
+
try:
|
253
|
+
result = registry.execute("add_item", {"wrong_param": "value"})
|
254
|
+
except ValidationError as e:
|
255
|
+
print(f"Ошибка валидации: {e}")
|
256
|
+
print(f"Детали: {e.errors()}")
|
257
|
+
|
258
|
+
try:
|
259
|
+
result = registry.execute("add_item", {"item_name": None})
|
260
|
+
except CommandExecutionError as e:
|
261
|
+
print(f"Ошибка выполнения: {e}")
|
262
|
+
print(f"Исходное исключение: {e.__cause__}")
|
263
|
+
```
|
264
|
+
|
265
|
+
## Валидация параметров
|
266
|
+
|
267
|
+
Включение проверки типов и валидации:
|
268
|
+
|
269
|
+
```python
|
270
|
+
# При создании диспетчера
|
271
|
+
dispatcher = CommandDispatcher(validate_types=True)
|
272
|
+
|
273
|
+
# Или при создании реестра
|
274
|
+
registry = CommandRegistry(dispatcher, validate_types=True)
|
275
|
+
```
|
276
|
+
|
277
|
+
## Генерация документации
|
278
|
+
|
279
|
+
```python
|
280
|
+
from command_registry.generators import OpenAPIGenerator
|
281
|
+
|
282
|
+
# Создание генератора OpenAPI
|
283
|
+
generator = OpenAPIGenerator(registry)
|
284
|
+
|
285
|
+
# Генерация документа OpenAPI
|
286
|
+
openapi_schema = generator.generate_schema(
|
287
|
+
title="Command Registry API",
|
288
|
+
version="1.0.0",
|
289
|
+
description="API для управления товарами"
|
290
|
+
)
|
291
|
+
|
292
|
+
# Сохранение схемы в файл
|
293
|
+
import json
|
294
|
+
with open("openapi.json", "w") as f:
|
295
|
+
json.dump(openapi_schema, f, indent=2)
|
296
|
+
```
|
297
|
+
|
298
|
+
## Полное демо-приложение
|
299
|
+
|
300
|
+
```python
|
301
|
+
from command_registry import CommandRegistry
|
302
|
+
from command_registry.dispatchers import CommandDispatcher
|
303
|
+
from command_registry.adapters import RESTAdapter
|
304
|
+
from fastapi import FastAPI
|
305
|
+
import uvicorn
|
306
|
+
from typing import Dict, Any, List, Optional
|
307
|
+
|
308
|
+
# Определение команд
|
309
|
+
def add_item(
|
310
|
+
item_name: str,
|
311
|
+
quantity: int = 1,
|
312
|
+
properties: Optional[Dict[str, Any]] = None
|
313
|
+
) -> Dict[str, Any]:
|
314
|
+
"""
|
315
|
+
Добавляет новый товар в систему.
|
316
|
+
|
317
|
+
Args:
|
318
|
+
item_name: Название товара
|
319
|
+
quantity: Количество товара (по умолчанию 1)
|
320
|
+
properties: Дополнительные свойства товара
|
321
|
+
|
322
|
+
Returns:
|
323
|
+
Информация о созданном товаре
|
324
|
+
"""
|
325
|
+
item_id = "item_" + str(hash(item_name))
|
326
|
+
item = {
|
327
|
+
"id": item_id,
|
328
|
+
"name": item_name,
|
329
|
+
"quantity": quantity,
|
330
|
+
"properties": properties or {}
|
331
|
+
}
|
332
|
+
return item
|
333
|
+
|
334
|
+
def get_items(
|
335
|
+
search_term: Optional[str] = None,
|
336
|
+
limit: int = 10,
|
337
|
+
offset: int = 0
|
338
|
+
) -> List[Dict[str, Any]]:
|
339
|
+
"""
|
340
|
+
Получает список товаров с возможностью поиска и пагинации.
|
341
|
+
|
342
|
+
Args:
|
343
|
+
search_term: Строка для поиска по названию (опционально)
|
344
|
+
limit: Максимальное количество возвращаемых товаров
|
345
|
+
offset: Смещение для пагинации результатов
|
346
|
+
|
347
|
+
Returns:
|
348
|
+
Список товаров, соответствующих критериям поиска
|
349
|
+
"""
|
350
|
+
items = [
|
351
|
+
{"id": f"item_{i}", "name": f"Товар {i}", "quantity": i % 10}
|
352
|
+
for i in range(offset, offset + limit)
|
353
|
+
]
|
354
|
+
|
355
|
+
if search_term:
|
356
|
+
items = [item for item in items if search_term.lower() in item["name"].lower()]
|
357
|
+
|
358
|
+
return items
|
359
|
+
|
360
|
+
# Создание реестра команд
|
361
|
+
dispatcher = CommandDispatcher(validate_types=True)
|
362
|
+
registry = CommandRegistry(dispatcher)
|
363
|
+
|
364
|
+
# Регистрация команд
|
365
|
+
registry.register_command("add_item", add_item)
|
366
|
+
registry.register_command("get_items", get_items)
|
367
|
+
|
368
|
+
# Создание FastAPI приложения
|
369
|
+
app = FastAPI(title="Inventory API")
|
370
|
+
|
371
|
+
# Создание REST адаптера и регистрация эндпоинтов
|
372
|
+
rest_adapter = RESTAdapter(registry)
|
373
|
+
rest_adapter.register_endpoints(app)
|
374
|
+
|
375
|
+
# Запуск приложения
|
376
|
+
if __name__ == "__main__":
|
377
|
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
378
|
+
```
|
379
|
+
|
380
|
+
Запустите приложение:
|
381
|
+
|
382
|
+
```bash
|
383
|
+
python app.py
|
384
|
+
```
|
385
|
+
|
386
|
+
После запуска вы можете:
|
387
|
+
|
388
|
+
1. Открыть документацию API по адресу: http://localhost:8000/docs
|
389
|
+
2. Тестировать эндпоинты через Swagger UI
|
390
|
+
3. Отправлять запросы к API с помощью curl или Postman
|
391
|
+
|
392
|
+
## Что дальше?
|
393
|
+
|
394
|
+
- Изучите [архитектуру системы](architecture.md) для лучшего понимания её компонентов
|
395
|
+
- Прочитайте [руководство по разработке команд](command_development.md) для изучения лучших практик
|
396
|
+
- Познакомьтесь с возможностями [валидации](validation.md)
|
397
|
+
- Изучите [примеры использования](examples.md) для различных сценариев
|