matrice-inference 0.1.33__tar.gz

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 (50) hide show
  1. matrice_inference-0.1.33/LICENSE.txt +21 -0
  2. matrice_inference-0.1.33/PKG-INFO +28 -0
  3. matrice_inference-0.1.33/README.md +2 -0
  4. matrice_inference-0.1.33/matrice_inference.egg-info/PKG-INFO +28 -0
  5. matrice_inference-0.1.33/matrice_inference.egg-info/SOURCES.txt +48 -0
  6. matrice_inference-0.1.33/matrice_inference.egg-info/dependency_links.txt +1 -0
  7. matrice_inference-0.1.33/matrice_inference.egg-info/not-zip-safe +1 -0
  8. matrice_inference-0.1.33/matrice_inference.egg-info/top_level.txt +1 -0
  9. matrice_inference-0.1.33/pyproject.toml +32 -0
  10. matrice_inference-0.1.33/setup.cfg +4 -0
  11. matrice_inference-0.1.33/setup.py +322 -0
  12. matrice_inference-0.1.33/src/matrice_inference/__init__.py +91 -0
  13. matrice_inference-0.1.33/src/matrice_inference/py.typed +0 -0
  14. matrice_inference-0.1.33/src/matrice_inference/server/__init__.py +29 -0
  15. matrice_inference-0.1.33/src/matrice_inference/server/inference_interface.py +176 -0
  16. matrice_inference-0.1.33/src/matrice_inference/server/model/__init__.py +1 -0
  17. matrice_inference-0.1.33/src/matrice_inference/server/model/model_manager.py +274 -0
  18. matrice_inference-0.1.33/src/matrice_inference/server/model/model_manager_wrapper.py +602 -0
  19. matrice_inference-0.1.33/src/matrice_inference/server/model/triton_model_manager.py +385 -0
  20. matrice_inference-0.1.33/src/matrice_inference/server/model/triton_server.py +1262 -0
  21. matrice_inference-0.1.33/src/matrice_inference/server/proxy_interface.py +371 -0
  22. matrice_inference-0.1.33/src/matrice_inference/server/server.py +1149 -0
  23. matrice_inference-0.1.33/src/matrice_inference/server/stream/__init__.py +0 -0
  24. matrice_inference-0.1.33/src/matrice_inference/server/stream/analytics_publisher.py +525 -0
  25. matrice_inference-0.1.33/src/matrice_inference/server/stream/app_deployment.py +1072 -0
  26. matrice_inference-0.1.33/src/matrice_inference/server/stream/app_event_listener.py +148 -0
  27. matrice_inference-0.1.33/src/matrice_inference/server/stream/camera_config_monitor.py +564 -0
  28. matrice_inference-0.1.33/src/matrice_inference/server/stream/consumer_worker.py +574 -0
  29. matrice_inference-0.1.33/src/matrice_inference/server/stream/deployment_refresh_listener.py +303 -0
  30. matrice_inference-0.1.33/src/matrice_inference/server/stream/frame_cache.py +350 -0
  31. matrice_inference-0.1.33/src/matrice_inference/server/stream/inference_metric_logger.py +534 -0
  32. matrice_inference-0.1.33/src/matrice_inference/server/stream/inference_worker.py +285 -0
  33. matrice_inference-0.1.33/src/matrice_inference/server/stream/metric_publisher.py +265 -0
  34. matrice_inference-0.1.33/src/matrice_inference/server/stream/post_processing_worker.py +429 -0
  35. matrice_inference-0.1.33/src/matrice_inference/server/stream/producer_worker.py +352 -0
  36. matrice_inference-0.1.33/src/matrice_inference/server/stream/stream_pipeline.py +896 -0
  37. matrice_inference-0.1.33/src/matrice_inference/server/stream/utils.py +23 -0
  38. matrice_inference-0.1.33/src/matrice_inference/server/stream/worker_metrics.py +441 -0
  39. matrice_inference-0.1.33/src/matrice_inference/tmp/abstract_model_manager.py +58 -0
  40. matrice_inference-0.1.33/src/matrice_inference/tmp/aggregator/__init__.py +18 -0
  41. matrice_inference-0.1.33/src/matrice_inference/tmp/aggregator/aggregator.py +330 -0
  42. matrice_inference-0.1.33/src/matrice_inference/tmp/aggregator/analytics.py +906 -0
  43. matrice_inference-0.1.33/src/matrice_inference/tmp/aggregator/ingestor.py +438 -0
  44. matrice_inference-0.1.33/src/matrice_inference/tmp/aggregator/latency.py +597 -0
  45. matrice_inference-0.1.33/src/matrice_inference/tmp/aggregator/pipeline.py +968 -0
  46. matrice_inference-0.1.33/src/matrice_inference/tmp/aggregator/publisher.py +431 -0
  47. matrice_inference-0.1.33/src/matrice_inference/tmp/aggregator/synchronizer.py +594 -0
  48. matrice_inference-0.1.33/src/matrice_inference/tmp/batch_manager.py +239 -0
  49. matrice_inference-0.1.33/src/matrice_inference/tmp/overall_inference_testing.py +334 -0
  50. matrice_inference-0.1.33/src/matrice_inference/tmp/triton_utils.py +638 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Matrice.ai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.4
