embed-client-dev 4.0.78__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 (48) hide show
  1. embed_client/__init__.py +36 -0
  2. embed_client/__main__.py +15 -0
  3. embed_client/_version.py +3 -0
  4. embed_client/adapter_config_factory.py +213 -0
  5. embed_client/adapter_config_normalizer.py +135 -0
  6. embed_client/adapter_generator_bridge.py +166 -0
  7. embed_client/auth.py +189 -0
  8. embed_client/cli.py +483 -0
  9. embed_client/cli_core.py +427 -0
  10. embed_client/client_factory.py +515 -0
  11. embed_client/client_factory_examples.py +375 -0
  12. embed_client/client_factory_helpers.py +59 -0
  13. embed_client/config.py +408 -0
  14. embed_client/config_defaults.py +77 -0
  15. embed_client/config_examples.py +228 -0
  16. embed_client/config_generator.py +652 -0
  17. embed_client/config_generator_cli.py +151 -0
  18. embed_client/config_presets.py +245 -0
  19. embed_client/config_validator.py +246 -0
  20. embed_client/config_validator_cli.py +141 -0
  21. embed_client/constants.py +52 -0
  22. embed_client/demo_cli.py +78 -0
  23. embed_client/demo_security_cli.py +206 -0
  24. embed_client/embed_file_output_validate.py +348 -0
  25. embed_client/embed_file_status_store.py +80 -0
  26. embed_client/embedding_client.py +1929 -0
  27. embed_client/embedding_client_helpers.py +105 -0
  28. embed_client/example_async_usage.py +357 -0
  29. embed_client/example_async_usage_demo.py +282 -0
  30. embed_client/example_async_usage_ru.py +340 -0
  31. embed_client/example_async_usage_ru_demo.py +313 -0
  32. embed_client/exceptions.py +122 -0
  33. embed_client/identifier_types.py +56 -0
  34. embed_client/json_embed_file_preflight.py +128 -0
  35. embed_client/local_json_embed_file.py +73 -0
  36. embed_client/md_embed_file_prep.py +197 -0
  37. embed_client/response_normalizer.py +160 -0
  38. embed_client/response_parsers.py +219 -0
  39. embed_client/security_cli.py +200 -0
  40. embed_client/security_cli_core.py +227 -0
  41. embed_client/ssl_examples.py +278 -0
  42. embed_client/ssl_manager.py +141 -0
  43. embed_client_dev-4.0.78.dist-info/METADATA +155 -0
  44. embed_client_dev-4.0.78.dist-info/RECORD +48 -0
  45. embed_client_dev-4.0.78.dist-info/WHEEL +5 -0
  46. embed_client_dev-4.0.78.dist-info/entry_points.txt +4 -0
  47. embed_client_dev-4.0.78.dist-info/licenses/LICENSE +21 -0
  48. embed_client_dev-4.0.78.dist-info/top_level.txt +1 -0
