sera-2 1.11.2__py3-none-any.whl → 1.12.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.
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from operator import is_
3
4
  from typing import Callable, Sequence
4
5
 
5
6
  from codegen.models import AST, DeferredVar, PredefinedFn, Program, expr, stmt
@@ -296,11 +297,14 @@ def make_python_data_model(
296
297
  ],
297
298
  )
298
299
 
300
+ if prop.cardinality.is_star_to_many():
301
+ pytype = pytype.as_list_type()
302
+ elif prop.is_optional:
303
+ pytype = pytype.as_optional_type()
304
+
299
305
  for dep in pytype.deps:
300
306
  program.import_(dep, True)
301
307
 
302
- if prop.cardinality.is_star_to_many():
303
- pytype = pytype.as_list_type()
304
308
  cls_ast(stmt.DefClassVarStatement(prop.name, pytype.type))
305
309
 
306
310
  # has_to_db = True
@@ -453,11 +457,14 @@ def make_python_data_model(
453
457
  ],
454
458
  )
455
459
 
460
+ if prop.cardinality.is_star_to_many():
461
+ pytype = pytype.as_list_type()
462
+ elif prop.is_optional:
463
+ pytype = pytype.as_optional_type()
464
+
456
465
  for dep in pytype.deps:
457
466
  program.import_(dep, True)
458
467
 
459
- if prop.cardinality.is_star_to_many():
460
- pytype = pytype.as_list_type()
461
468
  cls_ast(stmt.DefClassVarStatement(prop.name, pytype.type))
462
469
 
463
470
  cls_ast(
@@ -690,7 +697,12 @@ def make_python_relational_model(
690
697
  program.import_(dep, True)
691
698
 
692
699
  propname = prop.name
693
- proptype = f"Mapped[{sqltype.mapped_pytype}]"
700
+
701
+ if prop.is_optional:
702
+ program.import_("typing.Optional", True)
703
+ proptype = f"Mapped[Optional[{sqltype.mapped_pytype}]]"
704
+ else:
705
+ proptype = f"Mapped[{sqltype.mapped_pytype}]"
694
706
 
695
707
  propvalargs: list[expr.Expr] = [expr.ExprIdent(sqltype.type)]
696
708
  if prop.db.is_primary_key:
@@ -75,6 +75,10 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
75
75
  # use id type alias
76
76
  tstype = TsTypeWithDep(f"{cls.name}Id")
77
77
 
78
+ if prop.is_optional:
79
+ # convert type to optional
80
+ tstype = tstype.as_optional_type()
81
+
78
82
  deser_args.append(
79
83
  (
80
84
  expr.ExprIdent(propname),
@@ -95,6 +99,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
95
99
  )
96
100
  if prop.cardinality.is_star_to_many():
97
101
  tstype = tstype.as_list_type()
102
+ elif prop.is_optional:
103
+ # convert type to optional only if it isn't a list
104
+ tstype = tstype.as_optional_type()
98
105
  deser_args.append(
99
106
  (
100
107
  expr.ExprIdent(propname),
@@ -134,6 +141,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
134
141
  )
135
142
  )
136
143
  else:
144
+ if prop.is_optional:
145
+ # convert type to optional only if it isn't a list
146
+ tstype = tstype.as_optional_type()
137
147
  deser_args.append(
138
148
  (
139
149
  expr.ExprIdent(propname),
@@ -270,6 +280,7 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
270
280
  create_args = []
271
281
  update_args = []
272
282
  ser_args = []
283
+ to_record_args = []
273
284
  update_field_funcs: list[Callable[[AST], Any]] = []
274
285
 
275
286
  prop2tsname = {}
@@ -329,6 +340,10 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
329
340
  # for none id properties, we need to include a type for "invalid" value
330
341
  tstype = _inject_type_for_invalid_value(tstype)
331
342
 
343
+ if prop.is_optional:
344
+ # convert type to optional
345
+ tstype = tstype.as_optional_type()
346
+
332
347
  for dep in tstype.deps:
333
348
  program.import_(dep, True)
334
349
 
@@ -410,6 +425,41 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
410
425
  ),
411
426
  )
412
427
  )
428
+
429
+ if not prop.data.is_private:
430
+ # private property does not include in the public record
431
+ to_record_args.append(
432
+ (
433
+ expr.ExprIdent(propname),
434
+ (
435
+ expr.ExprTernary(
436
+ PredefinedFn.attr_getter(
437
+ expr.ExprFuncCall(
438
+ PredefinedFn.attr_getter(
439
+ expr.ExprIdent(draft_validators),
440
+ expr.ExprIdent(propname),
441
+ ),
442
+ [
443
+ PredefinedFn.attr_getter(
444
+ expr.ExprIdent("this"),
445
+ expr.ExprIdent(propname),
446
+ )
447
+ ],
448
+ ),
449
+ expr.ExprIdent("isValid"),
450
+ ),
451
+ PredefinedFn.attr_getter(
452
+ expr.ExprIdent("this"), expr.ExprIdent(propname)
453
+ ),
454
+ expr.ExprIdent("undefined"),
455
+ )
456
+ if prop.is_optional
457
+ else PredefinedFn.attr_getter(
458
+ expr.ExprIdent("this"), expr.ExprIdent(propname)
459
+ )
460
+ ),
461
+ )
462
+ )
413
463
  if not (prop.db is not None and prop.db.is_primary_key):
414
464
  # skip observable for primary key as it is not needed
415
465
  observable_args.append(
@@ -438,6 +488,10 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
438
488
  tstype = tstype.as_list_type()
439
489
  create_propvalue = expr.ExprConstant([])
440
490
  else:
491
+ if prop.is_optional:
492
+ # convert type to optional - for list type, we don't need to do this
493
+ # as we will use empty list as no value
494
+ tstype = tstype.as_optional_type()
441
495
  # if target class has an auto-increment primary key, we set a different default value
442
496
  # to be -1 to avoid start from 0
443
497
  target_idprop = prop.target.get_id_property()
@@ -463,6 +517,17 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
463
517
  ),
464
518
  )
465
519
  )
