sera-2 1.6.0__py3-none-any.whl → 1.6.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/libs/base_orm.py CHANGED
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from typing import Optional
4
4
 
5
5
  import orjson
6
+ from sera.typing import UNSET
6
7
  from sqlalchemy import LargeBinary, TypeDecorator
7
8
  from sqlalchemy import create_engine as sqlalchemy_create_engine
8
9
  from sqlalchemy import update
@@ -15,6 +16,8 @@ class BaseORM:
15
16
  args = {}
16
17
  for col in self.__table__.columns: # type: ignore
17
18
  val = getattr(self, col.name)
19
+ if val is UNSET:
20
+ continue
18
21
  if col.primary_key:
19
22
  q = q.where(getattr(self.__class__, col.name) == val)
20
23
  args[col.name] = val
@@ -22,7 +25,12 @@ class BaseORM:
22
25
  return q.values(**args)
23
26
 
24
27
  def get_update_args(self):
25
- return {col.name: getattr(self, col.name) for col in self.__table__.columns} # type: ignore
28
+ table = self.__table__ # type: ignore
29
+ return {
30
+ col.name: val
31
+ for col in table.columns
32
+ if (val := getattr(self, col.name)) is not UNSET
33
+ }
26
34
 
27
35
  @classmethod
28
36
  def from_dict(cls, data: dict):
sera/libs/base_service.py CHANGED
@@ -114,7 +114,7 @@ class BaseService(Generic[ID, R]):
114
114
 
115
115
  def update(self, record: R, session: Session) -> R:
116
116
  """Update an existing record."""
117
- session.add(record)
117
+ session.execute(record.get_update_query())
118
118
  session.commit()
119
119
  return record
120
120
 
sera/make/__main__.py CHANGED
@@ -4,8 +4,9 @@ from pathlib import Path
4
4
  from typing import Annotated
5
5
 
6
6
  import typer
7
+
7
8
  from sera.make.make_app import make_app
8
- from sera.models import Language
9
+ from sera.typing import Language
9
10
 
10
11
  app = typer.Typer(pretty_exceptions_short=True, pretty_exceptions_enable=False)
11
12
 
sera/make/make_app.py CHANGED
@@ -14,8 +14,13 @@ from sera.make.make_python_model import (
14
14
  make_python_relational_model,
15
15
  )
16
16
  from sera.make.make_python_services import make_python_service_structure
17
- from sera.make.make_typescript_model import make_typescript_data_model
18
- from sera.models import App, DataCollection, Language, parse_schema
17
+ from sera.make.make_typescript_model import (
18
+ make_typescript_data_model,
19
+ make_typescript_enum,
20
+ )
21
+ from sera.misc import Formatter
22
+ from sera.models import App, DataCollection, parse_schema
23
+ from sera.typing import Language
19
24
 
20
25
 
21
26
  def make_config(app: App):
@@ -77,6 +82,7 @@ def make_config(app: App):
77
82
  expr.ExprFuncCall(
78
83
  expr.ExprIdent("parse_schema"),
79
84
  [
85
+ expr.ExprConstant(app.name),
80
86
  PredefinedFn.list(
81
87
  [
82
88
  expr.ExprDivision(
@@ -87,7 +93,7 @@ def make_config(app: App):
87
93
  )
88
94
  for path in app.schema_files
89
95
  ]
90
- )
96
+ ),
91
97
  ],
92
98
  ),
93
99
  ),
