sera-2 1.6.4__py3-none-any.whl → 1.6.6__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.
sera/libs/base_orm.py CHANGED
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from typing import Optional
4
4
 
5
5
  import orjson
6
+ from msgspec.json import decode, encode
6
7
  from sera.typing import UNSET
7
8
  from sqlalchemy import LargeBinary, TypeDecorator
8
9
  from sqlalchemy import create_engine as sqlalchemy_create_engine
@@ -50,13 +51,12 @@ class DataclassType(TypeDecorator):
50
51
  def process_bind_param(self, value, dialect):
51
52
  if value is None:
52
53
  return None
53
- return orjson.dumps(value.to_dict())
54
+ return encode(value)
54
55
 
55
56
  def process_result_value(self, value, dialect):
56
57
  if value is None:
57
58
  return None
58
- result = orjson.loads(value)
59
- return self.cls.from_dict(result)
59
+ return decode(value, type=self.cls)
60
60
 
61
61
 
62
62
  class ListDataclassType(TypeDecorator):
@@ -72,13 +72,12 @@ class ListDataclassType(TypeDecorator):
72
72
  def process_bind_param(self, value, dialect):
73
73
  if value is None:
74
74
  return None
75
- return orjson.dumps([x.to_dict() for x in value])
75
+ return encode(value)
76
76
 
77
77
  def process_result_value(self, value, dialect):
78
78
  if value is None:
79
79
  return None
80
- result = orjson.loads(value)
81
- return [self.cls.from_dict(x) for x in result]
80
+ return decode(value, type=list[self.cls])
82
81
 
83
82
 
84
83
  class DictDataclassType(TypeDecorator):
@@ -94,13 +93,12 @@ class DictDataclassType(TypeDecorator):
94
93
  def process_bind_param(self, value, dialect):
95
94
  if value is None:
96
95
  return None
97
- return orjson.dumps({k: v.to_dict() for k, v in value.items()})
96
+ return encode(value)
98
97
 
99
98
  def process_result_value(self, value, dialect):
100
99
  if value is None:
101
100
  return None
102
- result = orjson.loads(value)
103
- return {k: self.cls.from_dict(v) for k, v in result.items()}
101
+ return decode(value, type=dict[str, self.cls])
104
102
 
105
103
 
106
104
  def create_engine(
@@ -49,6 +49,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
49
49
 
50
50
  idprop = cls.get_id_property()
51
51
  program = Program()
52
+ program.import_(
53
+ f"@.models.{pkg.dir.name}.Draft{cls.name}.Draft{cls.name}", True
54
+ )
52
55
 
53
56
  prop_defs = []
54
57
  prop_constructor_assigns = []
@@ -202,6 +205,21 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
202
205
  )
203
206
  )
204
207
  ),
208
+ stmt.LineBreak(),
209
+ lambda ast13: ast13.func(
210
+ "toDraft",
211
+ [],
212
+ expr.ExprIdent(f"Draft{cls.name}"),
213
+ comment="Convert the class instance to a draft for editing",
214
+ )(
215
+ stmt.ReturnStatement(
216
+ expr.ExprMethodCall(
217
+ expr.ExprIdent(f"Draft{cls.name}"),
218
+ "update",
219
+ [expr.ExprIdent("this")],
220
+ )
221
+ ),
222
+ ),
205
223
  ),
206
224
  )
207
225
 
@@ -815,91 +833,112 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
815
833
  else expr.ExprConstant("undefined")
816
834
  ),
817
835
  ),
836
+ (
837
+ expr.ExprIdent("constraints"),
838
+ PredefinedFn.list(
839
+ [
840
+ expr.ExprConstant(
841
+ constraint.get_typescript_constraint()
842
+ )
843
+ for constraint in prop.data.constraints
844
+ ]
845
+ ),
846
+ ),
818
847
  ]
819
848
  + tsprop
820
849
  ),
821
850
  )
822
851
  )
823
852
 
824
- program.import_("sera-db.Schema", True)
853
+ for type in ["Schema", "ObjectProperty", "DataProperty"]:
854
+ program.import_(f"sera-db.{type}", True)
855
+
825
856
  program.import_(f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}", True)
857
+ program.import_(f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}Id", True)
826
858
  program.import_(
827
859
  f"@.models.{pkg.dir.name}.Draft{cls.name}.Draft{cls.name}", True
828
860
  )
