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.
Files changed (44) hide show
  1. tests/__init__.py +0 -0
  2. tests/batch/__init__.py +0 -0
  3. tests/batch/test_batch.py +98 -0
  4. tests/core/__init__.py +0 -0
  5. tests/core/test_decorator.py +345 -0
  6. tests/database/__init__.py +0 -0
  7. tests/database/test_db.py +468 -0
  8. tests/database/test_db_search.py +163 -0
  9. tests/exception/__init__.py +0 -0
  10. tests/models/__init__.py +0 -0
  11. tests/models/test_db_config.py +152 -0
  12. tests/monitoring/__init__.py +0 -0
  13. tests/monitoring/test_tracer.py +202 -0
  14. tests/prediction/__init__.py +0 -0
  15. tests/vectorizer/__init__.py +0 -0
  16. vectorwave/__init__.py +13 -0
  17. vectorwave/batch/__init__.py +0 -0
  18. vectorwave/batch/batch.py +68 -0
  19. vectorwave/core/__init__.py +0 -0
  20. vectorwave/core/core.py +0 -0
  21. vectorwave/core/decorator.py +131 -0
  22. vectorwave/database/__init__.py +0 -0
  23. vectorwave/database/db.py +328 -0
  24. vectorwave/database/db_search.py +122 -0
  25. vectorwave/exception/__init__.py +0 -0
  26. vectorwave/exception/exceptions.py +22 -0
  27. vectorwave/models/__init__.py +0 -0
  28. vectorwave/models/db_config.py +92 -0
  29. vectorwave/monitoring/__init__.py +0 -0
  30. vectorwave/monitoring/monitoring.py +0 -0
  31. vectorwave/monitoring/tracer.py +131 -0
  32. vectorwave/prediction/__init__.py +0 -0
  33. vectorwave/prediction/predictor.py +0 -0
  34. vectorwave/vectorizer/__init__.py +0 -0
  35. vectorwave/vectorizer/base.py +12 -0
  36. vectorwave/vectorizer/factory.py +49 -0
  37. vectorwave/vectorizer/huggingface_vectorizer.py +33 -0
  38. vectorwave/vectorizer/openai_vectorizer.py +35 -0
  39. vectorwave-0.1.3.dist-info/METADATA +352 -0
  40. vectorwave-0.1.3.dist-info/RECORD +44 -0
  41. vectorwave-0.1.3.dist-info/WHEEL +5 -0
  42. vectorwave-0.1.3.dist-info/licenses/LICENSE +21 -0
  43. vectorwave-0.1.3.dist-info/licenses/NOTICE +31 -0
  44. vectorwave-0.1.3.dist-info/top_level.txt +2 -0
