vtjson 2.2.2__py3-none-any.whl → 2.2.4__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/vtjson.py +82 -56
- {vtjson-2.2.2.dist-info → vtjson-2.2.4.dist-info}/METADATA +3 -3
- vtjson-2.2.4.dist-info/RECORD +9 -0
- vtjson-2.2.2.dist-info/RECORD +0 -9
- {vtjson-2.2.2.dist-info → vtjson-2.2.4.dist-info}/AUTHORS +0 -0
- {vtjson-2.2.2.dist-info → vtjson-2.2.4.dist-info}/LICENSE +0 -0
- {vtjson-2.2.2.dist-info → vtjson-2.2.4.dist-info}/WHEEL +0 -0
- {vtjson-2.2.2.dist-info → vtjson-2.2.4.dist-info}/top_level.txt +0 -0
vtjson/vtjson.py
CHANGED
|
@@ -204,7 +204,7 @@ class SchemaError(Exception):
|
|
|
204
204
|
pass
|
|
205
205
|
|
|
206
206
|
|
|
207
|
-
__version__ = "2.2.
|
|
207
|
+
__version__ = "2.2.4"
|
|
208
208
|
|
|
209
209
|
|
|
210
210
|
@dataclass
|
|
@@ -323,7 +323,7 @@ T = TypeVar("T")
|
|
|
323
323
|
|
|
324
324
|
|
|
325
325
|
@overload
|
|
326
|
-
def _canonize_key(key:
|
|
326
|
+
def _canonize_key(key: StringKeyType) -> optional_key[str]: ...
|
|
327
327
|
|
|
328
328
|
|
|
329
329
|
@overload
|
|
@@ -445,6 +445,9 @@ class optional_key(Generic[K]):
|
|
|
445
445
|
return hash(self.key)
|
|
446
446
|
|
|
447
447
|
|
|
448
|
+
StringKeyType = TypeVar("StringKeyType", bound=Union[str, optional_key[str]])
|
|
449
|
+
|
|
450
|
+
|
|
448
451
|
class _union(compiled_schema):
|
|
449
452
|
schemas: list[compiled_schema]
|
|
450
453
|
|
|
@@ -725,29 +728,29 @@ class set_label(wrapper):
|
|
|
725
728
|
)
|
|
726
729
|
|
|
727
730
|
|
|
728
|
-
class
|
|
731
|
+
class _quote(compiled_schema):
|
|
732
|
+
|
|
733
|
+
def __init__(self, schema: object) -> None:
|
|
734
|
+
setattr(self, "__validate__", _const(schema, strict_eq=True).__validate__)
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
class quote(wrapper):
|
|
729
738
|
"""
|
|
730
739
|
An object matches the schema `quote(schema)` if it is equal to `schema`.
|
|
731
740
|
For example the schema `str` matches strings but the schema `quote(str)`
|
|
732
741
|
matches the object `str`.
|
|
733
742
|
"""
|
|
734
743
|
|
|
735
|
-
schema:
|
|
744
|
+
schema: object
|
|
736
745
|
|
|
737
746
|
def __init__(self, schema: object) -> None:
|
|
738
747
|
"""
|
|
739
748
|
:param schema: the schema to be quoted
|
|
740
749
|
"""
|
|
741
|
-
self.schema =
|
|
750
|
+
self.schema = schema
|
|
742
751
|
|
|
743
|
-
def
|
|
744
|
-
self
|
|
745
|
-
obj: object,
|
|
746
|
-
name: str = "object",
|
|
747
|
-
strict: bool = True,
|
|
748
|
-
subs: Mapping[str, object] = {},
|
|
749
|
-
) -> str:
|
|
750
|
-
return self.schema.__validate__(obj, name=name, strict=strict, subs=subs)
|
|
752
|
+
def __compile__(self, _deferred_compiles: _mapping | None = None) -> _quote:
|
|
753
|
+
return _quote(self.schema)
|
|
751
754
|
|
|
752
755
|
|
|
753
756
|
class _set_name(compiled_schema):
|
|
@@ -786,9 +789,8 @@ class _set_name(compiled_schema):
|
|
|
786
789
|
|
|
787
790
|
class set_name(wrapper):
|
|
788
791
|
"""
|
|
789
|
-
An object matches the schema `set_name(schema, name
|
|
790
|
-
|
|
791
|
-
messages.
|
|
792
|
+
An object matches the schema `set_name(schema, name)` if it matches `schema`,
|
|
793
|
+
but the `name` argument will be used in non-validation messages.
|
|
792
794
|
"""
|
|
793
795
|
|
|
794
796
|
reason: bool
|
|
@@ -799,11 +801,15 @@ class set_name(wrapper):
|
|
|
799
801
|
"""
|
|
800
802
|
:param schema: the original schema
|
|
801
803
|
:param name: name for use in non-validation messages
|
|
802
|
-
:param reason:
|
|
803
|
-
|
|
804
|
+
:param reason: if `True` then the original non-validation message
|
|
805
|
+
will not be suppressed
|
|
804
806
|
"""
|
|
805
807
|
if not isinstance(name, str):
|
|
806
808
|
raise SchemaError(f"The name {_c(name)} is not a string")
|
|
809
|
+
if not isinstance(reason, bool):
|
|
810
|
+
raise SchemaError(
|
|
811
|
+
f"The parameter 'reason' (value:{repr(reason)}) is not a boolean"
|
|
812
|
+
)
|
|
807
813
|
self.schema = schema
|
|
808
814
|
self.name = name
|
|
809
815
|
self.reason = reason
|
|
@@ -1493,7 +1499,9 @@ def _compile(
|
|
|
1493
1499
|
origin = object()
|
|
1494
1500
|
|
|
1495
1501
|
ret: compiled_schema
|
|
1496
|
-
if isinstance(schema,
|
|
1502
|
+
if isinstance(schema, compiled_schema):
|
|
1503
|
+
ret = schema
|
|
1504
|
+
elif isinstance(schema, type) and issubclass(schema, compiled_schema):
|
|
1497
1505
|
try:
|
|
1498
1506
|
ret = schema()
|
|
1499
1507
|
except Exception:
|
|
@@ -1504,8 +1512,6 @@ def _compile(
|
|
|
1504
1512
|
ret = _validate_schema(schema)
|
|
1505
1513
|
elif isinstance(schema, wrapper):
|
|
1506
1514
|
ret = schema.__compile__(_deferred_compiles=_deferred_compiles)
|
|
1507
|
-
elif isinstance(schema, compiled_schema):
|
|
1508
|
-
ret = schema
|
|
1509
1515
|
elif supports_TypedDict and typing.is_typeddict(schema):
|
|
1510
1516
|
ret = _compile(
|
|
1511
1517
|
protocol(schema, dict=True), _deferred_compiles=_deferred_compiles
|
|
@@ -2037,7 +2043,7 @@ class one_of(compiled_schema):
|
|
|
2037
2043
|
class keys(compiled_schema):
|
|
2038
2044
|
"""
|
|
2039
2045
|
This represents a dictionary containing all the keys in a collection of
|
|
2040
|
-
keys
|
|
2046
|
+
keys.
|
|
2041
2047
|
"""
|
|
2042
2048
|
|
|
2043
2049
|
args: tuple[object, ...]
|
|
@@ -2199,12 +2205,13 @@ class _fields(compiled_schema):
|
|
|
2199
2205
|
|
|
2200
2206
|
def __init__(
|
|
2201
2207
|
self,
|
|
2202
|
-
d: Mapping[
|
|
2208
|
+
d: Mapping[StringKeyType, object],
|
|
2203
2209
|
_deferred_compiles: _mapping | None = None,
|
|
2204
2210
|
) -> None:
|
|
2205
2211
|
self.d = {}
|
|
2206
2212
|
for k, v in d.items():
|
|
2207
|
-
|
|
2213
|
+
key_ = _canonize_key(k)
|
|
2214
|
+
self.d[key_] = _compile(v, _deferred_compiles=_deferred_compiles)
|
|
2208
2215
|
|
|
2209
2216
|
def __validate__(
|
|
2210
2217
|
self,
|
|
@@ -2234,23 +2241,22 @@ class _fields(compiled_schema):
|
|
|
2234
2241
|
return ""
|
|
2235
2242
|
|
|
2236
2243
|
|
|
2237
|
-
class fields(wrapper):
|
|
2244
|
+
class fields(wrapper, Generic[StringKeyType]):
|
|
2238
2245
|
"""
|
|
2239
2246
|
Matches Python objects with attributes `field1, field2, ..., fieldN` whose
|
|
2240
2247
|
corresponding values should validate against `schema1, schema2, ...,
|
|
2241
|
-
schemaN` respectively
|
|
2248
|
+
schemaN` respectively.
|
|
2242
2249
|
"""
|
|
2243
2250
|
|
|
2244
|
-
d:
|
|
2251
|
+
d: Mapping[StringKeyType, object]
|
|
2245
2252
|
|
|
2246
|
-
def __init__(self, d: Mapping[
|
|
2253
|
+
def __init__(self, d: Mapping[StringKeyType, object]) -> None:
|
|
2247
2254
|
"""
|
|
2248
2255
|
:param d: a dictionary associating fields with schemas
|
|
2249
2256
|
|
|
2250
2257
|
:raises SchemaError: exception thrown when the schema definition is
|
|
2251
2258
|
found to contain an error
|
|
2252
2259
|
"""
|
|
2253
|
-
self.d = {}
|
|
2254
2260
|
if not isinstance(d, Mapping):
|
|
2255
2261
|
raise SchemaError(f"{repr(d)} is not a Mapping")
|
|
2256
2262
|
for k, v in d.items():
|
|
@@ -2259,8 +2265,7 @@ class fields(wrapper):
|
|
|
2259
2265
|
f"key {repr(k)} in {repr(d)} is not an instance of"
|
|
2260
2266
|
" optional_key and not a string"
|
|
2261
2267
|
)
|
|
2262
|
-
|
|
2263
|
-
self.d[key_] = v
|
|
2268
|
+
self.d = d
|
|
2264
2269
|
|
|
2265
2270
|
def __compile__(self, _deferred_compiles: _mapping | None = None) -> _fields:
|
|
2266
2271
|
return _fields(self.d, _deferred_compiles=_deferred_compiles)
|
|
@@ -2682,6 +2687,48 @@ class _set(compiled_schema):
|
|
|
2682
2687
|
return str(self.schema_)
|
|
2683
2688
|
|
|
2684
2689
|
|
|
2690
|
+
class _protocol(compiled_schema):
|
|
2691
|
+
|
|
2692
|
+
def __init__(
|
|
2693
|
+
self,
|
|
2694
|
+
schema: object,
|
|
2695
|
+
dict: bool = False,
|
|
2696
|
+
_deferred_compiles: _mapping | None = None,
|
|
2697
|
+
) -> None:
|
|
2698
|
+
type_hints = _get_type_hints(schema)
|
|
2699
|
+
total = True
|
|
2700
|
+
if hasattr(schema, "__total__") and isinstance(schema.__total__, bool):
|
|
2701
|
+
total = schema.__total__
|
|
2702
|
+
type_dict = _to_dict(type_hints, total=total)
|
|
2703
|
+
if hasattr(schema, "__name__") and isinstance(schema.__name__, str):
|
|
2704
|
+
name = schema.__name__
|
|
2705
|
+
else:
|
|
2706
|
+
name = "schema"
|
|
2707
|
+
|
|
2708
|
+
if not dict:
|
|
2709
|
+
setattr(
|
|
2710
|
+
self,
|
|
2711
|
+
"__validate__",
|
|
2712
|
+
_set_name(
|
|
2713
|
+
fields(type_dict),
|
|
2714
|
+
name,
|
|
2715
|
+
reason=True,
|
|
2716
|
+
_deferred_compiles=_deferred_compiles,
|
|
2717
|
+
).__validate__,
|
|
2718
|
+
)
|
|
2719
|
+
else:
|
|
2720
|
+
setattr(
|
|
2721
|
+
self,
|
|
2722
|
+
"__validate__",
|
|
2723
|
+
_set_name(
|
|
2724
|
+
type_dict,
|
|
2725
|
+
name,
|
|
2726
|
+
reason=True,
|
|
2727
|
+
_deferred_compiles=_deferred_compiles,
|
|
2728
|
+
).__validate__,
|
|
2729
|
+
)
|
|
2730
|
+
|
|
2731
|
+
|
|
2685
2732
|
class protocol(wrapper):
|
|
2686
2733
|
"""
|
|
2687
2734
|
An object matches the schema `protocol(schema, dict=False)` if `schema` is
|
|
@@ -2689,9 +2736,8 @@ class protocol(wrapper):
|
|
|
2689
2736
|
which validate the corresponding fields in the object.
|
|
2690
2737
|
"""
|
|
2691
2738
|
|
|
2692
|
-
|
|
2739
|
+
schema: object
|
|
2693
2740
|
dict: bool
|
|
2694
|
-
__name__: str
|
|
2695
2741
|
|
|
2696
2742
|
def __init__(self, schema: object, dict: bool = False):
|
|
2697
2743
|
"""
|
|
@@ -2704,34 +2750,14 @@ class protocol(wrapper):
|
|
|
2704
2750
|
"""
|
|
2705
2751
|
if not isinstance(dict, bool):
|
|
2706
2752
|
raise SchemaError("bool flag is not a bool")
|
|
2707
|
-
|
|
2753
|
+
|
|
2708
2754
|
self.dict = dict
|
|
2709
|
-
|
|
2710
|
-
if hasattr(schema, "__total__") and isinstance(schema.__total__, bool):
|
|
2711
|
-
total = schema.__total__
|
|
2712
|
-
self.type_dict = _to_dict(type_hints, total=total)
|
|
2713
|
-
if hasattr(schema, "__name__") and isinstance(schema.__name__, str):
|
|
2714
|
-
self.__name__ = schema.__name__
|
|
2715
|
-
else:
|
|
2716
|
-
self.__name__ = "schema"
|
|
2755
|
+
self.schema = schema
|
|
2717
2756
|
|
|
2718
2757
|
def __compile__(
|
|
2719
2758
|
self, _deferred_compiles: _mapping | None = None
|
|
2720
2759
|
) -> compiled_schema:
|
|
2721
|
-
|
|
2722
|
-
return _set_name(
|
|
2723
|
-
_fields(self.type_dict),
|
|
2724
|
-
self.__name__,
|
|
2725
|
-
reason=True,
|
|
2726
|
-
_deferred_compiles=_deferred_compiles,
|
|
2727
|
-
)
|
|
2728
|
-
else:
|
|
2729
|
-
return _set_name(
|
|
2730
|
-
dict(self.type_dict),
|
|
2731
|
-
self.__name__,
|
|
2732
|
-
reason=True,
|
|
2733
|
-
_deferred_compiles=_deferred_compiles,
|
|
2734
|
-
)
|
|
2760
|
+
return _protocol(self.schema, self.dict)
|
|
2735
2761
|
|
|
2736
2762
|
|
|
2737
2763
|
class _Literal(compiled_schema):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: vtjson
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.4
|
|
4
4
|
Summary: An easy to use validation library compatible with Python type annotations
|
|
5
5
|
Author-email: Michel Van den Bergh <michel.vandenbergh@uhasselt.be>
|
|
6
6
|
Project-URL: Homepage, https://github.com/vdbergh/vtjson
|
|
@@ -78,7 +78,7 @@ class book_schema(TypedDict):
|
|
|
78
78
|
year: int
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
Attempting to validate the bad book would raise
|
|
81
|
+
Attempting to validate the bad book would raise a similar exception as before.
|
|
82
82
|
|
|
83
83
|
Schemas can of course be more complicated and in particular they can be nested.
|
|
84
84
|
Here is an example that shows more of the features of `vtjson`.
|
|
@@ -126,7 +126,7 @@ class person_schema(TypedDict):
|
|
|
126
126
|
class book_schema(TypedDict):
|
|
127
127
|
title: str
|
|
128
128
|
authors: list[person_schema]
|
|
129
|
-
editor: NotRequired[
|
|
129
|
+
editor: NotRequired[person_schema]
|
|
130
130
|
year: Annotated[int, ge(1900)]
|
|
131
131
|
```
|
|
132
132
|
|
|
@@ -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=-9xIldrpAY6Pf2PDtP9C5d81qb_9cRe4caxZ_Mk9Lj8,86872
|
|
4
|
+
vtjson-2.2.4.dist-info/AUTHORS,sha256=qmxaXxaIO-YPNHJAZ0dcCrnPCs1x9ocbtMksiy4i80M,21
|
|
5
|
+
vtjson-2.2.4.dist-info/LICENSE,sha256=n7xW-zX8xBLHzCdqWIMRuMzBD_ACLcNCwio0LEkKt1o,1077
|
|
6
|
+
vtjson-2.2.4.dist-info/METADATA,sha256=6xmw9KzIW_gMfBAcRJXJlGDfIjv1UxhPJBgmDxCX5Z4,3958
|
|
7
|
+
vtjson-2.2.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
8
|
+
vtjson-2.2.4.dist-info/top_level.txt,sha256=9DlSF3l63igcvnYPcj117F2hzOW4Nx0N-JBoW3jjBZM,7
|
|
9
|
+
vtjson-2.2.4.dist-info/RECORD,,
|
vtjson-2.2.2.dist-info/RECORD
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
vtjson/__init__.py,sha256=oLX4JH6_R7dYtTiGfBG3pQGR21IArspifdmZilbuGOw,68
|
|
2
|
-
vtjson/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
vtjson/vtjson.py,sha256=_NcOEWxuqZiVJQSn0ZoI9eGxL5GsbtacWIb-BwTPzTY,86274
|
|
4
|
-
vtjson-2.2.2.dist-info/AUTHORS,sha256=qmxaXxaIO-YPNHJAZ0dcCrnPCs1x9ocbtMksiy4i80M,21
|
|
5
|
-
vtjson-2.2.2.dist-info/LICENSE,sha256=n7xW-zX8xBLHzCdqWIMRuMzBD_ACLcNCwio0LEkKt1o,1077
|
|
6
|
-
vtjson-2.2.2.dist-info/METADATA,sha256=reeTR8tvW1KdngstUC6dTdOas_8NXHqdRroKLH_eUfU,3963
|
|
7
|
-
vtjson-2.2.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
8
|
-
vtjson-2.2.2.dist-info/top_level.txt,sha256=9DlSF3l63igcvnYPcj117F2hzOW4Nx0N-JBoW3jjBZM,7
|
|
9
|
-
vtjson-2.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|