76
76
77
77
78
78
def get_outer_type (field ):
79
- if hasattr (field , ' outer_type_' ):
79
+ if hasattr (field , " outer_type_" ):
80
80
return field .outer_type_
81
- elif isinstance (field .annotation , type ) or is_supported_container_type (field .annotation ):
81
+ elif isinstance (field .annotation , type ) or is_supported_container_type (
82
+ field .annotation
83
+ ):
82
84
return field .annotation
83
- elif not isinstance (field .annotation .__args__ [0 ], type ):
84
- return field .annotation .__args__ [0 ].__origin__
85
+ # elif not isinstance(field.annotation.__args__[0], type):
86
+ # return field.annotation.__args__[0].__origin__
85
87
else :
86
88
return field .annotation .__args__ [0 ]
87
89
90
+
88
91
class RedisModelError (Exception ):
89
92
"""Raised when a problem exists in the definition of a RedisModel."""
90
93
@@ -116,7 +119,9 @@ def __str__(self):
116
119
return str (self .name )
117
120
118
121
119
- ExpressionOrModelField = Union ["Expression" , "NegatedExpression" , ModelField , PydanticFieldInfo ]
122
+ ExpressionOrModelField = Union [
123
+ "Expression" , "NegatedExpression" , ModelField , PydanticFieldInfo
124
+ ]
120
125
121
126
122
127
def embedded (cls ):
@@ -140,8 +145,8 @@ def validate_model_fields(model: Type["RedisModel"], field_values: Dict[str, Any
140
145
if "__" in field_name :
141
146
obj = model
142
147
for sub_field in field_name .split ("__" ):
143
- if not isinstance (obj , ModelMeta ) and hasattr (obj , ' field' ):
144
- obj = getattr (obj , ' field' ).annotation
148
+ if not isinstance (obj , ModelMeta ) and hasattr (obj , " field" ):
149
+ obj = getattr (obj , " field" ).annotation
145
150
146
151
if not hasattr (obj , sub_field ):
147
152
raise QuerySyntaxError (
@@ -496,7 +501,9 @@ def validate_sort_fields(self, sort_fields: List[str]):
496
501
f"does not exist on the model { self .model } "
497
502
)
498
503
field_proxy = getattr (self .model , field_name )
499
- if isinstance (field_proxy .field , FieldInfo ) or isinstance (field_proxy .field , PydanticFieldInfo ):
504
+ if isinstance (field_proxy .field , FieldInfo ) or isinstance (
505
+ field_proxy .field , PydanticFieldInfo
506
+ ):
500
507
field_info = field_proxy .field
501
508
else :
502
509
field_info = field_proxy .field .field_info
@@ -510,7 +517,7 @@ def validate_sort_fields(self, sort_fields: List[str]):
510
517
511
518
@staticmethod
512
519
def resolve_field_type (field : ModelField , op : Operators ) -> RediSearchFieldTypes :
513
- if not hasattr (field , ' field_info' ):
520
+ if not hasattr (field , " field_info" ):
514
521
field_info = field
515
522
else :
516
523
field_info = field .field_info
@@ -528,6 +535,9 @@ def resolve_field_type(field: ModelField, op: Operators) -> RediSearchFieldTypes
528
535
529
536
field_type = outer_type_or_annotation (field )
530
537
538
+ if not isinstance (field_type , type ):
539
+ field_type = field_type .__origin__
540
+
531
541
# TODO: GEO fields
532
542
container_type = get_origin (field_type )
533
543
@@ -1270,10 +1280,11 @@ def __new__(cls, name, bases, attrs, **kwargs): # noqa C901
1270
1280
for base_candidate in bases :
1271
1281
if hasattr (base_candidate , field_name ):
1272
1282
inner_field = getattr (base_candidate , field_name )
1273
- if hasattr (inner_field , 'field' ) and isinstance (getattr (inner_field , 'field' ), FieldInfo ):
1274
- field .metadata .append (getattr (inner_field , 'field' ))
1275
- field = getattr (inner_field , 'field' )
1276
-
1283
+ if hasattr (inner_field , "field" ) and isinstance (
1284
+ getattr (inner_field , "field" ), FieldInfo
1285
+ ):
1286
+ field .metadata .append (getattr (inner_field , "field" ))
1287
+ field = getattr (inner_field , "field" )
1277
1288
1278
1289
if not field .alias :
1279
1290
field .alias = field_name
@@ -1288,9 +1299,11 @@ def __new__(cls, name, bases, attrs, **kwargs): # noqa C901
1288
1299
# Check if this is our FieldInfo version with extended ORM metadata.
1289
1300
# if isinstance(field.field_info, FieldInfo):
1290
1301
field_info = None
1291
- if hasattr (field , ' field_info' ) and isinstance (field .field_info , FieldInfo ):
1302
+ if hasattr (field , " field_info" ) and isinstance (field .field_info , FieldInfo ):
1292
1303
field_info = field .field_info
1293
- elif field_name in attrs and isinstance (attrs .__getitem__ (field_name ), FieldInfo ):
1304
+ elif field_name in attrs and isinstance (
1305
+ attrs .__getitem__ (field_name ), FieldInfo
1306
+ ):
1294
1307
field_info = attrs .__getitem__ (field_name )
1295
1308
field .field_info = field_info
1296
1309
@@ -1344,9 +1357,9 @@ def __new__(cls, name, bases, attrs, **kwargs): # noqa C901
1344
1357
1345
1358
1346
1359
def outer_type_or_annotation (field ):
1347
- if hasattr (field , ' outer_type_' ):
1360
+ if hasattr (field , " outer_type_" ):
1348
1361
return field .outer_type_
1349
- elif not hasattr (field .annotation , ' __args__' ):
1362
+ elif not hasattr (field .annotation , " __args__" ):
1350
1363
if not isinstance (field .annotation , type ):
1351
1364
raise AttributeError (f"could not extract outer type from field { field } " )
1352
1365
return field .annotation
@@ -1355,7 +1368,7 @@ def outer_type_or_annotation(field):
1355
1368
1356
1369
1357
1370
class RedisModel (BaseModel , abc .ABC , metaclass = ModelMeta ):
1358
- # class RedisModel(BaseModel, abc.ABC):
1371
+ # class RedisModel(BaseModel, abc.ABC):
1359
1372
pk : Optional [str ] = Field (default = None , primary_key = True )
1360
1373
# pk: Optional[str] = Field(default=None, primary_key=True)
1361
1374
@@ -1376,7 +1389,7 @@ def __lt__(self, other):
1376
1389
1377
1390
def key (self ):
1378
1391
"""Return the Redis key for this model."""
1379
- if hasattr (self ._meta .primary_key .field , ' name' ):
1392
+ if hasattr (self ._meta .primary_key .field , " name" ):
1380
1393
pk = getattr (self , self ._meta .primary_key .field .name )
1381
1394
else :
1382
1395
pk = getattr (self , self ._meta .primary_key .name )
@@ -1427,8 +1440,13 @@ def validate_primary_key(cls):
1427
1440
"""Check for a primary key. We need one (and only one)."""
1428
1441
primary_keys = 0
1429
1442
for name , field in cls .__fields__ .items ():
1430
- if not hasattr (field , 'field_info' ):
1431
- if not isinstance (field , FieldInfo ) and hasattr (field , 'metadata' ) and len (field .metadata ) > 0 and isinstance (field .metadata [0 ], FieldInfo ):
1443
+ if not hasattr (field , "field_info" ):
1444
+ if (
1445
+ not isinstance (field , FieldInfo )
1446
+ and hasattr (field , "metadata" )
1447
+ and len (field .metadata ) > 0
1448
+ and isinstance (field .metadata [0 ], FieldInfo )
1449
+ ):
1432
1450
field_info = field .metadata [0 ]
1433
1451
else :
1434
1452
field_info = field
@@ -1568,6 +1586,7 @@ def redisearch_schema(cls):
1568
1586
def check (self ):
1569
1587
"""Run all validations."""
1570
1588
from pydantic .version import VERSION as PYDANTIC_VERSION
1589
+
1571
1590
PYDANTIC_V2 = PYDANTIC_VERSION .startswith ("2." )
1572
1591
if not PYDANTIC_V2 :
1573
1592
* _ , validation_error = validate_model (self .__class__ , self .__dict__ )
@@ -1579,7 +1598,7 @@ class HashModel(RedisModel, abc.ABC):
1579
1598
def __init_subclass__ (cls , ** kwargs ):
1580
1599
super ().__init_subclass__ (** kwargs )
1581
1600
1582
- if hasattr (cls , ' __annotations__' ):
1601
+ if hasattr (cls , " __annotations__" ):
1583
1602
for name , field_type in cls .__annotations__ .items ():
1584
1603
origin = get_origin (field_type )
1585
1604
for typ in (Set , Mapping , List ):
@@ -1589,8 +1608,12 @@ def __init_subclass__(cls, **kwargs):
1589
1608
f" or mapping fields. Field: { name } "
1590
1609
)
1591
1610
if isinstance (field_type , type ) and issubclass (field_type , RedisModel ):
1592
- raise RedisModelError (f"HashModels cannot index embedded model fields. Field: { name } " )
1593
- elif isinstance (field_type , type ) and dataclasses .is_dataclass (field_type ):
1611
+ raise RedisModelError (
1612
+ f"HashModels cannot index embedded model fields. Field: { name } "
1613
+ )
1614
+ elif isinstance (field_type , type ) and dataclasses .is_dataclass (
1615
+ field_type
1616
+ ):
1594
1617
raise RedisModelError (
1595
1618
f"HashModels cannot index dataclass fields. Field: { name } "
1596
1619
)
@@ -1698,10 +1721,15 @@ def schema_for_fields(cls):
1698
1721
_type = outer_type_or_annotation (field )
1699
1722
is_subscripted_type = get_origin (_type )
1700
1723
1701
- if not isinstance (field , FieldInfo ) and hasattr (field , 'metadata' ) and len (field .metadata ) > 0 and isinstance (field .metadata [0 ], FieldInfo ):
1724
+ if (
1725
+ not isinstance (field , FieldInfo )
1726
+ and hasattr (field , "metadata" )
1727
+ and len (field .metadata ) > 0
1728
+ and isinstance (field .metadata [0 ], FieldInfo )
1729
+ ):
1702
1730
field = field .metadata [0 ]
1703
1731
1704
- if not hasattr (field , ' field_info' ):
1732
+ if not hasattr (field , " field_info" ):
1705
1733
field_info = field
1706
1734
else :
1707
1735
field_info = field .field_info
@@ -1712,9 +1740,7 @@ def schema_for_fields(cls):
1712
1740
f"{ name } TAG SEPARATOR { SINGLE_VALUE_TAG_FIELD_SEPARATOR } "
1713
1741
)
1714
1742
else :
1715
- redisearch_field = cls .schema_for_type (
1716
- name , _type , field_info
1717
- )
1743
+ redisearch_field = cls .schema_for_type (name , _type , field_info )
1718
1744
schema_parts .append (redisearch_field )
1719
1745
elif getattr (field_info , "index" , None ) is True :
1720
1746
schema_parts .append (cls .schema_for_type (name , _type , field_info ))
@@ -1730,9 +1756,7 @@ def schema_for_fields(cls):
1730
1756
log .warning ("Model %s defined an empty list field: %s" , cls , name )
1731
1757
continue
1732
1758
embedded_cls = embedded_cls [0 ]
1733
- schema_parts .append (
1734
- cls .schema_for_type (name , embedded_cls , field_info )
1735
- )
1759
+ schema_parts .append (cls .schema_for_type (name , embedded_cls , field_info ))
1736
1760
elif issubclass (_type , RedisModel ):
1737
1761
schema_parts .append (cls .schema_for_type (name , _type , field_info ))
1738
1762
return schema_parts
@@ -1875,7 +1899,7 @@ def schema_for_fields(cls):
1875
1899
for name , field in cls .__dict__ .items ():
1876
1900
if isinstance (field , FieldInfo ):
1877
1901
if not field .annotation :
1878
- field .annotation = cls .__annotations__ .get (name )
1902
+ field .annotation = cls .__annotations__ .get (name )
1879
1903
fields [name ] = field
1880
1904
for name , field in cls .__annotations__ .items ():
1881
1905
if name in fields :
@@ -1884,22 +1908,23 @@ def schema_for_fields(cls):
1884
1908
1885
1909
for name , field in fields .items ():
1886
1910
_type = get_outer_type (field )
1887
- if not isinstance (field , FieldInfo ) and hasattr (field , 'metadata' ) and len (field .metadata ) > 0 and isinstance (field .metadata [0 ], FieldInfo ):
1911
+ if (
1912
+ not isinstance (field , FieldInfo )
1913
+ and hasattr (field , "metadata" )
1914
+ and len (field .metadata ) > 0
1915
+ and isinstance (field .metadata [0 ], FieldInfo )
1916
+ ):
1888
1917
field = field .metadata [0 ]
1889
1918
1890
- if hasattr (field , ' field_info' ):
1919
+ if hasattr (field , " field_info" ):
1891
1920
field_info = field .field_info
1892
1921
else :
1893
1922
field_info = field
1894
1923
if getattr (field_info , "primary_key" , None ):
1895
1924
if issubclass (_type , str ):
1896
- redisearch_field = (
1897
- f"$.{ name } AS { name } TAG SEPARATOR { SINGLE_VALUE_TAG_FIELD_SEPARATOR } "
1898
- )
1925
+ redisearch_field = f"$.{ name } AS { name } TAG SEPARATOR { SINGLE_VALUE_TAG_FIELD_SEPARATOR } "
1899
1926
else :
1900
- redisearch_field = cls .schema_for_type (
1901
- name , _type , field_info
1902
- )
1927
+ redisearch_field = cls .schema_for_type (name , _type , field_info )
1903
1928
schema_parts .append (redisearch_field )
1904
1929
continue
1905
1930
schema_parts .append (
@@ -1982,9 +2007,13 @@ def schema_for_type(
1982
2007
name_prefix = f"{ name_prefix } _{ name } " if name_prefix else name
1983
2008
sub_fields = []
1984
2009
for embedded_name , field in typ .__fields__ .items ():
1985
- if hasattr (field , ' field_info' ):
2010
+ if hasattr (field , " field_info" ):
1986
2011
field_info = field .field_info
1987
- elif hasattr (field , 'metadata' ) and len (field .metadata ) > 0 and isinstance (field .metadata [0 ], FieldInfo ):
2012
+ elif (
2013
+ hasattr (field , "metadata" )
2014
+ and len (field .metadata ) > 0
2015
+ and isinstance (field .metadata [0 ], FieldInfo )
2016
+ ):
1988
2017
field_info = field .metadata [0 ]
1989
2018
else :
1990
2019
field_info = field
@@ -2031,6 +2060,9 @@ def schema_for_type(
2031
2060
"See docs: TODO"
2032
2061
)
2033
2062
2063
+ if not isinstance (typ , type ):
2064
+ typ = field_info .annotation .__args__ [0 ].__origin__
2065
+
2034
2066
# TODO: GEO field
2035
2067
if is_vector and vector_options :
2036
2068
schema = f"{ path } AS { index_field_name } { vector_options .schema } "
0 commit comments