@@ -0,0 +1,282 @@
1
+ """
2
+ Demonstration helpers for ``embed_client/example_async_usage.py``.
3
+
4
+ Author: Vasiliy Zdanovskiy
5
+ email: vasilyvz@gmail.com
6
+
7
+ **run_client_examples** — interactive smoke checks (health, OpenAPI, commands,
8
+ ``cmd("embed")``).
9
+
10
+ **demonstrate_security_modes** / **demonstrate_automatic_detection** /
11
+ **demonstrate_with_auth_method** — print-only illustrations of ``ClientFactory``
12
+ constructors (no live server required for most branches).
13
+
14
+ All functions use :class:`~embed_client.embedding_client.EmbeddingClient` or factory
15
+ helpers that yield compatible clients.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ from typing import Any, Dict, List
21
+
22
+ from embed_client.embedding_client import EmbeddingClient
23
+ from embed_client.exceptions import EmbedError
24
+ from embed_client.client_factory import ClientFactory, detect_security_mode
25
+ from embed_client.response_parsers import extract_embeddings
26
+
27
+
28
+ async def run_client_examples(client: EmbeddingClient) -> None:
29
+ """
30
+ Run a short interactive tour: health, OpenAPI schema, list_commands, then ``cmd('embed')``.
31
+
32
+ On the first :exc:`~embed_client.exceptions.EmbedError`, prints the error and returns early
33
+ from the health step only; later steps catch per-call.
34
+ """
35
+ # Check health
36
+ try:
37
+ health = await client.health()
38
+ print("Service health:", health)
39
+ except EmbedError as exc:
40
+ print(f"Error during health check: {exc}")
41
+ return
42
+
43
+ # Get OpenAPI schema
44
+ try:
45
+ schema = await client.fetch_openapi_schema()
46
+ print(
47
+ "OpenAPI schema version:",
48
+ schema.get("info", {}).get("version", "unknown"),
49
+ )
50
+ except EmbedError as exc:
51
+ print(f"Error getting OpenAPI schema: {exc}")
52
+
53
+ # Get available commands
54
+ try:
55
+ commands = await client.list_commands()
56
+ print(f"Available commands: {commands}")
57
+ except EmbedError as exc:
58
+ print(f"Error getting commands: {exc}")
59
+
60
+ # Test embedding generation
61
+ try:
62
+ texts = [
63
+ "Hello, world!",
64
+ "This is a test sentence.",
65
+ "Embedding service is working!",
66
+ ]
67
+ result = await client.cmd("embed", {"texts": texts})
68
+
69
+ # Extract embeddings using shared response_parsers helper
70
+ embeddings = extract_embeddings(result)
71
+ print(f"Generated {len(embeddings)} embeddings")
72
+ print(
73
+ "First embedding dimension:",
74
+ len(embeddings[0]) if embeddings else 0,
75
+ )
76
+ except EmbedError as exc:
77
+ print(f"Error during embedding generation: {exc}")
78
+
79
+
80
+ async def demonstrate_security_modes() -> None:
81
+ """
82
+ Print-oriented walkthrough of six factory construction patterns (HTTP through mTLS roles).
83
+
84
+ Does not connect to a real server unless the user later uses the returned configs elsewhere.
85
+ """
86
+ print("=== Security Modes Demonstration ===")
87
+ print("This demonstration shows how to create clients for all 6 security modes.")
88
+ print(
89
+ "Note: These examples create client configurations "
90
+ "but don't connect to actual servers."
91
+ )
92
+
93
+ # 1. HTTP mode
94
+ print("\n1. HTTP Mode (no authentication, no SSL):")
95
+ print(" Use case: Development, internal networks, trusted environments")
96
+ try:
97
+ client = ClientFactory.create_http_client("http://localhost", 8001)
98
+ print(f" ✓ Created HTTP client: {client!r}")
99
+ await client.close()
100
+ except Exception as exc: # noqa: BLE001
101
+ print(f" ✗ Error: {exc}")
102
+
103
+ # 2. HTTP + Token mode
104
+ print("\n2. HTTP + Token Mode (HTTP with API key):")
105
+ print(" Use case: API access control, simple authentication")
106
+ try:
107
+ client = ClientFactory.create_http_token_client(
108
+ "http://localhost", 8001, "api_key", api_key="demo_key"
109
+ )
110
+ print(f" ✓ Created HTTP + Token client: {client!r}")
111
+ await client.close()
112
+ except Exception as exc: # noqa: BLE001
113
+ print(f" ✗ Error: {exc}")
114
+
115
+ # 3. HTTPS mode
116
+ print("\n3. HTTPS Mode (HTTPS with server certificates):")
117
+ print(" Use case: Secure communication, public networks")
118
+ try:
119
+ client = ClientFactory.create_https_client("https://localhost", 9443)
120
+ print(f" ✓ Created HTTPS client: {client!r}")
121
+ await client.close()
122
+ except Exception as exc: # noqa: BLE001
123
+ print(f" ✗ Error: {exc}")
124
+
125
+ # 4. HTTPS + Token mode
126
+ print(
127
+ "\n4. HTTPS + Token Mode " "(HTTPS with server certificates + authentication):"
128
+ )
129
+ print(" Use case: Secure API access, production environments")
130
+ try:
131
+ client = ClientFactory.create_https_token_client(
132
+ "https://localhost",
133
+ 9443,
134
+ "basic",
135
+ username="admin",
136
+ password="secret",
137
+ )
138
+ print(f" ✓ Created HTTPS + Token client: {client!r}")
139
+ await client.close()
140
+ except Exception as exc: # noqa: BLE001
141
+ print(f" ✗ Error: {exc}")
142
+
143
+ # 5. mTLS mode
144
+ print("\n5. mTLS Mode (mutual TLS with client and server certificates):")
145
+ print(" Use case: High security, client certificate authentication")
146
+ try:
147
+ client = ClientFactory.create_mtls_client(
148
+ "https://localhost",
149
+ "mtls_certificates/client/embedding-service.crt",
150
+ "mtls_certificates/client/embedding-service.key",
151
+ 8443,
152
+ )
153
+ print(f" ✓ Created mTLS client: {client!r}")
154
+ await client.close()
155
+ except Exception as exc: # noqa: BLE001
156
+ print(f" ✗ Error: {exc}")
157
+
158
+ # 6. mTLS + Roles mode
159
+ print("\n6. mTLS + Roles Mode (mTLS with role-based access control):")
160
+ print(" Use case: Enterprise security, role-based permissions")
161
+ try:
162
+ client = ClientFactory.create_mtls_roles_client(
163
+ "https://localhost",
164
+ "mtls_certificates/client/embedding-service.crt",
165
+ "mtls_certificates/client/embedding-service.key",
166
+ 8443,
167
+ roles=["admin", "user"],
168
+ role_attributes={"department": "IT"},
169
+ )
170
+ print(f" ✓ Created mTLS + Roles client: {client!r}")
171
+ await client.close()
172
+ except Exception as exc: # noqa: BLE001
173
+ print(f" ✗ Error: {exc}")
174
+
175
+ print("\n=== Security Mode Summary ===")
176
+ print("1. HTTP: Basic connectivity, no security")
177
+ print("2. HTTP + Token: API key authentication over HTTP")
178
+ print("3. HTTPS: Encrypted communication with server certificates")
179
+ print("4. HTTPS + Token: Encrypted communication + authentication")
180
+ print("5. mTLS: Mutual certificate authentication")
181
+ print("6. mTLS + Roles: Mutual certificates + role-based access control")
182
+
183
+
184
+ async def demonstrate_automatic_detection() -> None:
185
+ """Demonstrate automatic security mode detection."""
186
+ print("\n=== Automatic Security Mode Detection ===")
187
+ print(
188
+ "This shows how the client automatically detects the "
189
+ "appropriate security mode."
190
+ )
191
+
192
+ test_cases: List[Any] = [
193
+ ("http://localhost", None, None, None, None, "HTTP"),
194
+ ("http://localhost", "api_key", None, None, None, "HTTP + Token"),
195
+ ("https://localhost", None, None, None, None, "HTTPS"),
196
+ ("https://localhost", "api_key", None, None, None, "HTTPS + Token"),
197
+ ("https://localhost", None, None, "cert.pem", "key.pem", "mTLS"),
198
+ (
199
+ "https://localhost",
200
+ None,
201
+ None,
202
+ "cert.pem",
203
+ "key.pem",
204
+ "mTLS + Roles",
205
+ {"roles": ["admin"]},
206
+ ),
207
+ ]
208
+
209
+ for case in test_cases:
210
+ if len(case) == 6:
211
+ base_url, auth_method, ssl_enabled, cert_file, key_file, expected = case
212
+ kwargs: Dict[str, Any] = {}
213
+ else:
214
+ (
215
+ base_url,
216
+ auth_method,
217
+ ssl_enabled,
218
+ cert_file,
219
+ key_file,
220
+ expected,
221
+ kwargs,
222
+ ) = case
223
+
224
+ try:
225
+ mode = detect_security_mode(
226
+ base_url, auth_method, ssl_enabled, cert_file, key_file, **kwargs
227
+ )
228
+ print(
229
+ f" ✓ {base_url} + {auth_method or 'none'} + "
230
+ f"{cert_file or 'no cert'} -> {mode} ({expected})"
231
+ )
232
+ except Exception as exc: # noqa: BLE001
233
+ print(f" ✗ Error detecting mode for {base_url}: {exc}")
234
+
235
+
236
+ async def demonstrate_with_auth_method() -> None:
237
+ """Demonstrate the with_auth method for dynamic authentication."""
238
+ print("\n=== Dynamic Authentication with with_auth() Method ===")
239
+ print(
240
+ "This shows how to create clients with different authentication "
241
+ "methods using the with_auth class method."
242
+ )
243
+
244
+ # Demonstrate different authentication methods
245
+ auth_examples = [
246
+ ("api_key", {"api_key": "dynamic_api_key"}, "API Key Authentication"),
247
+ (
248
+ "jwt",
249
+ {"secret": "secret", "username": "user", "password": "pass"},
250
+ "JWT Authentication",
251
+ ),
252
+ ("basic", {"username": "admin", "password": "secret"}, "Basic Authentication"),
253
+ (
254
+ "certificate",
255
+ {"cert_file": "client.crt", "key_file": "client.key"},
256
+ "Certificate Authentication",
257
+ ),
258
+ ]
259
+
260
+ for auth_method, kwargs, description in auth_examples:
261
+ try:
262
+ print(f"\n{description}:")
263
+ auth_client = EmbeddingClient.with_auth(
264
+ "http://localhost",
265
+ 8001,
266
+ auth_method,
267
+ **kwargs,
268
+ )
269
+ print(f" ✓ Client: {auth_client!r}")
270
+ await auth_client.close()
271
+ except Exception as exc: # noqa: BLE001
272
+ print(f" ✗ Error with {auth_method}: {exc}")
273
+
274
+ print("\n✓ Dynamic authentication demonstration completed.")
275
+
276
+
277
+ __all__ = [
278
+ "run_client_examples",
279
+ "demonstrate_security_modes",
280
+ "demonstrate_automatic_detection",
281
+ "demonstrate_with_auth_method",
282
+ ]
@@ -0,0 +1,340 @@
1
+ """
2
+ Пример :class:`~embed_client.embedding_client.EmbeddingClient` со всеми режимами безопасности и ``ClientFactory``.
3
+
4
+ Author: Vasiliy Zdanovskiy
5
+ email: vasilyvz@gmail.com
6
+
7
+ См. также (пути в репозитории): ``docs/client_integration_guide.md``, ``README.md``,
8
+ ``examples/canonical_mtls_localhost_8001.py`` (канонический mTLS localhost:8001).
9
+
10
+ **Код выхода:** ``0`` при успехе, ``1`` при ошибке конфигурации или необработанном исключении.
11
+ """
12
+
13
+ import argparse
14
+ import asyncio
15
+ import json
16
+ import os
17
+ import sys
18
+ from typing import Any, Dict
19
+
20
+ from embed_client.embedding_client import EmbeddingClient
21
+ from embed_client.exceptions import EmbedConfigError
22
+ from embed_client.config import ClientConfig
23
+ from embed_client.client_factory import ClientFactory, create_client
24
+ from embed_client.example_async_usage_ru_demo import (
25
+ run_client_examples,
26
+ demonstrate_security_modes,
27
+ demonstrate_automatic_detection,
28
+ )
29
+
30
+
31
+ def get_params() -> Any:
32
+ """Парсинг аргументов командной строки и переменных окружения для конфигурации клиента."""
33
+ parser = argparse.ArgumentParser(
34
+ description="Пример EmbeddingClient — все режимы безопасности (CLI + демо)"
35
+ )
36
+
37
+ # Базовые параметры подключения
38
+ parser.add_argument("--base-url", "-b", help="Базовый URL сервиса эмбеддингов")
39
+ parser.add_argument("--port", "-p", type=int, help="Порт сервиса эмбеддингов")
40
+ parser.add_argument("--config", "-c", help="Путь к файлу конфигурации")
41
+
42
+ # Режим фабрики клиентов
43
+ parser.add_argument(
44
+ "--factory-mode",
45
+ choices=[
46
+ "auto",
47
+ "http",
48
+ "http_token",
49
+ "https",
50
+ "https_token",
51
+ "mtls",
52
+ "mtls_roles",
53
+ ],
54
+ default="auto",
55
+ help="Режим фабрики клиентов (auto для автоматического определения)",
56
+ )
57
+
58
+ # Параметры аутентификации
59
+ parser.add_argument(
60
+ "--auth-method",
61
+ choices=["none", "api_key", "jwt", "basic", "certificate"],
62
+ default="none",
63
+ help="Метод аутентификации",
64
+ )
65
+ parser.add_argument("--api-key", help="API ключ для аутентификации api_key")
66
+ parser.add_argument("--jwt-secret", help="JWT секрет для аутентификации jwt")
67
+ parser.add_argument(
68
+ "--jwt-username", help="JWT имя пользователя для аутентификации jwt"
69
+ )
70
+ parser.add_argument("--jwt-password", help="JWT пароль для аутентификации jwt")
71
+ parser.add_argument(
72
+ "--username", help="Имя пользователя для базовой аутентификации"
73
+ )
74
+ parser.add_argument("--password", help="Пароль для базовой аутентификации")
75
+ parser.add_argument(
76
+ "--cert-file", help="Файл сертификата для аутентификации certificate"
77
+ )
78
+ parser.add_argument("--key-file", help="Файл ключа для аутентификации certificate")
79
+
80
+ # Параметры SSL/TLS
81
+ parser.add_argument(
82
+ "--ssl-verify-mode",
83
+ choices=["CERT_NONE", "CERT_OPTIONAL", "CERT_REQUIRED"],
84
+ default="CERT_REQUIRED",
85
+ help="Режим проверки SSL сертификатов",
86
+ )
87
+ parser.add_argument(
88
+ "--ssl-check-hostname",
89
+ action="store_true",
90
+ default=True,
91
+ help="Включить проверку имени хоста SSL",
92
+ )
93
+ parser.add_argument(
94
+ "--ssl-check-expiry",
95
+ action="store_true",
96
+ default=True,
97
+ help="Включить проверку срока действия SSL сертификатов",
98
+ )
99
+ parser.add_argument("--ca-cert-file", help="Файл CA сертификата для проверки SSL")
100
+
101
+ # Контроль доступа на основе ролей (для mTLS + Roles)
102
+ parser.add_argument(
103
+ "--roles", help="Список ролей через запятую для режима mTLS + Roles"
104
+ )
105
+ parser.add_argument(
106
+ "--role-attributes", help="JSON строка атрибутов ролей для режима mTLS + Roles"
107
+ )
108
+
109
+ # Дополнительные параметры
110
+ parser.add_argument(
111
+ "--timeout", type=float, default=30.0, help="Таймаут запроса в секундах"
112
+ )
113
+ parser.add_argument(
114
+ "--demo-mode",
115
+ action="store_true",
116
+ help="Запуск в демо режиме (показать все режимы безопасности)",
117
+ )
118
+
119
+ args = parser.parse_args()
120
+
121
+ # Если предоставлен файл конфигурации, загружаем его
122
+ if args.config:
123
+ try:
124
+ config = ClientConfig()
125
+ config.load_config_file(args.config)
126
+ return config
127
+ except Exception as e:
128
+ print(f"Ошибка загрузки файла конфигурации {args.config}: {e}")
129
+ sys.exit(1)
130
+
131
+ # Иначе строим конфигурацию из аргументов и переменных окружения
132
+ base_url = args.base_url or os.environ.get(
133
+ "EMBED_CLIENT_BASE_URL", "http://localhost"
134
+ )
135
+ port = args.port or int(os.environ.get("EMBED_CLIENT_PORT", "8001"))
136
+
137
+ if not base_url or not port:
138
+ print(
139
+ "Ошибка: base_url и port должны быть предоставлены через аргументы "
140
+ "--base-url/--port или переменные окружения EMBED_CLIENT_BASE_URL/"
141
+ "EMBED_CLIENT_PORT."
142
+ )
143
+ sys.exit(1)
144
+
145
+ # Строим словарь конфигурации
146
+ config_dict: Dict[str, Any] = {
147
+ "server": {"host": base_url, "port": port},
148
+ "client": {"timeout": args.timeout},
149
+ "auth": {"method": args.auth_method},
150
+ }
151
+
152
+ # Добавляем конфигурацию аутентификации
153
+ if args.auth_method == "api_key":
154
+ api_key = args.api_key or os.environ.get("EMBED_CLIENT_API_KEY")
155
+ if api_key:
156
+ config_dict["auth"]["api_keys"] = {"user": api_key}
157
+ else:
158
+ print("Предупреждение: API ключ не предоставлен для аутентификации api_key")
159
+
160
+ elif args.auth_method == "jwt":
161
+ jwt_secret = args.jwt_secret or os.environ.get("EMBED_CLIENT_JWT_SECRET")
162
+ jwt_username = args.jwt_username or os.environ.get("EMBED_CLIENT_JWT_USERNAME")
163
+ jwt_password = args.jwt_password or os.environ.get("EMBED_CLIENT_JWT_PASSWORD")
164
+
165
+ if jwt_secret and jwt_username and jwt_password:
166
+ config_dict["auth"]["jwt"] = {
167
+ "secret": jwt_secret,
168
+ "username": jwt_username,
169
+ "password": jwt_password,
170
+ }
171
+ else:
172
+ print("Предупреждение: JWT учетные данные не полностью предоставлены")
173
+
174
+ elif args.auth_method == "basic":
175
+ username = args.username or os.environ.get("EMBED_CLIENT_USERNAME")
176
+ password = args.password or os.environ.get("EMBED_CLIENT_PASSWORD")
177
+
178
+ if username and password:
179
+ config_dict["auth"]["basic"] = {"username": username, "password": password}
180
+ else:
181
+ print(
182
+ "Предупреждение: Учетные данные базовой аутентификации не полностью предоставлены"
183
+ )
184
+
185
+ elif args.auth_method == "certificate":
186
+ cert_file = args.cert_file or os.environ.get("EMBED_CLIENT_CERT_FILE")
187
+ key_file = args.key_file or os.environ.get("EMBED_CLIENT_KEY_FILE")
188
+
189
+ if cert_file and key_file:
190
+ config_dict["auth"]["certificate"] = {
191
+ "cert_file": cert_file,
192
+ "key_file": key_file,
193
+ }
194
+ else:
195
+ print("Предупреждение: Файлы сертификатов не полностью предоставлены")
196
+
197
+ # Добавляем конфигурацию SSL если используется HTTPS или предоставлены SSL параметры
198
+ if (
199
+ base_url.startswith("https://")
200
+ or args.ssl_verify_mode != "CERT_REQUIRED"
201
+ or args.ca_cert_file
202
+ ):
203
+ config_dict["ssl"] = {
204
+ "enabled": True,
205
+ "verify_mode": args.ssl_verify_mode,
206
+ "check_hostname": args.ssl_check_hostname,
207
+ "check_expiry": args.ssl_check_expiry,
208
+ }
209
+
210
+ if args.ca_cert_file:
211
+ config_dict["ssl"]["ca_cert_file"] = args.ca_cert_file
212
+
213
+ # Добавляем клиентские сертификаты для mTLS
214
+ if args.cert_file:
215
+ config_dict["ssl"]["cert_file"] = args.cert_file
216
+ if args.key_file:
217
+ config_dict["ssl"]["key_file"] = args.key_file
218
+
219
+ # Добавляем контроль доступа на основе ролей для mTLS + Roles
220
+ if args.roles:
221
+ roles = [role.strip() for role in args.roles.split(",")]
222
+ config_dict["roles"] = roles
223
+
224
+ if args.role_attributes:
225
+ try:
226
+ role_attributes = json.loads(args.role_attributes)
227
+ config_dict["role_attributes"] = role_attributes
228
+ except json.JSONDecodeError:
229
+ print("Предупреждение: Неверный JSON в role_attributes")
230
+
231
+ return config_dict
232
+
233
+
234
+ async def main():
235
+ try:
236
+ config = get_params()
237
+
238
+ # Проверяем, запрошен ли демо режим
239
+ if hasattr(config, "demo_mode") and config.demo_mode:
240
+ await demonstrate_security_modes()
241
+ await demonstrate_automatic_detection()
242
+ return
243
+
244
+ # Создаем клиент на основе режима фабрики
245
+ if isinstance(config, ClientConfig):
246
+ # Использование объекта конфигурации
247
+ client = EmbeddingClient.from_config(config)
248
+ else:
249
+ # Использование словаря конфигурации
250
+ factory_mode = getattr(config, "factory_mode", "auto")
251
+
252
+ if factory_mode == "auto":
253
+ # Автоматическое определение
254
+ client = create_client(
255
+ config["server"]["host"],
256
+ config["server"]["port"],
257
+ auth_method=config["auth"]["method"],
258
+ **{
259
+ k: v
260
+ for k, v in config.items()
261
+ if k not in ["server", "auth", "ssl", "client"]
262
+ },
263
+ )
264
+ else:
265
+ # Конкретный метод фабрики
266
+ base_url = config["server"]["host"]
267
+ port = config["server"]["port"]
268
+ auth_method = config["auth"]["method"]
269
+
270
+ if factory_mode == "http":
271
+ client = ClientFactory.create_http_client(base_url, port)
272
+ elif factory_mode == "http_token":
273
+ client = ClientFactory.create_http_token_client(
274
+ base_url, port, auth_method, **config.get("auth", {})
275
+ )
276
+ elif factory_mode == "https":
277
+ client = ClientFactory.create_https_client(base_url, port)
278
+ elif factory_mode == "https_token":
279
+ client = ClientFactory.create_https_token_client(
280
+ base_url, port, auth_method, **config.get("auth", {})
281
+ )
282
+ elif factory_mode == "mtls":
283
+ cert_file = config.get("ssl", {}).get(
284
+ "cert_file", "client_cert.pem"
285
+ )
286
+ key_file = config.get("ssl", {}).get("key_file", "client_key.pem")
287
+ client = ClientFactory.create_mtls_client(
288
+ base_url, cert_file, key_file, port
289
+ )
290
+ elif factory_mode == "mtls_roles":
291
+ cert_file = config.get("ssl", {}).get(
292
+ "cert_file", "client_cert.pem"
293
+ )
294
+ key_file = config.get("ssl", {}).get("key_file", "client_key.pem")
295
+ roles = config.get("roles", ["admin"])
296
+ role_attributes = config.get("role_attributes", {})
297
+ client = ClientFactory.create_mtls_roles_client(
298
+ base_url, cert_file, key_file, port, roles, role_attributes
299
+ )
300
+ else:
301
+ client = EmbeddingClient.from_config_dict(config)
302
+
303
+ print("Конфигурация клиента:")
304
+ print(f" Базовый URL: {client.base_url}")
305
+ print(f" Порт: {client.port}")
306
+ print(f" Аутентификация: {client.get_auth_method()}")
307
+ print(f" Аутентифицирован: {client.is_authenticated()}")
308
+ if client.is_authenticated():
309
+ headers = client.get_auth_headers()
310
+ print(f" Заголовки аутентификации: {headers}")
311
+ print(f" SSL включен: {client.is_ssl_enabled()}")
312
+ print(f" mTLS включен: {client.is_mtls_enabled()}")
313
+ if client.is_ssl_enabled():
314
+ ssl_config = client.get_ssl_config()
315
+ print(f" SSL конфигурация: {ssl_config}")
316
+ print()
317
+
318
+ # Пример явного открытия/закрытия
319
+ print("Пример явного открытия/закрытия сессии:")
320
+ await client.close()
321
+ print("Сессия закрыта явно (пример ручного закрытия).\n")
322
+
323
+ # Использование контекстного менеджера
324
+ if isinstance(config, ClientConfig):
325
+ async with EmbeddingClient.from_config(config) as client:
326
+ await run_client_examples(client)
327
+ else:
328
+ async with EmbeddingClient.from_config_dict(config) as client:
329
+ await run_client_examples(client)
330
+
331
+ except EmbedConfigError as e:
332
+ print(f"Ошибка конфигурации: {e}")
333
+ sys.exit(1)
334
+ except Exception as e:
335
+ print(f"Неожиданная ошибка: {e}")
336
+ sys.exit(1)
337
+
338
+
339
+ if __name__ == "__main__":
340
+ asyncio.run(main())