weaviate-cli 3.2.1__tar.gz → 3.2.3__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 (72) hide show
  1. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/PKG-INFO +5 -5
  2. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/README.md +3 -3
  3. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/cli.py +14 -0
  4. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/requirements-dev.txt +1 -1
  5. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/setup.cfg +1 -1
  6. weaviate_cli-3.2.3/test/integration/test_data_integration.py +391 -0
  7. weaviate_cli-3.2.3/test/unittests/test_managers/test_alias_manager.py +209 -0
  8. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/unittests/test_utils.py +61 -0
  9. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/commands/cancel.py +22 -0
  10. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/commands/create.py +142 -5
  11. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/commands/delete.py +72 -1
  12. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/commands/get.py +128 -1
  13. weaviate_cli-3.2.3/weaviate_cli/commands/query.py +225 -0
  14. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/commands/update.py +22 -0
  15. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/defaults.py +34 -8
  16. weaviate_cli-3.2.3/weaviate_cli/managers/alias_manager.py +52 -0
  17. weaviate_cli-3.2.3/weaviate_cli/managers/cluster_manager.py +220 -0
  18. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/managers/collection_manager.py +182 -34
  19. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/managers/data_manager.py +75 -43
  20. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/managers/node_manager.py +5 -3
  21. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/managers/role_manager.py +15 -1
  22. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/managers/tenant_manager.py +29 -17
  23. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/utils.py +28 -6
  24. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli.egg-info/PKG-INFO +5 -5
  25. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli.egg-info/SOURCES.txt +4 -0
  26. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli.egg-info/requires.txt +1 -1
  27. weaviate_cli-3.2.1/weaviate_cli/commands/query.py +0 -84
  28. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/.github/dependabot.yml +0 -0
  29. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/.github/workflows/main.yaml +0 -0
  30. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/.github/workflows/release.yaml +0 -0
  31. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/.gitignore +0 -0
  32. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/.pre-commit-config.yaml +0 -0
  33. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/CONTRIBUTING.md +0 -0
  34. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/Dockerfile +0 -0
  35. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/LICENSE +0 -0
  36. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/MANIFEST.in +0 -0
  37. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/Makefile +0 -0
  38. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/publish.md +0 -0
  39. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/pyproject.toml +0 -0
  40. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/setup.py +0 -0
  41. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/README.md +0 -0
  42. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/__init__.py +0 -0
  43. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/integration/test_auth_integration.py +0 -0
  44. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/integration/test_integration.py +0 -0
  45. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/unittests/conftest.py +0 -0
  46. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/unittests/test_cli.py +0 -0
  47. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/unittests/test_defaults.py +0 -0
  48. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/unittests/test_managers/test_collection_manager.py +0 -0
  49. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/unittests/test_managers/test_config_manager.py +0 -0
  50. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/unittests/test_managers/test_data_manager.py +0 -0
  51. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/unittests/test_managers/test_node_manager.py +0 -0
  52. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/unittests/test_managers/test_shard_manager.py +0 -0
  53. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/test/unittests/test_managers/test_user_manager.py +0 -0
  54. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/__init__.py +0 -0
  55. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/commands/__init__.py +0 -0
  56. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/commands/assign.py +0 -0
  57. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/commands/restore.py +0 -0
  58. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/commands/revoke.py +0 -0
  59. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/completion/__init__.py +0 -0
  60. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/completion/complete.py +0 -0
  61. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/datasets/__init__.py +0 -0
  62. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/datasets/movies.json +0 -0
  63. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/managers/__init__.py +0 -0
  64. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/managers/backup_manager.py +0 -0
  65. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/managers/config_manager.py +0 -0
  66. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/managers/shard_manager.py +0 -0
  67. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/managers/user_manager.py +0 -0
  68. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli/types/models.py +0 -0
  69. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli.egg-info/dependency_links.txt +0 -0
  70. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli.egg-info/entry_points.txt +0 -0
  71. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli.egg-info/not-zip-safe +0 -0
  72. {weaviate_cli-3.2.1 → weaviate_cli-3.2.3}/weaviate_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weaviate-cli
3
- Version: 3.2.1
3
+ Version: 3.2.3
4
4
  Summary: Command line interface to interact with weaviate
