matrixone-python-sdk 0.1.0__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 (122) hide show
  1. matrixone/__init__.py +155 -0
  2. matrixone/account.py +723 -0
  3. matrixone/async_client.py +3913 -0
  4. matrixone/async_metadata_manager.py +311 -0
  5. matrixone/async_orm.py +123 -0
  6. matrixone/async_vector_index_manager.py +633 -0
  7. matrixone/base_client.py +208 -0
  8. matrixone/client.py +4672 -0
  9. matrixone/config.py +452 -0
  10. matrixone/connection_hooks.py +286 -0
  11. matrixone/exceptions.py +89 -0
  12. matrixone/logger.py +782 -0
  13. matrixone/metadata.py +820 -0
  14. matrixone/moctl.py +219 -0
  15. matrixone/orm.py +2277 -0
  16. matrixone/pitr.py +646 -0
  17. matrixone/pubsub.py +771 -0
  18. matrixone/restore.py +411 -0
  19. matrixone/search_vector_index.py +1176 -0
  20. matrixone/snapshot.py +550 -0
  21. matrixone/sql_builder.py +844 -0
  22. matrixone/sqlalchemy_ext/__init__.py +161 -0
  23. matrixone/sqlalchemy_ext/adapters.py +163 -0
  24. matrixone/sqlalchemy_ext/dialect.py +534 -0
  25. matrixone/sqlalchemy_ext/fulltext_index.py +895 -0
  26. matrixone/sqlalchemy_ext/fulltext_search.py +1686 -0
  27. matrixone/sqlalchemy_ext/hnsw_config.py +194 -0
  28. matrixone/sqlalchemy_ext/ivf_config.py +252 -0
  29. matrixone/sqlalchemy_ext/table_builder.py +351 -0
  30. matrixone/sqlalchemy_ext/vector_index.py +1721 -0
  31. matrixone/sqlalchemy_ext/vector_type.py +948 -0
  32. matrixone/version.py +580 -0
  33. matrixone_python_sdk-0.1.0.dist-info/METADATA +706 -0
  34. matrixone_python_sdk-0.1.0.dist-info/RECORD +122 -0
  35. matrixone_python_sdk-0.1.0.dist-info/WHEEL +5 -0
  36. matrixone_python_sdk-0.1.0.dist-info/entry_points.txt +5 -0
  37. matrixone_python_sdk-0.1.0.dist-info/licenses/LICENSE +200 -0
  38. matrixone_python_sdk-0.1.0.dist-info/top_level.txt +2 -0
  39. tests/__init__.py +19 -0
  40. tests/offline/__init__.py +20 -0
  41. tests/offline/conftest.py +77 -0
  42. tests/offline/test_account.py +703 -0
  43. tests/offline/test_async_client_query_comprehensive.py +1218 -0
  44. tests/offline/test_basic.py +54 -0
  45. tests/offline/test_case_sensitivity.py +227 -0
  46. tests/offline/test_connection_hooks_offline.py +287 -0
  47. tests/offline/test_dialect_schema_handling.py +609 -0
  48. tests/offline/test_explain_methods.py +346 -0
  49. tests/offline/test_filter_logical_in.py +237 -0
  50. tests/offline/test_fulltext_search_comprehensive.py +795 -0
  51. tests/offline/test_ivf_config.py +249 -0
  52. tests/offline/test_join_methods.py +281 -0
  53. tests/offline/test_join_sqlalchemy_compatibility.py +276 -0
  54. tests/offline/test_logical_in_method.py +237 -0
  55. tests/offline/test_matrixone_version_parsing.py +264 -0
  56. tests/offline/test_metadata_offline.py +557 -0
  57. tests/offline/test_moctl.py +300 -0
  58. tests/offline/test_moctl_simple.py +251 -0
  59. tests/offline/test_model_support_offline.py +359 -0
  60. tests/offline/test_model_support_simple.py +225 -0
  61. tests/offline/test_pinecone_filter_offline.py +377 -0
  62. tests/offline/test_pitr.py +585 -0
  63. tests/offline/test_pubsub.py +712 -0
  64. tests/offline/test_query_update.py +283 -0
  65. tests/offline/test_restore.py +445 -0
  66. tests/offline/test_snapshot_comprehensive.py +384 -0
  67. tests/offline/test_sql_escaping_edge_cases.py +551 -0
  68. tests/offline/test_sqlalchemy_integration.py +382 -0
  69. tests/offline/test_sqlalchemy_vector_integration.py +434 -0
  70. tests/offline/test_table_builder.py +198 -0
  71. tests/offline/test_unified_filter.py +398 -0
  72. tests/offline/test_unified_transaction.py +495 -0
  73. tests/offline/test_vector_index.py +238 -0
  74. tests/offline/test_vector_operations.py +688 -0
  75. tests/offline/test_vector_type.py +174 -0
  76. tests/offline/test_version_core.py +328 -0
  77. tests/offline/test_version_management.py +372 -0
  78. tests/offline/test_version_standalone.py +652 -0
  79. tests/online/__init__.py +20 -0
  80. tests/online/conftest.py +216 -0
  81. tests/online/test_account_management.py +194 -0
  82. tests/online/test_advanced_features.py +344 -0
  83. tests/online/test_async_client_interfaces.py +330 -0
  84. tests/online/test_async_client_online.py +285 -0
  85. tests/online/test_async_model_insert_online.py +293 -0
  86. tests/online/test_async_orm_online.py +300 -0
  87. tests/online/test_async_simple_query_online.py +802 -0
  88. tests/online/test_async_transaction_simple_query.py +300 -0
  89. tests/online/test_basic_connection.py +130 -0
  90. tests/online/test_client_online.py +238 -0
  91. tests/online/test_config.py +90 -0
  92. tests/online/test_config_validation.py +123 -0
  93. tests/online/test_connection_hooks_new_online.py +217 -0
  94. tests/online/test_dialect_schema_handling_online.py +331 -0
  95. tests/online/test_filter_logical_in_online.py +374 -0
  96. tests/online/test_fulltext_comprehensive.py +1773 -0
  97. tests/online/test_fulltext_label_online.py +433 -0
  98. tests/online/test_fulltext_search_online.py +842 -0
  99. tests/online/test_ivf_stats_online.py +506 -0
  100. tests/online/test_logger_integration.py +311 -0
  101. tests/online/test_matrixone_query_orm.py +540 -0
  102. tests/online/test_metadata_online.py +579 -0
  103. tests/online/test_model_insert_online.py +255 -0
  104. tests/online/test_mysql_driver_validation.py +213 -0
  105. tests/online/test_orm_advanced_features.py +2022 -0
  106. tests/online/test_orm_cte_integration.py +269 -0
  107. tests/online/test_orm_online.py +270 -0
  108. tests/online/test_pinecone_filter.py +708 -0
  109. tests/online/test_pubsub_operations.py +352 -0
  110. tests/online/test_query_methods.py +225 -0
  111. tests/online/test_query_update_online.py +433 -0
  112. tests/online/test_search_vector_index.py +557 -0
  113. tests/online/test_simple_fulltext_online.py +915 -0
  114. tests/online/test_snapshot_comprehensive.py +998 -0
  115. tests/online/test_sqlalchemy_engine_integration.py +336 -0
  116. tests/online/test_sqlalchemy_integration.py +425 -0
  117. tests/online/test_transaction_contexts.py +1219 -0
  118. tests/online/test_transaction_insert_methods.py +356 -0
  119. tests/online/test_transaction_query_methods.py +288 -0
  120. tests/online/test_unified_filter_online.py +529 -0
  121. tests/online/test_vector_comprehensive.py +706 -0
  122. tests/online/test_version_management.py +291 -0
