sera-2 1.14.1__py3-none-any.whl → 1.14.3__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.
@@ -6,7 +6,7 @@ from codegen.models import DeferredVar, ImportHelper, PredefinedFn, Program, exp
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, SystemControlledMode
9
+ from sera.models import App, DataCollection, Module, Package
10
10
  from sera.typing import GLOBAL_IDENTS
11
11
 
12
12
 
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import sys
4
- from ast import Not
5
3
  from typing import Callable, Literal, Optional, Sequence
6
4
 
7
5
  from codegen.models import (
@@ -29,7 +27,6 @@ from sera.models import (
29
27
  PyTypeWithDep,
30
28
  Schema,
31
29
  )
32
- from sera.models._property import SystemControlledMode
33
30
  from sera.typing import GLOBAL_IDENTS, ObjectPath
34
31
 
35
32
 
@@ -937,14 +934,12 @@ def make_python_relational_model(
937
934
 
938
935
  if custom_type.cardinality.is_star_to_many():
939
936
  if custom_type.is_map:
940
- program.import_("typing.Mapping", True)
941
937
  program.import_("sera.libs.base_orm.DictDataclassType", True)
942
- type = f"Mapping[str, {custom_type.target.name}]"
938
+ type = f"dict[str, {custom_type.target.name}]"
943
939
  maptype = f"DictDataclassType({custom_type.target.name})"
944
940
  else:
945
- program.import_("typing.Sequence", True)
946
941
  program.import_("sera.libs.base_orm.ListDataclassType", True)
947
- type = f"Sequence[str, {custom_type.target.name}]"
942
+ type = f"list[{custom_type.target.name}]"
948
943
  maptype = f"ListDataclassType({custom_type.target.name})"
949
944
  else:
950
945
  program.import_("sera.libs.base_orm.DataclassType", True)
@@ -957,7 +952,7 @@ def make_python_relational_model(
957
952
 
958
953
  type_map.append((expr.ExprIdent(type), expr.ExprIdent(maptype)))
959
954
 
960
- cls_ast = program.root.class_(
955
+ program.root.class_(
961
956
  "Base", [expr.ExprIdent("DeclarativeBase"), expr.ExprIdent("BaseORM")]
962
957
  )(
963
958
  stmt.DefClassVarStatement(
@@ -1246,7 +1241,7 @@ def make_python_relational_object_property(
1246
1241
  return
1247
1242
 
1248
1243
  if prop.cardinality.is_star_to_many():
1249
- raise NotImplementedError()
1244
+ raise NotImplementedError((cls.name, prop.name))
1250
1245
 
1251
1246
  # we store this class in the database
1252
1247
  propname = f"{prop.name}_id"
@@ -1291,7 +1286,13 @@ def make_python_relational_object_property(
1291
1286
  is_import_attr=True,
1292
1287
  )
1293
1288
  propname = prop.name
1294
- proptype = f"Mapped[{prop.target.name}]"
1289
+ if prop.cardinality.is_star_to_many():
1290
+ if prop.is_map:
1291
+ proptype = f"Mapped[dict[str, {prop.target.name}]]"
1292
+ else:
1293
+ proptype = f"Mapped[list[{prop.target.name}]]"
1294
+ else:
1295
+ proptype = f"Mapped[{prop.target.name}]"
1295
1296
 
1296
1297
  # we have two choices, one is to create a composite class, one is to create a custom field
1297
1298
  if prop.db.is_embedded == "composite":
sera/models/__init__.py CHANGED
@@ -5,13 +5,7 @@ from sera.models._enum import Enum
5
5
  from sera.models._module import App, Module, Package
6
6
  from sera.models._multi_lingual_string import MultiLingualString
7
7
  from sera.models._parse import parse_schema
8
- from sera.models._property import (
9
- Cardinality,
10
- DataProperty,
11
- ObjectProperty,
12
- Property,
13
- SystemControlledMode,
14
- )
8
+ from sera.models._property import Cardinality, DataProperty, ObjectProperty, Property
15
9
  from sera.models._schema import Schema
16
10
 
17
11
  __all__ = [
@@ -31,5 +25,4 @@ __all__ = [
31
25
  "PyTypeWithDep",
32
26
  "TsTypeWithDep",
33
27
  "Enum",
34
- "SystemControlledMode",
35
28
  ]
sera/models/_class.py CHANGED
@@ -63,7 +63,7 @@ class Class:
63
63
  return prop
64
64
  assert (
65
65
  self.db is None
66
- ), "This class is stored in the database and thus, must have a primary key"
66
+ ), f"The class {self.name} is stored in the database and thus, must have a primary key"
67
67
  return None
68
68
 
69
69
  def get_pymodule_name(self) -> str:
@@ -4,6 +4,7 @@ from dataclasses import dataclass
4
4
  from typing import Literal
5
5
 
6
6
  ConstraintName = Literal[
7
+ "url",
7
8
  "phone_number",
8
9
  "email",
9
10
  "not_empty",
@@ -37,6 +38,8 @@ class Constraint:
37
38
  return "msgspec.Meta(ge=0)"
38
39
  elif self.name == "positive_number":
39
40
  return "msgspec.Meta(gt=0)"
41
+ elif self.name == "url":
42
+ return r"msgspec.Meta(pattern=r'^(https?|ftp)://[^\s/$.?#].[^\s]*$')"
40
43
 
41
44
  raise NotImplementedError()
42
45
 
@@ -57,4 +60,5 @@ predefined_constraints: dict[ConstraintName, Constraint] = {
57
60
  "password": Constraint("password", ()),
58
61
  "whole_number": Constraint("whole_number", ()),
59
62
  "positive_number": Constraint("positive_number", ()),
63
+ "url": Constraint("url", ()),
60
64
  }
sera/models/_module.py CHANGED
@@ -10,6 +10,7 @@ import black.mode
10
10
  import isort
11
11
  from codegen.models import Program
12
12
  from loguru import logger
13
+
13
14
  from sera.misc import File, Formatter
14
15
  from sera.typing import Language
15
16
 
@@ -62,7 +63,9 @@ class Module:
62
63
  target_versions={black.mode.TargetVersion.PY312},
63
64
  ),
64
65
  )
65
- code = isort.code(code, profile="black")
66
+ code = isort.code(
67
+ code, profile="black", known_first_party=[self.package.app.name]
68
+ )
66
69
  except:
67
70
  logger.error("Error writing module {}", self.path)
68
71
  print(">>> Program")
@@ -173,3 +176,4 @@ class App:
173
176
  def name(self) -> str:
174
177
  """Get the name of the application"""
175
178
  return self.root.dir.name
179
+ return self.root.dir.name
sera/models/_parse.py CHANGED
@@ -34,7 +34,6 @@ from sera.models._property import (
34
34
  ObjectProperty,
35
35
  PropDataAttrs,
36
36
  SystemControlledAttrs,
37
- SystemControlledMode,
38
37
  )
39
38
  from sera.models._schema import Schema
40
39
 
@@ -94,11 +93,14 @@ def _parse_enum(schema: Schema, enum_name: str, enum: dict) -> Enum:
94
93
  name=k, value=v, description=MultiLingualString.en("")
95
94
  )
96
95
  else:
97
- values[k] = EnumValue(
98
- name=k,
99
- value=v["value"],
100
- description=_parse_multi_lingual_string(v.get("desc", "")),
101
- )
96
+ try:
97
+ values[k] = EnumValue(
98
+ name=k,
99
+ value=v["value"],
100
+ description=_parse_multi_lingual_string(v.get("desc", "")),
101
+ )
102
+ except KeyError as e:
103
+ raise ValueError(f"Invalid enum value definition for {k}: {v}") from e
102
104
  return Enum(name=enum_name, values=values)
103
105
 
104
106
 
sera/models/_property.py CHANGED
@@ -56,19 +56,6 @@ class Cardinality(str, Enum):
56
56
  ]
57
57
 
58
58
 
59
- class SystemControlledMode(str, Enum):
60
- """Indicates if this property is controlled by the system.
61
-
62
- There are two modes:
63
- 1. The system automatically sets the value, and users cannot modify it.
64
- 2. Users with special roles are allowed to set the value and other users cannot modify it
65
- """
66
-
67
- AUTO = "auto"
68
- RESTRICTED = "restricted"
69
- NO = "no"
70
-
71
-
72
59
  @dataclass(kw_only=True)
73
60
  class GetSCPropValueFunc:
74
61
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sera-2
3
- Version: 1.14.1
3
+ Version: 1.14.3
4
4
  Summary:
5
5
  Author: Binh Vu
6
6
  Author-email: bvu687@gmail.com
@@ -8,9 +8,9 @@ Requires-Python: >=3.12,<4.0
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.12
10
10
  Classifier: Programming Language :: Python :: 3.13
11
- Requires-Dist: black (>=25.1.0,<26.0.0)
11
+ Requires-Dist: black (==25.1.0)
12
12
  Requires-Dist: codegen-2 (>=2.11.1,<3.0.0)
13
- Requires-Dist: isort (>=6.0.1,<7.0.0)
13
+ Requires-Dist: isort (==6.0.1)
14
14
  Requires-Dist: litestar (>=2.15.1,<3.0.0)
15
15
  Requires-Dist: loguru (>=0.7.0,<0.8.0)
16
16
  Requires-Dist: msgspec (>=0.19.0,<0.20.0)
@@ -16,26 +16,26 @@ sera/libs/middlewares/uscp.py,sha256=H5umW8iEQSCdb_MJ5Im49kxg1E7TpxSg1p2_2A5zI1U
16
16
  sera/make/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  sera/make/__main__.py,sha256=bt-gDF8E026OWc2zqr9_a3paMOiDkFd3ybWn8ltL2g0,1448
18
18
  sera/make/make_app.py,sha256=n9NtW73O3s_5Q31VHIRmnd-jEIcpDO7ksAsOdovde2s,5999
19
- sera/make/make_python_api.py,sha256=9Pr5IxhC5iFkNq8DEh8Wfqa01AGm9YUxf9qdLmMdf_Y,26875
20
- sera/make/make_python_model.py,sha256=Q9lirILQS_J00FfRBE8JZvMZTsfkZ6iziHknwxpU-fo,61420
19
+ sera/make/make_python_api.py,sha256=iXGbKQ3IJvsY1ur_fhurr_THFNnH66E3Wl85o0emUbw,26853
20
+ sera/make/make_python_model.py,sha256=pv8gkWE4kIexjTfmtc5GG4Pg2kR9yA3Urnqal1RJ6WI,61430
21
21
  sera/make/make_python_services.py,sha256=0ZpWLwQ7Nwfn8BXAikAB4JRpNknpSJyJgY5b1cjtxV4,2073
22
22
  sera/make/make_typescript_model.py,sha256=ugDdSTw_1ayHLuL--92RQ8hf_D-dpJtnvmUZNxcwcDs,63687
23
23
  sera/misc/__init__.py,sha256=Dh4uDq0D4N53h3zhvmwfa5a0TPVRSUvLzb0hkFuPirk,411
24
24
  sera/misc/_formatter.py,sha256=aCGYL08l8f3aLODHxSocxBBwkRYEo3K1QzCDEn3suj0,1685
25
25
  sera/misc/_utils.py,sha256=V5g4oLGHOhUCR75Kkcn1w01pAvGvaepK-T8Z3pIgHjI,1450
26
- sera/models/__init__.py,sha256=VcC7HvqXuYrkgXwzs2vOH6LJPpzFBkeDvYVNrd3P-6E,855
27
- sera/models/_class.py,sha256=Wf0e8x6-szG9TzoFkAlqj7_dG0SCICMBw_333n3paxk,2514
26
+ sera/models/__init__.py,sha256=vJC5Kzo_N7wd16ocNPy1VvAZDGNiWeiAhWJ4ihATKvA,780
27
+ sera/models/_class.py,sha256=9XSnJli2SGF-jm-v0swsfY6-omiQ5Xeh33R2pM9Kg_g,2526
28
28
  sera/models/_collection.py,sha256=ZnQEriKC4X88Zz48Kn1AVZKH-1_l8OgWa-zf2kcQOOE,1414
29
- sera/models/_constraints.py,sha256=PsSOX94b9-73wZTcUif9KTzV9uTfoF0WN87g4GZXQmU,1827
29
+ sera/models/_constraints.py,sha256=RpWDU-TfCslXaMUaTG9utWbl5z8Z6nzvF_fhqlek6ew,1987
30
30
  sera/models/_datatype.py,sha256=y5kfim0G3gLhnGjiokFBr8leU1Y6as_Vw7oK-caOo68,7140
31
31
  sera/models/_default.py,sha256=ABggW6qdPR4ZDqIPJdJ0GCGQ-7kfsfZmQ_DchgZEa-I,137
32
32
  sera/models/_enum.py,sha256=sy0q7E646F-APsqrVQ52r1fAQ_DCAeaNq5YM5QN3zIk,2070
33
- sera/models/_module.py,sha256=8QRSCubZmdDP9rL58rGAS6X5VCrkc1ZHvuMu1I1KrWk,5043
33
+ sera/models/_module.py,sha256=I-GfnTgAa-5R87qTAvEzOt-VVEGeFBBwubGCgUkXVSw,5159
34
34
  sera/models/_multi_lingual_string.py,sha256=JETN6k00VH4wrA4w5vAHMEJV8fp3SY9bJebskFTjQLA,1186
35
- sera/models/_parse.py,sha256=OpTnLC8tg_gCzsjMAAqgR_TbYNS7kmPjkHGRNERziBQ,12015
36
- sera/models/_property.py,sha256=ZAxTuQ4BVf1Vsfk4dFkYwH_UsP9mFLTPyUkTcBaTajY,7183
35
+ sera/models/_parse.py,sha256=ohexBbjFv6A1wZsEtokfw0zMVoR-RGXYrXa_tAub_Vs,12147
36
+ sera/models/_property.py,sha256=Y98bYIjuCQDcSWpDxERNIFgmxXIaJiwBNFtYeGbDYRE,6812
37
37
  sera/models/_schema.py,sha256=VxJEiqgVvbXgcSUK4UW6JnRcggk4nsooVSE6MyXmfNY,1636
38
38
  sera/typing.py,sha256=Fl4-UzLJu1GdLLk_g87fA7nT9wQGelNnGzag6dg_0gs,980
39
- sera_2-1.14.1.dist-info/METADATA,sha256=gBUE2fmwtUSMHXtZGo1cH2hv9VfAujNw88ZLHD4s8rs,867
40
- sera_2-1.14.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
41
- sera_2-1.14.1.dist-info/RECORD,,
39
+ sera_2-1.14.3.dist-info/METADATA,sha256=-PIatY73pPVkjplx7zJAXHmtRcyQFIMEMIu9Manov6M,852
40
+ sera_2-1.14.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
41
+ sera_2-1.14.3.dist-info/RECORD,,