vtjson 2.1.4__py3-none-any.whl → 2.1.5__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.
vtjson/py.typed ADDED
File without changes
vtjson/vtjson.py CHANGED
@@ -12,7 +12,7 @@ import urllib.parse
12
12
  import warnings
13
13
  from collections.abc import Sequence, Sized
14
14
  from dataclasses import dataclass
15
- from typing import Any, Callable, Type, TypeVar, Union, cast
15
+ from typing import Any, Callable, Mapping, Type, TypeVar, Union, cast
16
16
 
17
17
  try:
18
18
  from typing import Literal
@@ -45,6 +45,12 @@ if hasattr(typing, "get_origin"):
45
45
  else:
46
46
  supports_Generics = False
47
47
 
48
+ try:
49
+ Sequence[str]
50
+ supports_Generic_ABC = True
51
+ except Exception:
52
+ supports_Generic_ABC = False
53
+
48
54
  try:
49
55
  typing.get_type_hints(int, include_extras=True)
50
56
  supports_structural = True
@@ -83,7 +89,7 @@ class compiled_schema:
83
89
  object_: object,
84
90
  name: str,
85
91
  strict: bool,
86
- subs: dict[str, object],
92
+ subs: Mapping[str, object],
87
93
  ) -> str:
88
94
  return ""
89
95
 
@@ -115,14 +121,14 @@ class SchemaError(Exception):
115
121
  pass
116
122
 
117
123
 
118
- __version__ = "2.1.4"
124
+ __version__ = "2.1.5"
119
125
 
120
126
 
121
127
  @dataclass
122
128
  class Apply:
123
129
  skip_first: bool | None = None
124
130
  name: str | None = None
125
- labels: list[str] | None = None
131
+ labels: Sequence[str] | None = None
126
132
 
127
133
  def __call__(self, schemas: tuple[object, ...]) -> object:
128
134
  if len(schemas) == 0:
@@ -159,7 +165,9 @@ def _get_type_hints(schema: object) -> dict[str, object]:
159
165
  return type_hints
160
166
 
161
167
 
162
- def _to_dict(type_hints: dict[str, object], total: bool = True) -> dict[object, object]:
168
+ def _to_dict(
169
+ type_hints: Mapping[str, object], total: bool = True
170
+ ) -> dict[object, object]:
163
171
  d: dict[object, object] = {}
164
172
  if not supports_Generics:
165
173
  raise SchemaError("Generic types are not supported")
@@ -225,7 +233,7 @@ def _wrong_type_message(
225
233
  class _validate_meta(type):
226
234
  __schema__: object
227
235
  __strict__: bool
228
- __subs__: dict[str, object]
236
+ __subs__: Mapping[str, object]
229
237
  __dbg__: bool
230
238
 
231
239
  def __instancecheck__(cls, object_: object) -> bool:
@@ -242,7 +250,7 @@ def make_type(
242
250
  name: str | None = None,
243
251
  strict: bool = True,
244
252
  debug: bool = False,
245
- subs: dict[str, object] = {},
253
+ subs: Mapping[str, object] = {},
246
254
  ) -> _validate_meta:
247
255
  if name is None:
248
256
  if hasattr(schema, "__name__"):
@@ -293,7 +301,7 @@ class _union(compiled_schema):
293
301
  object_: object,
294
302
  name: str = "object",
295
303
  strict: bool = True,
296
- subs: dict[str, object] = {},
304
+ subs: Mapping[str, object] = {},
297
305
  ) -> str:
298
306
  messages = []
299
307
  for schema in self.schemas:
@@ -332,7 +340,7 @@ class _intersect(compiled_schema):
332
340
  object_: object,
333
341
  name: str = "object",
334
342
  strict: bool = True,
335
- subs: dict[str, object] = {},
343
+ subs: Mapping[str, object] = {},
336
344
  ) -> str:
337
345
  for schema in self.schemas:
338
346
  message = schema.__validate__(object_, name=name, strict=strict, subs=subs)
@@ -364,7 +372,7 @@ class _complement(compiled_schema):
364
372
  object_: object,
365
373
  name: str = "object",
366
374
  strict: bool = True,
367
- subs: dict[str, object] = {},
375
+ subs: Mapping[str, object] = {},
368
376
  ) -> str:
369
377
  message = self.schema.__validate__(object_, name=name, strict=strict, subs=subs)
370
378
  if message != "":
@@ -396,7 +404,7 @@ class _lax(compiled_schema):
396
404
  object_: object,
397
405
  name: str = "object",
398
406
  strict: bool = True,
399
- subs: dict[str, object] = {},
407
+ subs: Mapping[str, object] = {},
400
408
  ) -> str:
