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,141 @@
1
+ """
2
+ CLI entry point for the embed-client configuration validator.
3
+
4
+ This module provides the command-line interface for validating configuration
5
+ files using `ConfigValidator`.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import argparse
14
+ import sys
15
+ from pathlib import Path
16
+
17
+ from embed_client.config_validator import ConfigValidator
18
+
19
+
20
+ def main() -> int:
21
+ """
22
+ CLI entry point for the configuration validator.
23
+
24
+ Returns:
25
+ Exit code (0 for success, 1 for failure)
26
+ """
27
+ parser = argparse.ArgumentParser(
28
+ description="Validate embed-client configuration files",
29
+ formatter_class=argparse.RawDescriptionHelpFormatter,
30
+ epilog="""
31
+ Examples:
32
+ # Validate a single config file
33
+ embed-config-validator --file configs/http.json
34
+
35
+ # Validate all configs in a directory
36
+ embed-config-validator --dir configs
37
+
38
+ # Validate and show detailed errors
39
+ embed-config-validator --file configs/mtls.json --verbose
40
+ """,
41
+ )
42
+ parser.add_argument(
43
+ "--file",
44
+ type=str,
45
+ help="Path to configuration file to validate",
46
+ )
47
+ parser.add_argument(
48
+ "--dir",
49
+ type=str,
50
+ help="Directory containing configuration files to validate",
51
+ )
52
+ parser.add_argument(
53
+ "--verbose",
54
+ action="store_true",
55
+ help="Show detailed error messages",
56
+ )
57
+
58
+ args = parser.parse_args()
59
+
60
+ if not args.file and not args.dir:
61
+ parser.print_help()
62
+ return 1
63
+
64
+ validator = ConfigValidator()
65
+
66
+ if args.file:
67
+ # Validate single file
68
+ config_path = Path(args.file)
69
+ if not config_path.is_absolute():
70
+ config_path = Path.cwd() / config_path
71
+
72
+ print(f"šŸ” Validating: {config_path}")
73
+ is_valid, message, errors = validator.validate_config_file(config_path)
74
+
75
+ if is_valid:
76
+ print(f"āœ… Configuration is valid: {message}")
77
+ return 0
78
+ else:
79
+ print(f"āŒ Configuration validation failed: {message}")
80
+ if errors and args.verbose:
81
+ print("\nErrors:")
82
+ for error in errors:
83
+ print(f" • {error}")
84
+ elif errors:
85
+ print(f" Found {len(errors)} error(s). Use --verbose to see details.")
86
+ return 1
87
+
88
+ elif args.dir:
89
+ # Validate directory
90
+ config_dir = Path(args.dir)
91
+ if not config_dir.is_absolute():
92
+ config_dir = Path.cwd() / config_dir
93
+
94
+ if not config_dir.exists():
95
+ print(f"āŒ Directory not found: {config_dir}")
96
+ return 1
97
+
98
+ print(f"šŸ” Validating configurations in: {config_dir}")
99
+ print("=" * 70)
100
+
101
+ results = validator.validate_config_directory(config_dir)
102
+
103
+ if not results:
104
+ print("āš ļø No configuration files found")
105
+ return 1
106
+
107
+ all_valid = True
108
+ for config_name, (is_valid, message, errors) in results.items():
109
+ status = "āœ…" if is_valid else "āŒ"
110
+ print(f"{status} {config_name:35s} - {message}")
111
+
112
+ if not is_valid:
113
+ all_valid = False
114
+ if errors and args.verbose:
115
+ for error in errors:
116
+ print(f" āš ļø {error}")
117
+
118
+ print("=" * 70)
119
+
120
+ if all_valid:
121
+ print(f"āœ… All {len(results)} configuration files are valid!")
122
+ return 0
123
+ else:
124
+ failed = [
125
+ (name, errors)
126
+ for name, (valid, _, errors) in results.items()
127
+ if not valid
128
+ ]
129
+ print(f"āŒ {len(failed)} configuration file(s) failed validation:")
130
+ for name, errors in failed:
131
+ print(f" - {name}")
132
+ if args.verbose and errors:
133
+ for error in errors:
134
+ print(f" • {error}")
135
+ return 1
136
+
137
+ return 0
138
+
139
+
140
+ if __name__ == "__main__":
141
+ sys.exit(main())
@@ -0,0 +1,52 @@
1
+ """
2
+ Shared constants for embed-client package (aligned with embedding service server).
3
+
4
+ Author: Vasiliy Zdanovskiy
5
+ email: vasilyvz@gmail.com
6
+ """
7
+
8
+ from pathlib import Path
9
+ from typing import Union
10
+
11
+ # ---------------------------------------------------------------------------
12
+ # Embed command (schema, default policy) — matches server embed/constants.py
13
+ # ---------------------------------------------------------------------------
14
+ EMBED_COMMAND_SCHEMA_DEFAULT_ERROR_POLICY = "fail_fast"
15
+
16
+ # ---------------------------------------------------------------------------
17
+ # Environment variable names for embedding service connection
18
+ # ---------------------------------------------------------------------------
19
+ EMBEDDING_SERVICE_BASE_URL_ENV: str = "EMBEDDING_SERVICE_BASE_URL"
20
+ EMBEDDING_SERVICE_PORT_ENV: str = "EMBEDDING_SERVICE_PORT"
21
+
22
+ # Default connection settings
23
+ DEFAULT_BASE_URL: str = "http://localhost"
24
+ DEFAULT_PORT: int = 8001
25
+
26
+ # Default poll interval (seconds) when waiting for queued job completion
27
+ DEFAULT_POLL_INTERVAL: float = 0.3
28
+
29
+ # Max UTF-8 bytes per string item in local json_array preflight (override via
30
+ # EMBED_CLIENT_MAX_JSON_BLOCK_BYTES).
31
+ DEFAULT_MAX_JSON_EMBED_BLOCK_BYTES: int = 1_048_576
32
+
33
+
34
+ def get_embed_project_root(module_file: Union[str, Path]) -> Path:
35
+ """
36
+ Return project root (parent of parent of the given module file).
37
+
38
+ Use from main or CLI: ``get_embed_project_root(__file__)``.
39
+ """
40
+ return Path(module_file).resolve().parent.parent
41
+
42
+
43
+ __all__ = [
44
+ "EMBED_COMMAND_SCHEMA_DEFAULT_ERROR_POLICY",
45
+ "EMBEDDING_SERVICE_BASE_URL_ENV",
46
+ "EMBEDDING_SERVICE_PORT_ENV",
47
+ "DEFAULT_BASE_URL",
48
+ "DEFAULT_PORT",
49
+ "DEFAULT_POLL_INTERVAL",
50
+ "DEFAULT_MAX_JSON_EMBED_BLOCK_BYTES",
51
+ "get_embed_project_root",
52
+ ]
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Demo CLI Application for Text Vectorization
4
+ Simple demonstration of the CLI functionality.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ import asyncio
11
+ import sys
12
+ from pathlib import Path
13
+
14
+ # Add the project root to the path
15
+ sys.path.insert(0, str(Path(__file__).parent.parent))
16
+
17
+ from embed_client.cli import VectorizationCLI # noqa: E402
18
+
19
+
20
+ async def demo_vectorization():
21
+ """Demonstrate vectorization functionality."""
22
+ print("šŸš€ Embed-Client CLI Demo")
23
+ print("=" * 40)
24
+
25
+ # Configuration for demo
26
+ config = {
27
+ "server": {"host": "http://localhost", "port": 8001},
28
+ "auth": {"method": "none"},
29
+ "ssl": {"enabled": False},
30
+ "security": {"enabled": False},
31
+ }
32
+
33
+ cli = VectorizationCLI()
34
+
35
+ try:
36
+ # Connect to service
37
+ print("šŸ”Œ Connecting to embedding service...")
38
+ if not await cli.connect(config):
39
+ print("āŒ Failed to connect to service")
40
+ return
41
+
42
+ # Health check
43
+ print("\nšŸ„ Checking service health...")
44
+ await cli.health_check()
45
+
46
+ # Get help
47
+ print("\nā“ Getting help from service...")
48
+ await cli.get_help()
49
+
50
+ # Get commands
51
+ print("\nšŸ“‹ Getting available commands...")
52
+ await cli.get_commands()
53
+
54
+ # Vectorize texts
55
+ print("\nšŸ”¤ Vectorizing texts...")
56
+ texts = ["Hello world", "This is a test", "Machine learning is awesome"]
57
+
58
+ print(f"šŸ“ Vectorizing {len(texts)} texts:")
59
+ for i, text in enumerate(texts):
60
+ print(f" {i+1}. {text}")
61
+
62
+ await cli.vectorize_texts(texts, "json")
63
+
64
+ print("\nāœ… Demo completed successfully!")
65
+
66
+ except Exception as e:
67
+ print(f"āŒ Demo failed: {e}")
68
+ finally:
69
+ await cli.disconnect()
70
+
71
+
72
+ async def main():
73
+ """Main demo function."""
74
+ await demo_vectorization()
75
+
76
+
77
+ if __name__ == "__main__":
78
+ asyncio.run(main())
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Demo Security CLI Application
4
+ Demonstrates all 8 security modes using the security CLI.
5
+
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+
10
+ import asyncio
11
+ import sys
12
+ from pathlib import Path
13
+
14
+ # Add the project root to the path
15
+ sys.path.insert(0, str(Path(__file__).parent.parent))
16
+
17
+ from embed_client.security_cli import ( # noqa: E402
18
+ SecurityCLI,
19
+ create_config_from_security_mode,
20
+ )
21
+
22
+
23
+ async def demo_security_mode(mode: str, host: str, port: int, **kwargs):
24
+ """Demonstrate a specific security mode."""
25
+ print(f"\nšŸ” Demonstrating {mode} mode...")
26
+ print("=" * 50)
27
+
28
+ # Create configuration
29
+ config = create_config_from_security_mode(mode, host, port, **kwargs)
30
+
31
+ cli = SecurityCLI()
32
+
33
+ try:
34
+ # Connect to service
35
+ print(f"šŸ”Œ Connecting using {mode} mode...")
36
+ if not await cli.connect(config):
37
+ print(f"āŒ Failed to connect using {mode} mode")
38
+ return False
39
+
40
+ # Health check
41
+ print("šŸ„ Checking service health...")
42
+ health_ok = await cli.health_check()
43
+ if not health_ok:
44
+ print(f"āŒ Health check failed for {mode} mode")
45
+ return False
46
+
47
+ # Get help
48
+ print("ā“ Getting help from service...")
49
+ await cli.get_help()
50
+
51
+ # Get commands
52
+ print("šŸ“‹ Getting available commands...")
53
+ await cli.get_commands()
54
+
55
+ # Vectorize texts
56
+ texts = [
57
+ f"Hello from {mode} mode",
58
+ f"Security test for {mode}",
59
+ f"Vectorization using {mode}",
60
+ ]
61
+
62
+ print(f"šŸ”¤ Vectorizing {len(texts)} texts using {mode} mode...")
63
+ for i, text in enumerate(texts):
64
+ print(f" {i+1}. {text}")
65
+
66
+ # Test different output formats
67
+ print("\nšŸ“Š Testing JSON format:")
68
+ await cli.vectorize_texts(texts, "json")
69
+
70
+ print("\nšŸ“Š Testing CSV format:")
71
+ await cli.vectorize_texts(texts, "csv")
72
+
73
+ print("\nšŸ“Š Testing vectors format:")
74
+ await cli.vectorize_texts(texts, "vectors")
75
+
76
+ print(f"āœ… {mode} mode demonstration completed successfully!")
77
+ return True
78
+
79
+ except Exception as e:
80
+ print(f"āŒ {mode} mode demonstration failed: {e}")
81
+ return False
82
+ finally:
83
+ await cli.disconnect()
84
+
85
+
86
+ async def demo_all_security_modes():
87
+ """Demonstrate all 8 security modes."""
88
+ print("šŸš€ Security CLI Demo - All 8 Security Modes")
89
+ print("=" * 60)
90
+
91
+ # Demo configurations for each mode
92
+ demos = [
93
+ {
94
+ "mode": "http",
95
+ "host": "localhost",
96
+ "port": 10001,
97
+ "description": "Plain HTTP without authentication",
98
+ },
99
+ {
100
+ "mode": "http_token",
101
+ "host": "localhost",
102
+ "port": 10002,
103
+ "api_key": "admin-secret-key",
104
+ "description": "HTTP with API Key authentication",
105
+ },
106
+ {
107
+ "mode": "http_token_roles",
108
+ "host": "localhost",
109
+ "port": 10003,
110
+ "api_key": "admin-secret-key",
111
+ "description": "HTTP with API Key and role-based access control",
112
+ },
113
+ {
114
+ "mode": "https",
115
+ "host": "localhost",
116
+ "port": 10011,
117
+ "cert_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/server/embedding-service.crt",
118
+ "key_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/server/embedding-service.key",
119
+ "description": "HTTPS with server certificate verification",
120
+ },
121
+ {
122
+ "mode": "https_token",
123
+ "host": "localhost",
124
+ "port": 10012,
125
+ "api_key": "admin-secret-key",
126
+ "cert_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/server/embedding-service.crt",
127
+ "key_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/server/embedding-service.key",
128
+ "description": "HTTPS with server certificates + authentication",
129
+ },
130
+ {
131
+ "mode": "https_token_roles",
132
+ "host": "localhost",
133
+ "port": 10013,
134
+ "api_key": "admin-secret-key",
135
+ "cert_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/server/embedding-service.crt",
136
+ "key_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/server/embedding-service.key",
137
+ "description": "HTTPS with server certificates + authentication + roles",
138
+ },
139
+ {
140
+ "mode": "mtls",
141
+ "host": "localhost",
142
+ "port": 10021,
143
+ "cert_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/client/embedding-service.crt",
144
+ "key_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/client/embedding-service.key",
145
+ "ca_cert_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/ca/ca.crt",
146
+ "description": "Mutual TLS with client and server certificates",
147
+ },
148
+ {
149
+ "mode": "mtls_roles",
150
+ "host": "localhost",
151
+ "port": 10022,
152
+ "cert_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/client/embedding-service.crt",
153
+ "key_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/client/embedding-service.key",
154
+ "ca_cert_file": "/home/vasilyvz/projects/tools/embed/mtls_certificates/ca/ca.crt",
155
+ "description": "mTLS with role-based access control",
156
+ },
157
+ ]
158
+
159
+ results = {}
160
+
161
+ for demo in demos:
162
+ mode = demo["mode"]
163
+ description = demo["description"]
164
+
165
+ print(f"\nšŸ” {mode.upper()} - {description}")
166
+ print("-" * 50)
167
+
168
+ # Extract parameters for the demo
169
+ demo_params = {
170
+ k: v
171
+ for k, v in demo.items()
172
+ if k not in ["mode", "host", "port", "description"]
173
+ }
174
+
175
+ success = await demo_security_mode(
176
+ demo["mode"], demo["host"], demo["port"], **demo_params
177
+ )
178
+
179
+ results[mode] = success
180
+
181
+ # Print summary
182
+ print("\nšŸ“Š Demo Results Summary:")
183
+ print("=" * 50)
184
+ for mode, success in results.items():
185
+ status = "āœ… SUCCESS" if success else "āŒ FAILED"
186
+ print(f"{mode:20} {status}")
187
+
188
+ total_demos = len(results)
189
+ successful_demos = sum(1 for success in results.values() if success)
190
+ failed_demos = total_demos - successful_demos
191
+
192
+ print("\nšŸŽ‰ Demo completed!")
193
+ print(f"šŸ“Š Results: {successful_demos}/{total_demos} demos successful")
194
+ if failed_demos > 0:
195
+ print(f"āŒ {failed_demos} demos failed")
196
+ else:
197
+ print("āœ… All demos successful!")
198
+
199
+
200
+ async def main():
201
+ """Main demo function."""
202
+ await demo_all_security_modes()
203
+
204
+
205
+ if __name__ == "__main__":
206
+ asyncio.run(main())