5
5
  Home-page: https://github.com/weaviate/weaviate-cli
6
6
  Download-URL: https://github.com/weaviate/weaviate-cli
@@ -28,7 +28,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
28
28
  Requires-Python: >=3.9
29
29
  Description-Content-Type: text/markdown
30
30
  License-File: LICENSE
31
- Requires-Dist: weaviate-client>=4.14.3
31
+ Requires-Dist: weaviate-client>=4.16.0
32
32
  Requires-Dist: click==8.1.7
33
33
  Requires-Dist: semver>=3.0.2
34
34
  Requires-Dist: numpy>=1.24.0
@@ -86,10 +86,10 @@ weaviate-cli query data --collection movies --search-type hybrid --query "action
86
86
 
87
87
  ## Core Commands
88
88
 
89
- - **create**: Create collections, tenants, backups or import data
90
- - **delete**: Remove collections, tenants or data
89
+ - **create**: Create collections, tenants, backups, replications or import data
90
+ - **delete**: Remove collections, tenants, replications or data
91
91
  - **update**: Modify collection settings, tenant states or data
92
- - **get**: Retrieve collection info, tenant details or shard status
92
+ - **get**: Retrieve collection info, tenant details, replication operations or shard status
93
93
  - **query**: Search data using various methods
94
94
  - **restore**: Restore backups from supported backends
95
95
  - **assign**: Assign roles and permissions to users
@@ -46,10 +46,10 @@ weaviate-cli query data --collection movies --search-type hybrid --query "action
46
46
 
47
47
  ## Core Commands
48
48
 
49
- - **create**: Create collections, tenants, backups or import data
50
- - **delete**: Remove collections, tenants or data
49
+ - **create**: Create collections, tenants, backups, replications or import data
50
+ - **delete**: Remove collections, tenants, replications or data
51
51
  - **update**: Modify collection settings, tenant states or data
52
- - **get**: Retrieve collection info, tenant details or shard status
52
+ - **get**: Retrieve collection info, tenant details, replication operations or shard status
53
53
  - **query**: Search data using various methods
54
54
  - **restore**: Restore backups from supported backends
55
55
  - **assign**: Assign roles and permissions to users
@@ -1,3 +1,17 @@
1
+ import warnings
2
+
3
+ warnings.filterwarnings(
4
+ "ignore", message="pkg_resources is deprecated as an API.", category=UserWarning
5
+ )
6
+ warnings.filterwarnings(
7
+ "ignore",
8
+ message=(
9
+ r"Protobuf gencode version [\d\.]+ is exactly one major version older than the runtime version [\d\.]+ at v1/tenants\.proto\. "
10
+ r"Please update the gencode to avoid compatibility violations in the next runtime release\."
11
+ ),
12
+ category=UserWarning,
13
+ )
14
+
1
15
  from typing import Optional
2
16
  import click
3
17
  import sys
@@ -1,4 +1,4 @@
1
- weaviate-client>=4.14.3
1
+ weaviate-client>=4.16.0
2
2
  click==8.1.7
3
3
  twine
4
4
  pytest
@@ -36,7 +36,7 @@ classifiers =
36
36
  include_package_data = True
37
37
  python_requires = >=3.9
38
38
  install_requires =
39
- weaviate-client>=4.14.3
39
+ weaviate-client>=4.16.0
40
40
  click==8.1.7
41
41
  semver>=3.0.2
42
42
  numpy>=1.24.0
