vectorwave 0.1.3__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.
- tests/__init__.py +0 -0
- tests/batch/__init__.py +0 -0
- tests/batch/test_batch.py +98 -0
- tests/core/__init__.py +0 -0
- tests/core/test_decorator.py +345 -0
- tests/database/__init__.py +0 -0
- tests/database/test_db.py +468 -0
- tests/database/test_db_search.py +163 -0
- tests/exception/__init__.py +0 -0
- tests/models/__init__.py +0 -0
- tests/models/test_db_config.py +152 -0
- tests/monitoring/__init__.py +0 -0
- tests/monitoring/test_tracer.py +202 -0
- tests/prediction/__init__.py +0 -0
- tests/vectorizer/__init__.py +0 -0
- vectorwave/__init__.py +13 -0
- vectorwave/batch/__init__.py +0 -0
- vectorwave/batch/batch.py +68 -0
- vectorwave/core/__init__.py +0 -0
- vectorwave/core/core.py +0 -0
- vectorwave/core/decorator.py +131 -0
- vectorwave/database/__init__.py +0 -0
- vectorwave/database/db.py +328 -0
- vectorwave/database/db_search.py +122 -0
- vectorwave/exception/__init__.py +0 -0
- vectorwave/exception/exceptions.py +22 -0
- vectorwave/models/__init__.py +0 -0
- vectorwave/models/db_config.py +92 -0
- vectorwave/monitoring/__init__.py +0 -0
- vectorwave/monitoring/monitoring.py +0 -0
- vectorwave/monitoring/tracer.py +131 -0
- vectorwave/prediction/__init__.py +0 -0
- vectorwave/prediction/predictor.py +0 -0
- vectorwave/vectorizer/__init__.py +0 -0
- vectorwave/vectorizer/base.py +12 -0
- vectorwave/vectorizer/factory.py +49 -0
- vectorwave/vectorizer/huggingface_vectorizer.py +33 -0
- vectorwave/vectorizer/openai_vectorizer.py +35 -0
- vectorwave-0.1.3.dist-info/METADATA +352 -0
- vectorwave-0.1.3.dist-info/RECORD +44 -0
- vectorwave-0.1.3.dist-info/WHEEL +5 -0
- vectorwave-0.1.3.dist-info/licenses/LICENSE +21 -0
- vectorwave-0.1.3.dist-info/licenses/NOTICE +31 -0
- vectorwave-0.1.3.dist-info/top_level.txt +2 -0
tests/__init__.py
ADDED
|
File without changes
|
tests/batch/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from unittest.mock import MagicMock
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from vectorwave.batch.batch import get_batch_manager
|
|
5
|
+
from vectorwave.exception.exceptions import WeaviateConnectionError
|
|
6
|
+
from vectorwave.models.db_config import WeaviateSettings
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture
|
|
10
|
+
def mock_deps(monkeypatch):
|
|
11
|
+
"""
|
|
12
|
+
Fixture to mock dependencies for batch.py (db, config, atexit)
|
|
13
|
+
"""
|
|
14
|
+
# Mock WeaviateClient
|
|
15
|
+
mock_client = MagicMock()
|
|
16
|
+
mock_client.batch = MagicMock()
|
|
17
|
+
mock_client.batch.configure = MagicMock()
|
|
18
|
+
mock_client.batch.add_object = MagicMock()
|
|
19
|
+
mock_client.batch.flush = MagicMock()
|
|
20
|
+
|
|
21
|
+
mock_collection_data = MagicMock()
|
|
22
|
+
mock_collection = MagicMock()
|
|
23
|
+
mock_collection.data = mock_collection_data
|
|
24
|
+
mock_client.collections.get = MagicMock(return_value=mock_collection)
|
|
25
|
+
|
|
26
|
+
# Mock get_weaviate_client
|
|
27
|
+
mock_get_client = MagicMock(return_value=mock_client)
|
|
28
|
+
monkeypatch.setattr("vectorwave.batch.batch.get_weaviate_client", mock_get_client)
|
|
29
|
+
|
|
30
|
+
# Mock get_weaviate_settings
|
|
31
|
+
mock_settings = WeaviateSettings()
|
|
32
|
+
mock_get_settings = MagicMock(return_value=mock_settings)
|
|
33
|
+
monkeypatch.setattr("vectorwave.batch.batch.get_weaviate_settings", mock_get_settings)
|
|
34
|
+
|
|
35
|
+
# Mock atexit.register
|
|
36
|
+
mock_atexit_register = MagicMock()
|
|
37
|
+
monkeypatch.setattr("atexit.register", mock_atexit_register)
|
|
38
|
+
|
|
39
|
+
# Clear lru_cache
|
|
40
|
+
get_batch_manager.cache_clear()
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
"get_client": mock_get_client,
|
|
44
|
+
"get_settings": mock_get_settings,
|
|
45
|
+
"client": mock_client,
|
|
46
|
+
"settings": mock_settings,
|
|
47
|
+
"atexit": mock_atexit_register
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
def test_get_batch_manager_is_singleton(mock_deps):
|
|
51
|
+
"""
|
|
52
|
+
Case 1: Test if get_batch_manager() always returns the same instance (singleton)
|
|
53
|
+
"""
|
|
54
|
+
manager1 = get_batch_manager()
|
|
55
|
+
manager2 = get_batch_manager()
|
|
56
|
+
assert manager1 is manager2
|
|
57
|
+
|
|
58
|
+
def test_batch_manager_initialization(mock_deps):
|
|
59
|
+
"""
|
|
60
|
+
Case 2: Test if BatchManager correctly calls dependencies (configure, atexit) upon initialization
|
|
61
|
+
"""
|
|
62
|
+
manager = get_batch_manager()
|
|
63
|
+
|
|
64
|
+
mock_deps["get_settings"].assert_called_once()
|
|
65
|
+
mock_deps["get_client"].assert_called_once_with(mock_deps["settings"])
|
|
66
|
+
|
|
67
|
+
assert manager._initialized is True
|
|
68
|
+
|
|
69
|
+
def test_batch_manager_init_failure(monkeypatch):
|
|
70
|
+
"""
|
|
71
|
+
Case 3: Test if _initialized remains False when DB connection (get_weaviate_client) fails
|
|
72
|
+
"""
|
|
73
|
+
# Mock get_weaviate_client to raise an exception
|
|
74
|
+
mock_get_client_fail = MagicMock(side_effect=WeaviateConnectionError("Test connection error"))
|
|
75
|
+
monkeypatch.setattr("vectorwave.batch.batch.get_weaviate_client", mock_get_client_fail)
|
|
76
|
+
|
|
77
|
+
get_batch_manager.cache_clear()
|
|
78
|
+
manager = get_batch_manager()
|
|
79
|
+
|
|
80
|
+
# The _initialized flag should be False if initialization fails
|
|
81
|
+
assert manager._initialized is False
|
|
82
|
+
|
|
83
|
+
def test_add_object_calls_client_batch(mock_deps):
|
|
84
|
+
"""
|
|
85
|
+
Case 4: Test if add_object() correctly calls client.batch.add_object
|
|
86
|
+
"""
|
|
87
|
+
manager = get_batch_manager()
|
|
88
|
+
props = {"key": "value"}
|
|
89
|
+
|
|
90
|
+
manager.add_object(collection="TestCollection", properties=props, uuid="test-uuid")
|
|
91
|
+
|
|
92
|
+
mock_deps["client"].collections.get.assert_called_once_with("TestCollection")
|
|
93
|
+
|
|
94
|
+
mock_deps["client"].collections.get.return_value.data.insert.assert_called_once_with(
|
|
95
|
+
properties=props,
|
|
96
|
+
uuid="test-uuid",
|
|
97
|
+
vector=None
|
|
98
|
+
)
|
tests/core/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from unittest.mock import patch, MagicMock
|
|
3
|
+
import inspect
|
|
4
|
+
from weaviate.util import generate_uuid5
|
|
5
|
+
|
|
6
|
+
from vectorwave.core.decorator import vectorize
|
|
7
|
+
from vectorwave.models.db_config import WeaviateSettings
|
|
8
|
+
|
|
9
|
+
from vectorwave.batch.batch import get_batch_manager as real_get_batch_manager
|
|
10
|
+
from vectorwave.database.db import get_cached_client as real_get_cached_client
|
|
11
|
+
from vectorwave.models.db_config import get_weaviate_settings as real_get_settings
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.fixture
|
|
15
|
+
def mock_decorator_deps(monkeypatch):
|
|
16
|
+
"""
|
|
17
|
+
Mocks dependencies for decorator.py (get_batch_manager, get_weaviate_settings)
|
|
18
|
+
"""
|
|
19
|
+
# 1. Mock BatchManager
|
|
20
|
+
mock_batch_manager = MagicMock()
|
|
21
|
+
mock_batch_manager.add_object = MagicMock()
|
|
22
|
+
mock_get_batch_manager = MagicMock(return_value=mock_batch_manager)
|
|
23
|
+
|
|
24
|
+
# 2. Mock Settings
|
|
25
|
+
mock_custom_props = {
|
|
26
|
+
"run_id": {"data_type": "TEXT"},
|
|
27
|
+
"team": {"data_type": "TEXT"},
|
|
28
|
+
"priority": {"data_type": "INT"}
|
|
29
|
+
}
|
|
30
|
+
mock_settings = WeaviateSettings(
|
|
31
|
+
COLLECTION_NAME="TestFunctions",
|
|
32
|
+
EXECUTION_COLLECTION_NAME="TestExecutions",
|
|
33
|
+
custom_properties=mock_custom_props,
|
|
34
|
+
global_custom_values={"run_id": "test-run-abc"}
|
|
35
|
+
)
|
|
36
|
+
mock_get_settings = MagicMock(return_value=mock_settings)
|
|
37
|
+
|
|
38
|
+
mock_client = MagicMock()
|
|
39
|
+
mock_get_client = MagicMock(return_value=mock_client)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# --- decorator.py ---
|
|
43
|
+
monkeypatch.setattr("vectorwave.core.decorator.get_batch_manager", mock_get_batch_manager)
|
|
44
|
+
monkeypatch.setattr("vectorwave.core.decorator.get_weaviate_settings", mock_get_settings)
|
|
45
|
+
|
|
46
|
+
# --- tracer.py ---
|
|
47
|
+
monkeypatch.setattr("vectorwave.monitoring.tracer.get_batch_manager", mock_get_batch_manager)
|
|
48
|
+
monkeypatch.setattr("vectorwave.monitoring.tracer.get_weaviate_settings", mock_get_settings)
|
|
49
|
+
|
|
50
|
+
# --- batch.py (tracer가 get_batch_manager()를 호출할 때 사용) ---
|
|
51
|
+
# WeaviateBatchManager.__init__이 실패하지 않도록 패치
|
|
52
|
+
monkeypatch.setattr("vectorwave.batch.batch.get_weaviate_client", mock_get_client)
|
|
53
|
+
monkeypatch.setattr("vectorwave.batch.batch.get_weaviate_settings", mock_get_settings)
|
|
54
|
+
|
|
55
|
+
# 5. Clear caches to ensure mocks are used
|
|
56
|
+
real_get_batch_manager.cache_clear()
|
|
57
|
+
real_get_cached_client.cache_clear()
|
|
58
|
+
real_get_settings.cache_clear()
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
"get_batch": mock_get_batch_manager,
|
|
62
|
+
"get_settings": mock_get_settings,
|
|
63
|
+
"batch": mock_batch_manager,
|
|
64
|
+
"settings": mock_settings
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@pytest.fixture
|
|
69
|
+
def mock_decorator_deps_no_props(monkeypatch):
|
|
70
|
+
"""
|
|
71
|
+
Fixture variant where settings.custom_properties is None
|
|
72
|
+
"""
|
|
73
|
+
# 1. Mock BatchManager
|
|
74
|
+
mock_batch_manager = MagicMock()
|
|
75
|
+
mock_batch_manager.add_object = MagicMock()
|
|
76
|
+
mock_get_batch_manager = MagicMock(return_value=mock_batch_manager)
|
|
77
|
+
|
|
78
|
+
# 2. Mock Settings (custom_properties=None)
|
|
79
|
+
mock_settings = WeaviateSettings(
|
|
80
|
+
COLLECTION_NAME="TestFunctions",
|
|
81
|
+
EXECUTION_COLLECTION_NAME="TestExecutions",
|
|
82
|
+
custom_properties=None, # <-- No properties loaded
|
|
83
|
+
global_custom_values=None # <-- No globals
|
|
84
|
+
)
|
|
85
|
+
mock_get_settings = MagicMock(return_value=mock_settings)
|
|
86
|
+
|
|
87
|
+
mock_client = MagicMock()
|
|
88
|
+
mock_get_client = MagicMock(return_value=mock_client)
|
|
89
|
+
|
|
90
|
+
monkeypatch.setattr("vectorwave.core.decorator.get_batch_manager", mock_get_batch_manager)
|
|
91
|
+
monkeypatch.setattr("vectorwave.core.decorator.get_weaviate_settings", mock_get_settings)
|
|
92
|
+
monkeypatch.setattr("vectorwave.monitoring.tracer.get_batch_manager", mock_get_batch_manager)
|
|
93
|
+
monkeypatch.setattr("vectorwave.monitoring.tracer.get_weaviate_settings", mock_get_settings)
|
|
94
|
+
monkeypatch.setattr("vectorwave.batch.batch.get_weaviate_client", mock_get_client)
|
|
95
|
+
monkeypatch.setattr("vectorwave.batch.batch.get_weaviate_settings", mock_get_settings)
|
|
96
|
+
|
|
97
|
+
# 5. Clear caches
|
|
98
|
+
real_get_batch_manager.cache_clear()
|
|
99
|
+
real_get_cached_client.cache_clear()
|
|
100
|
+
real_get_settings.cache_clear()
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
"get_batch": mock_get_batch_manager,
|
|
104
|
+
"get_settings": mock_get_settings,
|
|
105
|
+
"batch": mock_batch_manager,
|
|
106
|
+
"settings": mock_settings
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_vectorize_static_data_collection(mock_decorator_deps):
|
|
111
|
+
"""
|
|
112
|
+
Case 1: Test if data is added once to 'VectorWaveFunctions' (static) when the decorator is loaded
|
|
113
|
+
"""
|
|
114
|
+
mock_batch = mock_decorator_deps["batch"]
|
|
115
|
+
mock_settings = mock_decorator_deps["settings"]
|
|
116
|
+
|
|
117
|
+
@vectorize(
|
|
118
|
+
search_description="Test search desc",
|
|
119
|
+
sequence_narrative="Test sequence narr"
|
|
120
|
+
)
|
|
121
|
+
def my_test_function_static():
|
|
122
|
+
"""My test docstring"""
|
|
123
|
+
pass
|
|
124
|
+
|
|
125
|
+
# --- ----------------- ---
|
|
126
|
+
|
|
127
|
+
# 1. Assert: get_batch_manager and get_weaviate_settings are called at load time
|
|
128
|
+
mock_decorator_deps["get_batch"].assert_called_once()
|
|
129
|
+
# (get_weaviate_settings might have already been called once during batch initialization,
|
|
130
|
+
# so check 'called' instead of 'call_count')
|
|
131
|
+
assert mock_decorator_deps["get_settings"].called
|
|
132
|
+
|
|
133
|
+
# 2. Assert: batch.add_object is called once
|
|
134
|
+
mock_batch.add_object.assert_called_once()
|
|
135
|
+
|
|
136
|
+
# 3. Assert: Check if the call arguments are for the 'VectorWaveFunctions' collection
|
|
137
|
+
args, kwargs = mock_batch.add_object.call_args
|
|
138
|
+
|
|
139
|
+
assert kwargs["collection"] == mock_settings.COLLECTION_NAME
|
|
140
|
+
assert kwargs["properties"]["function_name"] == "my_test_function_static"
|
|
141
|
+
assert kwargs["properties"]["docstring"] == "My test docstring"
|
|
142
|
+
assert "def my_test_function_static" in kwargs["properties"]["source_code"]
|
|
143
|
+
assert kwargs["properties"]["search_description"] == "Test search desc"
|
|
144
|
+
assert kwargs["properties"]["sequence_narrative"] == "Test sequence narr"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def test_vectorize_dynamic_data_logging_success(mock_decorator_deps):
|
|
148
|
+
"""
|
|
149
|
+
Case 2: Test if the decorated function adds a log to 'VectorWaveExecutions' (dynamic) on 'successful' execution
|
|
150
|
+
"""
|
|
151
|
+
mock_batch = mock_decorator_deps["batch"]
|
|
152
|
+
mock_settings = mock_decorator_deps["settings"]
|
|
153
|
+
|
|
154
|
+
@vectorize(search_description="Test", sequence_narrative="Test")
|
|
155
|
+
def my_test_function_dynamic():
|
|
156
|
+
return "Success"
|
|
157
|
+
|
|
158
|
+
result = my_test_function_dynamic()
|
|
159
|
+
|
|
160
|
+
# 1. Assert: Function returns the result normally
|
|
161
|
+
assert result == "Success"
|
|
162
|
+
|
|
163
|
+
# 2. Assert: add_object is called 2 times in total (1 static + 1 dynamic)
|
|
164
|
+
assert mock_batch.add_object.call_count == 2
|
|
165
|
+
|
|
166
|
+
# 3. Assert: Check arguments of the last call (dynamic log)
|
|
167
|
+
args, kwargs = mock_batch.add_object.call_args
|
|
168
|
+
|
|
169
|
+
assert kwargs["collection"] == mock_settings.EXECUTION_COLLECTION_NAME
|
|
170
|
+
assert kwargs["properties"]["status"] == "SUCCESS"
|
|
171
|
+
assert kwargs["properties"]["error_message"] is None
|
|
172
|
+
assert kwargs["properties"]["duration_ms"] > 0
|
|
173
|
+
# Check if global_custom_values (run_id) were merged
|
|
174
|
+
assert kwargs["properties"]["run_id"] == "test-run-abc"
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def test_vectorize_dynamic_data_logging_failure(mock_decorator_deps):
|
|
178
|
+
"""
|
|
179
|
+
Case 3: Test if the decorated function adds a 'status=ERROR' log on 'failed' execution
|
|
180
|
+
"""
|
|
181
|
+
mock_batch = mock_decorator_deps["batch"]
|
|
182
|
+
mock_settings = mock_decorator_deps["settings"]
|
|
183
|
+
|
|
184
|
+
@vectorize(search_description="FailTest", sequence_narrative="FailTest")
|
|
185
|
+
def my_failing_function():
|
|
186
|
+
raise ValueError("This is a test error")
|
|
187
|
+
|
|
188
|
+
with pytest.raises(ValueError, match="This is a test error"):
|
|
189
|
+
my_failing_function()
|
|
190
|
+
|
|
191
|
+
# 1. Assert: add_object is called 2 times in total (1 static + 1 dynamic)
|
|
192
|
+
assert mock_batch.add_object.call_count == 2
|
|
193
|
+
|
|
194
|
+
# 2. Assert: Check arguments of the last call (dynamic log)
|
|
195
|
+
args, kwargs = mock_batch.add_object.call_args
|
|
196
|
+
|
|
197
|
+
assert kwargs["collection"] == mock_settings.EXECUTION_COLLECTION_NAME
|
|
198
|
+
assert kwargs["properties"]["status"] == "ERROR"
|
|
199
|
+
assert "ValueError: This is a test error" in kwargs["properties"]["error_message"]
|
|
200
|
+
assert "Traceback (most recent call last):" in kwargs["properties"]["error_message"]
|
|
201
|
+
assert kwargs["properties"]["run_id"] == "test-run-abc"
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def test_vectorize_dynamic_data_with_execution_tags(mock_decorator_deps):
|
|
205
|
+
"""
|
|
206
|
+
Case 4: Test if execution logs correctly merge global tags (run_id) and
|
|
207
|
+
function-specific tags (team, priority) provided via **kwargs.
|
|
208
|
+
"""
|
|
209
|
+
mock_batch = mock_decorator_deps["batch"]
|
|
210
|
+
mock_settings = mock_decorator_deps["settings"]
|
|
211
|
+
|
|
212
|
+
# 1. Arrange: Define a function with function-specific execution tags
|
|
213
|
+
@vectorize(
|
|
214
|
+
search_description="Test with specific tags",
|
|
215
|
+
sequence_narrative="Tags should be merged",
|
|
216
|
+
team="backend", # <-- Function-specific tag
|
|
217
|
+
priority=1 # <-- Function-specific tag
|
|
218
|
+
)
|
|
219
|
+
def my_tagged_function():
|
|
220
|
+
return "Tagged success"
|
|
221
|
+
|
|
222
|
+
# 2. Act: Execute the decorated function
|
|
223
|
+
result = my_tagged_function()
|
|
224
|
+
|
|
225
|
+
# 3. Assert: Basic execution
|
|
226
|
+
assert result == "Tagged success"
|
|
227
|
+
# (1 static call + 1 dynamic call)
|
|
228
|
+
assert mock_batch.add_object.call_count == 2
|
|
229
|
+
|
|
230
|
+
# 4. Assert: Check the properties of the dynamic log (the last call)
|
|
231
|
+
args, kwargs = mock_batch.add_object.call_args
|
|
232
|
+
|
|
233
|
+
assert kwargs["collection"] == mock_settings.EXECUTION_COLLECTION_NAME
|
|
234
|
+
assert kwargs["properties"]["status"] == "SUCCESS"
|
|
235
|
+
|
|
236
|
+
# 4a. Verify Global Tag (from fixture)
|
|
237
|
+
assert kwargs["properties"]["run_id"] == "test-run-abc"
|
|
238
|
+
|
|
239
|
+
# 4b. Verify Function-Specific Tags (from @vectorize)
|
|
240
|
+
assert kwargs["properties"]["team"] == "backend"
|
|
241
|
+
assert kwargs["properties"]["priority"] == 1
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def test_vectorize_execution_tags_override_global_tags(mock_decorator_deps):
|
|
245
|
+
"""
|
|
246
|
+
Case 5: Test if a function-specific tag (e.g., 'run_id')
|
|
247
|
+
correctly overrides a global tag with the same name.
|
|
248
|
+
"""
|
|
249
|
+
mock_batch = mock_decorator_deps["batch"]
|
|
250
|
+
|
|
251
|
+
# 1. Arrange: Define function where 'run_id' will override the global value
|
|
252
|
+
# The fixture provides a global "run_id": "test-run-abc"
|
|
253
|
+
@vectorize(
|
|
254
|
+
search_description="Test override",
|
|
255
|
+
sequence_narrative="Next",
|
|
256
|
+
run_id="override-run-xyz" # <-- This should WIN against "test-run-abc"
|
|
257
|
+
)
|
|
258
|
+
def my_override_function():
|
|
259
|
+
pass
|
|
260
|
+
|
|
261
|
+
# 2. Act
|
|
262
|
+
my_override_function()
|
|
263
|
+
|
|
264
|
+
# 3. Assert
|
|
265
|
+
args, kwargs = mock_batch.add_object.call_args
|
|
266
|
+
|
|
267
|
+
# Verify that the function-specific 'run_id' overrode the global one
|
|
268
|
+
assert kwargs["properties"]["run_id"] == "override-run-xyz"
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def test_vectorize_filters_invalid_execution_tags(mock_decorator_deps):
|
|
272
|
+
"""
|
|
273
|
+
Case 6: Test that the decorator filters out execution tags that are
|
|
274
|
+
NOT in settings.custom_properties and only logs the valid tags.
|
|
275
|
+
(This test intentionally does not check the warning output mechanism)
|
|
276
|
+
"""
|
|
277
|
+
mock_batch = mock_decorator_deps["batch"]
|
|
278
|
+
mock_settings = mock_decorator_deps["settings"]
|
|
279
|
+
|
|
280
|
+
# 1. Arrange: Define function with valid tags ('team', 'priority')
|
|
281
|
+
# and one invalid tag ('unknown_tag')
|
|
282
|
+
# (Fixture defines 'run_id', 'team', 'priority' as custom_properties)
|
|
283
|
+
@vectorize(
|
|
284
|
+
search_description="Test tag filtering",
|
|
285
|
+
sequence_narrative="Next",
|
|
286
|
+
team="data-science", # <-- Valid
|
|
287
|
+
priority=2, # <-- Valid
|
|
288
|
+
unknown_tag="should-be-ignored" # <-- INVALID
|
|
289
|
+
)
|
|
290
|
+
def my_mixed_tags_function():
|
|
291
|
+
pass
|
|
292
|
+
|
|
293
|
+
# 2. Act
|
|
294
|
+
my_mixed_tags_function() # Run the wrapper
|
|
295
|
+
|
|
296
|
+
# 3. Assert: Check final execution log properties
|
|
297
|
+
# (We check the *last* call, which is the dynamic log)
|
|
298
|
+
args, kwargs = mock_batch.add_object.call_args
|
|
299
|
+
props = kwargs["properties"]
|
|
300
|
+
|
|
301
|
+
assert kwargs["collection"] == mock_settings.EXECUTION_COLLECTION_NAME
|
|
302
|
+
|
|
303
|
+
# 3a. Valid global tag should exist
|
|
304
|
+
assert props["run_id"] == "test-run-abc"
|
|
305
|
+
|
|
306
|
+
# 3b. Valid function-specific tags should exist
|
|
307
|
+
assert props["team"] == "data-science"
|
|
308
|
+
assert props["priority"] == 2
|
|
309
|
+
|
|
310
|
+
# 3c. Invalid tag should NOT exist
|
|
311
|
+
assert "unknown_tag" not in props
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def test_vectorize_handles_tags_when_no_props_file(mock_decorator_deps_no_props):
|
|
315
|
+
"""
|
|
316
|
+
Case 7: Test that if settings.custom_properties is None,
|
|
317
|
+
ALL execution_tags are ignored.
|
|
318
|
+
(This test intentionally does not check the warning output mechanism)
|
|
319
|
+
"""
|
|
320
|
+
mock_batch = mock_decorator_deps_no_props["batch"]
|
|
321
|
+
mock_settings = mock_decorator_deps_no_props["settings"]
|
|
322
|
+
|
|
323
|
+
# 1. Arrange
|
|
324
|
+
@vectorize(
|
|
325
|
+
search_description="Test no props",
|
|
326
|
+
sequence_narrative="Next",
|
|
327
|
+
team="should-be-ignored" # <-- Invalid (because no file)
|
|
328
|
+
)
|
|
329
|
+
def my_no_props_function():
|
|
330
|
+
pass
|
|
331
|
+
|
|
332
|
+
# 2. Act
|
|
333
|
+
my_no_props_function() # Run wrapper
|
|
334
|
+
|
|
335
|
+
# 3. Assert: Check final execution log properties
|
|
336
|
+
args, kwargs = mock_batch.add_object.call_args
|
|
337
|
+
props = kwargs["properties"]
|
|
338
|
+
|
|
339
|
+
assert kwargs["collection"] == mock_settings.EXECUTION_COLLECTION_NAME
|
|
340
|
+
|
|
341
|
+
# 3a. Basic properties should still exist
|
|
342
|
+
assert props["status"] == "SUCCESS"
|
|
343
|
+
|
|
344
|
+
# 3b. The tag should NOT exist
|
|
345
|
+
assert "team" not in props
|
|
File without changes
|