sera-2 1.1.0__py3-none-any.whl → 1.2.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/models/_datatype.py CHANGED
@@ -5,12 +5,29 @@ from dataclasses import dataclass
5
5
  from enum import Enum
6
6
  from typing import Literal
7
7
 
8
+ PyDataType = Literal["str", "int", "datetime", "float", "bool", "bytes", "dict"]
9
+ TypescriptDataType = Literal["string", "number", "boolean"]
10
+ SQLAlchemyDataType = Literal[
11
+ "String",
12
+ "Integer",
13
+ "Float",
14
+ "Boolean",
15
+ "DateTime",
16
+ "JSON",
17
+ "Text",
18
+ "LargeBinary",
19
+ ]
20
+
8
21
 
9
22
  @dataclass
10
23
  class TypeWithDep:
11
24
  type: str
12
25
  dep: str | None = None
13
26
 
27
+
28
+ @dataclass
29
+ class PyTypeWithDep(TypeWithDep):
30
+
14
31
  def get_python_type(self) -> type:
15
32
  """Get the Python type from the type string for typing annotation in Python."""
16
33
  if self.type == "str":
@@ -33,22 +50,43 @@ class TypeWithDep:
33
50
 
34
51
  @dataclass
35
52
  class DataType:
36
- type: Literal["str", "int", "datetime", "float", "bool", "bytes", "dict"]
53
+ pytype: PyDataType
54
+ sqltype: SQLAlchemyDataType
55
+ tstype: TypescriptDataType
56
+
37
57
  is_list: bool = False
38
- parent: DataType | None = None
39
58
 
40
59
  def get_python_type(self) -> TypeWithDep:
41
- if self.type in ["str", "int", "float", "bool", "bytes", "dict"]:
42
- return TypeWithDep(type=self.type)
43
- if self.type == "datetime":
60
+ if self.pytype in ["str", "int", "float", "bool", "bytes", "dict"]:
61
+ return TypeWithDep(type=self.pytype)
62
+ if self.pytype == "datetime":
44
63
  return TypeWithDep(type="datetime", dep="datetime.datetime")
45
- raise NotImplementedError(self.type)
64
+ raise NotImplementedError(self.pytype)
46
65
 
47
66
  def get_sqlalchemy_type(self) -> TypeWithDep:
48
- if self.type in ["str", "int", "float", "bool", "bytes"]:
49
- return TypeWithDep(type=self.type)
50
- if self.type == "dict":
67
+ if self.pytype in ["str", "int", "float", "bool", "bytes"]:
68
+ return TypeWithDep(type=self.pytype)
69
+ if self.pytype == "dict":
51
70
  return TypeWithDep(type="JSON")
52
- if self.type == "datetime":
71
+ if self.pytype == "datetime":
53
72
  return TypeWithDep(type="datetime", dep="datetime.datetime")
54
- raise NotImplementedError(self.type)
73
+ raise NotImplementedError(self.pytype)
74
+
75
+
76
+ predefined_datatypes = {
77
+ "string": DataType(pytype="str", sqltype="String", tstype="string", is_list=False),
78
+ "integer": DataType(
79
+ pytype="int", sqltype="Integer", tstype="number", is_list=False
80
+ ),
81
+ "datetime": DataType(
82
+ pytype="datetime", sqltype="DateTime", tstype="string", is_list=False
83
+ ),
84
+ "float": DataType(pytype="float", sqltype="Float", tstype="number", is_list=False),
85
+ "boolean": DataType(
86
+ pytype="bool", sqltype="Boolean", tstype="boolean", is_list=False
87
+ ),
88
+ "bytes": DataType(
89
+ pytype="bytes", sqltype="LargeBinary", tstype="string", is_list=False
90
+ ),
91
+ "dict": DataType(pytype="dict", sqltype="JSON", tstype="string", is_list=False),
92
+ }
sera/models/_module.py CHANGED
@@ -8,6 +8,7 @@ from typing import Sequence
8
8
 
9
9
  import black
10
10
  import black.mode
11
+ import isort
11
12
  from codegen.models import Program
12
13
  from loguru import logger
13
14
 
@@ -63,9 +64,9 @@ class Module:
63
64
  program.root.to_python(),
64
65
  mode=black.Mode(
65
66
  target_versions={black.mode.TargetVersion.PY312},
66
- line_length=120,
67
67
  ),