401
409
  return self.schema.__validate__(object_, name=name, strict=False, subs=subs)
402
410
 
@@ -424,7 +432,7 @@ class _strict(compiled_schema):
424
432
  object_: object,
425
433
  name: str = "object",
426
434
  strict: bool = True,
427
- subs: dict[str, object] = {},
435
+ subs: Mapping[str, object] = {},
428
436
  ) -> str:
429
437
  return self.schema.__validate__(object_, name=name, strict=True, subs=subs)
430
438
 
@@ -458,7 +466,7 @@ class _set_label(compiled_schema):
458
466
  object_: object,
459
467
  name: str = "object",
460
468
  strict: bool = True,
461
- subs: dict[str, object] = {},
469
+ subs: Mapping[str, object] = {},
462
470
  ) -> str:
463
471
  common_labels = tuple(set(subs.keys()).intersection(self.labels))
464
472
  if len(common_labels) >= 2:
@@ -511,7 +519,7 @@ class quote(compiled_schema):
511
519
  object_: object,
512
520
  name: str = "object",
513
521
  strict: bool = True,
514
- subs: dict[str, object] = {},
522
+ subs: Mapping[str, object] = {},
515
523
  ) -> str:
516
524
  return self.schema.__validate__(object_, name=name, strict=strict, subs=subs)
517
525
 
@@ -537,7 +545,7 @@ class _set_name(compiled_schema):
537
545
  object_: object,
538
546
  name: str = "object",
539
547
  strict: bool = True,
540
- subs: dict[str, object] = {},
548
+ subs: Mapping[str, object] = {},
541
549
  ) -> str:
542
550
  message = self.schema.__validate__(object_, name=name, strict=strict, subs=subs)
543
551
  if message != "":
@@ -608,7 +616,7 @@ class regex(compiled_schema):
608
616
  object_: object,
609
617
  name: str = "object",
610
618
  strict: bool = True,
611
- subs: dict[str, object] = {},
619
+ subs: Mapping[str, object] = {},
612
620
  ) -> str:
613
621
  if not isinstance(object_, str):
614
622
  return _wrong_type_message(object_, name, self.__name__)
@@ -647,7 +655,7 @@ class glob(compiled_schema):
647
655
  object_: object,
648
656
  name: str = "object",
649
657
  strict: bool = True,
650
- subs: dict[str, object] = {},
658
+ subs: Mapping[str, object] = {},
651
659
  ) -> str:
652
660
  if not isinstance(object_, str):
653
661
  return _wrong_type_message(object_, name, self.__name__)
@@ -683,7 +691,7 @@ class magic(compiled_schema):
683
691
  object_: object,
684
692
  name: str = "object",
685
693
  strict: bool = True,
686
- subs: dict[str, object] = {},
694
+ subs: Mapping[str, object] = {},
687
695
  ) -> str:
688
696
  if not isinstance(object_, (str, bytes)):
689
697
  return _wrong_type_message(object_, name, self.__name__)
@@ -732,7 +740,7 @@ class div(compiled_schema):
732
740
  object_: object,
733
741
  name: str = "object",
734
742
  strict: bool = True,
735
- subs: dict[str, object] = {},
743
+ subs: Mapping[str, object] = {},
736
744
  ) -> str:
737
745
  if not isinstance(object_, int):
738
746
  return _wrong_type_message(object_, name, "int")
@@ -779,7 +787,7 @@ class close_to(compiled_schema):
779
787
  object_: object,
780
788
  name: str = "object",
781
789
  strict: bool = True,
782
- subs: dict[str, object] = {},
790
+ subs: Mapping[str, object] = {},
783
791
  ) -> str:
784
792
  if not isinstance(object_, (float, int)):
785
793
  return _wrong_type_message(object_, name, "number")
@@ -809,7 +817,7 @@ class gt(compiled_schema):
809
817
  object_: object,
810
818
  name: str = "object",
811
819
  strict: bool = True,
812
- subs: dict[str, object] = {},
820
+ subs: Mapping[str, object] = {},
813
821
  ) -> str:
814
822
  try:
815
823
  if self.lb < object_:
@@ -840,7 +848,7 @@ class ge(compiled_schema):
840
848
  object_: object,
841
849
  name: str = "object",
842
850
  strict: bool = True,
843
- subs: dict[str, object] = {},
851
+ subs: Mapping[str, object] = {},
844
852
  ) -> str:
845
853
  try:
846
854
  if self.lb <= object_:
@@ -871,7 +879,7 @@ class lt(compiled_schema):
871
879
  object_: object,
872
880
  name: str = "object",
873
881
  strict: bool = True,
