sera-2 1.12.0__py3-none-any.whl → 1.12.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.
sera/make/make_python_model.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from operator import is_
|
4
|
-
from typing import Callable, Sequence
|
4
|
+
from typing import Callable, Optional, Sequence
|
5
5
|
|
6
6
|
from codegen.models import AST, DeferredVar, PredefinedFn, Program, expr, stmt
|
7
7
|
|
@@ -83,9 +83,25 @@ def make_python_data_model(
|
|
83
83
|
app = target_pkg.app
|
84
84
|
|
85
85
|
def from_db_type_conversion(
|
86
|
-
record: expr.ExprIdent,
|
86
|
+
record: expr.ExprIdent,
|
87
|
+
prop: DataProperty | ObjectProperty,
|
88
|
+
value_pass_as_args: Optional[expr.Expr] = None,
|
87
89
|
):
|
88
|
-
value
|
90
|
+
"""Convert the value from the database to the data model type.
|
91
|
+
|
92
|
+
Args:
|
93
|
+
record: The record to convert from.
|
94
|
+
prop: The property to convert.
|
95
|
+
value_pass_as_args: If provided, this value will be used instead of getting the value from the record. This is useful for functions that
|
96
|
+
receive the column value as an argument, such as the `as_composite` function.
|
97
|
+
"""
|
98
|
+
if value_pass_as_args is not None:
|
99
|
+
value = value_pass_as_args
|
100
|
+
assert record == expr.ExprIdent(
|
101
|
+
""
|
102
|
+
), "If value_pass_as_args is provided, record should not be used as a dummy value should be passed instead."
|
103
|
+
else:
|
104
|
+
value = PredefinedFn.attr_getter(record, expr.ExprIdent(prop.name))
|
89
105
|
if isinstance(prop, ObjectProperty) and prop.target.db is not None:
|
90
106
|
if prop.cardinality.is_star_to_many():
|
91
107
|
value = PredefinedFn.map_list(
|
@@ -95,6 +111,9 @@ def make_python_data_model(
|
|
95
111
|
),
|
96
112
|
)
|
97
113
|
else:
|
114
|
+
assert (
|
115
|
+
value_pass_as_args is None
|
116
|
+
), "Cannot use value_pass_as_args for a single object property."
|
98
117
|
value = PredefinedFn.attr_getter(
|
99
118
|
record, expr.ExprIdent(prop.name + "_id")
|
100
119
|
)
|
@@ -500,6 +519,69 @@ def make_python_data_model(
|
|
500
519
|
),
|
501
520
|
)
|
502
521
|
|
522
|
+
if cls.db is None:
|
523
|
+
as_composite_args = [DeferredVar.simple("cls")]
|
524
|
+
as_composite_null_condition = []
|
525
|
+
for prop in cls.properties.values():
|
526
|
+
assert (
|
527
|
+
not prop.data.is_private
|
528
|
+
), f"Embedded classes should not have private properties: {cls.name}.{prop.name}"
|
529
|
+
as_composite_args.append(DeferredVar.simple(prop.name))
|
530
|
+
as_composite_null_condition.append(
|
531
|
+
expr.ExprIs(expr.ExprIdent(prop.name), expr.ExprConstant(None))
|
532
|
+
)
|
533
|
+
|
534
|
+
# For simplicity, we assume that this embedded class can be used in a nullable field (check if all properties are None and return None).
|
535
|
+
# However, we could be more efficient by checking if there are any other classes that use this class as a composite and are non-optional,
|
536
|
+
# and eliminate the None check because we know that the class will always be re-created.
|
537
|
+
cls_ast(
|
538
|
+
stmt.LineBreak(),
|
539
|
+
stmt.PythonDecoratorStatement(
|
540
|
+
expr.ExprFuncCall(expr.ExprIdent("classmethod"), [])
|
541
|
+
),
|
542
|
+
lambda ast: ast.func(
|
543
|
+
"as_composite",
|
544
|
+
vars=as_composite_args,
|
545
|
+
return_type=expr.ExprIdent(f"Optional[{cls.name}]"),
|
546
|
+
comment="Create an embedded instance from the embedded columns in the database table. If all properties of this embedded class are None (indicating that the parent field is None), then this function will return None.",
|
547
|
+
)(
|
548
|
+
lambda ast_l1: ast_l1.if_(
|
549
|
+
expr.ExprLogicalAnd(as_composite_null_condition)
|
550
|
+
)(lambda ast_l2: ast_l2.return_(expr.ExprConstant(None))),
|
551
|
+
lambda ast_l1: ast_l1.return_(
|
552
|
+
expr.ExprFuncCall(
|
553
|
+
expr.ExprIdent("cls"),
|
554
|
+
[
|
555
|
+
from_db_type_conversion(
|
556
|
+
expr.ExprIdent(""), prop, expr.ExprIdent(prop.name)
|
557
|
+
)
|
558
|
+
for prop in cls.properties.values()
|
559
|
+
],
|
560
|
+
)
|
561
|
+
),
|
562
|
+
),
|
563
|
+
stmt.LineBreak(),
|
564
|
+
lambda ast: ast.func(
|
565
|
+
"__composite_values__",
|
566
|
+
[
|
567
|
+
DeferredVar.simple("self"),
|
568
|
+
],
|
569
|
+
return_type=expr.ExprIdent("tuple"),
|
570
|
+
comment="Return the values of the properties of this embedded class as a tuple. This is used to create a composite object in SQLAlchemy.",
|
571
|
+
)(
|
572
|
+
lambda ast_l1: ast_l1.return_(
|
573
|
+
PredefinedFn.tuple(
|
574
|
+
[
|
575
|
+
to_db_type_conversion(
|
576
|
+
program, expr.ExprIdent("self"), cls, prop
|
577
|
+
)
|
578
|
+
for prop in cls.properties.values()
|
579
|
+
]
|
580
|
+
)
|
581
|
+
)
|
582
|
+
),
|
583
|
+
)
|
584
|
+
|
503
585
|
for cls in schema.topological_sort():
|
504
586
|
if cls.name in reference_classes:
|
505
587
|
continue
|
@@ -1138,7 +1138,7 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
|
|
1138
1138
|
(
|
1139
1139
|
expr.ExprIdent("datatype"),
|
1140
1140
|
expr.ExprConstant(
|
1141
|
-
tstype.type if prop.target.db is not None else "
|
1141
|
+
tstype.type if prop.target.db is not None else "undefined"
|
1142
1142
|
),
|
1143
1143
|
),
|
1144
1144
|
(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: sera-2
|
3
|
-
Version: 1.12.
|
3
|
+
Version: 1.12.2
|
4
4
|
Summary:
|
5
5
|
Author: Binh Vu
|
6
6
|
Author-email: bvu687@gmail.com
|
@@ -9,7 +9,7 @@ Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.12
|
10
10
|
Classifier: Programming Language :: Python :: 3.13
|
11
11
|
Requires-Dist: black (>=25.1.0,<26.0.0)
|
12
|
-
Requires-Dist: codegen-2 (>=2.
|
12
|
+
Requires-Dist: codegen-2 (>=2.10.0,<3.0.0)
|
13
13
|
Requires-Dist: isort (>=6.0.1,<7.0.0)
|
14
14
|
Requires-Dist: litestar (>=2.15.1,<3.0.0)
|
15
15
|
Requires-Dist: loguru (>=0.7.0,<0.8.0)
|
@@ -13,9 +13,9 @@ sera/make/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
sera/make/__main__.py,sha256=G5O7s6135-708honwqMFn2yPTs06WbGQTHpupID0eZ4,1417
|
14
14
|
sera/make/make_app.py,sha256=n9NtW73O3s_5Q31VHIRmnd-jEIcpDO7ksAsOdovde2s,5999
|
15
15
|
sera/make/make_python_api.py,sha256=kq5DClmEeeNgg-a3Bb_8GN9jxvjnhjmW3RfBHNzynO8,25407
|
16
|
-
sera/make/make_python_model.py,sha256=
|
16
|
+
sera/make/make_python_model.py,sha256=ldaDnuwudkq81w2hwKZIuRqFnqhxOAaIT_VhYandXG4,46128
|
17
17
|
sera/make/make_python_services.py,sha256=RsinYZdfkrTlTn9CT50VgqGs9w6IZawsJx-KEmqfnEY,2062
|
18
|
-
sera/make/make_typescript_model.py,sha256
|
18
|
+
sera/make/make_typescript_model.py,sha256=ugDdSTw_1ayHLuL--92RQ8hf_D-dpJtnvmUZNxcwcDs,63687
|
19
19
|
sera/misc/__init__.py,sha256=Dh4uDq0D4N53h3zhvmwfa5a0TPVRSUvLzb0hkFuPirk,411
|
20
20
|
sera/misc/_formatter.py,sha256=aCGYL08l8f3aLODHxSocxBBwkRYEo3K1QzCDEn3suj0,1685
|
21
21
|
sera/misc/_utils.py,sha256=V5g4oLGHOhUCR75Kkcn1w01pAvGvaepK-T8Z3pIgHjI,1450
|
@@ -32,6 +32,6 @@ sera/models/_parse.py,sha256=uw6fvvh1ucGqE2jFTCCr-e6_qMfZfSVpaPolNxmrHww,9897
|
|
32
32
|
sera/models/_property.py,sha256=SJSm5fZJimd2rQuL4UH_aZuNyp9v7x64xMbEVbtYx8Q,5633
|
33
33
|
sera/models/_schema.py,sha256=r-Gqg9Lb_wR3UrbNvfXXgt_qs5bts0t2Ve7aquuF_OI,1155
|
34
34
|
sera/typing.py,sha256=Q4QMfbtfrCjC9tFfsZPhsAnbNX4lm4NHQ9lmjNXYdV0,772
|
35
|
-
sera_2-1.12.
|
36
|
-
sera_2-1.12.
|
37
|
-
sera_2-1.12.
|
35
|
+
sera_2-1.12.2.dist-info/METADATA,sha256=724nMBYqD82HxkFzUWLora6vu5V-BA7wjfou6AEHM30,858
|
36
|
+
sera_2-1.12.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
37
|
+
sera_2-1.12.2.dist-info/RECORD,,
|
File without changes
|