520
+
521
+ if not prop.data.is_private:
522
+ # private property does not include in the public record
523
+ to_record_args.append(
524
+ (
525
+ expr.ExprIdent(propname),
526
+ PredefinedFn.attr_getter(
527
+ expr.ExprIdent("this"), expr.ExprIdent(propname)
528
+ ),
529
+ )
530
+ )
466
531
  else:
467
532
  # we are going to store the whole object
468
533
  tstype = TsTypeWithDep(
@@ -492,10 +557,66 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
492
557
  expr.ExprIdent("this"), expr.ExprIdent(propname)
493
558
  ),
494
559
  lambda item: expr.ExprMethodCall(item, "ser", []),
560
+ (
561
+ (
562
+ lambda item: PredefinedFn.attr_getter(
563
+ expr.ExprFuncCall(
564
+ PredefinedFn.attr_getter(
565
+ expr.ExprIdent(
566
+ draft_validators
567
+ ),
568
+ expr.ExprIdent(propname),
569
+ ),
570
+ [item],
571
+ ),
572
+ expr.ExprIdent("isValid"),
573
+ )
574
+ )
575
+ if prop.is_optional
576
+ else None
577
+ ),
495
578
  ),
496
579
  )
497
580
  )
581
+ if not prop.data.is_private:
582
+ # private property does not include in the public record
583
+ to_record_args.append(
584
+ (
585
+ expr.ExprIdent(propname),
586
+ PredefinedFn.map_list(
587
+ PredefinedFn.attr_getter(
588
+ expr.ExprIdent("this"),
589
+ expr.ExprIdent(propname),
590
+ ),
591
+ lambda item: expr.ExprMethodCall(
592
+ item, "toRecord", []
593
+ ),
594
+ (
595
+ (
596
+ lambda item: PredefinedFn.attr_getter(
597
+ expr.ExprFuncCall(
598
+ PredefinedFn.attr_getter(
599
+ expr.ExprIdent(
600
+ draft_validators
601
+ ),
602
+ expr.ExprIdent(propname),
603
+ ),
604
+ [item],
605
+ ),
606
+ expr.ExprIdent("isValid"),
607
+ )
608
+ )
609
+ if prop.is_optional
610
+ else None
611
+ ),
612
+ ),
613
+ )
614
+ )
498
615
  else:
616
+ if prop.is_optional:
617
+ # convert type to optional - for list type, we don't need to do this
618
+ # as we will use empty list as no value
619
+ tstype = tstype.as_optional_type()
499
620
  create_propvalue = expr.ExprMethodCall(
500
621
  expr.ExprIdent(tstype.type),
501
622
  "create",
@@ -510,18 +631,103 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
510
631
  ),
511
632
  ],
512
633
  )
513
- ser_args.append(
514
- (
515
- expr.ExprIdent(prop.name),
516
- expr.ExprMethodCall(
517
- PredefinedFn.attr_getter(
518
- expr.ExprIdent("this"), expr.ExprIdent(propname)
634
+
635
+ if prop.is_optional:
636
+ ser_args.append(
637
+ (
638
+ expr.ExprIdent(prop.name),
639
+ expr.ExprTernary(
640
+ PredefinedFn.attr_getter(
641
+ expr.ExprFuncCall(
642
+ PredefinedFn.attr_getter(
643
+ expr.ExprIdent(draft_validators),
644
+ expr.ExprIdent(propname),
645
+ ),
646
+ [
647
+ PredefinedFn.attr_getter(
648
+ expr.ExprIdent("this"),
649
+ expr.ExprIdent(propname),
650
+ )
651
+ ],
652
+ ),
653
+ expr.ExprIdent("isValid"),
654
+ ),
655
+ expr.ExprMethodCall(
656
+ PredefinedFn.attr_getter(
657
+ expr.ExprIdent("this"),
658
+ expr.ExprIdent(propname),
659
+ ),
660
+ "ser",
661
+ [],
662
+ ),
663
+ expr.ExprIdent("undefined"),
519
664
  ),
520
- "ser",
521
- [],
522
- ),
665
+ )
523
666
  )
524
- )
667
+ if not prop.data.is_private:
668
+ # private property does not include in the public record
669
+ to_record_args.append(
670
+ (
671
+ expr.ExprIdent(propname),
672
+ expr.ExprTernary(
673
+ PredefinedFn.attr_getter(
674
+ expr.ExprFuncCall(
675
+ PredefinedFn.attr_getter(
676
+ expr.ExprIdent(
677
+ draft_validators
678
+ ),
679
+ expr.ExprIdent(propname),
680
+ ),
681
+ [
682
+ PredefinedFn.attr_getter(
683
+ expr.ExprIdent("this"),
684
+ expr.ExprIdent(propname),
685
+ )
686
+ ],
687
+ ),
688
+ expr.ExprIdent("isValid"),
689
+ ),
690
+ expr.ExprMethodCall(
691
+ PredefinedFn.attr_getter(
692
+ expr.ExprIdent("this"),
693
+ expr.ExprIdent(propname),
694
+ ),
695
+ "toRecord",
696
+ [],
697
+ ),
698
+ expr.ExprIdent("undefined"),
699
+ ),
700
+ )
701
+ )
702
+ else:
703
+ ser_args.append(
704
+ (
705
+ expr.ExprIdent(prop.name),
706
+ expr.ExprMethodCall(
707
+ PredefinedFn.attr_getter(
708
+ expr.ExprIdent("this"),
709
+ expr.ExprIdent(propname),
710
+ ),
711
+ "ser",
712
+ [],
713
+ ),
714
+ )
715
+ )
716
+ if not prop.data.is_private:
717
+ # private property does not include in the public record
718
+ to_record_args.append(
719
+ (
720
+ expr.ExprIdent(propname),
721
+ expr.ExprMethodCall(
722
+ PredefinedFn.attr_getter(
723
+ expr.ExprIdent("this"),
724
+ expr.ExprIdent(propname),
725
+ ),
726
+ "toRecord",
727
+ [],
728
+ ),
729
+ )
730
+ )
525
731
 
526
732
  for dep in tstype.deps:
527
733
  program.import_(
@@ -730,6 +936,20 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
730
936
  PredefinedFn.dict(ser_args),
731
937
  ),
732
938
  ),
939
+ stmt.LineBreak(),
940
+ lambda ast16: ast16.func(
941
+ "toRecord",
942
+ [],
943
+ expr.ExprIdent(cls.name),
944
+ comment="Convert the draft to a normal record. `isValid` must be called first to ensure all data is valid",
945
+ )(
946
+ stmt.ReturnStatement(
947
+ expr.ExprNewInstance(
948
+ expr.ExprIdent(cls.name),
949
+ [PredefinedFn.dict(to_record_args)],
950
+ ),
951
+ )
952
+ ),
733
953
  ),
