sera-2 1.12.3__py3-none-any.whl → 1.13.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/exports/__init__.py +0 -0
- sera/exports/schema.py +157 -0
- sera/exports/test.py +70 -0
- sera/libs/base_orm.py +21 -3
- sera/libs/base_service.py +29 -20
- sera/libs/middlewares/auth.py +3 -6
- sera/make/__main__.py +2 -1
- sera/make/make_python_api.py +100 -79
- sera/make/make_python_model.py +185 -51
- sera/make/make_python_services.py +3 -2
- sera/models/__init__.py +8 -1
- sera/models/_constraints.py +15 -1
- sera/models/_datatype.py +10 -0
- sera/models/_parse.py +9 -4
- sera/models/_property.py +14 -1
- sera/models/_schema.py +11 -0
- {sera_2-1.12.3.dist-info → sera_2-1.13.0.dist-info}/METADATA +3 -3
- {sera_2-1.12.3.dist-info → sera_2-1.13.0.dist-info}/RECORD +19 -16
- {sera_2-1.12.3.dist-info → sera_2-1.13.0.dist-info}/WHEEL +0 -0
sera/make/make_python_api.py
CHANGED
@@ -2,11 +2,13 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from typing import Sequence
|
4
4
|
|
5
|
-
from codegen.models import DeferredVar, PredefinedFn, Program, expr, stmt
|
5
|
+
from codegen.models import DeferredVar, ImportHelper, PredefinedFn, Program, expr, stmt
|
6
6
|
from loguru import logger
|
7
7
|
|
8
8
|
from sera.misc import assert_not_null, to_snake_case
|
9
|
-
from sera.models import App, DataCollection, Module, Package
|
9
|
+
from sera.models import App, DataCollection, Module, Package, SystemControlledMode
|
10
|
+
|
11
|
+
GLOBAL_IDENTS = {"AsyncSession": "sqlalchemy.ext.asyncio.AsyncSession"}
|
10
12
|
|
11
13
|
|
12
14
|
def make_python_api(app: App, collections: Sequence[DataCollection]):
|
@@ -112,12 +114,13 @@ def make_python_get_api(
|
|
112
114
|
app = target_pkg.app
|
113
115
|
|
114
116
|
program = Program()
|
117
|
+
import_helper = ImportHelper(program, GLOBAL_IDENTS)
|
118
|
+
|
115
119
|
program.import_("__future__.annotations", True)
|
116
120
|
program.import_("typing.Annotated", True)
|
117
121
|
program.import_("litestar.get", True)
|
118
122
|
program.import_("litestar.Request", True)
|
119
123
|
program.import_("litestar.params.Parameter", True)
|
120
|
-
program.import_("sqlalchemy.orm.Session", True)
|
121
124
|
program.import_(app.config.path + ".API_DEBUG", True)
|
122
125
|
program.import_(
|
123
126
|
app.services.path
|
@@ -191,7 +194,7 @@ def make_python_get_api(
|
|
191
194
|
),
|
192
195
|
DeferredVar.simple(
|
193
196
|
"session",
|
194
|
-
|
197
|
+
import_helper.use("AsyncSession"),
|
195
198
|
),
|
196
199
|
],
|
197
200
|
return_type=expr.ExprIdent(f"dict"),
|
@@ -226,35 +229,37 @@ def make_python_get_api(
|
|
226
229
|
),
|
227
230
|
lambda ast102: ast102.assign(
|
228
231
|
DeferredVar.simple("result"),
|
229
|
-
expr.
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
[
|
235
|
-
expr.ExprIdent("query"),
|
236
|
-
PredefinedFn.keyword_assignment(
|
237
|
-
"limit", expr.ExprIdent("limit")
|
238
|
-
),
|
239
|
-
PredefinedFn.keyword_assignment(
|
240
|
-
"offset", expr.ExprIdent("offset")
|
241
|
-
),
|
242
|
-
PredefinedFn.keyword_assignment(
|
243
|
-
"unique", expr.ExprIdent("unique")
|
244
|
-
),
|
245
|
-
PredefinedFn.keyword_assignment(
|
246
|
-
"sorted_by", expr.ExprIdent("sorted_by")
|
247
|
-
),
|
248
|
-
PredefinedFn.keyword_assignment(
|
249
|
-
"group_by", expr.ExprIdent("group_by")
|
250
|
-
),
|
251
|
-
PredefinedFn.keyword_assignment(
|
252
|
-
"fields", expr.ExprIdent("fields")
|
253
|
-
),
|
254
|
-
PredefinedFn.keyword_assignment(
|
255
|
-
"session", expr.ExprIdent("session")
|
232
|
+
expr.ExprAwait(
|
233
|
+
expr.ExprFuncCall(
|
234
|
+
PredefinedFn.attr_getter(
|
235
|
+
expr.ExprIdent("service"),
|
236
|
+
expr.ExprIdent("get"),
|
256
237
|
),
|
257
|
-
|
238
|
+
[
|
239
|
+
expr.ExprIdent("query"),
|
240
|
+
PredefinedFn.keyword_assignment(
|
241
|
+
"limit", expr.ExprIdent("limit")
|
242
|
+
),
|
243
|
+
PredefinedFn.keyword_assignment(
|
244
|
+
"offset", expr.ExprIdent("offset")
|
245
|
+
),
|
246
|
+
PredefinedFn.keyword_assignment(
|
247
|
+
"unique", expr.ExprIdent("unique")
|
248
|
+
),
|
249
|
+
PredefinedFn.keyword_assignment(
|
250
|
+
"sorted_by", expr.ExprIdent("sorted_by")
|
251
|
+
),
|
252
|
+
PredefinedFn.keyword_assignment(
|
253
|
+
"group_by", expr.ExprIdent("group_by")
|
254
|
+
),
|
255
|
+
PredefinedFn.keyword_assignment(
|
256
|
+
"fields", expr.ExprIdent("fields")
|
257
|
+
),
|
258
|
+
PredefinedFn.keyword_assignment(
|
259
|
+
"session", expr.ExprIdent("session")
|
260
|
+
),
|
261
|
+
],
|
262
|
+
)
|
258
263
|
),
|
259
264
|
),
|
260
265
|
lambda ast103: ast103.return_(
|
@@ -300,14 +305,13 @@ def make_python_get_by_id_api(
|
|
300
305
|
"""Make an endpoint for querying resource by id"""
|
301
306
|
app = target_pkg.app
|
302
307
|
|
303
|
-
ServiceNameDep = to_snake_case(f"{collection.name}ServiceDependency")
|
304
|
-
|
305
308
|
program = Program()
|
309
|
+
import_helper = ImportHelper(program, GLOBAL_IDENTS)
|
310
|
+
|
306
311
|
program.import_("__future__.annotations", True)
|
307
312
|
program.import_("litestar.get", True)
|
308
313
|
program.import_("litestar.status_codes", True)
|
309
314
|
program.import_("litestar.exceptions.HTTPException", True)
|
310
|
-
program.import_("sqlalchemy.orm.Session", True)
|
311
315
|
program.import_(
|
312
316
|
app.services.path
|
313
317
|
+ f".{collection.get_pymodule_name()}.{collection.get_service_name()}",
|
@@ -342,7 +346,7 @@ def make_python_get_by_id_api(
|
|
342
346
|
),
|
343
347
|
DeferredVar.simple(
|
344
348
|
"session",
|
345
|
-
|
349
|
+
import_helper.use("AsyncSession"),
|
346
350
|
),
|
347
351
|
],
|
348
352
|
return_type=expr.ExprIdent("dict"),
|
@@ -361,12 +365,14 @@ def make_python_get_by_id_api(
|
|
361
365
|
),
|
362
366
|
lambda ast11: ast11.assign(
|
363
367
|
DeferredVar.simple("record"),
|
364
|
-
expr.
|
365
|
-
expr.
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
368
|
+
expr.ExprAwait(
|
369
|
+
expr.ExprFuncCall(
|
370
|
+
expr.ExprIdent("service.get_by_id"),
|
371
|
+
[
|
372
|
+
expr.ExprIdent("id"),
|
373
|
+
expr.ExprIdent("session"),
|
374
|
+
],
|
375
|
+
)
|
370
376
|
),
|
371
377
|
),
|
372
378
|
lambda ast12: ast12.if_(PredefinedFn.is_null(expr.ExprIdent("record")))(
|
@@ -423,14 +429,13 @@ def make_python_has_api(
|
|
423
429
|
"""Make an endpoint for querying resource by id"""
|
424
430
|
app = target_pkg.app
|
425
431
|
|
426
|
-
ServiceNameDep = to_snake_case(f"{collection.name}ServiceDependency")
|
427
|
-
|
428
432
|
program = Program()
|
433
|
+
import_helper = ImportHelper(program, GLOBAL_IDENTS)
|
434
|
+
|
429
435
|
program.import_("__future__.annotations", True)
|
430
436
|
program.import_("litestar.head", True)
|
431
437
|
program.import_("litestar.status_codes", True)
|
432
438
|
program.import_("litestar.exceptions.HTTPException", True)
|
433
|
-
program.import_("sqlalchemy.orm.Session", True)
|
434
439
|
program.import_(
|
435
440
|
app.services.path
|
436
441
|
+ f".{collection.get_pymodule_name()}.{collection.get_service_name()}",
|
@@ -465,13 +470,15 @@ def make_python_has_api(
|
|
465
470
|
),
|
466
471
|
DeferredVar.simple(
|
467
472
|
"session",
|
468
|
-
|
473
|
+
import_helper.use("AsyncSession"),
|
469
474
|
),
|
470
475
|
],
|
471
476
|
return_type=expr.ExprConstant(None),
|
472
477
|
is_async=True,
|
473
478
|
)(
|
474
|
-
stmt.SingleExprStatement(
|
479
|
+
stmt.SingleExprStatement(
|
480
|
+
expr.ExprConstant("Checking if record exists by id")
|
481
|
+
),
|
475
482
|
lambda ast100: ast100.assign(
|
476
483
|
DeferredVar.simple("service"),
|
477
484
|
expr.ExprFuncCall(
|
@@ -484,12 +491,14 @@ def make_python_has_api(
|
|
484
491
|
),
|
485
492
|
lambda ast11: ast11.assign(
|
486
493
|
DeferredVar.simple("record_exist"),
|
487
|
-
expr.
|
488
|
-
expr.
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
494
|
+
expr.ExprAwait(
|
495
|
+
expr.ExprFuncCall(
|
496
|
+
expr.ExprIdent("service.has_id"),
|
497
|
+
[
|
498
|
+
expr.ExprIdent("id"),
|
499
|
+
expr.ExprIdent("session"),
|
500
|
+
],
|
501
|
+
)
|
493
502
|
),
|
494
503
|
),
|
495
504
|
lambda ast12: ast12.if_(expr.ExprNegation(expr.ExprIdent("record_exist")))(
|
@@ -524,9 +533,10 @@ def make_python_create_api(collection: DataCollection, target_pkg: Package):
|
|
524
533
|
app = target_pkg.app
|
525
534
|
|
526
535
|
program = Program()
|
536
|
+
import_helper = ImportHelper(program, GLOBAL_IDENTS)
|
537
|
+
|
527
538
|
program.import_("__future__.annotations", True)
|
528
539
|
program.import_("litestar.post", True)
|
529
|
-
program.import_("sqlalchemy.orm.Session", True)
|
530
540
|
program.import_(
|
531
541
|
app.services.path
|
532
542
|
+ f".{collection.get_pymodule_name()}.{collection.get_service_name()}",
|
@@ -540,12 +550,13 @@ def make_python_create_api(collection: DataCollection, target_pkg: Package):
|
|
540
550
|
|
541
551
|
# assuming the collection has only one class
|
542
552
|
cls = collection.cls
|
543
|
-
|
544
|
-
prop.data.is_system_controlled
|
553
|
+
has_restricted_system_controlled_prop = any(
|
554
|
+
prop.data.is_system_controlled == SystemControlledMode.RESTRICTED
|
555
|
+
for prop in cls.properties.values()
|
545
556
|
)
|
546
557
|
idprop = assert_not_null(cls.get_id_property())
|
547
558
|
|
548
|
-
if
|
559
|
+
if has_restricted_system_controlled_prop:
|
549
560
|
program.import_("sera.libs.api_helper.SingleAutoUSCP", True)
|
550
561
|
|
551
562
|
func_name = "create"
|
@@ -568,7 +579,7 @@ def make_python_create_api(collection: DataCollection, target_pkg: Package):
|
|
568
579
|
),
|
569
580
|
)
|
570
581
|
]
|
571
|
-
if
|
582
|
+
if has_restricted_system_controlled_prop
|
572
583
|
else []
|
573
584
|
),
|
574
585
|
)
|
@@ -582,7 +593,7 @@ def make_python_create_api(collection: DataCollection, target_pkg: Package):
|
|
582
593
|
),
|
583
594
|
DeferredVar.simple(
|
584
595
|
"session",
|
585
|
-
|
596
|
+
import_helper.use("AsyncSession"),
|
586
597
|
),
|
587
598
|
],
|
588
599
|
return_type=expr.ExprIdent(idprop.datatype.get_python_type().type),
|
@@ -601,13 +612,17 @@ def make_python_create_api(collection: DataCollection, target_pkg: Package):
|
|
601
612
|
),
|
602
613
|
lambda ast13: ast13.return_(
|
603
614
|
PredefinedFn.attr_getter(
|
604
|
-
expr.
|
605
|
-
expr.
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
615
|
+
expr.ExprAwait(
|
616
|
+
expr.ExprMethodCall(
|
617
|
+
expr.ExprIdent("service"),
|
618
|
+
"create",
|
619
|
+
[
|
620
|
+
expr.ExprMethodCall(
|
621
|
+
expr.ExprIdent("data"), "to_db", []
|
622
|
+
),
|
623
|
+
expr.ExprIdent("session"),
|
624
|
+
],
|
625
|
+
)
|
611
626
|
),
|
612
627
|
expr.ExprIdent(idprop.name),
|
613
628
|
)
|
@@ -626,9 +641,10 @@ def make_python_update_api(collection: DataCollection, target_pkg: Package):
|
|
626
641
|
app = target_pkg.app
|
627
642
|
|
628
643
|
program = Program()
|
644
|
+
import_helper = ImportHelper(program, GLOBAL_IDENTS)
|
645
|
+
|
629
646
|
program.import_("__future__.annotations", True)
|
630
647
|
program.import_("litestar.put", True)
|
631
|
-
program.import_("sqlalchemy.orm.Session", True)
|
632
648
|
program.import_(
|
633
649
|
app.services.path
|
634
650
|
+ f".{collection.get_pymodule_name()}.{collection.get_service_name()}",
|
@@ -645,10 +661,11 @@ def make_python_update_api(collection: DataCollection, target_pkg: Package):
|
|
645
661
|
id_prop = assert_not_null(cls.get_id_property())
|
646
662
|
id_type = id_prop.datatype.get_python_type().type
|
647
663
|
|
648
|
-
|
649
|
-
prop.data.is_system_controlled
|
664
|
+
has_restricted_system_controlled_prop = any(
|
665
|
+
prop.data.is_system_controlled == SystemControlledMode.RESTRICTED
|
666
|
+
for prop in cls.properties.values()
|
650
667
|
)
|
651
|
-
if
|
668
|
+
if has_restricted_system_controlled_prop:
|
652
669
|
program.import_("sera.libs.api_helper.SingleAutoUSCP", True)
|
653
670
|
|
654
671
|
func_name = "update"
|
@@ -671,7 +688,7 @@ def make_python_update_api(collection: DataCollection, target_pkg: Package):
|
|
671
688
|
),
|
672
689
|
)
|
673
690
|
]
|
674
|
-
if
|
691
|
+
if has_restricted_system_controlled_prop
|
675
692
|
else []
|
676
693
|
),
|
677
694
|
)
|
@@ -689,7 +706,7 @@ def make_python_update_api(collection: DataCollection, target_pkg: Package):
|
|
689
706
|
),
|
690
707
|
DeferredVar.simple(
|
691
708
|
"session",
|
692
|
-
|
709
|
+
import_helper.use("AsyncSession"),
|
693
710
|
),
|
694
711
|
],
|
695
712
|
return_type=expr.ExprIdent(id_prop.datatype.get_python_type().type),
|
@@ -715,13 +732,17 @@ def make_python_update_api(collection: DataCollection, target_pkg: Package):
|
|
715
732
|
),
|
716
733
|
lambda ast13: ast13.return_(
|
717
734
|
PredefinedFn.attr_getter(
|
718
|
-
expr.
|
719
|
-
expr.
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
735
|
+
expr.ExprAwait(
|
736
|
+
expr.ExprMethodCall(
|
737
|
+
expr.ExprIdent("service"),
|
738
|
+
"update",
|
739
|
+
[
|
740
|
+
expr.ExprMethodCall(
|
741
|
+
expr.ExprIdent("data"), "to_db", []
|
742
|
+
),
|
743
|
+
expr.ExprIdent("session"),
|
744
|
+
],
|
745
|
+
)
|
725
746
|
),
|
726
747
|
expr.ExprIdent(id_prop.name),
|
727
748
|
)
|