77the FT.CREATE command.
88"""
99
10+ import pytest
11+
1012from redisvl .index import SearchIndex
13+ from redisvl .redis .connection import RedisConnectionFactory
1114from redisvl .schema import IndexSchema
1215
16+ MIN_SEARCH_VERSION_FOR_INDEXMISSING = 21000 # RediSearch 2.10.0+
17+
18+
19+ def skip_if_search_version_below_for_indexmissing (client ) -> None :
20+ """Skip tests that require INDEXMISSING/INDEXEMPTY if RediSearch is too old."""
21+ modules = RedisConnectionFactory .get_modules (client )
22+ search_ver = modules .get ("search" , 0 )
23+ searchlight_ver = modules .get ("searchlight" , 0 )
24+ current_ver = max (search_ver , searchlight_ver )
25+ if current_ver < MIN_SEARCH_VERSION_FOR_INDEXMISSING :
26+ pytest .skip (
27+ "INDEXMISSING/INDEXEMPTY require RediSearch 2.10+ "
28+ f"(found module version { current_ver } )"
29+ )
30+
1331
1432class TestTextFieldModifierOrderingIntegration :
1533 """Integration tests for TextField modifier ordering."""
1634
1735 def test_textfield_sortable_and_index_missing (self , client , redis_url , worker_id ):
1836 """Test TextField with sortable and index_missing creates successfully."""
37+ skip_if_search_version_below_for_indexmissing (client )
1938 schema_dict = {
2039 "index" : {
2140 "name" : f"test_text_sortable_missing_{ worker_id } " ,
@@ -44,10 +63,14 @@ def test_textfield_sortable_and_index_missing(self, client, redis_url, worker_id
4463 )
4564 assert info is not None
4665 finally :
47- index .delete (drop = True )
66+ try :
67+ index .delete (drop = True )
68+ except Exception :
69+ pass # Index may not exist if test was skipped or failed early
4870
4971 def test_textfield_all_modifiers (self , client , redis_url , worker_id ):
5072 """Test TextField with all modifiers."""
73+ skip_if_search_version_below_for_indexmissing (client )
5174 schema_dict = {
5275 "index" : {
5376 "name" : f"test_text_all_mods_{ worker_id } " ,
@@ -79,14 +102,18 @@ def test_textfield_all_modifiers(self, client, redis_url, worker_id):
79102 info = client .execute_command ("FT.INFO" , f"test_text_all_mods_{ worker_id } " )
80103 assert info is not None
81104 finally :
82- index .delete (drop = True )
105+ try :
106+ index .delete (drop = True )
107+ except Exception :
108+ pass # Index may not exist if test was skipped or failed early
83109
84110
85111class TestTagFieldModifierOrderingIntegration :
86112 """Integration tests for TagField modifier ordering."""
87113
88114 def test_tagfield_sortable_and_index_missing (self , client , redis_url , worker_id ):
89115 """Test TagField with sortable and index_missing creates successfully."""
116+ skip_if_search_version_below_for_indexmissing (client )
90117 schema_dict = {
91118 "index" : {
92119 "name" : f"test_tag_sortable_missing_{ worker_id } " ,
@@ -115,10 +142,14 @@ def test_tagfield_sortable_and_index_missing(self, client, redis_url, worker_id)
115142 )
116143 assert info is not None
117144 finally :
118- index .delete (drop = True )
145+ try :
146+ index .delete (drop = True )
147+ except Exception :
148+ pass # Index may not exist if test was skipped or failed early
119149
120150 def test_tagfield_all_modifiers (self , client , redis_url , worker_id ):
121151 """Test TagField with all modifiers."""
152+ skip_if_search_version_below_for_indexmissing (client )
122153 schema_dict = {
123154 "index" : {
124155 "name" : f"test_tag_all_mods_{ worker_id } " ,
@@ -149,14 +180,18 @@ def test_tagfield_all_modifiers(self, client, redis_url, worker_id):
149180 info = client .execute_command ("FT.INFO" , f"test_tag_all_mods_{ worker_id } " )
150181 assert info is not None
151182 finally :
152- index .delete (drop = True )
183+ try :
184+ index .delete (drop = True )
185+ except Exception :
186+ pass # Index may not exist if test was skipped or failed early
153187
154188
155189class TestGeoFieldModifierOrderingIntegration :
156190 """Integration tests for GeoField modifier ordering."""
157191
158192 def test_geofield_sortable_and_index_missing (self , client , redis_url , worker_id ):
159193 """Test GeoField with sortable and index_missing creates successfully."""
194+ skip_if_search_version_below_for_indexmissing (client )
160195 schema_dict = {
161196 "index" : {
162197 "name" : f"test_geo_sortable_missing_{ worker_id } " ,
@@ -185,7 +220,10 @@ def test_geofield_sortable_and_index_missing(self, client, redis_url, worker_id)
185220 )
186221 assert info is not None
187222 finally :
188- index .delete (drop = True )
223+ try :
224+ index .delete (drop = True )
225+ except Exception :
226+ pass # Index may not exist if test was skipped or failed early
189227
190228
191229class TestNumericFieldModifierOrderingIntegration :
@@ -195,6 +233,7 @@ def test_numericfield_sortable_and_index_missing(
195233 self , client , redis_url , worker_id
196234 ):
197235 """Test NumericField with sortable and index_missing creates successfully."""
236+ skip_if_search_version_below_for_indexmissing (client )
198237 schema_dict = {
199238 "index" : {
200239 "name" : f"test_numeric_sortable_missing_{ worker_id } " ,
@@ -223,14 +262,18 @@ def test_numericfield_sortable_and_index_missing(
223262 )
224263 assert info is not None
225264 finally :
226- index .delete (drop = True )
265+ try :
266+ index .delete (drop = True )
267+ except Exception :
268+ pass # Index may not exist if test was skipped or failed early
227269
228270
229271class TestMultiFieldModifierOrderingIntegration :
230272 """Integration tests for multiple field types with modifiers."""
231273
232274 def test_mixed_field_types_with_modifiers (self , client , redis_url , worker_id ):
233275 """Test index with multiple field types all using modifiers."""
276+ skip_if_search_version_below_for_indexmissing (client )
234277 schema_dict = {
235278 "index" : {
236279 "name" : f"test_mixed_fields_{ worker_id } " ,
@@ -276,7 +319,10 @@ def test_mixed_field_types_with_modifiers(self, client, redis_url, worker_id):
276319 attrs_list = info [7 ]
277320 assert len (attrs_list ) == 4
278321 finally :
279- index .delete (drop = True )
322+ try :
323+ index .delete (drop = True )
324+ except Exception :
325+ pass # Index may not exist if test was skipped or failed early
280326
281327
282328class TestMultipleCommandsScenarioIntegration :
@@ -289,6 +335,7 @@ def test_mlp_commands_index_creation(self, client, redis_url, worker_id):
289335 (INDEXMISSING, SORTABLE, UNF) can be created successfully with
290336 correct field ordering.
291337 """
338+ skip_if_search_version_below_for_indexmissing (client )
292339 schema_dict = {
293340 "index" : {
294341 "name" : f"testidx_{ worker_id } " ,
@@ -315,10 +362,14 @@ def test_mlp_commands_index_creation(self, client, redis_url, worker_id):
315362 info = client .execute_command ("FT.INFO" , f"testidx_{ worker_id } " )
316363 assert info is not None
317364 finally :
318- index .delete (drop = True )
365+ try :
366+ index .delete (drop = True )
367+ except Exception :
368+ pass # Index may not exist if test was skipped or failed early
319369
320370 def test_indexmissing_enables_ismissing_query (self , client , redis_url , worker_id ):
321371 """Test that INDEXMISSING enables ismissing() query function."""
372+ skip_if_search_version_below_for_indexmissing (client )
322373 schema_dict = {
323374 "index" : {
324375 "name" : f"test_ismissing_{ worker_id } " ,
@@ -359,12 +410,15 @@ def test_indexmissing_enables_ismissing_query(self, client, redis_url, worker_id
359410 assert f"ismiss_{ worker_id } :2" in str (result )
360411
361412 finally :
362- client .delete (
363- f"ismiss_{ worker_id } :1" ,
364- f"ismiss_{ worker_id } :2" ,
365- f"ismiss_{ worker_id } :3" ,
366- )
367- index .delete (drop = True )
413+ try :
414+ client .delete (
415+ f"ismiss_{ worker_id } :1" ,
416+ f"ismiss_{ worker_id } :2" ,
417+ f"ismiss_{ worker_id } :3" ,
418+ )
419+ index .delete (drop = True )
420+ except Exception :
421+ pass # Index may not exist if test was skipped or failed early
368422
369423
370424class TestFieldTypeModifierSupport :
0 commit comments