sera-2 1.11.1__py3-none-any.whl → 1.11.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_service.py CHANGED
@@ -103,7 +103,7 @@ class BaseService(Generic[ID, R]):
103
103
 
104
104
  cq = select(func.count()).select_from(q.subquery())
105
105
  rq = q.limit(limit).offset(offset)
106
- records = self._process_result(session.execute(q)).scalars().all()
106
+ records = self._process_result(session.execute(rq)).scalars().all()
107
107
  total = session.execute(cq).scalar_one()
108
108
  return QueryResult(records, total)
109
109
 
@@ -234,8 +234,11 @@ def make_python_data_model(
234
234
 
235
235
  if isinstance(prop, DataProperty):
236
236
  pytype = prop.get_data_model_datatype().get_python_type()
237
- if pytype.dep is not None:
238
- program.import_(pytype.dep, True)
237
+ if prop.is_optional:
238
+ pytype = pytype.as_optional_type()
239
+
240
+ for dep in pytype.deps:
241
+ program.import_(dep, True)
239
242
 
240
243
  pytype_type = pytype.type
241
244
  if len(prop.data.constraints) > 0:
@@ -288,11 +291,13 @@ def make_python_data_model(
288
291
  else:
289
292
  pytype = PyTypeWithDep(
290
293
  f"Upsert{prop.target.name}",
291
- f"{target_pkg.module(prop.target.get_pymodule_name()).path}.Upsert{prop.target.name}",
294
+ [
295
+ f"{target_pkg.module(prop.target.get_pymodule_name()).path}.Upsert{prop.target.name}"
296
+ ],
292
297
  )
293
298
 
294
- if pytype.dep is not None:
295
- program.import_(pytype.dep, True)
299
+ for dep in pytype.deps:
300
+ program.import_(dep, True)
296
301
 
297
302
  if prop.cardinality.is_star_to_many():
298
303
  pytype = pytype.as_list_type()
@@ -426,8 +431,12 @@ def make_python_data_model(
426
431
 
427
432
  if isinstance(prop, DataProperty):
428
433
  pytype = prop.get_data_model_datatype().get_python_type()
429
- if pytype.dep is not None:
430
- program.import_(pytype.dep, True)
434
+ if prop.is_optional:
435
+ pytype = pytype.as_optional_type()
436
+
437
+ for dep in pytype.deps:
438
+ program.import_(dep, True)
439
+
431
440
  cls_ast(stmt.DefClassVarStatement(prop.name, pytype.type))
432
441
  elif isinstance(prop, ObjectProperty):
433
442
  if prop.target.db is not None:
@@ -439,11 +448,13 @@ def make_python_data_model(
439
448
  else:
440
449
  pytype = PyTypeWithDep(
441
450
  prop.target.name,
442
- f"{target_pkg.module(prop.target.get_pymodule_name()).path}.{prop.target.name}",
451
+ [
452
+ f"{target_pkg.module(prop.target.get_pymodule_name()).path}.{prop.target.name}"
453
+ ],
443
454
  )
444
455
 
445
- if pytype.dep is not None:
446
- program.import_(pytype.dep, True)
456
+ for dep in pytype.deps:
457
+ program.import_(dep, True)
447
458
 
448
459
  if prop.cardinality.is_star_to_many():
449
460
  pytype = pytype.as_list_type()
@@ -816,7 +827,7 @@ def make_python_relational_object_property(
816
827
  expr.ExprFuncCall(
817
828
  expr.ExprIdent("mapped_column"),
818
829
  [
819
- expr.ExprIdent(f"{prop.name}_{p.name}"),
830
+ expr.ExprConstant(f"{prop.name}_{p.name}"),
820
831
  expr.ExprIdent(
821
832
  assert_isinstance(p, DataProperty)
822
833
  .datatype.get_sqlalchemy_type()
@@ -824,7 +835,7 @@ def make_python_relational_object_property(
824
835
  ),
825
836
  PredefinedFn.keyword_assignment(
826
837
  "nullable",
827
- expr.ExprConstant(prop.is_optional),
838
+ expr.ExprConstant(prop.is_optional or p.is_optional),
828
839
  ),
829
840
  ],
830
841
  )
@@ -68,8 +68,8 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
68
68
 
69
69
  if isinstance(prop, DataProperty):
70
70
  tstype = prop.get_data_model_datatype().get_typescript_type()
71
- if tstype.dep is not None:
72
- program.import_(tstype.dep, True)
71
+ for dep in tstype.deps:
72
+ program.import_(dep, True)
73
73
 
74
74
  if idprop is not None and prop.name == idprop.name:
75
75
  # use id type alias
@@ -89,7 +89,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
89
89
  # this class is stored in the database, we store the id instead
90
90
  tstype = TsTypeWithDep(
91
91
  f"{prop.target.name}Id",
92
- f"@.models.{prop.target.get_tsmodule_name()}.{prop.target.name}.{prop.target.name}Id",
92
+ [
93
+ f"@.models.{prop.target.get_tsmodule_name()}.{prop.target.name}.{prop.target.name}Id"
94
+ ],
93
95
  )
94
96
  if prop.cardinality.is_star_to_many():
95
97
  tstype = tstype.as_list_type()
@@ -105,7 +107,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
105
107
  # we are going to store the whole object
106
108
  tstype = TsTypeWithDep(
107
109
  prop.target.name,
108
- f"@.models.{prop.target.get_tsmodule_name()}.{prop.target.name}.{prop.target.name}",
110
+ [
111
+ f"@.models.{prop.target.get_tsmodule_name()}.{prop.target.name}.{prop.target.name}"
112
+ ],
109
113
  )
110
114
  if prop.cardinality.is_star_to_many():
111
115
  tstype = tstype.as_list_type()
@@ -148,9 +152,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
148
152
  )
149
153
  )
150
154
 
151
- if tstype.dep is not None:
155
+ for dep in tstype.deps:
152
156
  program.import_(
153
- tstype.dep,
157
+ dep,
154
158
  True,
155
159
  )
156
160
 
@@ -319,14 +323,14 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
319
323
  # use id type alias
320
324
  tstype = TsTypeWithDep(
321
325
  f"{cls.name}Id",
322
- dep=f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}Id",
326
+ deps=[f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}Id"],
323
327
  )
324
328
  else:
325
329
  # for none id properties, we need to include a type for "invalid" value
326
330
  tstype = _inject_type_for_invalid_value(tstype)
327
331
 
328
- if tstype.dep is not None:
329
- program.import_(tstype.dep, True)
332
+ for dep in tstype.deps:
333
+ program.import_(dep, True)
330
334
 
331
335
  # however, if this is a primary key and auto-increment, we set a different default value
332
336
  # to be -1 to avoid start from 0
@@ -426,7 +430,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
426
430
  # this class is stored in the database, we store the id instead
427
431
  tstype = TsTypeWithDep(
428
432
  f"{prop.target.name}Id",
429
- f"@.models.{prop.target.get_tsmodule_name()}.{prop.target.name}.{prop.target.name}Id",
433
+ [
434
+ f"@.models.{prop.target.get_tsmodule_name()}.{prop.target.name}.{prop.target.name}Id"
435
+ ],
430
436
  )
431
437
  if prop.cardinality.is_star_to_many():
432
438
  tstype = tstype.as_list_type()
@@ -461,7 +467,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
461
467
  # we are going to store the whole object
462
468
  tstype = TsTypeWithDep(
463
469
  f"Draft{prop.target.name}",
464
- f"@.models.{prop.target.get_tsmodule_name()}.Draft{prop.target.name}.Draft{prop.target.name}",
470
+ [
471
+ f"@.models.{prop.target.get_tsmodule_name()}.Draft{prop.target.name}.Draft{prop.target.name}"
472
+ ],
465
473
  )
466
474
  if prop.cardinality.is_star_to_many():
467
475
  tstype = tstype.as_list_type()
@@ -515,9 +523,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
515
523
  )
516
524
  )
517
525
 
518
- if tstype.dep is not None:
526
+ for dep in tstype.deps:
519
527
  program.import_(
520
- tstype.dep,
528
+ dep,
521
529
  True,
522
530
  )
523
531
 
@@ -698,12 +706,16 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
698
706
  comment="Check if the draft is valid (only check the required fields as the non-required fields if it's invalid will be set to undefined)",
699
707
  )(
700
708
  stmt.ReturnStatement(
701
- stmt.TypescriptStatement(
709
+ expr.ExprRawTypescript(
702
710
  " && ".join(
703
711
  f"{draft_validators}.{prop2tsname[prop.name]}(this.{prop2tsname[prop.name]}).isValid"
704
712
  for prop in cls.properties.values()
705
713
  if not prop.is_optional
706
714
  )
715
+ if any(
716
+ not prop.is_optional for prop in cls.properties.values()
717
+ )
718
+ else "true"
707
719
  )
708
720
  )
709
721
  ),
@@ -859,8 +871,8 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
859
871
  # if prop.name == idprop.name:
860
872
  # # use id type alias
861
873
  # tstype = TsTypeWithDep(f"{cls.name}Id")
862
- if tstype.dep is not None:
863
- program.import_(tstype.dep, True)
874
+ for dep in tstype.deps:
875
+ program.import_(dep, True)
864
876
  tsprop = [
865
877
  (expr.ExprIdent("datatype"), expr.ExprConstant(tstype.type)),
866
878
  (
@@ -885,7 +897,9 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
885
897
  # we are going to store the whole object
886
898
  tstype = TsTypeWithDep(
887
899
  prop.target.name,
888
- f"@.models.{prop.target.get_tsmodule_name()}.{prop.target.name}.{prop.target.name}",
900
+ [
901
+ f"@.models.{prop.target.get_tsmodule_name()}.{prop.target.name}.{prop.target.name}"
902
+ ],
889
903
  )
890
904
 
891
905
  # we don't store the type itself, but just the name of the type
@@ -901,7 +915,12 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
901
915
  expr.ExprIdent("targetClass"),
902
916
  expr.ExprConstant(prop.target.name),
903
917
  ),
904
- (expr.ExprIdent("datatype"), expr.ExprConstant(tstype.type)),
918
+ (
919
+ expr.ExprIdent("datatype"),
920
+ expr.ExprConstant(
921
+ tstype.type if prop.target.db is not None else "embedded"
922
+ ),
923
+ ),
905
924
  (
906
925
  expr.ExprIdent("cardinality"),
907
926
  expr.ExprConstant(prop.cardinality.value),
@@ -957,24 +976,36 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
957
976
  )
958
977
  )
959
978
 
960
- for type in ["Schema", "ObjectProperty", "DataProperty"]:
979
+ for type in ["ObjectProperty", "DataProperty"]:
961
980
  program.import_(f"sera-db.{type}", True)
981
+ if cls.db is not None:
982
+ program.import_(f"sera-db.Schema", True)
983
+ else:
984
+ program.import_(f"sera-db.EmbeddedSchema", True)
962
985
 
963
986
  program.import_(f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}", True)
964
- program.import_(f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}Id", True)
965
987
  program.import_(
966
988
  f"@.models.{pkg.dir.name}.Draft{cls.name}.Draft{cls.name}", True
967
989
  )
968
990
  program.import_(
969
991
  f"@.models.{pkg.dir.name}.Draft{cls.name}.draft{cls.name}Validators", True
970
992
  )
993
+ if cls.db is not None:
994
+ program.import_(f"@.models.{pkg.dir.name}.{cls.name}.{cls.name}Id", True)
995
+
971
996
  program.root(
972
997
  stmt.LineBreak(),
973
998
  stmt.TypescriptStatement(
974
999
  f"export type {cls.name}SchemaType = "
975
1000
  + PredefinedFn.dict(
976
- [
977
- (expr.ExprIdent("id"), expr.ExprIdent(f"{cls.name}Id")),
1001
+ (
1002
+ [
1003
+ (expr.ExprIdent("id"), expr.ExprIdent(f"{cls.name}Id")),
1004
+ ]
1005
+ if cls.db is not None
1006
+ else []
1007
+ )
1008
+ + [
978
1009
  (
979
1010
  expr.ExprIdent("publicProperties"),
980
1011
  expr.ExprIdent(
@@ -1038,7 +1069,11 @@ def make_typescript_data_model(schema: Schema, target_pkg: Package):
1038
1069
  ),
1039
1070
  stmt.LineBreak(),
1040
1071
  stmt.TypescriptStatement(
1041
- f"export const {cls.name}Schema: Schema<{cls.name}SchemaType['id'], {cls.name}SchemaType['cls'], {cls.name}SchemaType['draftCls'], {cls.name}SchemaType['publicProperties'], {cls.name}SchemaType['allProperties'], {cls.name}SchemaType> = "
1072
+ (
1073
+ f"export const {cls.name}Schema: Schema<{cls.name}SchemaType['id'], {cls.name}SchemaType['cls'], {cls.name}SchemaType['draftCls'], {cls.name}SchemaType['publicProperties'], {cls.name}SchemaType['allProperties'], {cls.name}SchemaType> = "
1074
+ if cls.db is not None
1075
+ else f"export const {cls.name}Schema: EmbeddedSchema<{cls.name}SchemaType['cls'], {cls.name}SchemaType['draftCls'], {cls.name}SchemaType['publicProperties'], {cls.name}SchemaType['allProperties']> = "
1076
+ )
1042
1077
  + PredefinedFn.dict(
1043
1078
  [
1044
1079
  (
@@ -1211,7 +1246,7 @@ def _inject_type_for_invalid_value(tstype: TsTypeWithDep) -> TsTypeWithDep:
1211
1246
  else:
1212
1247
  # Need to add parentheses
1213
1248
  inner_type = f"({inner_type} | string)"
1214
- return TsTypeWithDep(inner_type + "[]", tstype.dep)
1249
+ return TsTypeWithDep(inner_type + "[]", tstype.deps)
1215
1250
 
1216
1251
  m = re.match(r"^\(?[a-zA-Z \|]+\)?$", tstype.type)
1217
1252
  if m is not None:
@@ -1222,7 +1257,7 @@ def _inject_type_for_invalid_value(tstype: TsTypeWithDep) -> TsTypeWithDep:
1222
1257
  else:
1223
1258
  # Needs parentheses for clarity
1224
1259
  new_type = f"({tstype.type} | string)"
1225
- return TsTypeWithDep(new_type, tstype.dep)
1260
+ return TsTypeWithDep(new_type, tstype.deps)
1226
1261
  return tstype
1227
1262
 
1228
1263
  raise NotImplementedError(tstype.type)
sera/models/_datatype.py CHANGED
@@ -24,7 +24,7 @@ SQLAlchemyDataType = Literal[
24
24
  @dataclass
25
25
  class PyTypeWithDep:
26
26
  type: str
27
- dep: str | None = None
27
+ deps: list[str] = field(default_factory=list)
28
28
 
29
29
  def get_python_type(self) -> type:
30
30
  """Get the Python type from the type string for typing annotation in Python."""
@@ -50,13 +50,25 @@ class PyTypeWithDep:
50
50
 
51
51
  def as_list_type(self) -> PyTypeWithDep:
52
52
  """Convert the type to a list type."""
53
- return PyTypeWithDep(type=f"list[{self.type}]", dep=self.dep)
53
+ return PyTypeWithDep(type=f"list[{self.type}]", deps=self.deps)
54
+
55
+ def as_optional_type(self) -> PyTypeWithDep:
56
+ """Convert the type to an optional type."""
57
+ if "typing.Optional" not in self.deps:
58
+ deps = self.deps + ["typing.Optional"]
59
+ else:
60
+ deps = self.deps
61
+ if "Optional[" in self.type:
62
+ raise NotImplementedError(
63
+ f"Have not handle nested optional yet: {self.type}"
64
+ )
65
+ return PyTypeWithDep(type=f"Optional[{self.type}]", deps=deps)
54
66
 
55
67
 
56
68
  @dataclass
57
69
  class TsTypeWithDep:
58
70
  type: str
59
- dep: str | None = None
71
+ deps: list[str] = field(default_factory=list)
60
72
 
61
73
  def get_default(self) -> expr.ExprConstant:
62
74
  if self.type.endswith("[]"):
@@ -83,7 +95,7 @@ class TsTypeWithDep:
83
95
  list_type = f"({self.type})[]"
84
96
  else:
85
97
  list_type = f"{self.type}[]"
86
- return TsTypeWithDep(type=list_type, dep=self.dep)
98
+ return TsTypeWithDep(type=list_type, deps=self.deps)
87
99
 
88
100
 
89
101
  @dataclass
@@ -137,16 +149,6 @@ predefined_datatypes = {
137
149
  tstype=TsTypeWithDep(type="string"),
138
150
  is_list=False,
139
151
  ),
140
- "optional[string]": DataType(
141
- pytype=PyTypeWithDep(type="Optional[str]", dep="typing.Optional"),
142
- sqltype=SQLTypeWithDep(
143
- type="String",
144
- mapped_pytype="Optional[str]",
145
- deps=["sqlalchemy.String", "typing.Optional"],
146
- ),
147
- tstype=TsTypeWithDep(type="string | undefined"),
148
- is_list=False,
149
- ),
150
152
  "integer": DataType(
151
153
  pytype=PyTypeWithDep(type="int"),
152
154
  sqltype=SQLTypeWithDep(
@@ -156,7 +158,7 @@ predefined_datatypes = {
156
158
  is_list=False,
157
159
  ),
158
160
  "datetime": DataType(
159
- pytype=PyTypeWithDep(type="datetime", dep="datetime.datetime"),
161
+ pytype=PyTypeWithDep(type="datetime", deps=["datetime.datetime"]),
160
162
  sqltype=SQLTypeWithDep(
161
163
  type="DateTime",
162
164
  mapped_pytype="datetime",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sera-2
3
- Version: 1.11.1
3
+ Version: 1.11.2
4
4
  Summary:
5
5
  Author: Binh Vu
6
6
  Author-email: bvu687@gmail.com
@@ -3,7 +3,7 @@ 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=47y1kcwk3Xd2ZEMnUj_0OwCuUmgwOs5kYrE95BDVUn4,5411
5
5
  sera/libs/base_orm.py,sha256=dyh0OT2sbHku5qPJXvRzYAHRTSXvvbQaS-Qwg65Bw04,2918
6
- sera/libs/base_service.py,sha256=tKvYyCNIBLUbcZUp0EbrU9T2vHSRu_oISbkPECjZEfo,4613
6
+ sera/libs/base_service.py,sha256=8uKMaIicLc8LbN5vyaK9dGWoCLf_wuaaOw9ooSiqSWM,4614
7
7
  sera/libs/dag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  sera/libs/dag/_dag.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  sera/libs/middlewares/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -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=UWI-HbpFjt8n5yLAv2oGQK68LgrF-m0BUI334qtB9Mk,41228
16
+ sera/make/make_python_model.py,sha256=MyEhVXeeHxAzqUkjSUuVzQJLUCCe7RKL6VxEMiCfTxk,41507
17
17
  sera/make/make_python_services.py,sha256=RsinYZdfkrTlTn9CT50VgqGs9w6IZawsJx-KEmqfnEY,2062
18
- sera/make/make_typescript_model.py,sha256=fMjz4YxdGHijb2pHI4xj7rKJf1PxyJxVLYW0ivsu70c,50128
18
+ sera/make/make_typescript_model.py,sha256=-FNeUlcrqz2Zd1Eg6P14usXTrgTXd9oGhpOApLqntOw,51395
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=eF71q-X7LA91sNYG29aXQiDVMjjr8-e6ez7P9NRwq_E,6376
26
+ sera/models/_datatype.py,sha256=zkqOKOTZIkoYhJkIpytWWhGp-LtD10Jzud7lxOSd5UQ,6533
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.1.dist-info/METADATA,sha256=vymmUgXvGuXjkCDXFhPc0Y8ZsM-Kwb7cBBLLy4I10ss,857
36
- sera_2-1.11.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
37
- sera_2-1.11.1.dist-info/RECORD,,
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,,