2
+ Name: matrice_inference
3
+ Version: 0.1.33
4
+ Summary: Common server utilities for Matrice.ai services
5
+ Author-email: "Matrice.ai" <dipendra@matrice.ai>
6
+ License-Expression: MIT
7
+ Keywords: matrice,common,utilities,pyarmor,obfuscated
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Classifier: Operating System :: MacOS
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE.txt
24
+ Dynamic: license-file
25
+ Dynamic: requires-python
26
+
27
+
28
+ # matrice\_inference
@@ -0,0 +1,2 @@
1
+
2
+ # matrice\_inference
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.4
2
+ Name: matrice_inference
3
+ Version: 0.1.33
4
+ Summary: Common server utilities for Matrice.ai services
5
+ Author-email: "Matrice.ai" <dipendra@matrice.ai>
6
+ License-Expression: MIT
7
+ Keywords: matrice,common,utilities,pyarmor,obfuscated
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Classifier: Operating System :: MacOS
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE.txt
24
+ Dynamic: license-file
25
+ Dynamic: requires-python
26
+
27
+
28
+ # matrice\_inference
@@ -0,0 +1,48 @@
1
+ LICENSE.txt
2
+ README.md
3
+ pyproject.toml
4
+ setup.py
5
+ matrice_inference.egg-info/PKG-INFO
6
+ matrice_inference.egg-info/SOURCES.txt
7
+ matrice_inference.egg-info/dependency_links.txt
8
+ matrice_inference.egg-info/not-zip-safe
9
+ matrice_inference.egg-info/top_level.txt
10
+ src/matrice_inference/__init__.py
11
+ src/matrice_inference/py.typed
12
+ src/matrice_inference/server/__init__.py
13
+ src/matrice_inference/server/inference_interface.py
14
+ src/matrice_inference/server/proxy_interface.py
15
+ src/matrice_inference/server/server.py
16
+ src/matrice_inference/server/model/__init__.py
17
+ src/matrice_inference/server/model/model_manager.py
18
+ src/matrice_inference/server/model/model_manager_wrapper.py
19
+ src/matrice_inference/server/model/triton_model_manager.py
20
+ src/matrice_inference/server/model/triton_server.py
21
+ src/matrice_inference/server/stream/__init__.py
22
+ src/matrice_inference/server/stream/analytics_publisher.py
23
+ src/matrice_inference/server/stream/app_deployment.py
24
+ src/matrice_inference/server/stream/app_event_listener.py
25
+ src/matrice_inference/server/stream/camera_config_monitor.py
26
+ src/matrice_inference/server/stream/consumer_worker.py
27
+ src/matrice_inference/server/stream/deployment_refresh_listener.py
28
+ src/matrice_inference/server/stream/frame_cache.py
29
+ src/matrice_inference/server/stream/inference_metric_logger.py
30
+ src/matrice_inference/server/stream/inference_worker.py
31
+ src/matrice_inference/server/stream/metric_publisher.py
32
+ src/matrice_inference/server/stream/post_processing_worker.py
33
+ src/matrice_inference/server/stream/producer_worker.py
34
+ src/matrice_inference/server/stream/stream_pipeline.py
35
+ src/matrice_inference/server/stream/utils.py
36
+ src/matrice_inference/server/stream/worker_metrics.py
37
+ src/matrice_inference/tmp/abstract_model_manager.py
38
+ src/matrice_inference/tmp/batch_manager.py
39
+ src/matrice_inference/tmp/overall_inference_testing.py
40
+ src/matrice_inference/tmp/triton_utils.py
41
+ src/matrice_inference/tmp/aggregator/__init__.py
42
+ src/matrice_inference/tmp/aggregator/aggregator.py
43
+ src/matrice_inference/tmp/aggregator/analytics.py
44
+ src/matrice_inference/tmp/aggregator/ingestor.py
45
+ src/matrice_inference/tmp/aggregator/latency.py
46
+ src/matrice_inference/tmp/aggregator/pipeline.py
47
+ src/matrice_inference/tmp/aggregator/publisher.py
48
+ src/matrice_inference/tmp/aggregator/synchronizer.py
@@ -0,0 +1 @@
1
+ matrice_inference
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=65.0.0", "wheel", "pyarmor>=8.0.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "matrice_inference"
7
+ dynamic = ["version"]
8
+ description = "Common server utilities for Matrice.ai services"
9
+ readme = "README.md"
10
+ authors = [{ name = "Matrice.ai", email = "dipendra@matrice.ai" }]
11
+ license = "MIT"
12
+ requires-python = ">=3.8, <4"
13
+ keywords = ["matrice", "common", "utilities", "pyarmor", "obfuscated"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "Operating System :: OS Independent",
18
+ "Operating System :: POSIX :: Linux",
19
+ "Operating System :: Microsoft :: Windows",
20
+ "Operating System :: MacOS",
21
+ "Topic :: Software Development :: Libraries :: Python Modules",
22
+ "Programming Language :: Python :: 3.8",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Typing :: Typed",
28
+ ]
29
+
30
+
31
+ # PyArmor configuration is handled via pyarmor.yml file
32
+ # The [tool.pyarmor] section is not used in PyArmor 8.x
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,322 @@
1
+ import os
2
+ import shutil
3
+ import subprocess
4
+ from pathlib import Path
5
+ from setuptools import setup, find_packages
6
+ from setuptools.command.build_py import build_py as _build_py
7
+ from setuptools.command.sdist import sdist as _sdist
8
+
9
+ # Configuration of package name and source directory
10
+ PACKAGE_NAME = "matrice_inference"
11
+ SOURCE_DIR = f"src/{PACKAGE_NAME}"
12
+ OBFUSCATED_DIR = f"{PACKAGE_NAME}_obfuscated"
13
+ BUILD_DIR = "build"
14
+
15
+ # Read version from appropriate version file based on environment
16
+ def get_version():
17
+ """Get version based on environment or git branch.
18
+ If environment is dev, append 'dev' suffix automatically."""
19
+ # Check environment variable first (set by CI/CD)
20
+ env_type = os.environ.get('BUILD_ENV', '').lower()
21
+ append_dev_suffix = False
22
+
23
+ if env_type == 'dev':
24
+ version_file = "version-dev.txt"
25
+ append_dev_suffix = True
26
+ elif env_type == 'staging':
27
+ version_file = "version-staging.txt"
28
+ elif env_type == 'prod':
29
+ version_file = "version-prod.txt"
30
+ else:
31
+ # Try to detect from git branch
32
+ try:
33
+ result = subprocess.run(
34
+ ['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
35
+ capture_output=True, text=True, check=True
36
+ )
37
+ branch = result.stdout.strip()
38
+
39
+ if branch == 'dev':
40
+ version_file = "version-dev.txt"
41
+ append_dev_suffix = True
42
+ elif branch == 'staging':
43
+ version_file = "version-staging.txt"
44
+ elif branch in ['main', 'master', 'prod']:
45
+ version_file = "version-prod.txt"
46
+ else:
47
+ # Default to dev for unknown branches
48
+ version_file = "version-dev.txt"
49
+ append_dev_suffix = True
50
+ except (subprocess.CalledProcessError, FileNotFoundError):
51
+ # Default to dev if git detection fails
52
+ version_file = "version-dev.txt"
53
+ append_dev_suffix = True
54
+
55
+ # Read the determined version file
56
+ try:
57
+ with open(version_file, "r", encoding="utf-8") as f:
58
+ version = f.read().strip()
59
+ if append_dev_suffix and not version.endswith("dev"):
60
+ version = f"{version}dev"
61
+ print(f"Using version {version} from {version_file}")
62
+ return version
63
+ except FileNotFoundError:
64
+ raise FileNotFoundError(f"Version file not found: {version_file}")
65
+
66
+ VERSION = get_version()
67
+
68
+ class PyArmorBuild(_build_py):
69
+ """Custom build_py to obfuscate Python files using PyArmor."""
70
+
71
+ def run(self):
72
+ try:
73
+ # Clean up previous obfuscated files
74
+ if os.path.exists(OBFUSCATED_DIR):
75
+ shutil.rmtree(OBFUSCATED_DIR)
76
+
77
+ # Run PyArmor obfuscation
78
+ self._obfuscate_package()
79
+
80
+ # Copy obfuscated files to build directory
81
+ self._copy_obfuscated_files()
82
+
83
+ except Exception as e:
84
+ print(f"Error in PyArmorBuild: {e}")
85
+ raise
86
+
87
+ def _obfuscate_package(self):
88
+ """Obfuscate the package using PyArmor."""
89
+ print(f"Obfuscating package {PACKAGE_NAME}...")
90
+
91
+ # Check if we should skip obfuscation
92
+ skip_obfuscation = os.environ.get('SKIP_PYARMOR_OBFUSCATION', '').lower() == 'true'
93
+ if skip_obfuscation:
94
+ print("⚠ Skipping PyArmor obfuscation (SKIP_PYARMOR_OBFUSCATION=true)")
95
+ self._copy_source_files()
96
+ return
97
+
98
+ # Create output directory
99
+ os.makedirs(OBFUSCATED_DIR, exist_ok=True)
100
+
101
+ # Try obfuscating core files first (most important)
102
+ core_files = self._get_core_files()
103
+ if core_files:
104
+ print(f"Attempting to obfuscate {len(core_files)} core files first...")
105
+ success = self._obfuscate_selective(core_files)
106
+ if not success:
107
+ print("⚠ Core file obfuscation failed, falling back to copying source files")
108
+ self._copy_source_files()
109
+ return
110
+
111
+ # Try full obfuscation
112
+ cmd = [
113
+ "pyarmor",
114
+ "gen",
115
+ "--output", OBFUSCATED_DIR,
116
+ SOURCE_DIR
117
+ ]
118
+
119
+ try:
120
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
121
+ print("✓ PyArmor obfuscation completed successfully")
122
+ if result.stdout:
123
+ print(f"PyArmor output: {result.stdout}")
124
+ except subprocess.CalledProcessError as e:
125
+ error_msg = e.stderr or str(e)
126
+ print(f"⚠ PyArmor obfuscation failed: {e}")
127
+ if e.stderr:
128
+ print(f"Error details: {e.stderr}")
129
+
130
+ # Handle specific license limitation error
131
+ if "out of license" in error_msg or "license" in error_msg.lower():
132
+ print("\n" + "="*60)
133
+ print("PyArmor Trial License Limitation Detected")
134
+ print("="*60)
135
+ print("The free trial version of PyArmor has a file limit.")
136
+ print("Your package has too many files to obfuscate with the trial version.")
137
+ print("\nOptions to resolve this:")
138
+ print("1. Purchase a PyArmor license: https://pyarmor.readthedocs.io/en/stable/licenses.html")
139
+ print("2. Reduce the number of files (exclude test files, examples, etc.)")
140
+ print("3. Set environment variable: SKIP_PYARMOR_OBFUSCATION=true")
141
+ print("4. Use selective obfuscation of core files only")
142
+ print("="*60)
143
+
144
+ # Fall back to copying source files without obfuscation
145
+ print("Falling back to building package without obfuscation...")
146
+ self._copy_source_files()
147
+ return
148
+ else:
149
+ raise
150
+ except FileNotFoundError:
151
+ print("PyArmor not found. Please install PyArmor: pip install pyarmor")
152
+ raise
153
+
154
+ def _get_core_files(self):
155
+ """Get list of core files to obfuscate (excluding tests, examples)."""
156
+ core_files = []
157
+ if not os.path.exists(SOURCE_DIR):
158
+ return core_files
159
+
160
+ for root, dirs, files in os.walk(SOURCE_DIR):
161
+ # Skip test directories and other non-essential directories
162
+ dirs[:] = [d for d in dirs if not d.startswith(('test', '__pycache__', 'example', 'demo'))]
163
+
164
+ for file in files:
165
+ if file.endswith('.py') and not file.startswith('test_'):
166
+ core_files.append(os.path.join(root, file))
167
+
168
+ return core_files
169
+
170
+ def _obfuscate_selective(self, file_list):
171
+ """Obfuscate only selected files."""
172
+ print(f"Attempting selective obfuscation of {len(file_list)} files...")
173
+
174
+ # Create a temporary directory with only core files
175
+ temp_source = f"{SOURCE_DIR}_temp"
176
+ try:
177
+ if os.path.exists(temp_source):
178
+ shutil.rmtree(temp_source)
179
+
180
+ # Copy only core files maintaining structure
181
+ for file_path in file_list:
182
+ rel_path = os.path.relpath(file_path, SOURCE_DIR)
183
+ dest_path = os.path.join(temp_source, rel_path)
184
+ os.makedirs(os.path.dirname(dest_path), exist_ok=True)
185
+ shutil.copy2(file_path, dest_path)
186
+
187
+ # Try to obfuscate the reduced set
188
+ cmd = ["pyarmor", "gen", "--output", OBFUSCATED_DIR, temp_source]
189
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
190
+ print("✓ Selective obfuscation completed successfully")
191
+ return True
192
+
193
+ except subprocess.CalledProcessError as e:
194
+ print(f"✗ Selective obfuscation also failed: {e}")
195
+ return False
196
+ finally:
197
+ if os.path.exists(temp_source):
198
+ shutil.rmtree(temp_source)
199
+
200
+ def _copy_source_files(self):
201
+ """Copy source files without obfuscation as fallback."""
202
+ print("Copying source files without obfuscation...")
203
+
204
+ if os.path.exists(SOURCE_DIR):
205
+ dest_package_dir = os.path.join(OBFUSCATED_DIR, PACKAGE_NAME)
206
+ if os.path.exists(dest_package_dir):
207
+ shutil.rmtree(dest_package_dir)
208
+ shutil.copytree(SOURCE_DIR, dest_package_dir)
209
+ print(f"✓ Source files copied to {dest_package_dir}")
210
+ else:
211
+ print(f"✗ Source directory not found: {SOURCE_DIR}")
212
+
213
+ def _copy_obfuscated_files(self):
214
+ """Copy obfuscated files to build directory."""
215
+ build_package_dir = os.path.join(self.build_lib, PACKAGE_NAME)
216
+ os.makedirs(build_package_dir, exist_ok=True)
217
+
218
+ # Find the obfuscated package directory
219
+ obfuscated_package_dir = None
220
+ for root, dirs, files in os.walk(OBFUSCATED_DIR):
221
+ if PACKAGE_NAME in dirs:
222
+ obfuscated_package_dir = os.path.join(root, PACKAGE_NAME)
223
+ break
224
+
225
+ if not obfuscated_package_dir:
226
+ # Try direct path if PyArmor created it differently
227
+ obfuscated_package_dir = os.path.join(OBFUSCATED_DIR, PACKAGE_NAME)
228
+
229
+ if os.path.exists(obfuscated_package_dir):
230
+ # Copy all obfuscated files
231
+ for root, dirs, files in os.walk(obfuscated_package_dir):
232
+ for file in files:
233
+ src_path = os.path.join(root, file)
234
+ rel_path = os.path.relpath(src_path, obfuscated_package_dir)
235
+ dest_path = os.path.join(build_package_dir, rel_path)
236
+ os.makedirs(os.path.dirname(dest_path), exist_ok=True)
237
+ shutil.copy2(src_path, dest_path)
238
+
239
+ print(f"Copied obfuscated files to {build_package_dir}")
240
+ else:
241
+ print(f"Warning: Obfuscated package directory not found at {obfuscated_package_dir}")
242
+ print(f"Available directories in {OBFUSCATED_DIR}:")
243
+ if os.path.exists(OBFUSCATED_DIR):
244
+ for item in os.listdir(OBFUSCATED_DIR):
245
+ print(f" - {item}")
246
+
247
+ class PyArmorSdist(_sdist):
248
+ """Custom sdist to include obfuscated files."""
249
+
250
+ def run(self):
251
+ try:
252
+ # Run the build command first to generate obfuscated files
253
+ self.run_command("build_py")
254
+ super().run()
255
+ except Exception as e:
256
+ print(f"Error in PyArmorSdist: {e}")
257
+ raise
258
+
259
+ def find_original_packages():
260
+ """Find packages in the original source directory."""
261
+ packages = []
262
+ source_path = Path(SOURCE_DIR)
263
+ if source_path.exists():
264
+ for py_file in source_path.rglob("__init__.py"):
265
+ package_dir = py_file.parent
266
+ rel_path = package_dir.relative_to(SOURCE_DIR)
267
+ if rel_path == Path("."):
268
+ packages.append(PACKAGE_NAME)
269
+ else:
270
+ packages.append(f"{PACKAGE_NAME}.{str(rel_path).replace(os.sep, '.')}")
271
+ return packages
272
+
273
+ def get_package_data():
274
+ """Get package data for obfuscated files."""
275
+ return {
276
+ PACKAGE_NAME: [
277
+ "*.py",
278
+ "*.pyi",
279
+ "*.pyx",
280
+ "*.so",
281
+ "*.pyd",
282
+ "py.typed",
283
+ "**/*.py",
284
+ "**/*.pyi",
285
+ "**/*.pyx",
286
+ "**/*.so",
287
+ "**/*.pyd",
288
+ "**/py.typed",
289
+ "pytransform/*",
290
+ "**/*",
291
+ ],
292
+ }
293
+
294
+ # Ensure py.typed exists for type hints
295
+ def ensure_py_typed():
296
+ """Create py.typed file if it doesn't exist."""
297
+ src_py_typed = os.path.join(SOURCE_DIR, "py.typed")
298
+ if not os.path.exists(src_py_typed):
299
+ with open(src_py_typed, "w") as f:
300
+ f.write("")
301
+ print("Created py.typed file")
302
+
303
+ # Create py.typed file
304
+ ensure_py_typed()
305
+
306
+ setup(
307
+ name=PACKAGE_NAME,
308
+ version=VERSION,
309
+ packages=find_original_packages(),
310
+ package_dir={PACKAGE_NAME: SOURCE_DIR},
311
+ include_package_data=True,
312
+ package_data=get_package_data(),
313
+ cmdclass={
314
+ 'build_py': PyArmorBuild,
315
+ 'sdist': PyArmorSdist,
316
+ },
317
+ zip_safe=False,
318
+ python_requires=">=3.8",
319
+ setup_requires=[
320
+ "pyarmor>=8.0.0",
321
+ ],
322
+ )
@@ -0,0 +1,91 @@
1
+ """Module providing __init__ functionality."""
2
+
3
+ import os
4
+ import sys
5
+ import platform
6
+ import subprocess
7
+
8
+ from matrice_common.utils import dependencies_check
9
+
10
+ base = [
11
+ "httpx",
12
+ "fastapi",
13
+ "uvicorn",
14
+ "pillow",
15
+ "confluent_kafka[snappy]",
16
+ "aiokafka",
17
+ "aiohttp",
18
+ "filterpy",
19
+ "scipy",
20
+ "scikit-learn",
21
+ "matplotlib",
22
+ "scikit-image",
23
+ "python-snappy",
24
+ "pyyaml",
25
+ "imagehash",
26
+ "Pillow",
27
+ "transformers"
28
+ ]
29
+
30
+ # Helper to attempt installation and verify importability
31
+ def _install_and_verify(pkg: str, import_name: str):
32
+ """Install a package expression and return True if the import succeeds."""
33
+ try:
34
+ if pkg=='onnxruntime-gpu':
35
+ pkg = 'onnxruntime'
36
+ __import__(pkg)
37
+ return True
38
+ except:
39
+ if dependencies_check([pkg]):
40
+ try:
41
+ __import__(import_name)
42
+ return True
43
+ except ImportError:
44
+ return False
45
+ return False
46
+
47
+ # Runtime gating for optional OCR bootstrap (default OFF), and never on Jetson
48
+ _ENABLE_OCR_BOOTSTRAP = os.getenv("MATRICE_ENABLE_OCR_BOOTSTRAP", "0")
49
+ _IS_JETSON = (platform.machine().lower() in ("aarch64", "arm64"))
50
+
51
+ print("*******************************Deployment ENV Info**********************************")
52
+ print(f"ENABLE_JETSON_PIP_SETTINGS: {_ENABLE_OCR_BOOTSTRAP}") #0 if OFF, 1 if ON, this will be set to 1 in jetson byom codebase.
53
+ print(f"IS_JETSON_ARCH?: {_IS_JETSON}") #True if Jetson, False otherwise
54
+ print("*************************************************************************************")
55
+
56
+ if not int(_ENABLE_OCR_BOOTSTRAP) and not _IS_JETSON:
57
+ # Install base dependencies first
58
+ dependencies_check(base)
59
+
60
+ if not dependencies_check(["opencv-python"]):
61
+ dependencies_check(["opencv-python-headless"])
62
+
63
+ # Attempt GPU-specific dependencies first
64
+ _gpu_ok = _install_and_verify("onnxruntime-gpu", "onnxruntime") and _install_and_verify(
65
+ "fast-plate-ocr[onnx-gpu]", "fast_plate_ocr"
66
+ )
67
+
68
+ if not _gpu_ok:
69
+ # Fallback to CPU variants
70
+ _cpu_ok = _install_and_verify("onnxruntime", "onnxruntime") and _install_and_verify(
71
+ "fast-plate-ocr[onnx]", "fast_plate_ocr"
72
+ )
73
+ if not _cpu_ok:
74
+ # Last-chance fallback without extras tag (PyPI sometimes lacks them)
75
+ _install_and_verify("fast-plate-ocr", "fast_plate_ocr")
76
+
77
+ # matrice_deps = ["matrice_common", "matrice_analytics", "matrice"]
78
+
79
+ # dependencies_check(matrice_deps)
80
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
81
+ from server.server import MatriceDeployServer # noqa: E402
82
+ from server.server import MatriceDeployServer as MatriceDeploy # noqa: E402 # Keep this for backwards compatibility
83
+ from server.inference_interface import InferenceInterface # noqa: E402
84
+ from server.proxy_interface import MatriceProxyInterface # noqa: E402
85
+
86
+ __all__ = [
87
+ "MatriceDeploy",
88
+ "MatriceDeployServer",
89
+ "InferenceInterface",
90
+ "MatriceProxyInterface",
91
+ ]
@@ -0,0 +1,29 @@
1
+ import os
2
+ import logging
3
+
4
+ # Define paths
5
+ log_path = os.path.join(os.getcwd(), "deploy_server.log")
6
+
7
+ # Create handlers explicitly
8
+ console_handler = logging.StreamHandler()
9
+ file_handler = logging.FileHandler(log_path)
10
+
11
+ # Set levels
12
+ console_handler.setLevel(logging.INFO)
13
+ file_handler.setLevel(logging.DEBUG)
14
+
15
+ # Define a formatter
16
+ formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
17
+ console_handler.setFormatter(formatter)
18
+ file_handler.setFormatter(formatter)
19
+
20
+ # Get the root logger
21
+ logger = logging.getLogger()
22
+ logger.setLevel(logging.DEBUG) # Root level must be the lowest (DEBUG)
23
+
24
+ # Optional: remove any default handlers if basicConfig was called earlier
25
+ if logger.hasHandlers():
26
+ logger.handlers.clear()
27
+
28
+ logger.addHandler(console_handler)
29
+ logger.addHandler(file_handler)