sera-2 1.25.0__py3-none-any.whl → 1.26.0__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.
@@ -8,6 +8,7 @@ from codegen.models.var import DeferredVar
8
8
  from loguru import logger
9
9
 
10
10
  from sera.make.ts_frontend.make_class_schema import make_class_schema
11
+ from sera.make.ts_frontend.make_query import make_query
11
12
  from sera.make.ts_frontend.misc import TS_GLOBAL_IDENTS, get_normalizer
12
13
  from sera.misc import (
13
14
  assert_isinstance,
@@ -1144,50 +1145,6 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
1144
1145
 
1145
1146
  outmod.write(program)
1146
1147
 
1147
- def make_query_processor(cls: Class, pkg: Package):
1148
- if not cls.is_public:
1149
- # skip classes that are not public
1150
- return
1151
-
1152
- outmod = pkg.module(cls.name + "Query")
1153
-
1154
- program = Program()
1155
- program.import_(f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}", True)
1156
- program.import_(f"sera-db.QueryProcessor", True)
1157
-
1158
- query_args = []
1159
- for prop in cls.properties.values():
1160
- pypropname = prop.name
1161
- tspropname = to_camel_case(prop.name)
1162
-
1163
- if isinstance(prop, ObjectProperty) and prop.target.db is not None:
1164
- tspropname = tspropname + "Id"
1165
- pypropname = prop.name + "_id"
1166
-
1167
- if tspropname != pypropname:
1168
- query_args.append(
1169
- (
1170
- expr.ExprIdent(tspropname),
1171
- expr.ExprConstant(pypropname),
1172
- )
1173
- )
1174
-
1175
- program.root(
1176
- stmt.LineBreak(),
1177
- stmt.TypescriptStatement(
1178
- f"export const query = "
1179
- + expr.ExprNewInstance(
1180
- expr.ExprIdent(f"QueryProcessor<{cls.name}>"),
1181
- [
1182
- PredefinedFn.dict(query_args),
1183
- ],
1184
- ).to_typescript()
1185
- + ";",
1186
- ),
1187
- )
1188
-
1189
- outmod.write(program)
1190
-
1191
1148
  def make_index(pkg: Package):
1192
1149
  outmod = pkg.module("index")
1193
1150
  if outmod.exists():
@@ -1209,7 +1166,11 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
1209
1166
  program.import_(
1210
1167
  f"@.models.{pkg.dir.name}.{cls.name}Schema.{cls.name}Schema", True
1211
1168
  )
1169
+ program.import_(
1170
+ f"@.models.{pkg.dir.name}.{cls.name}Query.{cls.name}Query", True
1171
+ )
1212
1172
  export_types.append(f"{cls.name}Schema")
1173
+ export_iso_types.append(f"{cls.name}Query")
1213
1174
  program.import_(
1214
1175
  f"@.models.{pkg.dir.name}.{cls.name}Schema.{cls.name}SchemaType", True
1215
1176
  )
@@ -1241,7 +1202,7 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
1241
1202
  pkg = target_pkg.pkg(cls.get_tsmodule_name())
1242
1203
  make_normal(cls, pkg)
1243
1204
  make_draft(cls, pkg)
1244
- make_query_processor(cls, pkg)
1205
+ make_query(schema, cls, pkg)
1245
1206
  make_table(cls, pkg)
1246
1207
  make_class_schema(schema, cls, pkg)
1247
1208
 
@@ -1,32 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
- import re
4
- from typing import Any, Callable
5
3
 
6
- from codegen.models import AST, ImportHelper, PredefinedFn, Program, expr, stmt
7
- from codegen.models.var import DeferredVar
8
- from loguru import logger
4
+ from codegen.models import PredefinedFn, Program, expr, stmt
9
5
 
10
- from sera.make.ts_frontend.make_class_schema import make_class_schema
11
- from sera.make.ts_frontend.misc import TS_GLOBAL_IDENTS, get_normalizer
12
- from sera.misc import (
13
- assert_isinstance,
14
- assert_not_null,
15
- identity,
16
- to_camel_case,
17
- to_pascal_case,
18
- to_snake_case,
19
- )
20
6
  from sera.models import (
21
- Class,
22
- DataProperty,
23
7
  Enum,
24
- ObjectProperty,
25
8
  Package,
26
9
  Schema,
27
- TsTypeWithDep,
28
10
  )
29
- from sera.typing import is_set
30
11
 
31
12
 
32
13
  def make_typescript_enums(schema: Schema, target_pkg: Package):
@@ -0,0 +1,146 @@
1
+ from __future__ import annotations
2
+
3
+ from codegen.models import AST, ImportHelper, PredefinedFn, Program, expr, stmt
4
+ from codegen.models.var import DeferredVar
5
+ from loguru import logger
6
+
7
+ from sera.misc import (
8
+ assert_isinstance,
9
+ assert_not_null,
10
+ identity,
11
+ to_camel_case,
12
+ to_pascal_case,
13
+ to_snake_case,
14
+ )
15
+ from sera.models import (
16
+ Class,
17
+ DataProperty,
18
+ Enum,
19
+ ObjectProperty,
20
+ Package,
21
+ Schema,
22
+ TsTypeWithDep,
23
+ )
24
+
25
+
26
+ def make_query(schema: Schema, cls: Class, pkg: Package):
27
+ """Make query processor and query schema.
28
+
29
+ Args:
30
+ schema: The overall schema of the application, which contains all classes & enums
31
+ cls: The class that we want to generate the query processor and schema
32
+ pkg: The output package (directory) for the class in the `@.models` package. For example, if the
33
+ class is `User`, then the package would be `src/models/user`.
34
+
35
+ Returns:
36
+ This function do not return anything as it writes the query helper directly to a file.
37
+ """
38
+ if not cls.is_public:
39
+ # skip classes that are not public
40
+ return
41
+
42
+ outmod = pkg.module(cls.name + "Query")
43
+
44
+ program = Program()
45
+ program.import_(f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}", True)
46
+ program.import_(f"sera-db.QueryProcessor", True)
47
+ program.import_(f"sera-db.Query", True)
48
+
49
+ query_args = []
50
+ for prop in cls.properties.values():
51
+ pypropname = prop.name
52
+ tspropname = to_camel_case(prop.name)
53
+
54
+ if isinstance(prop, ObjectProperty) and prop.target.db is not None:
55
+ tspropname = tspropname + "Id"
56
+ pypropname = prop.name + "_id"
57
+
58
+ if tspropname != pypropname:
59
+ query_args.append(
60
+ (
61
+ expr.ExprIdent(tspropname),
62
+ expr.ExprConstant(pypropname),
63
+ )
64
+ )
65
+
66
+ query_condition_args = []
67
+ for prop in cls.properties.values():
68
+ if prop.db is None or prop.data.is_private:
69
+ # This property is not stored in the database or it's private, so we skip it
70
+ continue
71
+ if (
72
+ isinstance(prop, DataProperty)
73
+ and prop.db is not None
74
+ and not prop.db.is_indexed
75
+ ):
76
+ # This property is not indexed, so we skip it
77
+ continue
78
+ if isinstance(prop, ObjectProperty) and prop.target.db is None:
79
+ # TODO: Implement this! This property is an embedded object property, we need to figure out
80
+ # which necessary properties are queryable and add them to the field names
81
+ continue
82
+
83
+ tspropname = to_camel_case(prop.name)
84
+ if isinstance(prop, ObjectProperty) and prop.target.db is not None:
85
+ # This property is an object property stored in the database, "Id" is added to the property name
86
+ tspropname = tspropname + "Id"
87
+
88
+ if isinstance(prop, DataProperty):
89
+ tstype = prop.datatype.get_typescript_type()
90
+ else:
91
+ assert isinstance(prop, ObjectProperty)
92
+ tstype = assert_not_null(
93
+ prop.target.get_id_property()
94
+ ).datatype.get_typescript_type()
95
+
96
+ for dep in tstype.deps:
97
+ program.import_(dep, is_import_attr=True)
98
+
99
+ if tstype.type == "string":
100
+ op = '"fuzzy"'
101
+ elif tstype.type in "number" or tstype.type == "Date":
102
+ op = '"eq" | "ne" | "lt" | "lte" | "gt" | "gte"'
103
+ elif tstype.is_enum_type():
104
+ op = '"eq" | "ne"'
105
+ else:
106
+ raise NotImplementedError(tstype.type)
107
+
108
+ if tstype.type == "Date":
109
+ # for date type, we use timestamp (number) for comparison
110
+ value = "number"
111
+ else:
112
+ value = tstype.type
113
+
114
+ query_condition_args.append(
115
+ (
116
+ expr.ExprIdent(tspropname + "?"),
117
+ PredefinedFn.dict(
118
+ [
119
+ (expr.ExprIdent("op"), expr.ExprIdent(op)),
120
+ (expr.ExprIdent("value"), expr.ExprIdent(value)),
121
+ ]
122
+ ),
123
+ )
124
+ )
125
+
126
+ program.root(
127
+ stmt.LineBreak(),
128
+ stmt.TypescriptStatement(
129
+ f"export const query = "
130
+ + expr.ExprNewInstance(
131
+ expr.ExprIdent(f"QueryProcessor<{cls.name}>"),
132
+ [
133
+ PredefinedFn.dict(query_args),
134
+ ],
135
+ ).to_typescript()
136
+ + ";",
137
+ ),
138
+ stmt.LineBreak(),
139
+ stmt.TypescriptStatement(
140
+ f"export type {cls.name}Query = Query<{cls.name}, "
141
+ + PredefinedFn.dict(query_condition_args).to_typescript()
142
+ + ">;"
143
+ ),
144
+ )
145
+
146
+ outmod.write(program)
@@ -2,17 +2,9 @@ from __future__ import annotations
2
2
 
3
3
  from typing import Optional
4
4
 
5
- from codegen.models import AST, ImportHelper, PredefinedFn, Program, expr, stmt
5
+ from codegen.models import ImportHelper, expr
6
6
 
7
- from sera.models import (
8
- Class,
9
- DataProperty,
10
- Enum,
11
- ObjectProperty,
12
- Package,
13
- Schema,
14
- TsTypeWithDep,
15
- )
7
+ from sera.models import TsTypeWithDep
16
8
 
17
9
  TS_GLOBAL_IDENTS = {
18
10
  "normalizers.normalizeNumber": "sera-db.normalizers",
@@ -55,7 +55,11 @@ class DataCollection:
55
55
  """Get the fields of this collection that can be used in join queries."""
56
56
  output = {}
57
57
  for prop in self.cls.properties.values():
58
- if isinstance(prop, DataProperty) and prop.db.foreign_key is not None:
58
+ if (
59
+ isinstance(prop, DataProperty)
60
+ and prop.db is not None
61
+ and prop.db.foreign_key is not None
62
+ ):
59
63
  # This property is a foreign key, so we add it to the output
60
64
  output[prop.name] = DataCollection(
61
65
  prop.db.foreign_key
sera/models/_module.py CHANGED
@@ -183,4 +183,3 @@ class App:
183
183
  def name(self) -> str:
184
184
  """Get the name of the application"""
185
185
  return self.root.dir.name
186
- return self.root.dir.name
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sera-2
3
- Version: 1.25.0
3
+ Version: 1.26.0
4
4
  Summary:
5
5
  Author: Binh Vu
6
6
  Author-email: bvu687@gmail.com
@@ -26,27 +26,28 @@ sera/make/make_app.py,sha256=dTzpJRPGoCojCdJr1TAzwbaquctwwitrGPxkRm9skpo,6033
26
26
  sera/make/make_python_api.py,sha256=sfaYnX6Vwj0xWPpvpWbBhq8GyNHgNkvwlyZr7NDCO0k,24770
27
27
  sera/make/make_python_model.py,sha256=FYqtzfVMfJxRPuEVhFuYCG5-DzVOS2aW_5RUtgiQY7Y,72685
28
28
  sera/make/make_python_services.py,sha256=SvdU--QF23FN_d-Ao07CeXIK9d5eL_-mdXYwXx69dRE,2102
29
- sera/make/make_typescript_model.py,sha256=Ax6xVrZ-x3xaKCsv6X4NKLdaMsAOau_GDrZK1TJ8NL8,57543
29
+ sera/make/make_typescript_model.py,sha256=SOuTojrMD3QQe_jW7cGpYdNV5upZwDYHR8QDW-wLOKc,56365
30
30
  sera/make/ts_frontend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  sera/make/ts_frontend/make_class_schema.py,sha256=FHTNQOJl-Zz6CHRT6J2GOZxpIeyMDqMRNTK9XUiM578,14489
32
- sera/make/ts_frontend/make_enums.py,sha256=7FILT_RO5ZCByMlYorr3OaOqFGnVtG1y6jFJqFpk_XM,3110
33
- sera/make/ts_frontend/misc.py,sha256=R96Tm4Sz05YPVk-gJ8vGW_GbMoUM7sLStar1LVnEn-I,1138
32
+ sera/make/ts_frontend/make_enums.py,sha256=3U6Dt5Y4DM6D_ZiitcVHXtNQyA9cTE046WCDQCDOvSU,2596
33
+ sera/make/ts_frontend/make_query.py,sha256=mQUK5H7jN5sgd8GzhswshWdt6_wKSFv1HnxuHj6uAd4,4771
34
+ sera/make/ts_frontend/misc.py,sha256=A54nMg4dsn1AC_6T1tFRW3rZAJ71d7SHEMrFOdsI3jo,1011
34
35
  sera/misc/__init__.py,sha256=ee7OODdWPKP8pCDxsfg1EOdxxKFMJCoNMljgV0NCxBw,767
35
36
  sera/misc/_formatter.py,sha256=aCGYL08l8f3aLODHxSocxBBwkRYEo3K1QzCDEn3suj0,1685
36
37
  sera/misc/_utils.py,sha256=_zWGjihxTEo3N1gzdxxB5CPCBBHxsviKWhQSCEonzVQ,13420
37
38
  sera/models/__init__.py,sha256=ZCnwzgUXhmHEcx5a7nYLopsBXJmSnfSkjt4kUH_vPnM,833
38
39
  sera/models/_class.py,sha256=495nP6j4pZIX1j0ZElUHNxe9doUX7vzSIwVrp_lAOHE,2922
39
- sera/models/_collection.py,sha256=72ZBdVa3UE8UyghJ8V-BPimO0f68zFRJvXdzfNaKDMo,2874
40
+ sera/models/_collection.py,sha256=5VsjmPMlZW-fYvcoYWOKD7Ch34zBYe4EPsjAn6bX7BY,2962
40
41
  sera/models/_constraints.py,sha256=SwUkvV8sESfuO3En6keA_r8GxKiarXYxMb5biml63lU,2021
41
42
  sera/models/_datatype.py,sha256=OlCnQlEpB4w9doz0hPhaZk5d4sF664CdGznSBvx0X9g,10293
42
43
  sera/models/_default.py,sha256=ABggW6qdPR4ZDqIPJdJ0GCGQ-7kfsfZmQ_DchgZEa-I,137
43
44
  sera/models/_enum.py,sha256=FRtEfto2httDB308W8OAuHh2LSazV3v16DHixlz1IZA,2088
44
- sera/models/_module.py,sha256=r9_3nEbLaZKO-jvbZuFYy9DkM6E9jY8hBsBhQBULpVU,5428
45
+ sera/models/_module.py,sha256=0jWfzb5iMF4IazeOKd_m9hWe7-xIsz7xlWF6mbdnHxw,5394
45
46
  sera/models/_multi_lingual_string.py,sha256=JETN6k00VH4wrA4w5vAHMEJV8fp3SY9bJebskFTjQLA,1186
46
47
  sera/models/_parse.py,sha256=nihBEDni-jKwecSBagd6bupDOuCzGviuoD9u6-rT64Q,13203
47
48
  sera/models/_property.py,sha256=Qo23KZl5OQNbuceygicgC3_Yv5ve1KxiFiMoWq6Ljj0,7758
48
49
  sera/models/_schema.py,sha256=VxJEiqgVvbXgcSUK4UW6JnRcggk4nsooVSE6MyXmfNY,1636
49
50
  sera/typing.py,sha256=7S6Ah-Yfcl8a0xAJ4lxEcguq3rYVM7SBeOiuxyJhC04,1089
50
- sera_2-1.25.0.dist-info/METADATA,sha256=7NpIOo2Jk7y1K6hK81XLFOJ0oJiP765h1M5Jch841V0,987
51
- sera_2-1.25.0.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
52
- sera_2-1.25.0.dist-info/RECORD,,
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,,