874
- subs: dict[str, object] = {},
882
+ subs: Mapping[str, object] = {},
875
883
  ) -> str:
876
884
  try:
877
885
  if self.ub > object_:
@@ -902,7 +910,7 @@ class le(compiled_schema):
902
910
  object_: object,
903
911
  name: str = "object",
904
912
  strict: bool = True,
905
- subs: dict[str, object] = {},
913
+ subs: Mapping[str, object] = {},
906
914
  ) -> str:
907
915
  try:
908
916
  if self.ub >= object_:
@@ -1006,7 +1014,7 @@ class size(compiled_schema):
1006
1014
  object_: object,
1007
1015
  name: str = "object",
1008
1016
  strict: bool = True,
1009
- subs: dict[str, object] = {},
1017
+ subs: Mapping[str, object] = {},
1010
1018
  ) -> str:
1011
1019
  if not isinstance(object_, Sized):
1012
1020
  return f"{name} (value:{_c(object_)}) has no len()"
@@ -1029,7 +1037,7 @@ class _deferred(compiled_schema):
1029
1037
  object_: object,
1030
1038
  name: str = "object",
1031
1039
  strict: bool = True,
1032
- subs: dict[str, object] = {},
1040
+ subs: Mapping[str, object] = {},
1033
1041
  ) -> str:
1034
1042
  if self.key not in self.collection:
1035
1043
  raise ValidationError(f"{name}: key {self.key} is unknown")
@@ -1131,12 +1139,20 @@ def _compile(
1131
1139
  schema,
1132
1140
  _deferred_compiles=_deferred_compiles,
1133
1141
  )
1134
- elif origin == list:
1135
- ret = _List(typing.get_args(schema)[0], _deferred_compiles=_deferred_compiles)
1136
1142
  elif origin == tuple:
1137
1143
  ret = _Tuple(typing.get_args(schema), _deferred_compiles=_deferred_compiles)
1138
- elif origin == dict:
1139
- ret = _Dict(typing.get_args(schema), _deferred_compiles=_deferred_compiles)
1144
+ elif isinstance(origin, type) and issubclass(origin, Sequence):
1145
+ ret = _List(
1146
+ typing.get_args(schema)[0],
1147
+ type_schema=origin,
1148
+ _deferred_compiles=_deferred_compiles,
1149
+ )
1150
+ elif isinstance(origin, type) and issubclass(origin, Mapping):
1151
+ ret = _Dict(
1152
+ typing.get_args(schema),
1153
+ type_schema=origin,
1154
+ _deferred_compiles=_deferred_compiles,
1155
+ )
1140
1156
  elif origin == Union:
1141
1157
  ret = _Union(typing.get_args(schema), _deferred_compiles=_deferred_compiles)
1142
1158
  elif supports_Literal and origin == Literal:
@@ -1149,9 +1165,9 @@ def _compile(
1149
1165
  ret = _type(schema)
1150
1166
  elif callable(schema):
1151
1167
  ret = _callable(schema)
1152
- elif isinstance(schema, tuple) or isinstance(schema, list):
1168
+ elif isinstance(schema, Sequence) and not isinstance(schema, str):
1153
1169
  ret = _sequence(schema, _deferred_compiles=_deferred_compiles)
1154
- elif isinstance(schema, dict):
1170
+ elif isinstance(schema, Mapping):
1155
1171
  ret = _dict(schema, _deferred_compiles=_deferred_compiles)
1156
1172
  elif isinstance(schema, set):
1157
1173
  ret = _set(schema, _deferred_compiles=_deferred_compiles)
@@ -1171,7 +1187,7 @@ def _validate(
1171
1187
  object_: object,
1172
1188
  name: str = "object",
1173
1189
  strict: bool = True,
1174
- subs: dict[str, object] = {},
1190
+ subs: Mapping[str, object] = {},
1175
1191
  ) -> str:
1176
1192
  return compile(schema).__validate__(object_, name=name, strict=strict, subs=subs)
1177
1193
 
@@ -1181,7 +1197,7 @@ def validate(
1181
1197
  object_: object,
1182
1198
  name: str = "object",
1183
1199
  strict: bool = True,
1184
- subs: dict[str, object] = {},
1200
+ subs: Mapping[str, object] = {},
1185
1201
  ) -> None:
1186
1202
  message = _validate(
1187
1203
  schema,
@@ -1210,7 +1226,7 @@ class number(compiled_schema):
1210
1226
  object_: object,
1211
1227
  name: str = "object",
1212
1228
  strict: bool = True,
1213
- subs: dict[str, object] = {},
1229
+ subs: Mapping[str, object] = {},
1214
1230
  ) -> str:
1215
1231
  if isinstance(object_, (int, float)):
1216
1232
  return ""
@@ -1233,7 +1249,7 @@ class email(compiled_schema):
1233
1249
  object_: object,
1234
1250
  name: str = "object",
1235
1251
  strict: bool = True,
1236
- subs: dict[str, object] = {},
1252
+ subs: Mapping[str, object] = {},
1237
1253
  ) -> str:
1238
1254
  if not isinstance(object_, str):
1239
1255
  return _wrong_type_message(
@@ -1270,7 +1286,7 @@ class ip_address(compiled_schema):
1270
1286
  object_: object,
1271
1287
  name: str = "object",
1272
1288
  strict: bool = True,
1273
- subs: dict[str, object] = {},
1289
+ subs: Mapping[str, object] = {},
1274
1290
  ) -> str:
1275
1291
  if not isinstance(object_, (int, str, bytes)):
1276
1292
  return _wrong_type_message(object_, name, self.__name__)
@@ -1287,7 +1303,7 @@ class url(compiled_schema):
1287
1303
  object_: object,
1288
1304
  name: str = "object",
1289
1305
  strict: bool = True,
1290
- subs: dict[str, object] = {},
1306
+ subs: Mapping[str, object] = {},
1291
1307
  ) -> str:
1292
1308
  if not isinstance(object_, str):
1293
1309
  return _wrong_type_message(object_, name, "url")
@@ -1313,7 +1329,7 @@ class date_time(compiled_schema):
1313
1329
  object_: object,
1314
1330
  name: str = "object",
1315
1331
  strict: bool = True,
1316
- subs: dict[str, object] = {},
1332
+ subs: Mapping[str, object] = {},
1317
1333
  ) -> str:
1318
1334
  if not isinstance(object_, str):
1319
1335
  return _wrong_type_message(object_, name, self.__name__)
@@ -1336,7 +1352,7 @@ class date(compiled_schema):
1336
1352
  object_: object,
1337
1353
  name: str = "object",
1338
1354
  strict: bool = True,
1339
- subs: dict[str, object] = {},
1355
+ subs: Mapping[str, object] = {},
1340
1356
  ) -> str:
1341
1357
  if not isinstance(object_, str):
1342
1358
  return _wrong_type_message(object_, name, "date")
@@ -1353,7 +1369,7 @@ class time(compiled_schema):
1353
1369
  object_: object,
1354
1370
  name: str = "object",
1355
1371
  strict: bool = True,
1356
- subs: dict[str, object] = {},
1372
+ subs: Mapping[str, object] = {},
1357
1373
  ) -> str:
1358
1374
  if not isinstance(object_, str):
1359
1375
  return _wrong_type_message(object_, name, "date")
@@ -1370,7 +1386,7 @@ class nothing(compiled_schema):
1370
1386
  object_: object,
1371
1387
  name: str = "object",
1372
1388
  strict: bool = True,
1373
- subs: dict[str, object] = {},
1389
+ subs: Mapping[str, object] = {},
1374
1390
  ) -> str:
1375
1391
  return _wrong_type_message(object_, name, "nothing")
1376
1392
 
@@ -1381,7 +1397,7 @@ class anything(compiled_schema):
1381
1397
  object_: object,
1382
1398
  name: str = "object",
1383
1399
  strict: bool = True,
1384
- subs: dict[str, object] = {},
1400
+ subs: Mapping[str, object] = {},
1385
1401
  ) -> str:
1386
1402
  return ""
1387
1403
 
@@ -1412,7 +1428,7 @@ class domain_name(compiled_schema):
1412
1428
  object_: object,
1413
1429
  name: str = "object",
1414
1430
  strict: bool = True,
1415
- subs: dict[str, object] = {},
1431
+ subs: Mapping[str, object] = {},
1416
1432
  ) -> str:
1417
1433
  if not isinstance(object_, str):
1418
1434
  return _wrong_type_message(object_, name, self.__name__)
@@ -1448,9 +1464,9 @@ class at_least_one_of(compiled_schema):
1448
1464
  object_: object,
1449
1465
  name: str = "object",
1450
1466
  strict: bool = True,
1451
- subs: dict[str, object] = {},
1467
+ subs: Mapping[str, object] = {},
1452
1468
  ) -> str:
1453
- if not isinstance(object_, dict):
1469
+ if not isinstance(object_, Mapping):
1454
1470
  return _wrong_type_message(object_, name, self.__name__)
1455
1471
  try:
1456
1472
  if any([a in object_ for a in self.args]):
@@ -1475,9 +1491,9 @@ class at_most_one_of(compiled_schema):
1475
1491
  object_: object,