@@ -0,0 +1,391 @@
1
+ import pytest
2
+ import weaviate
3
+ import numpy as np
4
+ from weaviate_cli.managers.collection_manager import CollectionManager
5
+ from weaviate_cli.managers.config_manager import ConfigManager
6
+ from weaviate_cli.managers.data_manager import DataManager
7
+ import weaviate.classes.config as wvc
8
+
9
+
10
+ @pytest.fixture
11
+ def client() -> weaviate.Client:
12
+ config = ConfigManager()
13
+ return config.get_client()
14
+
15
+
16
+ @pytest.fixture
17
+ def collection_manager(client: weaviate.Client) -> CollectionManager:
18
+ return CollectionManager(client)
19
+
20
+
21
+ @pytest.fixture
22
+ def data_manager(client: weaviate.Client) -> DataManager:
23
+ return DataManager(client)
24
+
25
+
26
+ @pytest.mark.parametrize("randomize", [False, True])
27
+ @pytest.mark.parametrize("vectorizer", ["transformers", "contextionary"])
28
+ def test_data_creation_with_different_configs(
29
+ collection_manager: CollectionManager,
30
+ data_manager: DataManager,
31
+ randomize: bool,
32
+ vectorizer: str,
33
+ ):
34
+ """Test data creation with different randomize and vectorizer configurations."""
35
+ collection_name = f"TestData{randomize}{vectorizer.capitalize()[:7]}"
36
+ # Contextionary does not know the word "contextionary", therefore we truncate it to "context" [0:7]
37
+
38
+ try:
39
+ # Create collection with specified vectorizer
40
+ collection_manager.create_collection(
41
+ collection=collection_name,
42
+ vectorizer=vectorizer,
43
+ replication_factor=1,
44
+ training_limit=1000,
45
+ async_enabled=True,
46
+ )
47
+
48
+ # Verify collection exists
49
+ assert collection_manager.client.collections.exists(collection_name)
50
+
51
+ # Create data with specified randomize setting
52
+ data_manager.create_data(
53
+ collection=collection_name,
54
+ limit=50,
55
+ consistency_level="one",
56
+ randomize=randomize,
57
+ skip_seed=True,
58
+ )
59
+
60
+ # Get the collection and verify data was created
61
+ collection = collection_manager.client.collections.get(collection_name)
62
+
63
+ # Wait for indexing to complete
64
+ collection.batch.wait_for_vector_indexing()
65
+
66
+ # Query objects to verify they have content and vectors
67
+ objects = collection.query.fetch_objects(limit=50, include_vector=True)
68
+
69
+ # Verify we got the expected number of objects
70
+ assert len(objects.objects) == 50
71
+
72
+ # Verify each object has content and vectors
73
+ for obj in objects.objects:
74
+ # Check that object has properties
75
+ assert hasattr(obj, "properties")
76
+ assert obj.properties is not None
77
+
78
+ # Check that object has a title (required field)
79
+ assert "title" in obj.properties
80
+ assert obj.properties["title"] is not None
81
+ assert len(obj.properties["title"]) > 0
82
+
83
+ # Check that object has genres
84
+ assert "genres" in obj.properties
85
+ assert obj.properties["genres"] is not None
86
+
87
+ # Check that object has keywords
88
+ assert "keywords" in obj.properties
89
+ assert obj.properties["keywords"] is not None
90
+
91
+ # Verify vector was created
92
+ assert hasattr(obj, "vector")
93
+ assert obj.vector is not None
94
+
95
+ vector_dimensions = {
96
+ "transformers": 384,
97
+ "contextionary": 300,
98
+ }
99
+
100
+ # Check vector dimensions (should be 1536 for default)
101
+ assert len(obj.vector["default"]) == vector_dimensions[vectorizer]
102
+
103
+ # Verify vector is not all zeros (should have meaningful values)
104
+ assert not np.allclose(
105
+ obj.vector["default"], np.zeros(vector_dimensions[vectorizer])
106
+ )
107
+
108
+ # Verify vector has finite values
109
+ assert np.all(np.isfinite(obj.vector["default"]))
110
+
111
+ finally:
112
+ # Clean up
113
+ if collection_manager.client.collections.exists(collection_name):
114
+ collection_manager.delete_collection(collection=collection_name)
115
+
116
+
117
+ @pytest.mark.parametrize("vectorizer", ["transformers", "none"])
118
+ @pytest.mark.parametrize(
119
+ "named_vector_name", ["custom_vector", "movie_embedding", "content_vector"]
120
+ )
121
+ def test_data_creation_with_named_vectors(
122
+ collection_manager: CollectionManager,
123
+ data_manager: DataManager,
124
+ named_vector_name: str,
125
+ vectorizer: str,
126
+ ):
127
+ """Test data creation with named vectors and verify the correct vector name is set."""
128
+ collection_name = f"TestNamedVector{named_vector_name}{vectorizer.capitalize()}"
129
+
130
+ try:
131
+ # Create collection with named vector
132
+ collection_manager.create_collection(
133
+ collection=collection_name,
134
+ vectorizer=vectorizer,
135
+ replication_factor=1,
136
+ training_limit=1000,
137
+ async_enabled=True,
138
+ named_vector=True,
139
+ named_vector_name=named_vector_name,
140
+ )
141
+
142
+ # Verify collection exists
143
+ assert collection_manager.client.collections.exists(collection_name)
144
+
145
+ # Create data
146
+ data_manager.create_data(
147
+ collection=collection_name,
148
+ limit=30,
149
+ consistency_level="one",
150
+ vector_dimensions=384 if vectorizer == "none" else None,
151
+ randomize=True,
152
+ skip_seed=True,
153
+ )
154
+
155
+ # Get the collection and verify data was created
156
+ collection = collection_manager.client.collections.get(collection_name)
157
+
158
+ # Wait for indexing to complete
159
+ collection.batch.wait_for_vector_indexing()
160
+
161
+ # Query objects to verify they have content and named vectors
162
+ objects = collection.query.fetch_objects(limit=30, include_vector=True)
163
+
164
+ # Verify we got the expected number of objects
165
+ assert len(objects.objects) == 30
166
+
167
+ # Verify each object has content and the correct named vector
168
+ for obj in objects.objects:
169
+ # Check that object has properties
170
+ assert hasattr(obj, "properties")
171
+ assert obj.properties is not None
172
+
173
+ # Check that object has a title
174
+ assert "title" in obj.properties
175
+ assert obj.properties["title"] is not None
176
+
177
+ # Check that object has genres
178
+ assert "genres" in obj.properties
179
+ assert obj.properties["genres"] is not None
180
+
181
+ # Check that object has keywords
182
+ assert "keywords" in obj.properties
183
+ assert obj.properties["keywords"] is not None
184
+
185
+ # Verify named vector was created with correct name
186
+ assert hasattr(obj, "vector")
187
+ assert obj.vector is not None
188
+
189
+ # Check that the named vector exists
190
+ assert named_vector_name in obj.vector
191
+
192
+ # Get the named vector
193
+ named_vector = obj.vector[named_vector_name]
194
+ assert named_vector is not None
195
+
196
+ # Check vector dimensions (should be 768 for transformers)
197
+ assert len(named_vector) == 384
198
+
199
+ # Verify vector is not all zeros
200
+ assert not np.allclose(named_vector, np.zeros(384))
201
+
202
+ # Verify vector has finite values
203
+ assert np.all(np.isfinite(named_vector))
204
+
205
+ finally:
206
+ # Clean up
207
+ if collection_manager.client.collections.exists(collection_name):
208
+ collection_manager.delete_collection(collection=collection_name)
209
+
210
+
211
+ def test_data_creation_with_multi_vector(
212
+ collection_manager: CollectionManager,
213
+ data_manager: DataManager,
214
+ ):
215
+ """Test data creation with multi-vector enabled."""
216
+ collection_name = "TestMultiVector"
217
+
218
+ try:
219
+ # Create collection
220
+ collection_manager.create_collection(
221
+ collection=collection_name,
222
+ vectorizer="none",
223
+ replication_factor=1,
224
+ training_limit=1000,
225
+ async_enabled=True,
226
+ vector_index="hnsw_multivector",
227
+ named_vector=True,
228
+ )
229
+
230
+ # Verify collection exists
231
+ assert collection_manager.client.collections.exists(collection_name)
232
+
233
+ # Create data with multi-vector enabled
234
+ data_manager.create_data(
235
+ collection=collection_name,
236
+ limit=25,
237
+ consistency_level="one",
238
+ randomize=True,
239
+ skip_seed=True,
240
+ multi_vector=True,
241
+ vector_dimensions=1536,
242
+ )
243
+
244
+ # Get the collection and verify data was created
245
+ collection = collection_manager.client.collections.get(collection_name)
246
+
247
+ # Wait for indexing to complete
248
+ collection.batch.wait_for_vector_indexing()
249
+
250
+ # Query objects to verify they have content and vectors
251
+ objects = collection.query.fetch_objects(limit=25, include_vector=True)
252
+
253
+ # Verify we got the expected number of objects
254
+ assert len(objects.objects) == 25
255
+
256
+ # Verify each object has content and vectors
257
+ for obj in objects.objects:
258
+ # Check that object has properties
259
+ assert hasattr(obj, "properties")
260
+ assert obj.properties is not None
261
+
262
+ # Check that object has a title
263
+ assert "title" in obj.properties
264
+ assert obj.properties["title"] is not None
265
+
266
+ # Check that object has genres
267
+ assert "genres" in obj.properties
268
+ assert obj.properties["genres"] is not None
269
+
270
+ # Check that object has keywords
271
+ assert "keywords" in obj.properties
272
+ assert obj.properties["keywords"] is not None
273
+
274
+ # Verify vector was created
275
+ assert hasattr(obj, "vector")
276
+ assert obj.vector is not None
277
+
278
+ # Check vector dimensions
279
+ for vector in obj.vector["default"]:
280
+ assert len(vector) == 1536
281
+
282
+ # Verify vector is not all zeros
283
+ for vector in obj.vector["default"]:
284
+ assert not np.allclose(vector, np.zeros(1536))
285
+
286
+ # Verify vector has finite values
287
+ for vector in obj.vector["default"]:
288
+ assert np.all(np.isfinite(vector))
289
+
290
+ finally:
291
+ # Clean up
292
+ if collection_manager.client.collections.exists(collection_name):
293
+ collection_manager.delete_collection(collection=collection_name)
294
+
295
+
296
+ def test_data_creation_with_custom_vector_dimensions(
297
+ collection_manager: CollectionManager,
298
+ data_manager: DataManager,
299
+ ):
300
+ """Test data creation with custom vector dimensions."""
301
+ collection_name = "TestCustomDimensions"
302
+ custom_dimensions = 768 # Different from default 1536
303
+
304
+ try:
305
+ # Create collection
306
+ collection_manager.create_collection(
307
+ collection=collection_name,
308
+ vectorizer="none",
309
+ replication_factor=1,
310
+ training_limit=1000,
311
+ async_enabled=True,
312
+ )
313
+
314
+ # Verify collection exists
315
+ assert collection_manager.client.collections.exists(collection_name)
316
+
317
+ # Create data with custom vector dimensions
318
+ data_manager.create_data(
319
+ collection=collection_name,
320
+ limit=20,
321
+ consistency_level="one",
322
+ randomize=True,
323
+ skip_seed=True,
324
+ vector_dimensions=custom_dimensions,
325
+ )
326
+
327
+ # Get the collection and verify data was created
328
+ collection = collection_manager.client.collections.get(collection_name)
329
+
330
+ # Wait for indexing to complete
331
+ collection.batch.wait_for_vector_indexing()
332
+
333
+ # Query objects to verify they have content and vectors with custom dimensions
334
+ objects = collection.query.fetch_objects(limit=20, include_vector=True)
335
+
336
+ # Verify we got the expected number of objects
337
+ assert len(objects.objects) == 20
338
+
339
+ # Verify each object has content and vectors with correct dimensions
340
+ for obj in objects.objects:
341
+ # Check that object has properties
342
+ assert hasattr(obj, "properties")
343
+ assert obj.properties is not None
344
+
345
+ # Check that object has a title
346
+ assert "title" in obj.properties
347
+ assert obj.properties["title"] is not None
348
+
349
+ # Check that object has genres
350
+ assert "genres" in obj.properties
351
+ assert obj.properties["genres"] is not None
352
+
353
+ # Check that object has keywords
354
+ assert "keywords" in obj.properties
355
+ assert obj.properties["keywords"] is not None
356
+
357
+ # Verify vector was created with custom dimensions
358
+ assert hasattr(obj, "vector")
359
+ assert obj.vector is not None
360
+
361
+ # Check vector dimensions (should be custom_dimensions)
362
+ assert len(obj.vector["default"]) == custom_dimensions
363
+
364
+ # Verify vector is not all zeros
365
+ assert not np.allclose(obj.vector["default"], np.zeros(custom_dimensions))
366
+
367
+ # Verify vector has finite values
368
+ assert np.all(np.isfinite(obj.vector["default"]))
369
+
370
+ finally:
371
+ # Clean up
372
+ if collection_manager.client.collections.exists(collection_name):
373
+ collection_manager.delete_collection(collection=collection_name)
374
+
375
+
376
+ def test_data_creation_error_handling(
377
+ collection_manager: CollectionManager,
378
+ data_manager: DataManager,
379
+ ):
380
+ """Test error handling when creating data in non-existent collection."""
381
+
382
+ # Try to create data in non-existent collection
383
+ with pytest.raises(Exception) as exc_info:
384
+ data_manager.create_data(
385
+ collection="NonExistentCollection",
386
+ limit=10,
387
+ consistency_level="one",
388
+ )
389
+
390
+ # Verify error message
391
+ assert "does not exist in Weaviate" in str(exc_info.value)
@@ -0,0 +1,209 @@
1
+ import pytest
2
+ from unittest.mock import MagicMock
3
+ from weaviate.aliases.alias import AliasReturn
4
+
5
+ from weaviate_cli.managers.alias_manager import AliasManager
6
+
7
+
8
+ @pytest.fixture
9
+ def alias_manager(mock_client: MagicMock) -> AliasManager:
10
+ """
11
+ Returns an AliasManager instance with a mocked WeaviateClient.
12
+ """
13
+ mock_client.alias = MagicMock()
14
+ return AliasManager(mock_client)
15
+
16
+
17
+ def test_create_alias_success(
18
+ alias_manager: AliasManager, mock_client: MagicMock
19
+ ) -> None:
20
+ """
21
+ Test successful alias creation.
22
+ """
23
+ alias_name = "test_alias"
24
+ collection_name = "TestCollection"
25
+
26
+ alias_manager.create_alias(alias_name, collection_name)
27
+
28
+ mock_client.alias.create.assert_called_once_with(
29
+ alias_name=alias_name, target_collection=collection_name
30
+ )
31
+
32
+
33
+ def test_create_alias_error(
34
+ alias_manager: AliasManager, mock_client: MagicMock
35
+ ) -> None:
36
+ """
37
+ Test alias creation with an exception.
38
+ """
39
+ alias_name = "test_alias"
40
+ collection_name = "TestCollection"
41
+ error_message = "Failed to create"
42
+ mock_client.alias.create.side_effect = Exception(error_message)
43
+
44
+ with pytest.raises(Exception) as exc_info:
45
+ alias_manager.create_alias(alias_name, collection_name)
46
+
47
+ assert f"Error creating alias '{alias_name}': {error_message}" in str(
48
+ exc_info.value
49
+ )
50
+
51
+
52
+ def test_update_alias_success(
53
+ alias_manager: AliasManager, mock_client: MagicMock
54
+ ) -> None:
55
+ """
56
+ Test successful alias update.
57
+ """
58
+ alias_name = "test_alias"
59
+ collection_name = "NewTestCollection"
60
+
61
+ alias_manager.update_alias(alias_name, collection_name)
62
+
63
+ mock_client.alias.update.assert_called_once_with(
64
+ alias_name=alias_name, new_target_collection=collection_name
65
+ )
66
+
67
+
68
+ def test_update_alias_error(
69
+ alias_manager: AliasManager, mock_client: MagicMock
70
+ ) -> None:
71
+ """
72
+ Test alias update with an exception.
73
+ """
74
+ alias_name = "test_alias"
75
+ collection_name = "NewTestCollection"
76
+ error_message = "Failed to update"
77
+ mock_client.alias.update.side_effect = Exception(error_message)
78
+
79
+ with pytest.raises(Exception) as exc_info:
80
+ alias_manager.update_alias(alias_name, collection_name)
81
+
82
+ assert f"Error updating alias '{alias_name}': {error_message}" in str(
83
+ exc_info.value
84
+ )
85
+
86
+
87
+ def test_get_alias_success(alias_manager: AliasManager, mock_client: MagicMock) -> None:
88
+ """
89
+ Test successful alias retrieval.
90
+ """
91
+ alias_name = "test_alias"
92
+ expected_alias = AliasReturn(alias=alias_name, collection="SomeCollection")
93
+ mock_client.alias.get.return_value = expected_alias
94
+
95
+ result = alias_manager.get_alias(alias_name)
96
+
97
+ assert result == expected_alias
98
+ mock_client.alias.get.assert_called_once_with(alias_name=alias_name)
99
+
100
+
101
+ def test_get_alias_error(alias_manager: AliasManager, mock_client: MagicMock) -> None:
102
+ """
103
+ Test alias retrieval with an exception.
104
+ """
105
+ alias_name = "test_alias"
106
+ error_message = "Failed to get"
107
+ mock_client.alias.get.side_effect = Exception(error_message)
108
+
109
+ with pytest.raises(Exception) as exc_info:
110
+ alias_manager.get_alias(alias_name)
111
+
112
+ assert f"Error getting alias '{alias_name}': {error_message}" in str(exc_info.value)
113
+
114
+
115
+ def test_delete_alias_success(
116
+ alias_manager: AliasManager, mock_client: MagicMock
117
+ ) -> None:
118
+ """
119
+ Test successful alias deletion.
120
+ """
121
+ alias_name = "test_alias"
122
+
123
+ alias_manager.delete_alias(alias_name)
124
+
125
+ mock_client.alias.delete.assert_called_once_with(alias_name=alias_name)
126
+
127
+
128
+ def test_delete_alias_error(
129
+ alias_manager: AliasManager, mock_client: MagicMock
130
+ ) -> None:
131
+ """
132
+ Test alias deletion with an exception.
133
+ """
134
+ alias_name = "test_alias"
135
+ error_message = "Failed to delete"
136
+ mock_client.alias.delete.side_effect = Exception(error_message)
137
+
138
+ with pytest.raises(Exception) as exc_info:
139
+ alias_manager.delete_alias(alias_name)
140
+
141
+ assert f"Error deleting alias '{alias_name}': {error_message}" in str(
142
+ exc_info.value
143
+ )
144
+
145
+
146
+ def test_list_aliases_all_success(
147
+ alias_manager: AliasManager, mock_client: MagicMock
148
+ ) -> None:
149
+ """
150
+ Test successful listing of all aliases.
151
+ """
152
+ expected_aliases = {
153
+ "alias1": AliasReturn(alias="alias1", collection="collection1"),
154
+ "alias2": AliasReturn(alias="alias2", collection="collection2"),
155
+ }
156
+ mock_client.alias.list_all.return_value = expected_aliases
157
+
158
+ result = alias_manager.list_aliases()
159
+
160
+ assert result == expected_aliases
161
+ mock_client.alias.list_all.assert_called_once_with(collection=None)
162
+
163
+
164
+ def test_list_aliases_for_collection_success(
165
+ alias_manager: AliasManager, mock_client: MagicMock
166
+ ) -> None:
167
+ """
168
+ Test successful listing of aliases for a specific collection.
169
+ """
170
+ collection_name = "TestCollection"
171
+ expected_aliases = {
172
+ "alias1": AliasReturn(alias="alias1", collection="TestCollection"),
173
+ "alias2": AliasReturn(alias="alias2", collection="TestCollection"),
174
+ }
175
+ mock_client.alias.list_all.return_value = expected_aliases
176
+
177
+ result = alias_manager.list_aliases(collection=collection_name)
178
+
179
+ assert result == expected_aliases
180
+ mock_client.alias.list_all.assert_called_once_with(collection=collection_name)
181
+
182
+
183
+ def test_list_aliases_error(
184
+ alias_manager: AliasManager, mock_client: MagicMock
185
+ ) -> None:
186
+ """
187
+ Test listing aliases with an exception.
188
+ """
189
+ error_message = "Failed to list"
190
+ mock_client.alias.list_all.side_effect = Exception(error_message)
191
+
192
+ with pytest.raises(Exception) as exc_info:
193
+ alias_manager.list_aliases()
194
+
195
+ assert f"Error listing aliases: {error_message}" in str(exc_info.value)
196
+
197
+
198
+ def test_print_alias(alias_manager: AliasManager, capsys) -> None:
199
+ """
200
+ Test the output of the print_alias method.
201
+ """
202
+ alias_name = "my_alias"
203
+ collection_name = "MyCollection"
204
+ alias = AliasReturn(alias=alias_name, collection=collection_name)
205
+
206
+ alias_manager.print_alias(alias)
207
+
208
+ captured = capsys.readouterr()
209
+ assert captured.out == f"Alias: {alias_name} -> {collection_name}\n"