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.
- sera/make/make_typescript_model.py +6 -45
- sera/make/ts_frontend/make_enums.py +1 -20
- sera/make/ts_frontend/make_query.py +146 -0
- sera/make/ts_frontend/misc.py +2 -10
- sera/models/_collection.py +5 -1
- sera/models/_module.py +0 -1
- {sera_2-1.25.0.dist-info → sera_2-1.26.0.dist-info}/METADATA +1 -1
- {sera_2-1.25.0.dist-info → sera_2-1.26.0.dist-info}/RECORD +9 -8
- {sera_2-1.25.0.dist-info → sera_2-1.26.0.dist-info}/WHEEL +0 -0
@@ -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
|
-
|
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
|
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)
|
sera/make/ts_frontend/misc.py
CHANGED
@@ -2,17 +2,9 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from typing import Optional
|
4
4
|
|
5
|
-
from codegen.models import
|
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",
|
sera/models/_collection.py
CHANGED
@@ -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
|
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
@@ -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=
|
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=
|
33
|
-
sera/make/ts_frontend/
|
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=
|
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=
|
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.
|
51
|
-
sera_2-1.
|
52
|
-
sera_2-1.
|
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,,
|
File without changes
|