734
954
  stmt.LineBreak(),
735
955
  stmt.TypescriptStatement(
sera/models/_datatype.py CHANGED
@@ -97,6 +97,13 @@ class TsTypeWithDep:
97
97
  list_type = f"{self.type}[]"
98
98
  return TsTypeWithDep(type=list_type, deps=self.deps)
99
99
 
100
+ def as_optional_type(self) -> TsTypeWithDep:
101
+ if "undefined" in self.type:
102
+ raise NotImplementedError(
103
+ f"Have not handle nested optional yet: {self.type}"
104
+ )
105
+ return TsTypeWithDep(type=f"{self.type} | undefined", deps=self.deps)
106
+
100
107
 
101
108
  @dataclass
102
109
  class SQLTypeWithDep:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sera-2
3
- Version: 1.11.2
3
+ Version: 1.12.0
4
4
  Summary:
5
5
  Author: Binh Vu
6
6
  Author-email: bvu687@gmail.com
@@ -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=MyEhVXeeHxAzqUkjSUuVzQJLUCCe7RKL6VxEMiCfTxk,41507
16
+ sera/make/make_python_model.py,sha256=AlNJyyovb99TWocS2jtfTxy0C5YaFizx-Bhwdw1mUNw,41923
17
17
  sera/make/make_python_services.py,sha256=RsinYZdfkrTlTn9CT50VgqGs9w6IZawsJx-KEmqfnEY,2062
18
- sera/make/make_typescript_model.py,sha256=-FNeUlcrqz2Zd1Eg6P14usXTrgTXd9oGhpOApLqntOw,51395
18
+ sera/make/make_typescript_model.py,sha256=-Z3vHblUcEpWvMMdzQGZ9XWhUjLv99PBJGqZHsF0m1o,63686
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
@@ -23,7 +23,7 @@ sera/models/__init__.py,sha256=vJC5Kzo_N7wd16ocNPy1VvAZDGNiWeiAhWJ4ihATKvA,780
23
23
  sera/models/_class.py,sha256=Wf0e8x6-szG9TzoFkAlqj7_dG0SCICMBw_333n3paxk,2514
24
24
  sera/models/_collection.py,sha256=ZnQEriKC4X88Zz48Kn1AVZKH-1_l8OgWa-zf2kcQOOE,1414
25
25
  sera/models/_constraints.py,sha256=L6QwKL3hRJ5DvvIB4JNgLoyvTKbE9FrpYRzezM4CweE,1484
26
- sera/models/_datatype.py,sha256=zkqOKOTZIkoYhJkIpytWWhGp-LtD10Jzud7lxOSd5UQ,6533
26
+ sera/models/_datatype.py,sha256=RDn0lDl_b0O_PwRqobcD1O903owEAEoMzRf4dyRcgBk,6819
27
27
  sera/models/_default.py,sha256=ABggW6qdPR4ZDqIPJdJ0GCGQ-7kfsfZmQ_DchgZEa-I,137
28
28
  sera/models/_enum.py,sha256=sy0q7E646F-APsqrVQ52r1fAQ_DCAeaNq5YM5QN3zIk,2070
29
29
  sera/models/_module.py,sha256=8QRSCubZmdDP9rL58rGAS6X5VCrkc1ZHvuMu1I1KrWk,5043
@@ -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.11.2.dist-info/METADATA,sha256=t32pt4lTWNgWc27jVQKlmlK_xf9c99crcgWGVVQjo-Y,857
36
- sera_2-1.11.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
37
- sera_2-1.11.2.dist-info/RECORD,,
35
+ sera_2-1.12.0.dist-info/METADATA,sha256=9OsTsh39Me41u3v-tRUiddDVkLKE-Qra7eMQLa8Kt2k,857
36
+ sera_2-1.12.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
37
+ sera_2-1.12.0.dist-info/RECORD,,