@@ -164,8 +170,10 @@ def make_app(
164
170
  # generate services
165
171
  make_python_service_structure(app, collections)
166
172
  elif language == Language.Typescript:
173
+ make_typescript_enum(schema, app.models)
167
174
  make_typescript_data_model(schema, app.models)
168
175
 
176
+ Formatter.get_instance().process()
169
177
  return app
170
178
 
171
179
 
@@ -159,11 +159,24 @@ def make_python_data_model(
159
159
  else:
160
160
  value = expr.ExprMethodCall(value, "to_db", [])
161
161
  elif isinstance(prop, DataProperty) and prop.is_diff_data_model_datatype():
162
- # convert the value to the python type used in db.
163
- value = get_data_conversion(
162
+ # convert the value to the python type used in db
163
+ converted_value = get_data_conversion(
164
164
  prop.get_data_model_datatype().get_python_type().type,
165
165
  prop.datatype.get_python_type().type,
166
166
  )(value)
167
+
168
+ if prop.data.is_private:
169
+ # if the property is private and it's UNSET, we cannot transform it to the database type
170
+ # and has to use the UNSET value (the update query will ignore this field)
171
+ program.import_("sera.typing.UNSET", True)
172
+ program.import_("sera.typing.is_set", True)
173
+ value = expr.ExprTernary(
174
+ expr.ExprFuncCall(expr.ExprIdent("is_set"), [value]),
175
+ converted_value,
176
+ expr.ExprIdent("UNSET"),
177
+ )
178
+ else:
179
+ value = converted_value
167
180
  return value
168
181
 
169
182
  def make_upsert(program: Program, cls: Class):
@@ -177,11 +190,13 @@ def make_python_data_model(
177
190
  alias=f"{cls.name}DB",
178
191
  )
179
192
  cls_ast = program.root.class_(
180
- "Upsert" + cls.name, [expr.ExprIdent("msgspec.Struct")]
193
+ "Upsert" + cls.name,
194
+ [expr.ExprIdent("msgspec.Struct"), expr.ExprIdent("kw_only=True")],
181
195
  )
182
196
  for prop in cls.properties.values():
183
197
  # this is a create object, so users can create private field
184
- # hence, we do not check for prop.is_private
198
+ # hence, we do not check for prop.is_private -- however, this field can be omitted
199
+ # during update, so we need to mark it as optional
185
200
  # if prop.data.is_private:
186
201
  # continue
187
202
 
@@ -189,7 +204,14 @@ def make_python_data_model(
189
204
  pytype = prop.get_data_model_datatype().get_python_type()
190
205
  if pytype.dep is not None:
191
206
  program.import_(pytype.dep, True)
207
+
192
208
  pytype_type = pytype.type
209
+ if prop.data.is_private:
210
+ program.import_("typing.Union", True)
211
+ program.import_("sera.typing.UnsetType", True)
212
+ program.import_("sera.typing.UNSET", True)
213
+ pytype_type = f"Union[{pytype_type}, UnsetType]"
214
+
193
215
  if len(prop.data.constraints) > 0:
194
216
  # if the property has constraints, we need to figure out
195
217
  program.import_("typing.Annotated", True)
@@ -202,7 +224,9 @@ def make_python_data_model(
202
224
  raise NotImplementedError(prop.data.constraints)
203
225
 
204
226
  prop_default_value = None
205
- if prop.default_value is not None:
227
+ if prop.data.is_private:
228
+ prop_default_value = expr.ExprIdent("UNSET")
229
+ elif prop.default_value is not None:
206
230
  prop_default_value = expr.ExprConstant(prop.default_value)
207
231
  elif prop.default_factory is not None:
208
232
  program.import_(prop.default_factory.pyfunc, True)
@@ -215,6 +239,7 @@ def make_python_data_model(
215
239
  )
216
240
  ],
217
241
  )
242
+
218
243
  cls_ast(
219
244
  stmt.DefClassVarStatement(
220
245
  prop.name, pytype_type, prop_default_value
@@ -5,6 +5,7 @@ from typing import Any, Callable
5
5
  from codegen.models import AST, PredefinedFn, Program, expr, stmt
6
6
  from codegen.models.var import DeferredVar
7
7
  from loguru import logger
8
+
8
9
  from sera.misc import (
9
10
  assert_isinstance,
10
11
  assert_not_null,
@@ -15,6 +16,7 @@ from sera.misc import (
15
16
  from sera.models import (
16
17
  Class,
17
18
  DataProperty,
19
+ Enum,
18
20
  ObjectProperty,
19
21
  Package,
20
22
  Schema,
@@ -26,6 +28,15 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
26
28
  """Generate TypeScript data model from the schema. The data model aligns with the public data model in Python, not the database model."""
27
29
  app = target_pkg.app
28
30
 
31
+ # mapping from type alias of idprop to its real type
32
+ idprop_aliases = {}
33
+ for cls in schema.classes.values():
34
+ idprop = cls.get_id_property()
35
+ if idprop is not None:
36
+ idprop_aliases[f"{cls.name}Id"] = (
37
+ idprop.get_data_model_datatype().get_typescript_type()
38
+ )
39
+
29
40
  def clone_prop(prop: DataProperty | ObjectProperty, value: expr.Expr):
30
41
  # detect all complex types is hard, we can assume that any update to this does not mutate
31
42
  # the original object, then it's okay.
@@ -38,7 +49,6 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
38
49
  return
39
50
 
40
51
  idprop = cls.get_id_property()
41
-
42
52
  program = Program()
43
53
 
44
54
  prop_defs = []
@@ -161,7 +171,8 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
161
171
  else None
162
172
  ),
163
173
  stmt.LineBreak(),
164
- lambda ast00: ast00.interface(
174
+ lambda ast00: ast00.class_like(
175
+ "interface",
165
176
  cls.name + "ConstructorArgs",
166
177
  )(*prop_defs),
167
178
  stmt.LineBreak(),
@@ -230,9 +241,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
230
241
  update_field_funcs: list[Callable[[AST], Any]] = []
231
242
 
232
243
  for prop in cls.properties.values():
233
- if prop.data.is_private:
234
- # skip private fields as this is for APIs exchange
235
- continue
244
+ # if prop.data.is_private:
245
+ # # skip private fields as this is for APIs exchange
246
+ # continue
236
247
 
237
248
  propname = to_camel_case(prop.name)
238
249
 
@@ -291,15 +302,23 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
291
302
  ):
292
303
  create_propvalue = expr.ExprConstant(-1)
293
304
  else:
294
- create_propvalue = tstype.get_default()
305
+ if tstype.type in idprop_aliases:
306
+ create_propvalue = idprop_aliases[tstype.type].get_default()
307
+ else:
308
+ create_propvalue = tstype.get_default()
295
309
 
296
310
  if prop.db is not None and prop.db.is_primary_key:
297
311
  # for checking if the primary key is from the database or default (create_propvalue)
298
312
  cls_pk = (expr.ExprIdent(propname), create_propvalue)
299
313
 
300
- update_propvalue = PredefinedFn.attr_getter(
301
- expr.ExprIdent("record"), expr.ExprIdent(propname)
302
- )
314
+ # if this field is private, we cannot get it from the normal record
315
+ # we have to create a default value for it.
316
+ if prop.data.is_private:
317
+ update_propvalue = create_propvalue
318
+ else:
319
+ update_propvalue = PredefinedFn.attr_getter(
320
+ expr.ExprIdent("record"), expr.ExprIdent(propname)
321
+ )
303
322
 
304
323
  ser_args.append(
305
324
  (
@@ -333,7 +352,22 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
333
352
  )
334
353
  if prop.cardinality.is_star_to_many():
335
354
  tstype = tstype.as_list_type()
336
- create_propvalue = tstype.get_default()
355
+ create_propvalue = expr.ExprConstant([])
356
+ else:
357
+ # if target class has an auto-increment primary key, we set a different default value
358
+ # to be -1 to avoid start from 0
359
+ target_idprop = prop.target.get_id_property()
360
+ if (
361
+ target_idprop is not None
362
+ and target_idprop.db is not None
363
+ and target_idprop.db.is_primary_key
364
+ and target_idprop.db.is_auto_increment
365
+ ):
366
+ create_propvalue = expr.ExprConstant(-1)
367
+ else:
368
+ assert tstype.type in idprop_aliases
369
+ create_propvalue = idprop_aliases[tstype.type].get_default()
370
+
337
371
  update_propvalue = PredefinedFn.attr_getter(
338
372
  expr.ExprIdent("record"), expr.ExprIdent(propname)
339
373
  )
@@ -474,7 +508,8 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
474
508
  observable_args.sort(key=lambda x: {"observable": 0, "action": 1}[x[1].ident])
475
509
 
476
510
  program.root(
477
- lambda ast00: ast00.interface(
511
+ lambda ast00: ast00.class_like(
512
+ "interface",
478
513
  draft_clsname + "ConstructorArgs",
479
514
  )(*prop_defs),
480
515
  stmt.LineBreak(),
@@ -861,3 +896,44 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
861
896
  make_definition(cls, pkg)
862
897
 
863
898
  make_index(pkg)
899
+
900
+
901
+ def make_typescript_enum(schema: Schema, target_pkg: Package):
902
+ """Make typescript enum for the schema"""
903
+ enum_pkg = target_pkg.pkg("enums")
904
+
905
+ def make_enum(enum: Enum, pkg: Package):
906
+ program = Program()
907
+ program.root(
908
+ stmt.LineBreak(),
909
+ lambda ast: ast.class_like("enum", enum.name)(
910
+ *[
911
+ stmt.DefClassVarStatement(
912
+ name=value.name,
913
+ type=None,
914
+ value=expr.ExprConstant(value.value),
915
+ )
916
+ for value in enum.values.values()
917
+ ]
918
+ ),
919
+ stmt.LineBreak(),
920
+ stmt.TypescriptStatement("export " + enum.name + ";"),
921
+ )
922
+ pkg.module(enum.get_tsmodule_name()).write(program)
923
+
924
+ for enum in schema.enums.values():
925
+ make_enum(enum, enum_pkg)
926
+
927
+ program = Program()
928
+ for enum in schema.enums.values():
929
+ program.import_(f"@.models.enums.{enum.get_tsmodule_name()}.{enum.name}", True)
930
+
931
+ program.root(
932
+ stmt.LineBreak(),
933
+ stmt.TypescriptStatement(
934
+ "export { "
935
+ + ", ".join([enum.name for enum in schema.enums.values()])
936
+ + "};"
937
+ ),
938
+ )
939
+ enum_pkg.module("index").write(program)
sera/misc/__init__.py CHANGED
@@ -1,3 +1,4 @@
1
+ from sera.misc._formatter import File, Formatter
1
2
  from sera.misc._utils import (
2
3
  assert_isinstance,
3
4
  assert_not_null,
@@ -14,4 +15,7 @@ __all__ = [
14
15
  "assert_not_null",
15
16
  "to_snake_case",
16
17
  "to_camel_case",
18
+ "to_pascal_case",
19
+ "Formatter",
20
+ "File",
17
21
  ]
@@ -0,0 +1,63 @@
1
+ from __future__ import annotations
2
+
3
+ import subprocess
4
+ from concurrent.futures import ThreadPoolExecutor
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+
8
+ from sera.typing import Language
9
+ from tqdm import tqdm
10
+
11
+
12
+ @dataclass
13
+ class File:
14
+ path: Path
15
+ language: Language
16
+
17
+
18
+ class Formatter:
19
+ instance = None
20
+
21
+ def __init__(self):
22
+ self.pending_files: list[File] = []
23
+
24
+ @staticmethod
25
+ def get_instance():
26
+ if Formatter.instance is None:
27
+ Formatter.instance = Formatter()
28
+ return Formatter.instance
29
+
30
+ def register(self, file: File):
31
+ self.pending_files.append(file)
32
+
33
+ def process(self):
34
+ """Format pending files in parallel"""
35
+
36
+ def format_file(file: File):
37
+ if file.language == Language.Typescript:
38
+ try:
39
+ subprocess.check_output(
40
+ ["npx", "prettier", "--write", str(file.path.absolute())],
41
+ cwd=file.path.parent,
42
+ )
43
+ except subprocess.CalledProcessError as e:
44
+ print(f"Error formatting {file.path}: {e}")
45
+ raise
46
+ else:
47
+ raise NotImplementedError(
48
+ f"Formatting not implemented for {file.language}"
49
+ )
50
+
51
+ if len(self.pending_files) == 0:
52
+ return
53
+
54
+ with ThreadPoolExecutor() as executor:
55
+ list(
56
+ tqdm(
57
+ executor.map(format_file, self.pending_files),
58
+ total=len(self.pending_files),
59
+ desc="Formatting files",
60
+ )
61
+ )
62
+
63
+ self.pending_files.clear()
sera/models/__init__.py CHANGED
@@ -1,7 +1,8 @@
1
1
  from sera.models._class import Class
2
2
  from sera.models._collection import DataCollection
3
3
  from sera.models._datatype import DataType, PyTypeWithDep, TsTypeWithDep
4
- from sera.models._module import App, Language, Module, Package
4
+ from sera.models._enum import Enum
5
+ from sera.models._module import App, Module, Package
5
6
  from sera.models._multi_lingual_string import MultiLingualString
6
7
  from sera.models._parse import parse_schema
7
8
  from sera.models._property import Cardinality, DataProperty, ObjectProperty, Property
@@ -21,7 +22,7 @@ __all__ = [
21
22
  "DataCollection",
22
23
  "Module",
23
24
  "App",
24
- "Language",
25
25
  "PyTypeWithDep",
26
26
  "TsTypeWithDep",
27
+ "Enum",
27
28
  ]
sera/models/_enum.py CHANGED
@@ -39,9 +39,13 @@ class Enum:
39
39
  )
40
40
 
41
41
  def get_pymodule_name(self) -> str:
42
- """Get the python module name of this class as if there is a python module created to store this class only."""
42
+ """Get the python module name of this enum as if there is a python module created to store this enum only."""
43
43
  return to_snake_case(self.name)
44
44
 
45
+ def get_tsmodule_name(self) -> str:
46
+ """Get the typescript module name of this enum as if there is a typescript module created to store this enum only."""
47
+ return self.name[0].lower() + self.name[1:]
48
+
45
49
  def is_str_enum(self) -> bool:
46
50
  """Check if this enum is a string enum."""
47
51
  return all(isinstance(value.value, str) for value in self.values.values())
sera/models/_module.py CHANGED
@@ -2,7 +2,6 @@ from __future__ import annotations
2
2
 
3
3
  import subprocess
4
4
  from dataclasses import dataclass
5
- from enum import Enum
6
5
  from pathlib import Path
7
6
  from typing import Sequence
8
7
 
@@ -11,11 +10,8 @@ import black.mode
11
10
  import isort
12
11
  from codegen.models import Program
13
12
  from loguru import logger
14
-
15
-
16
- class Language(str, Enum):
17
- Python = "python"
18
- Typescript = "typescript"
13
+ from sera.misc import File, Formatter
14
+ from sera.typing import Language
19
15
 
20
16
 
21
17
  @dataclass
@@ -106,15 +102,9 @@ class Module:
106
102
  outfile.write_text(copyright_statement + code)
107
103
 
108
104
  if self.language == Language.Typescript:
109
- # invoke prettier to format the code
110
- try:
111
- subprocess.check_output(
112
- ["npx", "prettier", "--write", str(outfile.absolute())],
113
- cwd=self.package.app.root.dir,
114
- )
115
- except Exception as e:
116
- logger.error("Error formatting Typescript file: {}", e)
117
- raise
105
+ Formatter.get_instance().register(
106
+ File(path=outfile, language=self.language)
107
+ )
118
108
 
119
109
  def exists(self) -> bool:
120
110
  """Check if the module exists"""
@@ -178,3 +168,8 @@ class App:
178
168
  self.schema_files = schema_files
179
169
 
180
170
  self.language = language
171
+
172
+ @property
173
+ def name(self) -> str:
174
+ """Get the name of the application"""
175
+ return self.root.dir.name
sera/typing.py CHANGED
@@ -1,6 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Annotated, TypeVar
3
+ from enum import Enum
4
+ from typing import Annotated, Any, TypeGuard, TypeVar, Union
5
+
6
+ import msgspec
4
7
 
5
8
 
6
9
  class doc(str):
@@ -12,3 +15,18 @@ FieldName = Annotated[str, doc("field name of a class")]
12
15
  ObjectPath = Annotated[
13
16
  str, doc("path of an object (e.g., can be function, class, etc.)")
14
17
  ]
18
+
19
+
20
+ class Language(str, Enum):
21
+ Python = "python"
22
+ Typescript = "typescript"
23
+
24
+
25
+ # re-export msgspec.UnsetType & msgspec.UNSET, so that we are consistent with ORM & data modules
26
+ UnsetType = msgspec.UnsetType
27
+ UNSET: Any = msgspec.UNSET
28
+
29
+
30
+ def is_set(value: Union[T, UnsetType]) -> TypeGuard[T]:
31
+ """Typeguard to check if a value is set (not UNSET)"""
32
+ return value is not UNSET
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sera-2
3
- Version: 1.6.0
3
+ Version: 1.6.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.5.1,<3.0.0)
12
+ Requires-Dist: codegen-2 (>=2.6.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)
@@ -2,30 +2,31 @@ sera/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  sera/constants.py,sha256=mzAaMyIx8TJK0-RYYJ5I24C4s0Uvj26OLMJmBo0pxHI,123
3
3
  sera/libs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  sera/libs/api_helper.py,sha256=hUEy0INHM18lxTQ348tgbXNceOHcjiAnqmuL_8CRpLQ,2509
5
- sera/libs/base_orm.py,sha256=Fte-NOq62-4ulpjKmdO4V5pQKy9JfaL3ryBqpRRKkNQ,2913
6
- sera/libs/base_service.py,sha256=CNAdOPxgXfvdANj75qd4GW5EC0WYW-L5Utm0ozfBbio,4075
5
+ sera/libs/base_orm.py,sha256=sTiHvbvLALSFygCITKFTXK1w-8UtxXGT_Te-1PEAiCI,3094
6
+ sera/libs/base_service.py,sha256=l5D4IjxIiz8LBRranUYddb8J0Y6SwSyetKYTLrCUdQA,4098
7
7
  sera/make/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- sera/make/__main__.py,sha256=EvskvcZ5BikA6c0QyUXMbHfKrjr44W0JTmW_-iXFEGg,1416
9
- sera/make/make_app.py,sha256=HB6zIi456FZiLDtNMmO1crsCs3GlMLLUH-aJXHHaZxE,5771
8
+ sera/make/__main__.py,sha256=G5O7s6135-708honwqMFn2yPTs06WbGQTHpupID0eZ4,1417
9
+ sera/make/make_app.py,sha256=n9NtW73O3s_5Q31VHIRmnd-jEIcpDO7ksAsOdovde2s,5999
10
10
  sera/make/make_python_api.py,sha256=RuJUm9z-4plBEtjobeOPr12o27OT-0tSeXI4ZlM3IY0,29433
11
- sera/make/make_python_model.py,sha256=8U3fmIK_ahpxyMsCypQvISBVoncRUspYEppWX-_MLtU,35402
11
+ sera/make/make_python_model.py,sha256=xf4revAwVWEnF6QhxbbqPyUGgXOOB--Gu3jPxsESg0Y,36593
12
12
  sera/make/make_python_services.py,sha256=RsinYZdfkrTlTn9CT50VgqGs9w6IZawsJx-KEmqfnEY,2062
13
- sera/make/make_typescript_model.py,sha256=HMwiYjNSQwDNNVXZzzNGJE2wDOW51q4JXafIh03AW_I,34035
14
- sera/misc/__init__.py,sha256=G-vpwJtdS596Yle7W007vArHRwmK0QgGmLhzlqTiHMQ,311
13
+ sera/make/make_typescript_model.py,sha256=dT1ZHpsDvegX07jxDRncd_iu4FAiaV_7xyioWBJdbes,36999
14
+ sera/misc/__init__.py,sha256=Dh4uDq0D4N53h3zhvmwfa5a0TPVRSUvLzb0hkFuPirk,411
15
+ sera/misc/_formatter.py,sha256=aCGYL08l8f3aLODHxSocxBBwkRYEo3K1QzCDEn3suj0,1685
15
16
  sera/misc/_utils.py,sha256=V5g4oLGHOhUCR75Kkcn1w01pAvGvaepK-T8Z3pIgHjI,1450
16
- sera/models/__init__.py,sha256=Kz3Cg7GIVzsM0qFG5ERB5gobLAxBy2SdxItIl73ui2g,759
17
+ sera/models/__init__.py,sha256=vJC5Kzo_N7wd16ocNPy1VvAZDGNiWeiAhWJ4ihATKvA,780
17
18
  sera/models/_class.py,sha256=Wf0e8x6-szG9TzoFkAlqj7_dG0SCICMBw_333n3paxk,2514
18
19
  sera/models/_collection.py,sha256=ZnQEriKC4X88Zz48Kn1AVZKH-1_l8OgWa-zf2kcQOOE,1414
19
20
  sera/models/_constraints.py,sha256=lZmCh6Py0UVMdhTR7zUOPPzGqJGbmDCzf7xH7yITcbQ,1278
20
21
  sera/models/_datatype.py,sha256=uMxK_8wBLowaIMIAYCb3V17YmkzJrKKc5orjImzqWbA,5818
21
22
  sera/models/_default.py,sha256=ABggW6qdPR4ZDqIPJdJ0GCGQ-7kfsfZmQ_DchgZEa-I,137
22
- sera/models/_enum.py,sha256=n9e0Nde9RSsO0V5zIAQbY4-qur8Q2euDQJSa6yP_VV8,1853
23
- sera/models/_module.py,sha256=4xZO8Ey4La7JTiCRfU50pYw4V6ssECH6dGIuplodwQY,5215
23
+ sera/models/_enum.py,sha256=sy0q7E646F-APsqrVQ52r1fAQ_DCAeaNq5YM5QN3zIk,2070
24
+ sera/models/_module.py,sha256=8QRSCubZmdDP9rL58rGAS6X5VCrkc1ZHvuMu1I1KrWk,5043
24
25
  sera/models/_multi_lingual_string.py,sha256=JETN6k00VH4wrA4w5vAHMEJV8fp3SY9bJebskFTjQLA,1186
25
26
  sera/models/_parse.py,sha256=sJYfQtwek96ltpgxExG4xUbiLnU3qvNYhTP1CeyXGjs,9746
26
27
  sera/models/_property.py,sha256=CmEmgOShtSyNFq05YW3tGupwCIVRzPMKudXWld8utPk,5530
27
28
  sera/models/_schema.py,sha256=r-Gqg9Lb_wR3UrbNvfXXgt_qs5bts0t2Ve7aquuF_OI,1155
28
- sera/typing.py,sha256=QkzT07FtBwoiX2WHXDUrU1zSPLoRmKJgsXa2kLyLMxU,327
29
- sera_2-1.6.0.dist-info/METADATA,sha256=QF_GIRGrujh3P3FFhjE4F-eVuMy3qWEFiJ4SS5r9-QQ,856
30
- sera_2-1.6.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
31
- sera_2-1.6.0.dist-info/RECORD,,
29
+ sera/typing.py,sha256=Q4QMfbtfrCjC9tFfsZPhsAnbNX4lm4NHQ9lmjNXYdV0,772
30
+ sera_2-1.6.2.dist-info/METADATA,sha256=B_Brp3KBIu2C0iqX-5cjwdWAfen1DttoeUyj0ms_7-4,856
31
+ sera_2-1.6.2.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
32
+ sera_2-1.6.2.dist-info/RECORD,,
File without changes