@@ -0,0 +1,468 @@
1
+ import pytest
2
+ from unittest.mock import MagicMock, patch, ANY
3
+ import weaviate
4
+ import weaviate.classes.config as wvc
5
+ # Import the specific driver exception to mock it
6
+ from weaviate.exceptions import WeaviateConnectionError as WeaviateClientConnectionError
7
+
8
+ # Import functions to be tested
9
+ # (Assuming pytest is run from the project root and pytest.ini is set)
10
+ from vectorwave.database.db import get_weaviate_client, create_vectorwave_schema
11
+ from vectorwave.models.db_config import WeaviateSettings, get_weaviate_settings
12
+ from vectorwave.exception.exceptions import (
13
+ WeaviateConnectionError,
14
+ WeaviateNotReadyError,
15
+ SchemaCreationError
16
+ )
17
+
18
+ from vectorwave.database.db import create_execution_schema
19
+
20
+
21
+ # --- Test Fixtures ---
22
+
23
+ @pytest.fixture
24
+ def test_settings() -> WeaviateSettings:
25
+ """Returns a test Weaviate settings object."""
26
+ return WeaviateSettings(
27
+ WEAVIATE_HOST="test.host.local",
28
+ WEAVIATE_PORT=1234,
29
+ WEAVIATE_GRPC_PORT=5678,
30
+ COLLECTION_NAME="TestCollection",
31
+ IS_VECTORIZE_COLLECTION_NAME=False
32
+ )
33
+
34
+ # --- Tests for get_weaviate_client ---
35
+
36
+ @patch('vectorwave.database.db.weaviate.connect_to_local')
37
+ def test_get_weaviate_client_success(mock_connect_to_local, test_settings):
38
+ """
39
+ Case 1: Weaviate connection is successful.
40
+ - .connect_to_local() should be called.
41
+ - .is_ready() should return True.
42
+ - The created client object should be returned.
43
+ """
44
+ # 1. Arrange
45
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
46
+ mock_client.is_ready.return_value = True
47
+ mock_connect_to_local.return_value = mock_client
48
+
49
+ # 2. Act
50
+ client = get_weaviate_client(settings=test_settings)
51
+
52
+ # 3. Assert
53
+ # Check if 'connect_to_local' was called once with the correct args
54
+ mock_connect_to_local.assert_called_once_with(
55
+ host=test_settings.WEAVIATE_HOST,
56
+ port=test_settings.WEAVIATE_PORT,
57
+ grpc_port=test_settings.WEAVIATE_GRPC_PORT,
58
+ additional_config=ANY
59
+ )
60
+ mock_client.is_ready.assert_called_once()
61
+ assert client == mock_client
62
+
63
+
64
+ @patch('vectorwave.database.db.weaviate.connect_to_local')
65
+ def test_get_weaviate_client_connection_refused(mock_connect_to_local, test_settings):
66
+ """
67
+ Case 2: Connection is refused because Weaviate server is down.
68
+ - Should raise WeaviateConnectionError.
69
+ """
70
+ # 1. Arrange
71
+ # Mock the original Weaviate driver exception
72
+ mock_connect_to_local.side_effect = WeaviateClientConnectionError("Connection refused")
73
+
74
+ # 2. Act & 3. Assert
75
+ with pytest.raises(WeaviateConnectionError) as exc_info:
76
+ get_weaviate_client(settings=test_settings)
77
+
78
+ # Check if the error message from the original exception is included
79
+ assert "Connection refused" in str(exc_info.value)
80
+ assert "Failed to connect to Weaviate" in str(exc_info.value)
81
+
82
+
83
+ @patch('vectorwave.database.db.weaviate.connect_to_local')
84
+ def test_get_weaviate_client_not_ready(mock_connect_to_local, test_settings):
85
+ """
86
+ Case 3: Connected, but Weaviate is not ready (.is_ready() returns False).
87
+ - Should raise WeaviateNotReadyError.
88
+ """
89
+ # 1. Arrange
90
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
91
+ mock_client.is_ready.return_value = False # This is the trigger
92
+ mock_connect_to_local.return_value = mock_client
93
+
94
+ # 2. Act & 3. Assert
95
+ with pytest.raises(WeaviateNotReadyError) as exc_info:
96
+ get_weaviate_client(settings=test_settings)
97
+
98
+ assert "server is not ready" in str(exc_info.value)
99
+
100
+
101
+ # --- Tests for create_vectorwave_schema ---
102
+
103
+ def test_create_schema_new(test_settings):
104
+ """
105
+ Case 4: Schema doesn't exist and is created successfully.
106
+ - .collections.exists() returns False.
107
+ - .collections.create() should be called.
108
+ - .collections.get() should not be called.
109
+ """
110
+ # 1. Arrange
111
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
112
+ mock_collections = MagicMock()
113
+ mock_collections.exists.return_value = False # Trigger for creation
114
+ mock_new_collection = MagicMock()
115
+ mock_collections.create.return_value = mock_new_collection
116
+ mock_client.collections = mock_collections
117
+
118
+ # 2. Act
119
+ collection = create_vectorwave_schema(mock_client, test_settings)
120
+
121
+ # 3. Assert
122
+ mock_collections.exists.assert_called_once_with(test_settings.COLLECTION_NAME)
123
+ mock_collections.create.assert_called_once()
124
+
125
+ # Check if 'create' was called with the correct 'name'
126
+ call_args = mock_collections.create.call_args
127
+ assert call_args.kwargs.get('name') == test_settings.COLLECTION_NAME
128
+
129
+ # Check if key properties were passed
130
+ passed_props = [prop.name for prop in call_args.kwargs.get('properties', [])]
131
+ assert "function_name" in passed_props
132
+ assert "source_code" in passed_props
133
+
134
+ mock_collections.get.assert_not_called()
135
+ assert collection == mock_new_collection
136
+
137
+
138
+ def test_create_schema_existing(test_settings):
139
+ """
140
+ Case 5: Schema already exists.
141
+ - .collections.exists() returns True.
142
+ - .collections.create() should not be called.
143
+ - .collections.get() should be called.
144
+ """
145
+ # 1. Arrange
146
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
147
+ mock_collections = MagicMock()
148
+ mock_collections.exists.return_value = True # Trigger for skipping
149
+ mock_existing_collection = MagicMock()
150
+ mock_collections.get.return_value = mock_existing_collection
151
+ mock_client.collections = mock_collections
152
+
153
+ # 2. Act
154
+ collection = create_vectorwave_schema(mock_client, test_settings)
155
+
156
+ # 3. Assert
157
+ mock_collections.exists.assert_called_once_with(test_settings.COLLECTION_NAME)
158
+ mock_collections.create.assert_not_called()
159
+ mock_collections.get.assert_called_once_with(test_settings.COLLECTION_NAME)
160
+ assert collection == mock_existing_collection
161
+
162
+
163
+ def test_create_schema_creation_error(test_settings):
164
+ """
165
+ Case 6: An error occurs during schema creation (e.g., bad API key).
166
+ - Should raise SchemaCreationError.
167
+ """
168
+ # 1. Arrange
169
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
170
+ mock_collections = MagicMock()
171
+ mock_collections.exists.return_value = False
172
+ # Set .create() to raise an exception
173
+ mock_collections.create.side_effect = Exception("Invalid OpenAI API Key")
174
+ mock_client.collections = mock_collections
175
+
176
+ # 2. Act & 3. Assert
177
+ with pytest.raises(SchemaCreationError) as exc_info:
178
+ create_vectorwave_schema(mock_client, test_settings)
179
+
180
+ assert "Error during schema creation" in str(exc_info.value)
181
+ assert "Invalid OpenAI API Key" in str(exc_info.value)
182
+
183
+
184
+ @pytest.fixture
185
+ def settings_with_custom_props() -> WeaviateSettings:
186
+ """
187
+ Returns a WeaviateSettings object assuming 'get_weaviate_settings'
188
+ successfully loaded the JSON.
189
+ """
190
+ settings = WeaviateSettings(
191
+ COLLECTION_NAME="TestCollection",
192
+ IS_VECTORIZE_COLLECTION_NAME=False
193
+ )
194
+ # Manually inject the loaded data into the custom_properties field
195
+ settings.custom_properties = {
196
+ "run_id": {
197
+ "data_type": "TEXT",
198
+ "description": "The ID of the specific test run"
199
+ },
200
+ "experiment_id": {
201
+ "data_type": "INT",
202
+ "description": "Identifier for the experiment"
203
+ }
204
+ }
205
+ return settings
206
+
207
+ @pytest.fixture
208
+ def settings_with_invalid_type_prop() -> WeaviateSettings:
209
+ """Returns settings with an invalid string in 'data_type'."""
210
+ settings = WeaviateSettings(COLLECTION_NAME="TestCollection")
211
+ settings.custom_properties = {
212
+ "bad_prop": {
213
+ "data_type": "INVALID_WEAVIATE_TYPE", # <-- Invalid type
214
+ "description": "This should fail"
215
+ }
216
+ }
217
+ return settings
218
+
219
+ @pytest.fixture
220
+ def settings_with_missing_type_prop() -> WeaviateSettings:
221
+ """Returns settings where the 'data_type' key itself is missing."""
222
+ settings = WeaviateSettings(COLLECTION_NAME="TestCollection")
223
+ settings.custom_properties = {
224
+ "another_bad_prop": {
225
+ "description": "data_type key is missing" # <-- data_type missing
226
+ }
227
+ }
228
+ return settings
229
+
230
+
231
+
232
+ # [New] Test Cases for Issue #11: Custom Property *Parsing*
233
+
234
+ def test_create_schema_with_custom_properties(settings_with_custom_props):
235
+ """
236
+ Case 7: Test if custom properties (run_id, experiment_id) are correctly added to the schema
237
+ - .collections.create() should be called with the correct 'properties' argument
238
+ """
239
+ # 1. Arrange
240
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
241
+ mock_collections = MagicMock()
242
+ mock_collections.exists.return_value = False # Trigger creation
243
+ mock_new_collection = MagicMock()
244
+ mock_collections.create.return_value = mock_new_collection
245
+ mock_client.collections = mock_collections
246
+
247
+ # 2. Act
248
+ # Use the 'settings_with_custom_props' fixture
249
+ create_vectorwave_schema(mock_client, settings_with_custom_props)
250
+
251
+ # 3. Assert
252
+ # Check if create was called
253
+ mock_collections.create.assert_called_once()
254
+
255
+ # Check the arguments (kwargs) passed to create
256
+ call_args = mock_collections.create.call_args
257
+ passed_props_list = call_args.kwargs.get('properties', [])
258
+
259
+ # For convenience, convert the list to a map by name
260
+ passed_props_map = {prop.name: prop for prop in passed_props_list}
261
+
262
+ # Check if base properties still exist
263
+ assert "function_name" in passed_props_map
264
+ assert "source_code" in passed_props_map
265
+ assert passed_props_map["function_name"].dataType == wvc.DataType.TEXT
266
+
267
+ assert "search_description" in passed_props_map
268
+ assert "sequence_narrative" in passed_props_map
269
+
270
+ # --- Custom Property Validation ---
271
+ assert "run_id" in passed_props_map
272
+ assert "experiment_id" in passed_props_map
273
+
274
+
275
+ # Validate 'run_id' type and description
276
+ run_id_prop = passed_props_map["run_id"]
277
+ assert run_id_prop.dataType == wvc.DataType.TEXT
278
+ assert run_id_prop.description == "The ID of the specific test run"
279
+
280
+ # Validate 'experiment_id' type and description
281
+ exp_id_prop = passed_props_map["experiment_id"]
282
+ assert exp_id_prop.dataType == wvc.DataType.INT
283
+ assert exp_id_prop.description == "Identifier for the experiment"
284
+
285
+
286
+ # Check total property count (5 base + 2 custom)
287
+ assert len(passed_props_list) == 6 + 2
288
+
289
+
290
+ def test_create_schema_custom_prop_invalid_type(settings_with_invalid_type_prop):
291
+ """
292
+ Case 8: Test if SchemaCreationError is raised when 'data_type' has an invalid value
293
+ """
294
+ # 1. Arrange
295
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
296
+ mock_collections = MagicMock()
297
+ mock_collections.exists.return_value = False
298
+ mock_client.collections = mock_collections
299
+
300
+ # 2. Act & 3. Assert
301
+ with pytest.raises(SchemaCreationError) as exc_info:
302
+ create_vectorwave_schema(mock_client, settings_with_invalid_type_prop)
303
+
304
+ # Check if the error message includes the invalid type name
305
+ assert "Invalid data_type 'INVALID_WEAVIATE_TYPE'" in str(exc_info.value)
306
+ assert "bad_prop" in str(exc_info.value)
307
+
308
+
309
+ def test_create_schema_custom_prop_missing_type(settings_with_missing_type_prop):
310
+ """
311
+ Case 9: Test if SchemaCreationError is raised when the 'data_type' key is missing
312
+ """
313
+ # 1. Arrange
314
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
315
+ mock_collections = MagicMock()
316
+ mock_collections.exists.return_value = False
317
+ mock_client.collections = mock_collections
318
+
319
+ # 2. Act & 3. Assert
320
+ with pytest.raises(SchemaCreationError) as exc_info:
321
+ create_vectorwave_schema(mock_client, settings_with_missing_type_prop)
322
+
323
+ # Check if the error message indicates 'data_type' is missing
324
+ assert "missing 'data_type'" in str(exc_info.value)
325
+ assert "another_bad_prop" in str(exc_info.value)
326
+
327
+
328
+ @patch('vectorwave.database.db.wvc.Configure.Vectorizer.none')
329
+ def test_create_execution_schema_new(mock_vectorizer_none, test_settings):
330
+ """
331
+ Case 10: Test if 'VectorWaveExecutions' schema is created successfully when it does not exist
332
+ """
333
+ # 1. Arrange
334
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
335
+ mock_collections = MagicMock()
336
+ mock_collections.exists.return_value = False # 생성 트리거
337
+ mock_new_collection = MagicMock()
338
+ mock_collections.create.return_value = mock_new_collection
339
+ mock_client.collections = mock_collections
340
+
341
+ # 2. Act
342
+ collection = create_execution_schema(mock_client, test_settings)
343
+
344
+ # 3. Assert
345
+ mock_collections.exists.assert_called_once_with(test_settings.EXECUTION_COLLECTION_NAME)
346
+ mock_collections.create.assert_called_once()
347
+
348
+ call_args = mock_collections.create.call_args
349
+ assert call_args.kwargs.get('name') == test_settings.EXECUTION_COLLECTION_NAME
350
+
351
+ # Check if base properties are included
352
+ passed_props_map = {prop.name: prop for prop in call_args.kwargs.get('properties', [])}
353
+ assert "function_uuid" in passed_props_map
354
+ assert "timestamp_utc" in passed_props_map
355
+ assert "status" in passed_props_map
356
+ assert "duration_ms" in passed_props_map
357
+
358
+ assert collection == mock_new_collection
359
+
360
+
361
+ def test_create_execution_schema_existing(test_settings):
362
+ """
363
+ Case 11: Test if creation is skipped when 'VectorWaveExecutions' schema already exists
364
+ """
365
+ # 1. Arrange
366
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
367
+ mock_collections = MagicMock()
368
+ mock_collections.exists.return_value = True
369
+ mock_existing_collection = MagicMock()
370
+ mock_collections.get.return_value = mock_existing_collection
371
+ mock_client.collections = mock_collections
372
+
373
+ # 2. Act
374
+ collection = create_execution_schema(mock_client, test_settings)
375
+
376
+ # 3. Assert
377
+ mock_collections.exists.assert_called_once_with(test_settings.EXECUTION_COLLECTION_NAME)
378
+ mock_collections.create.assert_not_called() # create should not be called
379
+ mock_collections.get.assert_called_once_with(test_settings.EXECUTION_COLLECTION_NAME) # get should be called
380
+ assert collection == mock_existing_collection
381
+
382
+
383
+
384
+
385
+ def test_create_schema_vectorizer_openai(test_settings):
386
+ """
387
+ Case 12: Test if the correct dict config is passed when VECTORIZER_CONFIG='text2vec-openai'
388
+ """
389
+ # 1. Arrange
390
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
391
+ mock_collections = MagicMock()
392
+ mock_collections.exists.return_value = False
393
+ mock_client.collections = mock_collections
394
+
395
+ test_settings.VECTORIZER = "weaviate_module"
396
+ test_settings.WEAVIATE_VECTORIZER_MODULE = "text2vec-openai"
397
+
398
+ # [수정] test_settings.GENERATIVE_CONFIG = "generative-openai" ->
399
+ test_settings.WEAVIATE_GENERATIVE_MODULE = "generative-openai"
400
+
401
+
402
+ # 2. Act
403
+ create_vectorwave_schema(mock_client, test_settings)
404
+
405
+ # 3. Assert
406
+ mock_collections.create.assert_called_once()
407
+
408
+ call_args = mock_collections.create.call_args
409
+
410
+ vector_config_arg = call_args.kwargs.get('vector_config')
411
+ # assert isinstance(vector_config_arg, wvc.Configure.Vectorizer)
412
+ # assert vector_config_arg.name == "text2vec-openai"
413
+
414
+ assert vector_config_arg.vectorizer == "text2vec-openai"
415
+
416
+ # 3b. Generative Config 검증
417
+ generative_config_arg = call_args.kwargs.get('generative_config')
418
+ assert generative_config_arg.generative == "generative-openai"
419
+
420
+
421
+
422
+
423
+ def test_create_schema_vectorizer_none(test_settings):
424
+ """
425
+ Case 13: Test if the correct dict config is passed when VECTORIZER_CONFIG='none'
426
+ """
427
+ # 1. Arrange
428
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
429
+ mock_collections = MagicMock()
430
+ mock_collections.exists.return_value = False
431
+ mock_client.collections = mock_collections
432
+
433
+ test_settings.VECTORIZER = "none"
434
+ test_settings.WEAVIATE_VECTORIZER_MODULE = ""
435
+
436
+ # 2. Act
437
+ create_vectorwave_schema(mock_client, test_settings)
438
+
439
+ # 3. Assert
440
+ mock_collections.create.assert_called_once()
441
+
442
+ call_args = mock_collections.create.call_args
443
+ # mock_none.assert_called_once() -> 삭제
444
+
445
+ vector_config_arg = call_args.kwargs.get('vector_config')
446
+
447
+
448
+ assert vector_config_arg.vectorizer == "none"
449
+
450
+
451
+ def test_create_schema_vectorizer_invalid(test_settings):
452
+ """
453
+ Case 14: Test if SchemaCreationError is raised for an unsupported VECTORIZER_CONFIG value
454
+ """
455
+ # 1. Arrange
456
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
457
+ mock_collections = MagicMock()
458
+ mock_collections.exists.return_value = False
459
+ mock_client.collections = mock_collections
460
+
461
+ test_settings.VECTORIZER = "unsupported-module"
462
+
463
+ # 2. Act & 3. Assert
464
+ with pytest.raises(SchemaCreationError) as exc_info:
465
+ create_vectorwave_schema(mock_client, test_settings)
466
+
467
+ assert "Invalid VECTORIZER setting" in str(exc_info.value)
468
+ assert "unsupported-module" in str(exc_info.value)
@@ -0,0 +1,163 @@
1
+ import pytest
2
+ from unittest.mock import patch, MagicMock, ANY
3
+ import weaviate.classes as wvc
4
+ import weaviate
5
+
6
+ # Functions to test
7
+ from vectorwave.database.db_search import (
8
+ search_functions,
9
+ search_executions,
10
+ _build_weaviate_filters
11
+ )
12
+ from vectorwave.models.db_config import WeaviateSettings
13
+
14
+
15
+ @pytest.fixture
16
+ def mock_search_deps(monkeypatch):
17
+ """ Mock dependencies for search_functions (mocking near_text method) """
18
+ mock_settings = WeaviateSettings(COLLECTION_NAME="TestFunctions")
19
+ mock_get_settings = MagicMock(return_value=mock_settings)
20
+ monkeypatch.setattr("vectorwave.database.db_search.get_weaviate_settings", mock_get_settings)
21
+
22
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
23
+ mock_collections_obj = MagicMock()
24
+ mock_func_collection = MagicMock()
25
+
26
+ mock_query_obj = MagicMock()
27
+ mock_obj = MagicMock()
28
+ mock_obj.properties = {"name": "test_func"}
29
+ mock_obj.metadata = MagicMock(uuid="test-uuid")
30
+ mock_query_obj.near_text.return_value = MagicMock(objects=[mock_obj])
31
+
32
+ mock_func_collection.query = mock_query_obj
33
+
34
+ def get_collection_side_effect(name):
35
+ if name == "TestFunctions":
36
+ return mock_func_collection
37
+ return MagicMock()
38
+
39
+ mock_collections_obj.get = MagicMock(side_effect=get_collection_side_effect)
40
+ mock_client.collections = mock_collections_obj
41
+
42
+ mock_get_client = MagicMock(return_value=mock_client)
43
+ monkeypatch.setattr("vectorwave.database.db_search.get_cached_client", mock_get_client)
44
+
45
+ return {
46
+ "client": mock_client,
47
+ "collection": mock_func_collection,
48
+ "query": mock_query_obj, # Return query object for testing
49
+ "settings": mock_settings
50
+ }
51
+
52
+ # --- Test _build_weaviate_filters helper function ---
53
+
54
+ def test_build_filters_none_or_empty():
55
+ assert _build_weaviate_filters(None) is None
56
+ assert _build_weaviate_filters({}) is None
57
+
58
+ def test_build_filters_single():
59
+ filters = {"team": "billing"}
60
+ result = _build_weaviate_filters(filters)
61
+ # [MODIFIED] isinstance -> is not None (Fix AssertionError)
62
+ assert result is not None
63
+
64
+ def test_build_filters_multiple():
65
+ filters = {"team": "billing", "priority": 1}
66
+ result = _build_weaviate_filters(filters)
67
+ # [MODIFIED] isinstance -> is not None (Fix AssertionError)
68
+ assert result is not None
69
+
70
+
71
+ # --- Basic tests for search_functions ---
72
+
73
+ def test_search_functions_basic_call(mock_search_deps):
74
+ # [MODIFIED] Test the near_text method instead of fetch_objects.
75
+ mock_query = mock_search_deps["query"]
76
+ search_functions(query="test query", limit=3)
77
+
78
+ mock_query.near_text.assert_called_once_with(
79
+ query="test query",
80
+ limit=3,
81
+ filters=None,
82
+ return_metadata=wvc.query.MetadataQuery(distance=True)
83
+ )
84
+
85
+ def test_search_functions_with_filters(mock_search_deps):
86
+ mock_query = mock_search_deps["query"]
87
+ test_filters = {"team": "billing"}
88
+
89
+ search_functions(query="filtered query", limit=5, filters=test_filters)
90
+
91
+ mock_query.near_text.assert_called_once()
92
+ call_args = mock_query.near_text.call_args
93
+
94
+ assert call_args.kwargs['query'] == "filtered query"
95
+ assert call_args.kwargs['limit'] == 5
96
+ assert call_args.kwargs['filters'] is not None
97
+
98
+
99
+ # --- Tests for search_executions ---
100
+
101
+ @pytest.fixture
102
+ def mock_search_exec_deps(monkeypatch):
103
+ """ Mock dependencies for search_executions (no change) """
104
+ mock_settings = WeaviateSettings(EXECUTION_COLLECTION_NAME="TestExecutions")
105
+ mock_get_settings = MagicMock(return_value=mock_settings)
106
+ monkeypatch.setattr("vectorwave.database.db_search.get_weaviate_settings", mock_get_settings)
107
+
108
+ mock_client = MagicMock(spec=weaviate.WeaviateClient)
109
+ mock_collections_obj = MagicMock()
110
+ mock_exec_collection = MagicMock()
111
+ mock_exec_collection.query.fetch_objects.return_value = MagicMock(objects=[])
112
+
113
+ def get_collection_side_effect(name):
114
+ if name == "TestExecutions":
115
+ return mock_exec_collection
116
+ return MagicMock()
117
+
118
+ mock_collections_obj.get = MagicMock(side_effect=get_collection_side_effect)
119
+ mock_client.collections = mock_collections_obj
120
+
121
+ mock_get_client = MagicMock(return_value=mock_client)
122
+ monkeypatch.setattr("vectorwave.database.db_search.get_cached_client", mock_get_client)
123
+
124
+ return {
125
+ "client": mock_client,
126
+ "collection": mock_exec_collection,
127
+ "settings": mock_settings
128
+ }
129
+
130
+ def test_search_executions_default_sort(mock_search_exec_deps):
131
+ mock_collection = mock_search_exec_deps["collection"]
132
+ search_executions(limit=5)
133
+
134
+ mock_collection.query.fetch_objects.assert_called_once_with(
135
+ limit=5,
136
+ filters=None,
137
+ sort=ANY
138
+ )
139
+
140
+ call_args = mock_collection.query.fetch_objects.call_args
141
+ sort_arg = call_args.kwargs['sort']
142
+
143
+ assert sort_arg is not None
144
+
145
+ def test_search_executions_filter_and_sort_duration(mock_search_exec_deps):
146
+ mock_collection = mock_search_exec_deps["collection"]
147
+ test_filters = {"status": "SUCCESS"}
148
+
149
+ search_executions(
150
+ limit=3,
151
+ filters=test_filters,
152
+ sort_by="duration_ms",
153
+ sort_ascending=False
154
+ )
155
+
156
+ mock_collection.query.fetch_objects.assert_called_once()
157
+ call_args = mock_collection.query.fetch_objects.call_args
158
+
159
+ assert call_args.kwargs['limit'] == 3
160
+ assert call_args.kwargs['filters'] is not None
161
+
162
+ sort_arg = call_args.kwargs['sort']
163
+ assert sort_arg is not None
File without changes
File without changes