68
68
  )
69
+ code = isort.code(code, profile="black")
69
70
  except:
70
71
  logger.error("Error writing module {}", self.path)
71
72
  print(">>> Program")
@@ -76,8 +77,16 @@ class Module:
76
77
  assert self.language == Language.Typescript
77
78
  raise NotImplementedError()
78
79
 
79
- copyright_statement = f"# Generated automatically at {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}. All rights reserved.\n\n"
80
- (self.package.dir / f"{self.name}.py").write_text(copyright_statement + code)
80
+ outfile = self.package.dir / f"{self.name}.py"
81
+ if outfile.exists():
82
+ if outfile.read_text().startswith("# sera:skip"):
83
+ logger.info(
84
+ "`{}` already exists and is in manual edit mode. Skip updating it.",
85
+ outfile,
86
+ )
87
+ return
88
+ copyright_statement = f"# Generated by SERA \n\n"
89
+ outfile.write_text(copyright_statement + code)
81
90
 
82
91
  def exists(self) -> bool:
83
92
  """Check if the module exists"""
sera/models/_parse.py CHANGED
@@ -1,11 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from copy import deepcopy
3
4
  from pathlib import Path
4
5
  from typing import Sequence
5
6
 
6
7
  import serde.yaml
7
8
  from sera.models._class import Class, ClassDBMapInfo
8
- from sera.models._datatype import DataType
9
+ from sera.models._datatype import DataType, predefined_datatypes
9
10
  from sera.models._multi_lingual_string import MultiLingualString