1476
1492
  name: str = "object",
1477
1493
  strict: bool = True,
1478
- subs: dict[str, object] = {},
1494
+ subs: Mapping[str, object] = {},
1479
1495
  ) -> str:
1480
- if not isinstance(object_, dict):
1496
+ if not isinstance(object_, Mapping):
1481
1497
  return _wrong_type_message(object_, name, self.__name__)
1482
1498
  try:
1483
1499
  if sum([a in object_ for a in self.args]) <= 1:
@@ -1502,9 +1518,9 @@ class one_of(compiled_schema):
1502
1518
  object_: object,
1503
1519
  name: str = "object",
1504
1520
  strict: bool = True,
1505
- subs: dict[str, object] = {},
1521
+ subs: Mapping[str, object] = {},
1506
1522
  ) -> str:
1507
- if not isinstance(object_, dict):
1523
+ if not isinstance(object_, Mapping):
1508
1524
  return _wrong_type_message(object_, name, self.__name__)
1509
1525
  try:
1510
1526
  if sum([a in object_ for a in self.args]) == 1:
@@ -1526,10 +1542,10 @@ class keys(compiled_schema):
1526
1542
  object_: object,
1527
1543
  name: str = "object",
1528
1544
  strict: bool = True,
1529
- subs: dict[str, object] = {},
1545
+ subs: Mapping[str, object] = {},
1530
1546
  ) -> str:
1531
- if not isinstance(object_, dict):
1532
- return _wrong_type_message(object_, name, "dict") # TODO: __name__
1547
+ if not isinstance(object_, Mapping):
1548
+ return _wrong_type_message(object_, name, "Mapping") # TODO: __name__
1533
1549
  for k in self.args:
1534
1550
  if k not in object_:
1535
1551
  return f"{name}[{repr(k)}] is missing"
@@ -1562,7 +1578,7 @@ class _ifthen(compiled_schema):
1562
1578
  object_: object,
1563
1579
  name: str = "object",
1564
1580
  strict: bool = True,
1565
- subs: dict[str, object] = {},
1581
+ subs: Mapping[str, object] = {},
1566
1582
  ) -> str:
1567
1583
  if (
1568
1584
  self.if_schema.__validate__(object_, name=name, strict=strict, subs=subs)
@@ -1624,7 +1640,7 @@ class _cond(compiled_schema):
1624
1640
  object_: object,
1625
1641
  name: str = "object",
1626
1642
  strict: bool = True,
1627
- subs: dict[str, object] = {},
1643
+ subs: Mapping[str, object] = {},
1628
1644
  ) -> str:
1629
1645
  for c in self.conditions:
1630
1646
  if c[0].__validate__(object_, name=name, strict=strict, subs=subs) == "":
@@ -1649,7 +1665,7 @@ class _fields(compiled_schema):
1649
1665
  d: dict[str, compiled_schema]
1650
1666
 
1651
1667
  def __init__(
1652
- self, d: dict[str, object], _deferred_compiles: _mapping | None = None
1668
+ self, d: Mapping[str, object], _deferred_compiles: _mapping | None = None
1653
1669
  ) -> None:
1654
1670
  self.d = {}
1655
1671
  for k, v in d.items():
@@ -1660,7 +1676,7 @@ class _fields(compiled_schema):
1660
1676
  object_: object,
1661
1677
  name: str = "object",
1662
1678
  strict: bool = True,
1663
- subs: dict[str, object] = {},
1679
+ subs: Mapping[str, object] = {},
1664
1680
  ) -> str:
1665
1681
  for k, v in self.d.items():
1666
1682
  name_ = f"{name}.{k}"
@@ -1676,8 +1692,8 @@ class _fields(compiled_schema):
1676
1692
 
1677
1693
  class fields:
1678
1694
  def __init__(self, d: object) -> None:
1679
- if not isinstance(d, dict):
1680
- raise SchemaError(f"{repr(d)} is not a dictionary")
1695
+ if not isinstance(d, Mapping):
1696
+ raise SchemaError(f"{repr(d)} is not a Mapping")
1681
1697
  for k in d:
1682
1698
  if not isinstance(k, str):
1683
1699
  raise SchemaError(f"key {repr(k)} in {repr(d)} is not a string")
@@ -1716,7 +1732,7 @@ class _filter(compiled_schema):
1716
1732
  object_: object,
1717
1733
  name: str = "object",
1718
1734
  strict: bool = True,
1719
- subs: dict[str, object] = {},
1735
+ subs: Mapping[str, object] = {},
1720
1736
  ) -> str:
1721
1737
  try:
1722
1738
  object_ = self.filter(object_)