829
861
  program.root(
830
862
  stmt.LineBreak(),
831
863
  stmt.TypescriptStatement(
832
- f"export type {cls.name}Properties = "
833
- + " | ".join(
864
+ f"export type {cls.name}SchemaType = "
865
+ + PredefinedFn.dict(
834
866
  [
835
- expr.ExprConstant(to_camel_case(prop.name)).to_typescript()
836
- for prop in cls.properties.values()
837
- if not prop.data.is_private
867
+ (expr.ExprIdent("id"), expr.ExprIdent(f"{cls.name}Id")),
868
+ (
869
+ expr.ExprIdent("publicProperties"),
870
+ expr.ExprIdent(
871
+ " | ".join(
872
+ [
873
+ expr.ExprConstant(
874
+ to_camel_case(prop.name)
875
+ ).to_typescript()
876
+ for prop in cls.properties.values()
877
+ if not prop.data.is_private
878
+ ]
879
+ )
880
+ ),
881
+ ),
882
+ (
883
+ expr.ExprIdent("allProperties"),
884
+ expr.ExprIdent(
885
+ f"{cls.name}SchemaType['publicProperties']"
886
+ + (
887
+ " | "
888
+ + " | ".join(
889
+ [
890
+ expr.ExprConstant(
891
+ to_camel_case(prop.name)
892
+ ).to_typescript()
893
+ for prop in cls.properties.values()
894
+ if prop.data.is_private
895
+ ]
896
+ )
897
+ if any(
898
+ prop.data.is_private
899
+ for prop in cls.properties.values()
900
+ )
901
+ else ""
902
+ )
903
+ ),
904
+ ),
905
+ (
906
+ expr.ExprIdent("cls"),
907
+ expr.ExprIdent(cls.name),
908
+ ),
909
+ (
910
+ expr.ExprIdent("draftCls"),
911
+ expr.ExprIdent(f"Draft{cls.name}"),
912
+ ),
838
913
  ]
839
- )
840
- + ";"
841
- ),
842
- stmt.LineBreak(),
843
- (
844
- stmt.TypescriptStatement(
845
- f"export type Draft{cls.name}Properties = {cls.name}Properties"
846
- + (
847
- " | "
848
- + " | ".join(
849
- [
850
- expr.ExprConstant(
851
- to_camel_case(prop.name)
852
- ).to_typescript()
853
- for prop in cls.properties.values()
854
- if prop.data.is_private
855
- ]
856
- )
857
- if any(prop.data.is_private for prop in cls.properties.values())
858
- else ""
859
- )
860
- + ";"
861
- )
914
+ ).to_typescript()
915
+ + ";",
862
916
  ),
863
917
  stmt.LineBreak(),
864
918
  stmt.TypescriptStatement(
865
- f"export const {cls.name}Schema: Schema<{cls.name}, {cls.name}Properties> = "
919
+ f"const publicProperties: Record<{cls.name}SchemaType['publicProperties'], DataProperty | ObjectProperty> = "
866
920
  + PredefinedFn.dict(
867
921
  [
868
- (
869
- expr.ExprIdent("properties"),
870
- PredefinedFn.dict(
871
- [
872
- (prop_name, prop_def)
873
- for prop, prop_name, prop_def in prop_defs
874
- if not prop.data.is_private
875
- ]
876
- ),
877
- ),
922
+ (prop_name, prop_def)
923
+ for prop, prop_name, prop_def in prop_defs
924
+ if not prop.data.is_private
878
925
  ]
879
- + (
880
- [
881
- (
882
- expr.ExprIdent("primaryKey"),
883
- expr.ExprConstant(
884
- assert_not_null(cls.get_id_property()).name
885
- ),
886
- )
887
- ]
888
- if cls.db is not None
889
- else []
890
- )
891
926
  ).to_typescript()
892
927
  + ";"
893
928
  ),
894
929
  stmt.LineBreak(),
895
930
  stmt.TypescriptStatement(
896
- f"export const Draft{cls.name}Schema: Schema<Draft{cls.name}, Draft{cls.name}Properties> = "
931
+ f"export const {cls.name}Schema: Schema<{cls.name}SchemaType> = "
897
932
  + PredefinedFn.dict(
898
933
  [
899
934
  (
900
- expr.ExprIdent("properties"),
935
+ expr.ExprIdent("publicProperties"),
936
+ expr.ExprIdent("publicProperties"),
937
+ ),
938
+ (
939
+ expr.ExprIdent("allProperties"),
901
940
  expr.ExprIdent(
902
- f"{{ ...{cls.name}Schema.properties, "
941
+ "{ ...publicProperties, "
903
942
  + ", ".join(
904
943
  [
905
944
  f"{prop_name.to_typescript()}: {prop_def.to_typescript()}"
@@ -909,7 +948,7 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
909
948
  )
910
949
  + "}"
911
950
  ),
912
- )
951
+ ),
913
952
  ]
914
953
  + (
915
954
  [
@@ -937,6 +976,7 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
937
976
  return
938
977
 
939
978
  export_types = []
979
+ export_iso_types = [] # isolatedModules required separate export type clause
940
980
 
941
981
  program = Program()
942
982
  program.import_(f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}", True)
@@ -944,15 +984,16 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
944
984
  if cls.db is not None:
945
985
  # only import the id if this class is stored in the database
946
986
  program.import_(f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}Id", True)
987
+ export_iso_types.append(f"{cls.name}Id")
947
988
 
948
- for type in [
949
- f"{cls.name}Schema",
950
- f"Draft{cls.name}Schema",
951
- f"{cls.name}Properties",
952
- f"Draft{cls.name}Properties",
953
- ]:
954
- program.import_(f"@.models.{pkg.dir.name}.{cls.name}Schema.{type}", True)
955
- export_types.append(type)
989
+ program.import_(
990
+ f"@.models.{pkg.dir.name}.{cls.name}Schema.{cls.name}Schema", True
991
+ )
992
+ export_types.append(f"{cls.name}Schema")
993
+ program.import_(
994
+ f"@.models.{pkg.dir.name}.{cls.name}Schema.{cls.name}SchemaType", True
995
+ )
996
+ export_iso_types.append(f"{cls.name}SchemaType")
956
997
 
957
998
  program.import_(
958
999
  f"@.models.{pkg.dir.name}.Draft{cls.name}.Draft{cls.name}", True
@@ -968,9 +1009,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
968
1009
  stmt.LineBreak(),
969
1010
  stmt.TypescriptStatement("export { %s };" % (", ".join(export_types))),
970
1011
  (
971
- stmt.TypescriptStatement(f"export type {{ {cls.name}Id }};")
972
- if cls.db
973
- else None
1012
+ stmt.TypescriptStatement(
1013
+ "export type { %s };" % (", ".join(export_iso_types))
1014
+ )
974
1015
  ),
975
1016
  )
976
1017
 
@@ -28,6 +28,14 @@ class Constraint:
28
28
 
29
29
  raise NotImplementedError()
30
30
 
31
+ def get_typescript_constraint(self) -> str | dict:
32
+ if len(self.args) == 0:
33
+ return self.name
34
+ return {
35
+ "name": self.name,
36
+ "args": self.args,
37
+ }
38
+
31
39
 
32
40
  predefined_constraints: dict[ConstraintName, Constraint] = {
33
41
  "phone_number": Constraint("phone_number", ()),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sera-2
3
- Version: 1.6.4
3
+ Version: 1.6.6
4
4
  Summary:
5
5
  Author: Binh Vu
6
6
  Author-email: bvu687@gmail.com
@@ -2,7 +2,7 @@ sera/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  sera/constants.py,sha256=mzAaMyIx8TJK0-RYYJ5I24C4s0Uvj26OLMJmBo0pxHI,123
3
3
  sera/libs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  sera/libs/api_helper.py,sha256=hUEy0INHM18lxTQ348tgbXNceOHcjiAnqmuL_8CRpLQ,2509
5
- sera/libs/base_orm.py,sha256=sTiHvbvLALSFygCITKFTXK1w-8UtxXGT_Te-1PEAiCI,3094
5
+ sera/libs/base_orm.py,sha256=dyh0OT2sbHku5qPJXvRzYAHRTSXvvbQaS-Qwg65Bw04,2918
6
6
  sera/libs/base_service.py,sha256=l5D4IjxIiz8LBRranUYddb8J0Y6SwSyetKYTLrCUdQA,4098
7
7
  sera/make/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  sera/make/__main__.py,sha256=G5O7s6135-708honwqMFn2yPTs06WbGQTHpupID0eZ4,1417
@@ -10,14 +10,14 @@ sera/make/make_app.py,sha256=n9NtW73O3s_5Q31VHIRmnd-jEIcpDO7ksAsOdovde2s,5999
10
10
  sera/make/make_python_api.py,sha256=RuJUm9z-4plBEtjobeOPr12o27OT-0tSeXI4ZlM3IY0,29433
11
11
  sera/make/make_python_model.py,sha256=xf4revAwVWEnF6QhxbbqPyUGgXOOB--Gu3jPxsESg0Y,36593
12
12
  sera/make/make_python_services.py,sha256=RsinYZdfkrTlTn9CT50VgqGs9w6IZawsJx-KEmqfnEY,2062
13
- sera/make/make_typescript_model.py,sha256=RPfMDpEY3MwBSAV_NH0Rsm5dI2FvOSJj0oWwHAIYGdg,40606
13
+ sera/make/make_typescript_model.py,sha256=xblFD1e7YDKH7ADgA4OhLZBt7bMzT8-0yopxP81fuiY,42853
14
14
  sera/misc/__init__.py,sha256=Dh4uDq0D4N53h3zhvmwfa5a0TPVRSUvLzb0hkFuPirk,411
15
15
  sera/misc/_formatter.py,sha256=aCGYL08l8f3aLODHxSocxBBwkRYEo3K1QzCDEn3suj0,1685
16
16
  sera/misc/_utils.py,sha256=V5g4oLGHOhUCR75Kkcn1w01pAvGvaepK-T8Z3pIgHjI,1450
17
17
  sera/models/__init__.py,sha256=vJC5Kzo_N7wd16ocNPy1VvAZDGNiWeiAhWJ4ihATKvA,780
18
18
  sera/models/_class.py,sha256=Wf0e8x6-szG9TzoFkAlqj7_dG0SCICMBw_333n3paxk,2514
19
19
  sera/models/_collection.py,sha256=ZnQEriKC4X88Zz48Kn1AVZKH-1_l8OgWa-zf2kcQOOE,1414
20
- sera/models/_constraints.py,sha256=lZmCh6Py0UVMdhTR7zUOPPzGqJGbmDCzf7xH7yITcbQ,1278
20
+ sera/models/_constraints.py,sha256=hWnHfaxGAMF6x_7eUnlChyUYPoARom2ZA6vaUg3CYY4,1484
21
21
  sera/models/_datatype.py,sha256=uMxK_8wBLowaIMIAYCb3V17YmkzJrKKc5orjImzqWbA,5818
22
22
  sera/models/_default.py,sha256=ABggW6qdPR4ZDqIPJdJ0GCGQ-7kfsfZmQ_DchgZEa-I,137
23
23
  sera/models/_enum.py,sha256=sy0q7E646F-APsqrVQ52r1fAQ_DCAeaNq5YM5QN3zIk,2070
@@ -27,6 +27,6 @@ sera/models/_parse.py,sha256=sJYfQtwek96ltpgxExG4xUbiLnU3qvNYhTP1CeyXGjs,9746
27
27
  sera/models/_property.py,sha256=CmEmgOShtSyNFq05YW3tGupwCIVRzPMKudXWld8utPk,5530
28
28
  sera/models/_schema.py,sha256=r-Gqg9Lb_wR3UrbNvfXXgt_qs5bts0t2Ve7aquuF_OI,1155
29
29
  sera/typing.py,sha256=Q4QMfbtfrCjC9tFfsZPhsAnbNX4lm4NHQ9lmjNXYdV0,772
30
- sera_2-1.6.4.dist-info/METADATA,sha256=_VtnA4zI_oLY9RjlfftgNh3cyssJnWboBOLF53bieog,856
31
- sera_2-1.6.4.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
32
- sera_2-1.6.4.dist-info/RECORD,,
30
+ sera_2-1.6.6.dist-info/METADATA,sha256=Q8gitA1NPJcPKmDHj5VdT5v9oli0ywv8d-xZ3syxwFE,856
31
+ sera_2-1.6.6.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
32
+ sera_2-1.6.6.dist-info/RECORD,,
File without changes