10
11
  from sera.models._property import (
11
12
  Cardinality,
@@ -111,8 +112,18 @@ def _parse_property(
111
112
  db=(
112
113
  ObjectPropDBInfo(
113
114
  is_embedded=db.get("is_embedded", None),
114
- on_delete=ForeignKeyOnDelete(db.get("on_delete", "restrict")),
115
- on_update=ForeignKeyOnUpdate(db.get("on_update", "restrict")),
115
+ on_target_delete=ForeignKeyOnDelete(
116
+ db.get("on_target_delete", "restrict")
117
+ ),
118
+ on_target_update=ForeignKeyOnUpdate(
119
+ db.get("on_target_update", "restrict")
120
+ ),
121
+ on_source_delete=ForeignKeyOnDelete(
122
+ db.get("on_source_delete", "restrict")
123
+ ),
124
+ on_source_update=ForeignKeyOnUpdate(
125
+ db.get("on_source_update", "restrict")
126
+ ),
116
127
  )
117
128
  if "db" in prop
118
129
  else None
@@ -135,19 +146,9 @@ def _parse_datatype(datatype: str) -> DataType:
135
146
  else:
136
147
  is_list = False
137
148
 
138
- if datatype == "string":
139
- return DataType("str", is_list=is_list, parent=None)
140
- if datatype == "integer":
141
- return DataType("int", is_list=is_list, parent=None)
142
- if datatype == "datetime":
143
- return DataType("datetime", is_list=is_list, parent=None)
144
- if datatype == "bool":
145
- return DataType("bool", is_list=is_list, parent=None)
146
- if datatype == "float":
147
- return DataType("float", is_list=is_list, parent=None)
148
- if datatype == "bytes":
149
- return DataType("bytes", is_list=is_list, parent=None)
150
- if datatype == "dict":
151
- return DataType("dict", is_list=is_list, parent=None)
152
-
153
- raise NotImplementedError(datatype)
149
+ if datatype not in predefined_datatypes:
150
+ raise NotImplementedError(datatype)
151
+
152
+ dt = deepcopy(predefined_datatypes[datatype])
153
+ dt.is_list = is_list
154
+ return dt
sera/models/_property.py CHANGED
@@ -103,8 +103,12 @@ class ObjectPropDBInfo:
103
103
  is_embedded: Optional[Literal["composite", "json"]] = None
104
104
 
105
105
  # if the target class is stored in the database, control the cascade behavior
106
- on_delete: ForeignKeyOnDelete = ForeignKeyOnDelete.RESTRICT
107
- on_update: ForeignKeyOnUpdate = ForeignKeyOnUpdate.RESTRICT
106
+ on_target_delete: ForeignKeyOnDelete = ForeignKeyOnDelete.RESTRICT
107
+ on_target_update: ForeignKeyOnUpdate = ForeignKeyOnUpdate.RESTRICT
108
+
109
+ # this is the case for many-to-many relationships
110
+ on_source_delete: ForeignKeyOnDelete = ForeignKeyOnDelete.RESTRICT
111
+ on_source_update: ForeignKeyOnUpdate = ForeignKeyOnUpdate.RESTRICT
108
112
 
109
113
 
110
114
  @dataclass(kw_only=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sera-2
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary:
5
5
  Author: Binh Vu
6
6
  Author-email: bvu687@gmail.com
@@ -0,0 +1,31 @@
1
+ sera/.DS_Store,sha256=uxbN5p3UqIMOKQf9WM4OqbouyMKq7pHMXHv9wrnjscw,6148
2
+ sera/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ sera/libs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ sera/libs/api_helper.py,sha256=hUEy0INHM18lxTQ348tgbXNceOHcjiAnqmuL_8CRpLQ,2509
5
+ sera/libs/base_orm.py,sha256=Xs1rx_c3FfCQ2EUA8plqBLvZEABqsscLTaCYRhXbIas,2913
6
+ sera/libs/base_service.py,sha256=mC4s2SREWoOtr3JcHPHQ_MvcFaguNEKZ0CmqvBqlnBw,2729
7
+ sera/make/.DS_Store,sha256=1lFlJ5EFymdzGAUAaI30vcaaLHt3F1LwpG7xILf9jsM,6148
8
+ sera/make/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ sera/make/__main__.py,sha256=TLHA3e9QVoE0Nic6HSQDNiAe1MrTTw5IdYlNSNxjN5Q,912
10
+ sera/make/make_app.py,sha256=QDMN1wwfIKu3d68ovapMZWig24hDKJ4hJilNHjJq4EU,4598
11
+ sera/make/make_python_api.py,sha256=lYNitE1a1Es29fB7p5ryD6X_NASBlwNYAbH-rZ5pBbI,28337
12
+ sera/make/make_python_model.py,sha256=2KFgATb1DRZ3M8_cVVuhAZWuGamkO4HMfAqqr5fVUEs,25688
13
+ sera/make/make_python_services.py,sha256=RsinYZdfkrTlTn9CT50VgqGs9w6IZawsJx-KEmqfnEY,2062
14
+ sera/make/make_typescript_model.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
15
+ sera/misc/__init__.py,sha256=hjW2Lf1itdqlDjf1X8hwSZZfmE0XKDFlYtMMC1AXkT4,300
16
+ sera/misc/_rdf.py,sha256=G0ekWLUSw-eiKUOaPSGkELbZld19S9d36gWwiswjrrs,1671
17
+ sera/misc/_utils.py,sha256=MY85CZruRLYI2bf44d-a8g4lJibznD2MnAfd9VY1UdQ,1094
18
+ sera/models/__init__.py,sha256=1B3b-MOMh6_Xe3CsPouOjXLDuJg5G6NcRDPXcA0sQjA,687
19
+ sera/models/_class.py,sha256=saWzNGtw0BIuisgd_6PI5-0pFN690TBHp_7KCTMoh28,1923
20
+ sera/models/_collection.py,sha256=u3k4t7Z38FiZj9CstPArnf9KsIGr05zbwUn2ZrbQVJE,1078
21
+ sera/models/_datatype.py,sha256=tGpgZhFeHMA6sJdG5lyMQon2OC1r-fxo_IRGA1GyRtc,2762
22
+ sera/models/_module.py,sha256=YB2w9CZR7d_rF_W09dNZ9Pr4HXW2thXaWMgof1yYo8c,3982
23
+ sera/models/_multi_lingual_string.py,sha256=cVoxge1SW68dVmOjDZJU93tUq2ccJse3kSPqxrNkmgc,1091
24
+ sera/models/_parse.py,sha256=1WKiiU_P46ynWqGNYhU6KqCX7p0s6wq7mwPqFSiGfAQ,4986
25
+ sera/models/_property.py,sha256=uOVP154lafx10GFsdKuETHdho2SDm663BvO5umHEMlE,4229
26
+ sera/models/_schema.py,sha256=1F_Ict1NLvDcQDUZwcvnRS5MtsOTv584y3ChymUeUYA,1046
27
+ sera/namespace.py,sha256=5NJ0A7weZwblqkncpgY2Vfcat04mNtigNcVrqu7TGOc,123
28
+ sera/typing.py,sha256=CsazgVptDN-far3yISogTtA2KBJlFFOn0lK_WyZFDv8,230
29
+ sera_2-1.2.0.dist-info/METADATA,sha256=t9k96UhhRZZ1SYCfGP3PfIRrT2u5ICfoKiftB02TqH8,599
30
+ sera_2-1.2.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
31
+ sera_2-1.2.0.dist-info/RECORD,,
@@ -1,29 +0,0 @@
1
- sera/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- sera/libs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- sera/libs/api_helper.py,sha256=hUEy0INHM18lxTQ348tgbXNceOHcjiAnqmuL_8CRpLQ,2509
4
- sera/libs/base_orm.py,sha256=IxsHjNPjF60YbLyTsMTOhQbjQX-L30UZtvE_vJDgZfo,2950
5
- sera/libs/base_service.py,sha256=nVHODZjdTqC8rrDKxYUWrK95APrtdMSCYzflePNxXns,2379
6
- sera/make/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- sera/make/__main__.py,sha256=TLHA3e9QVoE0Nic6HSQDNiAe1MrTTw5IdYlNSNxjN5Q,912
8
- sera/make/make_app.py,sha256=e0DQpx6ilB76lxg2BYF6wjL7RFRQzvmOXq2322xm2SQ,4398
9
- sera/make/make_python_api.py,sha256=ikZfJrJ4B606td4os1QgX-7G5QJypmR-3qgLvGOIRh0,8765
10
- sera/make/make_python_model.py,sha256=1zC_NaFkyLYpZ3ytT-ZV6d8xmxtQHUpEFsqd0PkJ6x4,12031
11
- sera/make/make_python_services.py,sha256=RsinYZdfkrTlTn9CT50VgqGs9w6IZawsJx-KEmqfnEY,2062
12
- sera/make/make_typescript_model.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
13
- sera/misc/__init__.py,sha256=hjW2Lf1itdqlDjf1X8hwSZZfmE0XKDFlYtMMC1AXkT4,300
14
- sera/misc/_rdf.py,sha256=G0ekWLUSw-eiKUOaPSGkELbZld19S9d36gWwiswjrrs,1671
15
- sera/misc/_utils.py,sha256=MY85CZruRLYI2bf44d-a8g4lJibznD2MnAfd9VY1UdQ,1094
16
- sera/models/__init__.py,sha256=3ooJQulUc7oyUoMM89KT5f6nsoYagCjYEyC0AmyYyzY,661
17
- sera/models/_class.py,sha256=vFCuzG0vfAHYBjk1HQMFszT7zUAqGex-VAVJ2CUPIaE,1824
18
- sera/models/_collection.py,sha256=u3k4t7Z38FiZj9CstPArnf9KsIGr05zbwUn2ZrbQVJE,1078
19
- sera/models/_datatype.py,sha256=JkD3aRQ11DWicS2xaiNPwhBzJNJPwSkktBunx3EVr1s,1714
20
- sera/models/_module.py,sha256=-XW4bJ3v4QZPYPRMnbUW2zp0F5aJVH8uve_MrnwYz7w,3736
21
- sera/models/_multi_lingual_string.py,sha256=cVoxge1SW68dVmOjDZJU93tUq2ccJse3kSPqxrNkmgc,1091
22
- sera/models/_parse.py,sha256=l106WMAFTLjKio5L3rBK3B0NtwjnXh-sLF4Ofk2uFHE,5072
23
- sera/models/_property.py,sha256=lrI6V2zEblUVuEy9lahbLPLFisFRX6zrkO8wFWzU35k,4018
24
- sera/models/_schema.py,sha256=1F_Ict1NLvDcQDUZwcvnRS5MtsOTv584y3ChymUeUYA,1046
25
- sera/namespace.py,sha256=5NJ0A7weZwblqkncpgY2Vfcat04mNtigNcVrqu7TGOc,123
26
- sera/typing.py,sha256=CsazgVptDN-far3yISogTtA2KBJlFFOn0lK_WyZFDv8,230
27
- sera_2-1.1.0.dist-info/METADATA,sha256=zmJ_UdY6SLvr7d6pkcQL-oCo9DYB8gxpiM3CikxzySU,599
28
- sera_2-1.1.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
29
- sera_2-1.1.0.dist-info/RECORD,,
File without changes