@@ -1775,7 +1791,7 @@ class _type(compiled_schema):
1775
1791
  object_: object,
1776
1792
  name: str = "object",
1777
1793
  strict: bool = True,
1778
- subs: dict[str, object] = {},
1794
+ subs: Mapping[str, object] = {},
1779
1795
  ) -> str:
1780
1796
  try:
1781
1797
  if self.schema == float and isinstance(object_, int):
@@ -1792,7 +1808,7 @@ class _type(compiled_schema):
1792
1808
  object_: object,
1793
1809
  name: str = "object",
1794
1810
  strict: bool = True,
1795
- subs: dict[str, object] = {},
1811
+ subs: Mapping[str, object] = {},
1796
1812
  ) -> str:
1797
1813
  # consider int as a subtype of float
1798
1814
  if isinstance(object_, (int, float)):
@@ -1805,7 +1821,7 @@ class _type(compiled_schema):
1805
1821
  object_: object,
1806
1822
  name: str = "object",
1807
1823
  strict: bool = True,
1808
- subs: dict[str, object] = {},
1824
+ subs: Mapping[str, object] = {},
1809
1825
  ) -> str:
1810
1826
  # consider int, float as subtypes of complex
1811
1827
  if isinstance(object_, (int, float, complex)):
@@ -1824,10 +1840,14 @@ class _sequence(compiled_schema):
1824
1840
 
1825
1841
  def __init__(
1826
1842
  self,
1827
- schema: list[object] | tuple[object, ...],
1843
+ schema: Sequence[object],
1844
+ type_schema: type | None = None,
1828
1845
  _deferred_compiles: _mapping | None = None,
1829
1846
  ) -> None:
1830
- self.type_schema = type(schema)
1847
+ if type_schema is None:
1848
+ self.type_schema = type(schema)
1849
+ else:
1850
+ self.type_schema = type_schema
1831
1851
  self.schema = [
1832
1852
  _compile(o, _deferred_compiles=_deferred_compiles)
1833
1853
  for o in schema
@@ -1847,10 +1867,10 @@ class _sequence(compiled_schema):
1847
1867
  object_: object,
1848
1868
  name: str = "object",
1849
1869
  strict: bool = True,
1850
- subs: dict[str, object] = {},
1870
+ subs: Mapping[str, object] = {},
1851
1871
  ) -> str:
1852
1872
  if not isinstance(object_, self.type_schema):
1853
- return _wrong_type_message(object_, name, type(self.schema).__name__)
1873
+ return _wrong_type_message(object_, name, self.type_schema.__name__)
1854
1874
  ls = len(self.schema)
1855
1875
  lo = len(object_)
1856
1876
  if strict:
@@ -1870,10 +1890,10 @@ class _sequence(compiled_schema):
1870
1890
  object_: object,
1871
1891
  name: str = "object",
1872
1892
  strict: bool = True,
1873
- subs: dict[str, object] = {},
1893
+ subs: Mapping[str, object] = {},
1874
1894
  ) -> str:
1875
1895
  if not isinstance(object_, self.type_schema):
1876
- return _wrong_type_message(object_, name, type(self.schema).__name__)
1896
+ return _wrong_type_message(object_, name, self.type_schema.__name__)
1877
1897
  ls = len(self.schema)
1878
1898
  lo = len(object_)
1879
1899
  if ls > lo:
@@ -1910,7 +1930,7 @@ class _const(compiled_schema):
1910
1930
  object_: object,
1911
1931
  name: str = "object",
1912
1932
  strict: bool = True,
1913
- subs: dict[str, object] = {},
1933
+ subs: Mapping[str, object] = {},
1914
1934
  ) -> str:
1915
1935
  if object_ != self.schema:
1916
1936
  return self.message(name, object_)
@@ -1936,7 +1956,7 @@ class _callable(compiled_schema):
1936
1956
  object_: object,
1937
1957
  name: str = "object",
1938
1958
  strict: bool = True,
1939
- subs: dict[str, object] = {},
1959
+ subs: Mapping[str, object] = {},
1940
1960
  ) -> str:
1941
1961
  try:
1942
1962
  if self.schema(object_):
@@ -1955,12 +1975,18 @@ class _dict(compiled_schema):
1955
1975
  const_keys: set[object]
1956
1976
  other_keys: set[compiled_schema]
1957
1977
  schema: dict[object, compiled_schema]
1978
+ type_schema: Type[Mapping[object, object]]
1958
1979
 
1959
1980
  def __init__(
1960
1981
  self,
1961
- schema: dict[object, object],
1982
+ schema: Mapping[object, object],
1983
+ type_schema: type | None = None,
1962
1984
  _deferred_compiles: _mapping | None = None,
1963
1985
  ) -> None:
1986
+ if type_schema is None:
1987
+ self.type_schema = type(schema)
1988
+ else:
1989
+ self.type_schema = type_schema
1964
1990
  self.min_keys = set()
1965
1991
  self.const_keys = set()
1966
1992
  self.other_keys = set()
@@ -1990,10 +2016,10 @@ class _dict(compiled_schema):
1990
2016
  object_: object,
1991
2017
  name: str = "object",
1992
2018
  strict: bool = True,
1993
- subs: dict[str, object] = {},
2019
+ subs: Mapping[str, object] = {},
1994
2020
  ) -> str:
1995
- if not isinstance(object_, dict):
1996
- return _wrong_type_message(object_, name, "dict")
2021
+ if not isinstance(object_, self.type_schema):
2022
+ return _wrong_type_message(object_, name, self.type_schema.__name__)
1997
2023
 
1998
2024
  for k in self.min_keys:
1999
2025
  if k not in object_:
@@ -2056,7 +2082,7 @@ class _set(compiled_schema):
2056
2082
  object_: object,
2057
2083
  name: str = "object",
2058
2084
  strict: bool = True,
2059
- subs: dict[str, object] = {},
2085
+ subs: Mapping[str, object] = {},
2060
2086
  ) -> str:
2061
2087
  return self.schema.__validate__(object_, name=name, strict=True, subs=subs)
2062
2088
 
@@ -2065,7 +2091,7 @@ class _set(compiled_schema):
2065
2091
  object_: object,
2066
2092
  name: str = "object",
2067
2093
  strict: bool = True,
2068
- subs: dict[str, object] = {},
2094
+ subs: Mapping[str, object] = {},
2069
2095
  ) -> str:
2070
2096
  if not isinstance(object_, set):
2071
2097
  return _wrong_type_message(object_, name, "set")
@@ -2081,7 +2107,7 @@ class _set(compiled_schema):
2081
2107
  object_: object,
2082
2108
  name: str = "object",
2083
2109
  strict: bool = True,
2084
- subs: dict[str, object] = {},
2110
+ subs: Mapping[str, object] = {},
2085
2111
  ) -> str:
2086
2112
  if not isinstance(object_, set):
2087
2113
  return _wrong_type_message(object_, name, "set")
@@ -2119,9 +2145,8 @@ class protocol:
2119
2145
  self, _deferred_compiles: _mapping | None = None
2120
2146
  ) -> compiled_schema:
2121
2147
  if not self.dict:
2122
- type_dict_ = cast(dict[str, object], self.type_dict)
2123
2148
  return _set_name(
2124
- fields(type_dict_),
2149
+ fields(self.type_dict),
2125
2150
  self.__name__,
2126
2151
  reason=True,
2127
2152
  _deferred_compiles=_deferred_compiles,
@@ -2159,13 +2184,18 @@ class _Union(compiled_schema):
2159
2184
 
2160
2185
  class _List(compiled_schema):
2161
2186
  def __init__(
2162
- self, schema: object, _deferred_compiles: _mapping | None = None
2187
+ self,
2188
+ schema: object,
2189
+ type_schema: type | None = None,
2190
+ _deferred_compiles: _mapping | None = None,
2163
2191
  ) -> None:
2164
2192
  setattr(
2165
2193
  self,
2166
2194
  "__validate__",
2167
2195
  _sequence(
2168
- [schema, ...], _deferred_compiles=_deferred_compiles
2196
+ [schema, ...],
2197
+ type_schema=type_schema,
2198
+ _deferred_compiles=_deferred_compiles,
2169
2199
  ).__validate__,
2170
2200
  )
2171
2201
 
@@ -2183,13 +2213,18 @@ class _Tuple(compiled_schema):
2183
2213
 
2184
2214
  class _Dict(compiled_schema):
2185
2215
  def __init__(
2186
- self, schema: tuple[object, ...], _deferred_compiles: _mapping | None = None
2216
+ self,
2217
+ schema: tuple[object, ...],
2218
+ type_schema: type | None = None,
2219
+ _deferred_compiles: _mapping | None = None,
2187
2220
  ) -> None:
2188
2221
  k, v = schema
2189
2222
  setattr(
2190
2223
  self,
2191
2224
  "__validate__",
2192
- _dict({k: v}, _deferred_compiles=_deferred_compiles).__validate__,
2225
+ _dict(
2226
+ {k: v}, type_schema=type_schema, _deferred_compiles=_deferred_compiles
2227
+ ).__validate__,
2193
2228
  )
2194
2229
 
2195
2230
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vtjson
3
- Version: 2.1.4
3
+ Version: 2.1.5
4
4
  Summary: A lightweight package for validating JSON like Python objects
5
5
  Author-email: Michel Van den Bergh <michel.vandenbergh@uhasselt.be>
6
6
  Project-URL: Homepage, https://github.com/vdbergh/vtjson
@@ -163,8 +163,8 @@ A schema can be, in order of precedence:
163
163
  - A Python type hint such as `list[str]`. This is discussed further below.
164
164
  - A Python type. In that case validation is done by checking membership. By convention the schema `float` matches both ints and floats. Similarly the schema `complex` matches ints and floats besides of course complex numbers.
165
165
  - A callable. Validation is done by applying the callable to the object. If applying the callable throws an exception then the corresponding message will be part of the non-validation message.
166
- - A `list` or a `tuple`. Validation is done by first checking membership of the corresponding types, and then performing validation for each of the entries of the object being validated against the corresponding entries of the schema.
167
- - A dictionary. Validation is done by first checking membership of the `dict` type, and then performing validation for each of the values of the object being validated against the corresponding values of the schema. Keys are themselves considered as schemas. E.g. `{str: str}` represents a dictionary whose keys and values are both strings. A more elaborate discussion of validation of dictionaries is given below.
166
+ - An instance of `Sequence` that is not an instance of `str` (e.g a `list` or a `tuple`). Validation is done by first checking membership of the schema type, and then performing validation for each of the entries of the object being validated against the corresponding entries of the schema.
167
+ - An instance of `Mapping`. Validation is done by first checking membership of the schema type, and then performing validation for each of the values of the object being validated against the corresponding values of the schema. Keys are themselves considered as schemas. E.g. `{str: str}` represents a dictionary whose keys and values are both strings. A more elaborate discussion of validation of dictionaries is given below.
168
168
  - A `set`. A set validates an object if the object is a set and the elements of the object are validated by an element of the schema.
169
169
  - An arbitrary Python object. Validation is done by checking equality of the schema and the object, except when the schema is `float`, in which case `math.isclose` is used. Below we call such an object a `const schema`.
170
170
 
@@ -0,0 +1,9 @@
1
+ vtjson/__init__.py,sha256=oLX4JH6_R7dYtTiGfBG3pQGR21IArspifdmZilbuGOw,68
2
+ vtjson/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ vtjson/vtjson.py,sha256=xq5w9FrmPf6ctjLml2To0nEfd5Okm3ijND44GLWarr0,67357
4
+ vtjson-2.1.5.dist-info/AUTHORS,sha256=qmxaXxaIO-YPNHJAZ0dcCrnPCs1x9ocbtMksiy4i80M,21
5
+ vtjson-2.1.5.dist-info/LICENSE,sha256=n7xW-zX8xBLHzCdqWIMRuMzBD_ACLcNCwio0LEkKt1o,1077
6
+ vtjson-2.1.5.dist-info/METADATA,sha256=eALkzFzpWaZECpnduYIsaT1KSCREWw-fTXjLqCbyrjg,24035
7
+ vtjson-2.1.5.dist-info/WHEEL,sha256=a7TGlA-5DaHMRrarXjVbQagU3Man_dCnGIWMJr5kRWo,91
8
+ vtjson-2.1.5.dist-info/top_level.txt,sha256=9DlSF3l63igcvnYPcj117F2hzOW4Nx0N-JBoW3jjBZM,7
9
+ vtjson-2.1.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,8 +0,0 @@
1
- vtjson/__init__.py,sha256=oLX4JH6_R7dYtTiGfBG3pQGR21IArspifdmZilbuGOw,68
2
- vtjson/vtjson.py,sha256=08SzgFL0RElK6DVp51aps3FoDpO4BL8psUXl9TF-qFY,66284
3
- vtjson-2.1.4.dist-info/AUTHORS,sha256=qmxaXxaIO-YPNHJAZ0dcCrnPCs1x9ocbtMksiy4i80M,21
4
- vtjson-2.1.4.dist-info/LICENSE,sha256=n7xW-zX8xBLHzCdqWIMRuMzBD_ACLcNCwio0LEkKt1o,1077
5
- vtjson-2.1.4.dist-info/METADATA,sha256=eucM4JfjNhSxIqmqNPpk1ia6_JdKyR5xBZHjwtOh-70,23966
6
- vtjson-2.1.4.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
7
- vtjson-2.1.4.dist-info/top_level.txt,sha256=9DlSF3l63igcvnYPcj117F2hzOW4Nx0N-JBoW3jjBZM,7
8
- vtjson-2.1.4.dist-info/RECORD,,