@@ -0,0 +1,174 @@
1
+ # Copyright 2021 - 2022 Matrix Origin
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Offline tests for VectorType SQLAlchemy integration.
17
+ """
18
+
19
+ import pytest
20
+ import sys
21
+ from unittest.mock import Mock
22
+ from matrixone.sqlalchemy_ext import VectorType, Vectorf32, Vectorf64, VectorTypeDecorator
23
+
24
+ pytestmark = pytest.mark.vector
25
+
26
+ # No longer needed - global mocks have been fixed
27
+
28
+
29
+ class TestVectorType:
30
+ """Test VectorType functionality."""
31
+
32
+ def test_vector_type_creation(self):
33
+ """Test VectorType creation with different parameters."""
34
+ # Test with dimension
35
+ vec_type = VectorType(dimension=128, precision="f32")
36
+ assert vec_type.dimension == 128
37
+ assert vec_type.precision == "f32"
38
+
39
+ # Test without dimension
40
+ vec_type_no_dim = VectorType(precision="f64")
41
+ assert vec_type_no_dim.dimension is None
42
+ assert vec_type_no_dim.precision == "f64"
43
+
44
+ def test_vector_type_column_spec(self):
45
+ """Test VectorType column specification."""
46
+ # Test with dimension
47
+ vec_type = VectorType(dimension=64, precision="f32")
48
+ spec = vec_type.get_col_spec()
49
+ assert spec == "vecf32(64)"
50
+
51
+ # Test without dimension
52
+ vec_type_no_dim = VectorType(precision="f64")
53
+ spec = vec_type_no_dim.get_col_spec()
54
+ assert spec == "vecf64"
55
+
56
+ def test_vector_type_bind_processor(self):
57
+ """Test VectorType bind processor."""
58
+ vec_type = VectorType(dimension=3, precision="f32")
59
+ processor = vec_type.bind_processor(None)
60
+
61
+ # Test with list
62
+ result = processor([1.0, 2.0, 3.0])
63
+ assert result == "[1.0,2.0,3.0]"
64
+
65
+ # Test with string
66
+ result = processor("[1.0,2.0,3.0]")
67
+ assert result == "[1.0,2.0,3.0]"
68
+
69
+ # Test with None
70
+ result = processor(None)
71
+ assert result is None
72
+
73
+ def test_vector_type_result_processor(self):
74
+ """Test VectorType result processor."""
75
+ vec_type = VectorType(dimension=3, precision="f32")
76
+ processor = vec_type.result_processor(None, None)
77
+
78
+ # Test with vector string
79
+ result = processor("[1.0,2.0,3.0]")
80
+ assert result == [1.0, 2.0, 3.0]
81
+
82
+ # Test with empty vector
83
+ result = processor("[]")
84
+ assert result == []
85
+
86
+ # Test with None
87
+ result = processor(None)
88
+ assert result is None
89
+
90
+ def test_vectorf32_convenience_class(self):
91
+ """Test Vectorf32 convenience class."""
92
+ vec32 = Vectorf32(dimension=64)
93
+ assert vec32.dimension == 64
94
+ assert vec32.precision == "f32"
95
+
96
+ spec = vec32.get_col_spec()
97
+ assert spec == "vecf32(64)"
98
+
99
+ def test_vectorf64_convenience_class(self):
100
+ """Test Vectorf64 convenience class."""
101
+ vec64 = Vectorf64(dimension=128)
102
+ assert vec64.dimension == 128
103
+ assert vec64.precision == "f64"
104
+
105
+ spec = vec64.get_col_spec()
106
+ assert spec == "vecf64(128)"
107
+
108
+ def test_vector_type_decorator(self):
109
+ """Test VectorTypeDecorator functionality."""
110
+ decorator = VectorTypeDecorator(dimension=256, precision="f32")
111
+ assert decorator.dimension == 256
112
+ assert decorator.precision == "f32"
113
+
114
+ def test_vector_type_decorator_bind_processing(self):
115
+ """Test VectorTypeDecorator bind parameter processing."""
116
+ decorator = VectorTypeDecorator(dimension=3, precision="f32")
117
+
118
+ # Test with list
119
+ result = decorator.process_bind_param([1.0, 2.0, 3.0], None)
120
+ assert result == "[1.0,2.0,3.0]"
121
+
122
+ # Test with string
123
+ result = decorator.process_bind_param("[1.0,2.0,3.0]", None)
124
+ assert result == "[1.0,2.0,3.0]"
125
+
126
+ # Test with None
127
+ result = decorator.process_bind_param(None, None)
128
+ assert result is None
129
+
130
+ def test_vector_type_decorator_result_processing(self):
131
+ """Test VectorTypeDecorator result processing."""
132
+ decorator = VectorTypeDecorator(dimension=3, precision="f32")
133
+
134
+ # Test with vector string
135
+ result = decorator.process_result_value("[1.0,2.0,3.0]", None)
136
+ assert result == [1.0, 2.0, 3.0]
137
+
138
+ # Test with empty vector
139
+ result = decorator.process_result_value("[]", None)
140
+ assert result == []
141
+
142
+ # Test with None
143
+ result = decorator.process_result_value(None, None)
144
+ assert result is None
145
+
146
+ def test_vector_type_repr(self):
147
+ """Test VectorType string representation."""
148
+ # Test with dimension
149
+ vec_type = VectorType(dimension=128, precision="f32")
150
+ repr_str = repr(vec_type)
151
+ assert "VectorType" in repr_str
152
+ assert "dimension=128" in repr_str
153
+ assert "precision='f32'" in repr_str
154
+
155
+ # Test without dimension
156
+ vec_type_no_dim = VectorType(precision="f64")
157
+ repr_str = repr(vec_type_no_dim)
158
+ assert "VectorType" in repr_str
159
+ assert "precision='f64'" in repr_str
160
+
161
+ def test_vector_type_decorator_repr(self):
162
+ """Test VectorTypeDecorator string representation."""
163
+ # Test with dimension
164
+ decorator = VectorTypeDecorator(dimension=256, precision="f32")
165
+ repr_str = repr(decorator)
166
+ assert "VectorTypeDecorator" in repr_str
167
+ assert "dimension=256" in repr_str
168
+ assert "precision='f32'" in repr_str
169
+
170
+ # Test without dimension
171
+ decorator_no_dim = VectorTypeDecorator(precision="f64")
172
+ repr_str = repr(decorator_no_dim)
173
+ assert "VectorTypeDecorator" in repr_str
174
+ assert "precision='f64'" in repr_str
@@ -0,0 +1,328 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright 2021 - 2022 Matrix Origin
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ """
18
+ MatrixOne Python SDK - Version Management Core Tests
19
+
20
+ Test suite for the version management framework core functionality
21
+ (without external dependencies).
22
+ """
23
+
24
+ import unittest
25
+ import sys
26
+ import os
27
+
28
+ # Add the matrixone package to the path
29
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'matrixone'))
30
+
31
+ # Import only the version management module
32
+ from matrixone.version import (
33
+ VersionManager,
34
+ VersionInfo,
35
+ FeatureRequirement,
36
+ VersionComparison,
37
+ requires_version,
38
+ VersionError,
39
+ )
40
+
41
+
42
+ class TestVersionParsing(unittest.TestCase):
43
+ """Test version parsing functionality"""
44
+
45
+ def setUp(self):
46
+ self.version_manager = VersionManager()
47
+
48
+ def test_valid_version_parsing(self):
49
+ """Test parsing valid version strings"""
50
+ test_cases = [
51
+ ("3.0.1", VersionInfo(3, 0, 1)),
52
+ ("1.0.0", VersionInfo(1, 0, 0)),
53
+ ("10.25.100", VersionInfo(10, 25, 100)),
54
+ ("0.0.1", VersionInfo(0, 0, 1)),
55
+ ]
56
+
57
+ for version_str, expected in test_cases:
58
+ with self.subTest(version=version_str):
59
+ result = self.version_manager.parse_version(version_str)
60
+ self.assertEqual(result.major, expected.major)
61
+ self.assertEqual(result.minor, expected.minor)
62
+ self.assertEqual(result.patch, expected.patch)
63
+
64
+ def test_invalid_version_parsing(self):
65
+ """Test parsing invalid version strings"""
66
+ invalid_versions = [
67
+ "3.0", # Missing patch
68
+ "3.0.1.2", # Too many components
69
+ "3.0.a", # Non-numeric component
70
+ "3.0.1-beta", # Pre-release suffix
71
+ "", # Empty string
72
+ "invalid", # Completely invalid
73
+ ]
74
+
75
+ for invalid_version in invalid_versions:
76
+ with self.subTest(version=invalid_version):
77
+ with self.assertRaises(ValueError):
78
+ self.version_manager.parse_version(invalid_version)
79
+
80
+ def test_version_string_representation(self):
81
+ """Test version string representation"""
82
+ version = VersionInfo(3, 0, 1)
83
+ self.assertEqual(str(version), "3.0.1")
84
+
85
+
86
+ class TestVersionComparison(unittest.TestCase):
87
+ """Test version comparison functionality"""
88
+
89
+ def setUp(self):
90
+ self.version_manager = VersionManager()
91
+
92
+ def test_version_comparisons(self):
93
+ """Test various version comparisons"""
94
+ test_cases = [
95
+ # (version1, version2, expected_result)
96
+ ("3.0.2", "3.0.1", VersionComparison.GREATER),
97
+ ("3.0.1", "3.0.2", VersionComparison.LESS),
98
+ ("3.0.1", "3.0.1", VersionComparison.EQUAL),
99
+ ("2.1.19", "3.0.9", VersionComparison.LESS),
100
+ ("3.0.9", "2.1.19", VersionComparison.GREATER),
101
+ ("1.0.0", "2.0.0", VersionComparison.LESS),
102
+ ("2.0.0", "1.9.9", VersionComparison.GREATER),
103
+ ]
104
+
105
+ for v1, v2, expected in test_cases:
106
+ with self.subTest(v1=v1, v2=v2):
107
+ result = self.version_manager.compare_versions(v1, v2)
108
+ self.assertEqual(result, expected)
109
+
110
+ def test_version_compatibility_checks(self):
111
+ """Test version compatibility checking"""
112
+ self.version_manager.set_backend_version("3.0.1")
113
+
114
+ # Test >= operator
115
+ self.assertTrue(self.version_manager.is_version_compatible("3.0.0", operator=">="))
116
+ self.assertTrue(self.version_manager.is_version_compatible("3.0.1", operator=">="))
117
+ self.assertFalse(self.version_manager.is_version_compatible("3.0.2", operator=">="))
118
+
119
+ # Test > operator
120
+ self.assertTrue(self.version_manager.is_version_compatible("3.0.0", operator=">"))
121
+ self.assertFalse(self.version_manager.is_version_compatible("3.0.1", operator=">"))
122
+ self.assertFalse(self.version_manager.is_version_compatible("3.0.2", operator=">"))
123
+
124
+ # Test <= operator
125
+ self.assertFalse(self.version_manager.is_version_compatible("3.0.0", operator="<="))
126
+ self.assertTrue(self.version_manager.is_version_compatible("3.0.1", operator="<="))
127
+ self.assertTrue(self.version_manager.is_version_compatible("3.0.2", operator="<="))
128
+
129
+ # Test < operator
130
+ self.assertFalse(self.version_manager.is_version_compatible("3.0.0", operator="<"))
131
+ self.assertFalse(self.version_manager.is_version_compatible("3.0.1", operator="<"))
132
+ self.assertTrue(self.version_manager.is_version_compatible("3.0.2", operator="<"))
133
+
134
+ # Test == operator
135
+ self.assertFalse(self.version_manager.is_version_compatible("3.0.0", operator="=="))
136
+ self.assertTrue(self.version_manager.is_version_compatible("3.0.1", operator="=="))
137
+ self.assertFalse(self.version_manager.is_version_compatible("3.0.2", operator="=="))
138
+
139
+ # Test != operator
140
+ self.assertTrue(self.version_manager.is_version_compatible("3.0.0", operator="!="))
141
+ self.assertFalse(self.version_manager.is_version_compatible("3.0.1", operator="!="))
142
+ self.assertTrue(self.version_manager.is_version_compatible("3.0.2", operator="!="))
143
+
144
+
145
+ class TestFeatureRequirements(unittest.TestCase):
146
+ """Test feature requirement functionality"""
147
+
148
+ def setUp(self):
149
+ self.version_manager = VersionManager()
150
+
151
+ def test_feature_registration_and_availability(self):
152
+ """Test feature registration and availability checking"""
153
+ # Register a feature requirement
154
+ feature = FeatureRequirement(
155
+ feature_name="test_feature",
156
+ min_version=VersionInfo(3, 0, 0),
157
+ max_version=VersionInfo(3, 5, 0),
158
+ description="Test feature",
159
+ alternative="Use alternative_feature instead",
160
+ )
161
+ self.version_manager.register_feature_requirement(feature)
162
+
163
+ # Test with compatible version
164
+ self.version_manager.set_backend_version("3.1.0")
165
+ self.assertTrue(self.version_manager.is_feature_available("test_feature"))
166
+
167
+ # Test with version too low
168
+ self.version_manager.set_backend_version("2.9.0")
169
+ self.assertFalse(self.version_manager.is_feature_available("test_feature"))
170
+
171
+ # Test with version too high
172
+ self.version_manager.set_backend_version("3.6.0")
173
+ self.assertFalse(self.version_manager.is_feature_available("test_feature"))
174
+
175
+ def test_feature_info_retrieval(self):
176
+ """Test feature information retrieval"""
177
+ feature = FeatureRequirement(
178
+ feature_name="info_test",
179
+ min_version=VersionInfo(2, 0, 0),
180
+ description="Information test feature",
181
+ alternative="Alternative approach",
182
+ )
183
+ self.version_manager.register_feature_requirement(feature)
184
+
185
+ retrieved = self.version_manager.get_feature_info("info_test")
186
+ self.assertIsNotNone(retrieved)
187
+ self.assertEqual(retrieved.feature_name, "info_test")
188
+ self.assertEqual(retrieved.description, "Information test feature")
189
+ self.assertEqual(retrieved.alternative, "Alternative approach")
190
+
191
+ # Test non-existent feature
192
+ self.assertIsNone(self.version_manager.get_feature_info("non_existent"))
193
+
194
+ def test_version_hints(self):
195
+ """Test version hint generation"""
196
+ self.version_manager.register_feature_requirement(
197
+ FeatureRequirement(
198
+ feature_name="hint_test",
199
+ min_version=VersionInfo(3, 0, 0),
200
+ description="Hint test feature",
201
+ alternative="Use hint_alternative",
202
+ )
203
+ )
204
+
205
+ # Test with version too low
206
+ self.version_manager.set_backend_version("2.5.0")
207
+ hint = self.version_manager.get_version_hint("hint_test", "Test context")
208
+
209
+ self.assertIn("3.0.0", hint)
210
+ self.assertIn("2.5.0", hint)
211
+ self.assertIn("hint_alternative", hint)
212
+ self.assertIn("Test context", hint)
213
+
214
+
215
+ class TestVersionDecorator(unittest.TestCase):
216
+ """Test version checking decorator"""
217
+
218
+ def test_successful_version_check(self):
219
+ """Test successful version check"""
220
+
221
+ class TestClass:
222
+ def __init__(self):
223
+ # Set global version manager
224
+ from matrixone.version import _version_manager
225
+
226
+ _version_manager.set_backend_version("3.0.0")
227
+
228
+ @requires_version(min_version="2.0.0", feature_name="test_feature", description="Test feature")
229
+ def test_method(self):
230
+ return "success"
231
+
232
+ obj = TestClass()
233
+ result = obj.test_method()
234
+ self.assertEqual(result, "success")
235
+
236
+ def test_failed_version_check(self):
237
+ """Test failed version check"""
238
+
239
+ class TestClass:
240
+ def __init__(self):
241
+ # Set global version manager
242
+ from matrixone.version import _version_manager
243
+
244
+ _version_manager.set_backend_version("1.0.0")
245
+
246
+ @requires_version(
247
+ min_version="2.0.0",
248
+ feature_name="test_feature",
249
+ description="Test feature",
250
+ alternative="Use alternative method",
251
+ )
252
+ def test_method(self):
253
+ return "success"
254
+
255
+ obj = TestClass()
256
+ with self.assertRaises(VersionError):
257
+ obj.test_method()
258
+
259
+ def test_version_range_check(self):
260
+ """Test version range checking"""
261
+
262
+ class TestClass:
263
+ def __init__(self, version):
264
+ # Set global version manager
265
+ from matrixone.version import _version_manager
266
+
267
+ _version_manager.set_backend_version(version)
268
+
269
+ @requires_version(
270
+ min_version="2.0.0",
271
+ max_version="2.9.9",
272
+ feature_name="legacy_feature",
273
+ description="Legacy feature",
274
+ )
275
+ def legacy_method(self):
276
+ return "legacy success"
277
+
278
+ # Test within range
279
+ obj = TestClass("2.5.0")
280
+ result = obj.legacy_method()
281
+ self.assertEqual(result, "legacy success")
282
+
283
+ # Test below range
284
+ obj = TestClass("1.9.0")
285
+ with self.assertRaises(VersionError):
286
+ obj.legacy_method()
287
+
288
+ # Test above range
289
+ obj = TestClass("3.0.0")
290
+ with self.assertRaises(VersionError):
291
+ obj.legacy_method()
292
+
293
+
294
+ def run_tests():
295
+ """Run all tests"""
296
+ # Create test suite
297
+ test_suite = unittest.TestSuite()
298
+
299
+ # Add test classes
300
+ test_classes = [
301
+ TestVersionParsing,
302
+ TestVersionComparison,
303
+ TestFeatureRequirements,
304
+ TestVersionDecorator,
305
+ ]
306
+
307
+ for test_class in test_classes:
308
+ tests = unittest.TestLoader().loadTestsFromTestCase(test_class)
309
+ test_suite.addTests(tests)
310
+
311
+ # Run tests
312
+ runner = unittest.TextTestRunner(verbosity=2)
313
+ result = runner.run(test_suite)
314
+
315
+ return result.wasSuccessful()
316
+
317
+
318
+ if __name__ == "__main__":
319
+ print("MatrixOne Python SDK - Version Management Core Test Suite")
320
+ print("=" * 60)
321
+
322
+ success = run_tests()
323
+
324
+ if success:
325
+ print("\n✓ All tests passed!")
326
+ else:
327
+ print("\n✗ Some tests failed!")
328
+ sys.exit(1)