1414 ClassVar ,
1515 Dict ,
1616 List ,
17+ Literal ,
1718 Mapping ,
1819 Optional ,
1920 Sequence ,
@@ -141,10 +142,10 @@ def embedded(cls):
141142
142143def is_supported_container_type (typ : Optional [type ]) -> bool :
143144 # TODO: Wait, why don't we support indexing sets?
144- if typ == list or typ == tuple :
145+ if typ == list or typ == tuple or typ == Literal :
145146 return True
146147 unwrapped = get_origin (typ )
147- return unwrapped == list or unwrapped == tuple
148+ return unwrapped == list or unwrapped == tuple or unwrapped == Literal
148149
149150
150151def validate_model_fields (model : Type ["RedisModel" ], field_values : Dict [str , Any ]):
@@ -889,7 +890,9 @@ def resolve_redisearch_query(cls, expression: ExpressionOrNegated) -> str:
889890
890891 return result
891892
892- async def execute (self , exhaust_results = True , return_raw_result = False ):
893+ async def execute (
894+ self , exhaust_results = True , return_raw_result = False , return_query_args = False
895+ ):
893896 args : List [Union [str , bytes ]] = [
894897 "FT.SEARCH" ,
895898 self .model .Meta .index_name ,
@@ -914,6 +917,9 @@ async def execute(self, exhaust_results=True, return_raw_result=False):
914917 if self .nocontent :
915918 args .append ("NOCONTENT" )
916919
920+ if return_query_args :
921+ return self .model .Meta .index_name , args
922+
917923 # Reset the cache if we're executing from offset 0.
918924 if self .offset == 0 :
919925 self ._model_cache .clear ()
@@ -947,6 +953,10 @@ async def execute(self, exhaust_results=True, return_raw_result=False):
947953 self ._model_cache += _results
948954 return self ._model_cache
949955
956+ async def get_query (self ):
957+ query = self .copy ()
958+ return await query .execute (return_query_args = True )
959+
950960 async def first (self ):
951961 query = self .copy (offset = 0 , limit = 1 , sort_fields = self .sort_fields )
952962 results = await query .execute (exhaust_results = False )
@@ -1436,6 +1446,8 @@ def outer_type_or_annotation(field):
14361446 if not isinstance (field .annotation , type ):
14371447 raise AttributeError (f"could not extract outer type from field { field } " )
14381448 return field .annotation
1449+ elif get_origin (field .annotation ) == Literal :
1450+ return str
14391451 else :
14401452 return field .annotation .__args__ [0 ]
14411453
@@ -2081,21 +2093,33 @@ def schema_for_type(
20812093 # find any values marked as indexed.
20822094 if is_container_type and not is_vector :
20832095 field_type = get_origin (typ )
2084- embedded_cls = get_args (typ )
2085- if not embedded_cls :
2086- log .warning (
2087- "Model %s defined an empty list or tuple field: %s" , cls , name
2096+ if field_type == Literal :
2097+ path = f"{ json_path } .{ name } "
2098+ return cls .schema_for_type (
2099+ path ,
2100+ name ,
2101+ name_prefix ,
2102+ str ,
2103+ field_info ,
2104+ parent_type = field_type ,
2105+ )
2106+ else :
2107+ embedded_cls = get_args (typ )
2108+ if not embedded_cls :
2109+ log .warning (
2110+ "Model %s defined an empty list or tuple field: %s" , cls , name
2111+ )
2112+ return ""
2113+ path = f"{ json_path } .{ name } [*]"
2114+ embedded_cls = embedded_cls [0 ]
2115+ return cls .schema_for_type (
2116+ path ,
2117+ name ,
2118+ name_prefix ,
2119+ embedded_cls ,
2120+ field_info ,
2121+ parent_type = field_type ,
20882122 )
2089- return ""
2090- embedded_cls = embedded_cls [0 ]
2091- return cls .schema_for_type (
2092- f"{ json_path } .{ name } [*]" ,
2093- name ,
2094- name_prefix ,
2095- embedded_cls ,
2096- field_info ,
2097- parent_type = field_type ,
2098- )
20992123 elif field_is_model :
21002124 name_prefix = f"{ name_prefix } _{ name } " if name_prefix else name
21012125 sub_fields = []
0 commit comments