sera-2 1.26.0__py3-none-any.whl → 1.26.2__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.
@@ -140,12 +140,20 @@ class Query(msgspec.Struct):
140
140
  continue
141
141
 
142
142
  # normalize the value based on the field type.
143
- prop = cls.properties[clause.field]
144
- assert isinstance(prop, DataProperty)
145
- if prop.datatype.pytype.is_enum_type():
146
- # skip enum types -- we directly use it as string.
147
- continue
148
- clause.value = FieldTypeValidator.typemap[prop.datatype.pytype.type](
143
+ if clause.field not in cls.properties and clause.field.endswith("_id"):
144
+ # this should be a foreign key field
145
+ prop = cls.properties[clause.field[:-3]]
146
+ assert isinstance(prop, ObjectProperty)
147
+ field_type = prop.target.get_id_property().datatype.pytype.type
148
+ else:
149
+ prop = cls.properties[clause.field]
150
+ assert isinstance(prop, DataProperty)
151
+ if prop.datatype.pytype.is_enum_type():
152
+ # skip enum types -- we directly use it as string.
153
+ continue
154
+ field_type = prop.datatype.pytype.type
155
+
156
+ clause.value = FieldTypeValidator.typemap[field_type](
149
157
  clause.field, clause.value
150
158
  )
151
159
 
@@ -12,6 +12,7 @@ from codegen.models import (
12
12
  stmt,
13
13
  )
14
14
 
15
+ from sera.make.py_backend.misc import get_python_property_name
15
16
  from sera.misc import (
16
17
  assert_isinstance,
17
18
  assert_not_null,
@@ -110,21 +111,21 @@ def make_python_data_model(
110
111
  ), "If value_pass_as_args is provided, record should not be used as a dummy value should be passed instead."
111
112
  else:
112
113
  value = PredefinedFn.attr_getter(record, expr.ExprIdent(prop.name))
114
+
115
+ propname = get_python_property_name(prop)
113
116
  if isinstance(prop, ObjectProperty) and prop.target.db is not None:
114
117
  if prop.cardinality.is_star_to_many():
115
118
  value = PredefinedFn.map_list(
116
119
  value,
117
120
  lambda item: PredefinedFn.attr_getter(
118
- item, expr.ExprIdent(prop.name + "_id")
121
+ item, expr.ExprIdent(propname)
119
122
  ),
120
123
  )
121
124
  else:
122
125
  assert (
123
126
  value_pass_as_args is None
124
127
  ), "Cannot use value_pass_as_args for a single object property."
125
- value = PredefinedFn.attr_getter(
126
- record, expr.ExprIdent(prop.name + "_id")
127
- )
128
+ value = PredefinedFn.attr_getter(record, expr.ExprIdent(propname))
128
129
 
129
130
  target_idprop = assert_not_null(prop.target.get_id_property())
130
131
  conversion_fn = get_data_conversion(
@@ -147,10 +148,8 @@ def make_python_data_model(
147
148
  mode: Literal["create", "update"],
148
149
  prop: DataProperty | ObjectProperty,
149
150
  ):
150
- if isinstance(prop, ObjectProperty) and prop.target.db is not None:
151
- propname = prop.name + "_id"
152
- else:
153
- propname = prop.name
151
+ propname = get_python_property_name(prop)
152
+
154
153
  value = PredefinedFn.attr_getter(slf, expr.ExprIdent(propname))
155
154
  if isinstance(prop, ObjectProperty):
156
155
  if (
@@ -178,7 +177,7 @@ def make_python_data_model(
178
177
  expr.ExprIdent(AssociationTable),
179
178
  [
180
179
  PredefinedFn.keyword_assignment(
181
- f"{prop.name}_id", conversion_fn(item)
180
+ propname, conversion_fn(item)
182
181
  )
183
182
  ],
184
183
  ),
@@ -236,6 +235,8 @@ def make_python_data_model(
236
235
  if prop.data.system_controlled is None:
237
236
  continue
238
237
 
238
+ propname = get_python_property_name(prop)
239
+
239
240
  update_func = None
240
241
  if mode == "create":
241
242
  if prop.data.system_controlled.on_create_bypass is not None:
@@ -294,7 +295,7 @@ def make_python_data_model(
294
295
 
295
296
  smt = stmt.AssignStatement(
296
297
  PredefinedFn.attr_getter(
297
- expr.ExprIdent("self"), expr.ExprIdent(prop.name)
298
+ expr.ExprIdent("self"), expr.ExprIdent(propname)
298
299
  ),
299
300
  epr,
300
301
  )
@@ -374,6 +375,7 @@ def make_python_data_model(
374
375
  ):
375
376
  continue
376
377
 
378
+ propname = get_python_property_name(prop)
377
379
  if isinstance(prop, DataProperty):
378
380
  pytype = prop.get_data_model_datatype().get_python_type().clone()
379
381
  if len(prop.data.constraints) > 0:
@@ -419,21 +421,17 @@ def make_python_data_model(
419
421
  )
420
422
 
421
423
  cls_ast(
422
- stmt.DefClassVarStatement(
423
- prop.name, pytype.type, prop_default_value
424
- )
424
+ stmt.DefClassVarStatement(propname, pytype.type, prop_default_value)
425
425
  )
426
426
  elif isinstance(prop, ObjectProperty):
427
427
  if prop.target.db is not None:
428
428
  # if the target class is in the database, we expect the user to pass the foreign key for it.
429
- propname = prop.name + "_id"
430
429
  pytype = (
431
430
  assert_not_null(prop.target.get_id_property())
432
431
  .get_data_model_datatype()
433
432
  .get_python_type()
434
433
  )
435
434
  else:
436
- propname = prop.name
437
435
  pytype = PyTypeWithDep(
438
436
  f"Create{prop.target.name}",
439
437
  [
@@ -561,6 +559,8 @@ def make_python_data_model(
561
559
  ):
562
560
  continue
563
561
 
562
+ propname = get_python_property_name(prop)
563
+
564
564
  if isinstance(prop, DataProperty):
565
565
  pytype = prop.get_data_model_datatype().get_python_type().clone()
566
566
 
@@ -605,13 +605,10 @@ def make_python_data_model(
605
605
  )
606
606
 
607
607
  cls_ast(
608
- stmt.DefClassVarStatement(
609
- prop.name, pytype.type, prop_default_value
610
- )
608
+ stmt.DefClassVarStatement(propname, pytype.type, prop_default_value)
611
609
  )
612
610
  elif isinstance(prop, ObjectProperty):
613
611
  if prop.target.db is not None:
614
- propname = prop.name + "_id"
615
612
  # if the target class is in the database, we expect the user to pass the foreign key for it.
616
613
  pytype = (
617
614
  assert_not_null(prop.target.get_id_property())
@@ -620,7 +617,6 @@ def make_python_data_model(
620
617
  )
621
618
 
622
619
  else:
623
- propname = prop.name
624
620
  pytype = PyTypeWithDep(
625
621
  f"Update{prop.target.name}",
626
622
  [
@@ -686,7 +682,9 @@ def make_python_data_model(
686
682
  [
687
683
  PredefinedFn.attr_getter(
688
684
  expr.ExprIdent("self"),
689
- expr.ExprIdent(prop.name),
685
+ expr.ExprIdent(
686
+ get_python_property_name(prop)
687
+ ),
690
688
  )
691
689
  ],
692
690
  )
@@ -750,7 +748,7 @@ def make_python_data_model(
750
748
  # skip private fields as this is for APIs exchange
751
749
  continue
752
750
 
753
- propname = prop.name
751
+ propname = get_python_property_name(prop)
754
752
  if isinstance(prop, DataProperty):
755
753
  pytype = prop.get_data_model_datatype().get_python_type()
756
754
  if prop.is_optional:
@@ -759,10 +757,9 @@ def make_python_data_model(
759
757
  for dep in pytype.deps:
760
758
  program.import_(dep, True)
761
759
 
762
- cls_ast(stmt.DefClassVarStatement(prop.name, pytype.type))
760
+ cls_ast(stmt.DefClassVarStatement(propname, pytype.type))
763
761
  elif isinstance(prop, ObjectProperty):
764
762
  if prop.target.db is not None:
765
- propname = prop.name + "_id"
766
763
  pytype = (
767
764
  assert_not_null(prop.target.get_id_property())
768
765
  .get_data_model_datatype()
@@ -823,12 +820,14 @@ def make_python_data_model(
823
820
  as_composite_args = [DeferredVar.simple("cls")]
824
821
  as_composite_null_condition = []
825
822
  for prop in cls.properties.values():
823
+ propname = get_python_property_name(prop)
824
+
826
825
  assert (
827
826
  not prop.data.is_private
828
- ), f"Embedded classes should not have private properties: {cls.name}.{prop.name}"
829
- as_composite_args.append(DeferredVar.simple(prop.name))
827
+ ), f"Embedded classes should not have private properties: {cls.name}.{propname}"
828
+ as_composite_args.append(DeferredVar.simple(propname))
830
829
  as_composite_null_condition.append(
831
- expr.ExprIs(expr.ExprIdent(prop.name), expr.ExprConstant(None))
830
+ expr.ExprIs(expr.ExprIdent(propname), expr.ExprConstant(None))
832
831
  )
833
832
 
834
833
  # For simplicity, we assume that this embedded class can be used in a nullable field (check if all properties are None and return None).
@@ -855,7 +854,9 @@ def make_python_data_model(
855
854
  expr.ExprIdent("cls"),
856
855
  [
857
856
  from_db_type_conversion(
858
- expr.ExprIdent(""), prop, expr.ExprIdent(prop.name)
857
+ expr.ExprIdent(""),
858
+ prop,
859
+ expr.ExprIdent(get_python_property_name(prop)),
859
860
  )
860
861
  for prop in cls.properties.values()
861
862
  ],
@@ -946,12 +947,6 @@ def make_python_relational_model(
946
947
  """
947
948
  app = target_pkg.app
948
949
 
949
- def get_property_name(prop: DataProperty | ObjectProperty):
950
- if isinstance(prop, ObjectProperty):
951
- if prop.target.db is not None:
952
- return f"{prop.name}_id"
953
- return prop.name
954
-
955
950
  def make_base(custom_types: Sequence[ObjectProperty]):
956
951
  """Make a base class for our database."""
957
952
  program = Program()
@@ -1229,19 +1224,20 @@ def make_python_relational_model(
1229
1224
  or not prop.db.is_indexed
1230
1225
  ):
1231
1226
  continue
1227
+ propname = get_python_property_name(prop)
1232
1228
  if prop.db.index_type == IndexType.POSTGRES_FTS_SEVI:
1233
1229
  fts_index.append(
1234
1230
  expr.ExprFuncCall(
1235
1231
  expr.ExprIdent("Index"),
1236
1232
  [
1237
1233
  expr.ExprConstant(
1238
- f"ix_{cls.db.table_name}_{get_property_name(prop)}_gin"
1234
+ f"ix_{cls.db.table_name}_{propname}_gin"
1239
1235
  ),
1240
1236
  expr.ExprFuncCall(
1241
1237
  ident_manager.use("text"),
1242
1238
  [
1243
1239
  expr.ExprConstant(
1244
- f"to_tsvector('sevi', {get_property_name(prop)})"
1240
+ f"to_tsvector('sevi', {propname})"
1245
1241
  )
1246
1242
  ],
1247
1243
  ),
@@ -1257,13 +1253,13 @@ def make_python_relational_model(
1257
1253
  expr.ExprIdent("Index"),
1258
1254
  [
1259
1255
  expr.ExprConstant(
1260
- f"ix_{cls.db.table_name}_{get_property_name(prop)}_gist"
1256
+ f"ix_{cls.db.table_name}_{propname}_gist"
1261
1257
  ),
1262
1258
  expr.ExprFuncCall(
1263
1259
  expr.ExprIdent("text"),
1264
1260
  [
1265
1261
  expr.ExprConstant(
1266
- f"f_unaccent({get_property_name(prop)}) gist_trgm_ops(siglen=256)"
1262
+ f"f_unaccent({propname}) gist_trgm_ops(siglen=256)"
1267
1263
  )
1268
1264
  ],
1269
1265
  ),
@@ -1286,7 +1282,7 @@ def make_python_relational_model(
1286
1282
  [expr.ExprConstant(index.name)]
1287
1283
  + [
1288
1284
  expr.ExprConstant(
1289
- get_property_name(cls.properties[prop])
1285
+ get_python_property_name(cls.properties[prop])
1290
1286
  )
1291
1287
  for prop in index.columns
1292
1288
  ]
@@ -1496,7 +1492,7 @@ def make_python_relational_object_property(
1496
1492
  )
1497
1493
 
1498
1494
  # we store this class in the database
1499
- propname = f"{prop.name}_id"
1495
+ propname = get_python_property_name(prop)
1500
1496
  idprop = prop.target.get_id_property()
1501
1497
  assert idprop is not None
1502
1498
  idprop_pytype = idprop.datatype.get_sqlalchemy_type()
File without changes
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from sera.models import DataProperty, ObjectProperty
4
+
5
+
6
+ def get_python_property_name(prop: DataProperty | ObjectProperty) -> str:
7
+ """Get property name of a property in Python model"""
8
+ if isinstance(prop, ObjectProperty) and prop.target.db is not None:
9
+ # the property value is a foreign key to another table, we should add _id to
10
+ # the end of the property name
11
+ return prop.name + "_id"
12
+ else:
13
+ return prop.name
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sera-2
3
- Version: 1.26.0
3
+ Version: 1.26.2
4
4
  Summary:
5
5
  Author: Binh Vu
6
6
  Author-email: bvu687@gmail.com
@@ -19,14 +19,16 @@ sera/libs/directed_computing_graph/_type_conversion.py,sha256=_XGvDidOJVmHS4gqdP
19
19
  sera/libs/middlewares/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  sera/libs/middlewares/auth.py,sha256=r6aix1ZBwxMd1Jv5hMCTB8a_gFOJQ6egvxIrf3DWEOs,2323
21
21
  sera/libs/middlewares/uscp.py,sha256=DRy99nmS3qS5HLjRMIGP0oNUtQIci_a4hL5xQh-lXNY,2322
22
- sera/libs/search_helper.py,sha256=3ADhO6s6iIL3TWuH2zicAm_NmJfIm7wPY0cRQjESx2Y,13779
22
+ sera/libs/search_helper.py,sha256=3ZAEw0QZAgRT-i6GB58wuPJvHTyVxhfILim0avEjGx4,14188
23
23
  sera/make/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  sera/make/__main__.py,sha256=HRfOR53p351h6KblVvYm3DLhDIfEtk6R0kjl78_S_S8,1453
25
25
  sera/make/make_app.py,sha256=dTzpJRPGoCojCdJr1TAzwbaquctwwitrGPxkRm9skpo,6033
26
26
  sera/make/make_python_api.py,sha256=sfaYnX6Vwj0xWPpvpWbBhq8GyNHgNkvwlyZr7NDCO0k,24770
27
- sera/make/make_python_model.py,sha256=FYqtzfVMfJxRPuEVhFuYCG5-DzVOS2aW_5RUtgiQY7Y,72685
27
+ sera/make/make_python_model.py,sha256=cW3RGVttuZWLVWrEg-NppSknWoTKCRE2mar9yyhj-gU,72545
28
28
  sera/make/make_python_services.py,sha256=SvdU--QF23FN_d-Ao07CeXIK9d5eL_-mdXYwXx69dRE,2102
29
29
  sera/make/make_typescript_model.py,sha256=SOuTojrMD3QQe_jW7cGpYdNV5upZwDYHR8QDW-wLOKc,56365
30
+ sera/make/py_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ sera/make/py_backend/misc.py,sha256=lZNkrniR2OZiyK4rei1Yl_mRYBR_QzOpqVO_gMWbJD4,487
30
32
  sera/make/ts_frontend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
33
  sera/make/ts_frontend/make_class_schema.py,sha256=FHTNQOJl-Zz6CHRT6J2GOZxpIeyMDqMRNTK9XUiM578,14489
32
34
  sera/make/ts_frontend/make_enums.py,sha256=3U6Dt5Y4DM6D_ZiitcVHXtNQyA9cTE046WCDQCDOvSU,2596
@@ -48,6 +50,6 @@ sera/models/_parse.py,sha256=nihBEDni-jKwecSBagd6bupDOuCzGviuoD9u6-rT64Q,13203
48
50
  sera/models/_property.py,sha256=Qo23KZl5OQNbuceygicgC3_Yv5ve1KxiFiMoWq6Ljj0,7758
49
51
  sera/models/_schema.py,sha256=VxJEiqgVvbXgcSUK4UW6JnRcggk4nsooVSE6MyXmfNY,1636
50
52
  sera/typing.py,sha256=7S6Ah-Yfcl8a0xAJ4lxEcguq3rYVM7SBeOiuxyJhC04,1089
51
- sera_2-1.26.0.dist-info/METADATA,sha256=NhH3zPi7Ds4TERKJ_c6UBD2EwFZNlM7qIsUEv-Fypi0,987
52
- sera_2-1.26.0.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
53
- sera_2-1.26.0.dist-info/RECORD,,
53
+ sera_2-1.26.2.dist-info/METADATA,sha256=vOrf5maMTAY8NaLVi_mAZEmiWwNWnWkNbAPnsEPz4LE,987
54
+ sera_2-1.26.2.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
55
+ sera_2-1.26.2.dist-info/RECORD,,