vtjson 2.2.6__py3-none-any.whl → 2.2.8__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 +267 -77
- {vtjson-2.2.6.dist-info → vtjson-2.2.8.dist-info}/METADATA +1 -1
- vtjson-2.2.8.dist-info/RECORD +9 -0
- {vtjson-2.2.6.dist-info → vtjson-2.2.8.dist-info}/WHEEL +1 -1
- vtjson-2.2.6.dist-info/RECORD +0 -9
- {vtjson-2.2.6.dist-info → vtjson-2.2.8.dist-info}/licenses/AUTHORS +0 -0
- {vtjson-2.2.6.dist-info → vtjson-2.2.8.dist-info}/licenses/LICENSE +0 -0
- {vtjson-2.2.6.dist-info → vtjson-2.2.8.dist-info}/top_level.txt +0 -0
vtjson/vtjson.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import datetime
|
|
4
|
+
import functools
|
|
5
|
+
import inspect
|
|
4
6
|
import ipaddress
|
|
5
7
|
import math
|
|
6
8
|
import pathlib
|
|
@@ -10,7 +12,7 @@ import types
|
|
|
10
12
|
import typing
|
|
11
13
|
import urllib.parse
|
|
12
14
|
import warnings
|
|
13
|
-
from collections.abc import Sequence, Set, Sized
|
|
15
|
+
from collections.abc import Iterable, Sequence, Set, Sized
|
|
14
16
|
from dataclasses import dataclass
|
|
15
17
|
from typing import (
|
|
16
18
|
Any,
|
|
@@ -204,7 +206,7 @@ class SchemaError(Exception):
|
|
|
204
206
|
pass
|
|
205
207
|
|
|
206
208
|
|
|
207
|
-
__version__ = "2.2.
|
|
209
|
+
__version__ = "2.2.8"
|
|
208
210
|
|
|
209
211
|
|
|
210
212
|
@dataclass
|
|
@@ -248,14 +250,79 @@ skip_first = Apply(skip_first=True)
|
|
|
248
250
|
_dns_resolver: dns.resolver.Resolver | None = None
|
|
249
251
|
|
|
250
252
|
|
|
251
|
-
def
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
def _to_name(s: object) -> str:
|
|
254
|
+
if hasattr(s, "__name__"):
|
|
255
|
+
return str(s.__name__)
|
|
256
|
+
else:
|
|
257
|
+
if isinstance(s, str):
|
|
258
|
+
return repr(s)
|
|
259
|
+
elif s == Ellipsis:
|
|
260
|
+
return "..."
|
|
255
261
|
else:
|
|
256
|
-
return str(
|
|
262
|
+
return str(s)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _generic_name(origin: type, args: tuple[object, ...]) -> str:
|
|
266
|
+
return _to_name(origin) + "[" + ",".join([_to_name(arg) for arg in args]) + "]"
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _make_name(
|
|
270
|
+
type: type,
|
|
271
|
+
args: tuple[object, ...],
|
|
272
|
+
kw: dict[str, object],
|
|
273
|
+
defaults: dict[str, object] = {},
|
|
274
|
+
) -> str:
|
|
275
|
+
arg_list = []
|
|
276
|
+
for a in args:
|
|
277
|
+
arg_list.append(_to_name(a))
|
|
278
|
+
for k, v in kw.items():
|
|
279
|
+
if k not in defaults or v != defaults[k]:
|
|
280
|
+
arg_list.append(f"{k}={_to_name(v)}")
|
|
281
|
+
if len(arg_list) == 0:
|
|
282
|
+
return _to_name(type)
|
|
283
|
+
else:
|
|
284
|
+
return f"{_to_name(type)}({','.join(arg_list)})"
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
C = TypeVar("C")
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _set__name__(c: type[C]) -> type[C]:
|
|
291
|
+
defaults = {}
|
|
292
|
+
a = inspect.getfullargspec(c.__init__)
|
|
293
|
+
a_defaults: tuple[object, ...] = ()
|
|
294
|
+
if a.defaults is not None:
|
|
295
|
+
a_defaults = a.defaults
|
|
296
|
+
|
|
297
|
+
if a is None or a.args is None:
|
|
298
|
+
raise Exception(f"Could not get signature of {c.__name__}")
|
|
299
|
+
start = len(a.args) - len(a_defaults)
|
|
300
|
+
for i in range(start, len(a.args)):
|
|
301
|
+
defaults[a.args[i]] = a_defaults[i - start]
|
|
302
|
+
__init__org = c.__init__
|
|
303
|
+
|
|
304
|
+
@functools.wraps(c.__init__)
|
|
305
|
+
def __init__wrapper(self: C, *args: object, **kw: object) -> None:
|
|
306
|
+
setattr(
|
|
307
|
+
self, "__name__", _make_name(self.__class__, args, kw, defaults=defaults)
|
|
308
|
+
)
|
|
309
|
+
return __init__org(self, *args, **kw)
|
|
310
|
+
|
|
311
|
+
@functools.wraps(c.__str__)
|
|
312
|
+
def __str__(self: C) -> str:
|
|
313
|
+
assert hasattr(self, "__name__")
|
|
314
|
+
return str(self.__name__)
|
|
315
|
+
|
|
316
|
+
@functools.wraps(c.__repr__)
|
|
317
|
+
def __repr__(self: C) -> str:
|
|
318
|
+
assert hasattr(self, "__name__")
|
|
319
|
+
return str(self.__name__)
|
|
257
320
|
|
|
258
|
-
|
|
321
|
+
setattr(c, "__init__", __init__wrapper)
|
|
322
|
+
setattr(c, "__str__", __str__)
|
|
323
|
+
setattr(c, "__repr__", __repr__)
|
|
324
|
+
|
|
325
|
+
return c
|
|
259
326
|
|
|
260
327
|
|
|
261
328
|
def _get_type_hints(schema: object) -> dict[str, object]:
|
|
@@ -414,6 +481,7 @@ def make_type(
|
|
|
414
481
|
K = TypeVar("K")
|
|
415
482
|
|
|
416
483
|
|
|
484
|
+
@_set__name__
|
|
417
485
|
class optional_key(Generic[K]):
|
|
418
486
|
"""
|
|
419
487
|
Make a key in a Mapping schema optional. In the common case that the key
|
|
@@ -424,6 +492,7 @@ class optional_key(Generic[K]):
|
|
|
424
492
|
|
|
425
493
|
key: K
|
|
426
494
|
optional: bool
|
|
495
|
+
__name__: str
|
|
427
496
|
|
|
428
497
|
def __init__(self, key: K, _optional: bool = True) -> None:
|
|
429
498
|
"""
|
|
@@ -445,6 +514,13 @@ class optional_key(Generic[K]):
|
|
|
445
514
|
return hash(self.key)
|
|
446
515
|
|
|
447
516
|
|
|
517
|
+
# def __str__(self) -> str:
|
|
518
|
+
# return self.__name__
|
|
519
|
+
#
|
|
520
|
+
# def __repr__(self) -> str:
|
|
521
|
+
# return self.__name__
|
|
522
|
+
|
|
523
|
+
|
|
448
524
|
StringKeyType = TypeVar("StringKeyType", bound=Union[str, optional_key[str]])
|
|
449
525
|
|
|
450
526
|
|
|
@@ -467,6 +543,8 @@ class _union(compiled_schema):
|
|
|
467
543
|
strict: bool = True,
|
|
468
544
|
subs: Mapping[str, object] = {},
|
|
469
545
|
) -> str:
|
|
546
|
+
if len(self.schemas) == 0:
|
|
547
|
+
return _wrong_type_message(obj, name, "union()")
|
|
470
548
|
messages = []
|
|
471
549
|
for schema in self.schemas:
|
|
472
550
|
message = schema.__validate__(obj, name=name, strict=strict, subs=subs)
|
|
@@ -823,6 +901,7 @@ class set_name(wrapper):
|
|
|
823
901
|
)
|
|
824
902
|
|
|
825
903
|
|
|
904
|
+
@_set__name__
|
|
826
905
|
class regex(compiled_schema):
|
|
827
906
|
"""
|
|
828
907
|
This matches the strings which match the given pattern.
|
|
@@ -857,10 +936,6 @@ class regex(compiled_schema):
|
|
|
857
936
|
if not isinstance(name, str):
|
|
858
937
|
raise SchemaError(f"The regex name {_c(name)} is not a string")
|
|
859
938
|
self.__name__ = name
|
|
860
|
-
else:
|
|
861
|
-
_flags = "" if flags == 0 else f", flags={flags}"
|
|
862
|
-
_fullmatch = "" if fullmatch else ", fullmatch=False"
|
|
863
|
-
self.__name__ = f"regex({repr(regex)}{_fullmatch}{_flags})"
|
|
864
939
|
|
|
865
940
|
try:
|
|
866
941
|
self.pattern = re.compile(regex, flags)
|
|
@@ -878,7 +953,9 @@ class regex(compiled_schema):
|
|
|
878
953
|
subs: Mapping[str, object] = {},
|
|
879
954
|
) -> str:
|
|
880
955
|
if not isinstance(obj, str):
|
|
881
|
-
return _wrong_type_message(
|
|
956
|
+
return _wrong_type_message(
|
|
957
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
958
|
+
)
|
|
882
959
|
try:
|
|
883
960
|
if self.fullmatch and self.pattern.fullmatch(obj):
|
|
884
961
|
return ""
|
|
@@ -889,6 +966,7 @@ class regex(compiled_schema):
|
|
|
889
966
|
return _wrong_type_message(obj, name, self.__name__)
|
|
890
967
|
|
|
891
968
|
|
|
969
|
+
@_set__name__
|
|
892
970
|
class glob(compiled_schema):
|
|
893
971
|
"""
|
|
894
972
|
Unix style filename matching. This is implemented using
|
|
@@ -910,9 +988,7 @@ class glob(compiled_schema):
|
|
|
910
988
|
|
|
911
989
|
self.pattern = pattern
|
|
912
990
|
|
|
913
|
-
if name is None:
|
|
914
|
-
self.__name__ = f"glob({repr(pattern)})"
|
|
915
|
-
else:
|
|
991
|
+
if name is not None:
|
|
916
992
|
self.__name__ = name
|
|
917
993
|
|
|
918
994
|
try:
|
|
@@ -931,7 +1007,9 @@ class glob(compiled_schema):
|
|
|
931
1007
|
subs: Mapping[str, object] = {},
|
|
932
1008
|
) -> str:
|
|
933
1009
|
if not isinstance(obj, str):
|
|
934
|
-
return _wrong_type_message(
|
|
1010
|
+
return _wrong_type_message(
|
|
1011
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
1012
|
+
)
|
|
935
1013
|
try:
|
|
936
1014
|
if pathlib.PurePath(obj).match(self.pattern):
|
|
937
1015
|
return ""
|
|
@@ -941,6 +1019,7 @@ class glob(compiled_schema):
|
|
|
941
1019
|
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
942
1020
|
|
|
943
1021
|
|
|
1022
|
+
@_set__name__
|
|
944
1023
|
class magic(compiled_schema):
|
|
945
1024
|
"""
|
|
946
1025
|
Checks if a buffer (for example a string or a byte array) has the given
|
|
@@ -966,9 +1045,7 @@ class magic(compiled_schema):
|
|
|
966
1045
|
|
|
967
1046
|
self.mime_type = mime_type
|
|
968
1047
|
|
|
969
|
-
if name is None:
|
|
970
|
-
self.__name__ = f"magic({repr(mime_type)})"
|
|
971
|
-
else:
|
|
1048
|
+
if name is not None:
|
|
972
1049
|
self.__name__ = name
|
|
973
1050
|
|
|
974
1051
|
def __validate__(
|
|
@@ -979,7 +1056,12 @@ class magic(compiled_schema):
|
|
|
979
1056
|
subs: Mapping[str, object] = {},
|
|
980
1057
|
) -> str:
|
|
981
1058
|
if not isinstance(obj, (str, bytes)):
|
|
982
|
-
return _wrong_type_message(
|
|
1059
|
+
return _wrong_type_message(
|
|
1060
|
+
obj,
|
|
1061
|
+
name,
|
|
1062
|
+
self.__name__,
|
|
1063
|
+
explanation=f"{_c(obj)} is not a string nor bytes",
|
|
1064
|
+
)
|
|
983
1065
|
try:
|
|
984
1066
|
objmime_type = magic_.from_buffer(obj, mime=True)
|
|
985
1067
|
except Exception as e:
|
|
@@ -994,6 +1076,7 @@ class magic(compiled_schema):
|
|
|
994
1076
|
return ""
|
|
995
1077
|
|
|
996
1078
|
|
|
1079
|
+
@_set__name__
|
|
997
1080
|
class div(compiled_schema):
|
|
998
1081
|
"""
|
|
999
1082
|
This matches the integers `x` such that `(x - remainder) % divisor` == 0.
|
|
@@ -1024,13 +1107,7 @@ class div(compiled_schema):
|
|
|
1024
1107
|
self.divisor = divisor
|
|
1025
1108
|
self.remainder = remainder
|
|
1026
1109
|
|
|
1027
|
-
if name is None:
|
|
1028
|
-
_divisor = str(divisor)
|
|
1029
|
-
_remainder = ""
|
|
1030
|
-
if remainder != 0:
|
|
1031
|
-
_remainder = "," + str(remainder)
|
|
1032
|
-
self.__name__ = f"div({_divisor+_remainder})"
|
|
1033
|
-
else:
|
|
1110
|
+
if name is not None:
|
|
1034
1111
|
self.__name__ = name
|
|
1035
1112
|
|
|
1036
1113
|
def __validate__(
|
|
@@ -1041,13 +1118,16 @@ class div(compiled_schema):
|
|
|
1041
1118
|
subs: Mapping[str, object] = {},
|
|
1042
1119
|
) -> str:
|
|
1043
1120
|
if not isinstance(obj, int):
|
|
1044
|
-
return _wrong_type_message(
|
|
1121
|
+
return _wrong_type_message(
|
|
1122
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not an integer"
|
|
1123
|
+
)
|
|
1045
1124
|
elif (obj - self.remainder) % self.divisor == 0:
|
|
1046
1125
|
return ""
|
|
1047
1126
|
else:
|
|
1048
1127
|
return _wrong_type_message(obj, name, self.__name__)
|
|
1049
1128
|
|
|
1050
1129
|
|
|
1130
|
+
@_set__name__
|
|
1051
1131
|
class close_to(compiled_schema):
|
|
1052
1132
|
"""
|
|
1053
1133
|
This matches the real numbers that are close to `x` in the sense of
|
|
@@ -1087,9 +1167,6 @@ class close_to(compiled_schema):
|
|
|
1087
1167
|
)
|
|
1088
1168
|
self.kw["abs_tol"] = abs_tol
|
|
1089
1169
|
|
|
1090
|
-
kwl = [str(x)] + [f"{k}={v}" for (k, v) in self.kw.items()]
|
|
1091
|
-
kwl_ = ",".join(kwl)
|
|
1092
|
-
self.__name__ = f"close_to({kwl_})"
|
|
1093
1170
|
self.x = x
|
|
1094
1171
|
|
|
1095
1172
|
def __validate__(
|
|
@@ -1100,19 +1177,23 @@ class close_to(compiled_schema):
|
|
|
1100
1177
|
subs: Mapping[str, object] = {},
|
|
1101
1178
|
) -> str:
|
|
1102
1179
|
if not isinstance(obj, (float, int)):
|
|
1103
|
-
return _wrong_type_message(
|
|
1180
|
+
return _wrong_type_message(
|
|
1181
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not an integer"
|
|
1182
|
+
)
|
|
1104
1183
|
elif math.isclose(obj, self.x, **self.kw):
|
|
1105
1184
|
return ""
|
|
1106
1185
|
else:
|
|
1107
1186
|
return _wrong_type_message(obj, name, self.__name__)
|
|
1108
1187
|
|
|
1109
1188
|
|
|
1189
|
+
@_set__name__
|
|
1110
1190
|
class gt(compiled_schema):
|
|
1111
1191
|
"""
|
|
1112
1192
|
This checks if `object > lb`.
|
|
1113
1193
|
"""
|
|
1114
1194
|
|
|
1115
1195
|
lb: comparable
|
|
1196
|
+
__name__: str
|
|
1116
1197
|
|
|
1117
1198
|
def __init__(self, lb: comparable) -> None:
|
|
1118
1199
|
"""
|
|
@@ -1148,12 +1229,14 @@ class gt(compiled_schema):
|
|
|
1148
1229
|
return f"{self.message(name, obj)}: {str(e)}"
|
|
1149
1230
|
|
|
1150
1231
|
|
|
1232
|
+
@_set__name__
|
|
1151
1233
|
class ge(compiled_schema):
|
|
1152
1234
|
"""
|
|
1153
1235
|
This checks if `object >= lb`.
|
|
1154
1236
|
"""
|
|
1155
1237
|
|
|
1156
1238
|
lb: comparable
|
|
1239
|
+
__name__: str
|
|
1157
1240
|
|
|
1158
1241
|
def __init__(self, lb: comparable) -> None:
|
|
1159
1242
|
"""
|
|
@@ -1189,12 +1272,14 @@ class ge(compiled_schema):
|
|
|
1189
1272
|
return f"{self.message(name, obj)}: {str(e)}"
|
|
1190
1273
|
|
|
1191
1274
|
|
|
1275
|
+
@_set__name__
|
|
1192
1276
|
class lt(compiled_schema):
|
|
1193
1277
|
"""
|
|
1194
1278
|
This checks if `object < ub`.
|
|
1195
1279
|
"""
|
|
1196
1280
|
|
|
1197
1281
|
ub: comparable
|
|
1282
|
+
__name__: str
|
|
1198
1283
|
|
|
1199
1284
|
def __init__(self, ub: comparable) -> None:
|
|
1200
1285
|
"""
|
|
@@ -1230,12 +1315,14 @@ class lt(compiled_schema):
|
|
|
1230
1315
|
return f"{self.message(name, obj)}: {str(e)}"
|
|
1231
1316
|
|
|
1232
1317
|
|
|
1318
|
+
@_set__name__
|
|
1233
1319
|
class le(compiled_schema):
|
|
1234
1320
|
"""
|
|
1235
1321
|
This checks if `object <= ub`.
|
|
1236
1322
|
"""
|
|
1237
1323
|
|
|
1238
1324
|
ub: comparable
|
|
1325
|
+
__name__: str
|
|
1239
1326
|
|
|
1240
1327
|
def __init__(self, ub: comparable) -> None:
|
|
1241
1328
|
"""
|
|
@@ -1271,6 +1358,7 @@ class le(compiled_schema):
|
|
|
1271
1358
|
return f"{self.message(name, obj)}: {str(e)}"
|
|
1272
1359
|
|
|
1273
1360
|
|
|
1361
|
+
@_set__name__
|
|
1274
1362
|
class interval(compiled_schema):
|
|
1275
1363
|
"""
|
|
1276
1364
|
This checks if `lb <= object <= ub`, provided the comparisons make sense.
|
|
@@ -1278,6 +1366,7 @@ class interval(compiled_schema):
|
|
|
1278
1366
|
|
|
1279
1367
|
lb_s: str
|
|
1280
1368
|
ub_s: str
|
|
1369
|
+
__name__: str
|
|
1281
1370
|
|
|
1282
1371
|
def __init__(
|
|
1283
1372
|
self,
|
|
@@ -1346,6 +1435,7 @@ class interval(compiled_schema):
|
|
|
1346
1435
|
setattr(self, "__validate__", anything().__validate__)
|
|
1347
1436
|
|
|
1348
1437
|
|
|
1438
|
+
@_set__name__
|
|
1349
1439
|
class size(compiled_schema):
|
|
1350
1440
|
"""
|
|
1351
1441
|
Matches the objects (which support `len()` such as strings or lists) whose
|
|
@@ -1353,6 +1443,7 @@ class size(compiled_schema):
|
|
|
1353
1443
|
"""
|
|
1354
1444
|
|
|
1355
1445
|
interval_: interval
|
|
1446
|
+
__name__: str
|
|
1356
1447
|
|
|
1357
1448
|
def __init__(self, lb: int, ub: int | types.EllipsisType | None = None) -> None:
|
|
1358
1449
|
"""
|
|
@@ -1625,11 +1716,14 @@ def validate(
|
|
|
1625
1716
|
# Some predefined schemas
|
|
1626
1717
|
|
|
1627
1718
|
|
|
1719
|
+
@_set__name__
|
|
1628
1720
|
class number(compiled_schema):
|
|
1629
1721
|
"""
|
|
1630
1722
|
A deprecated alias for `float`.
|
|
1631
1723
|
"""
|
|
1632
1724
|
|
|
1725
|
+
__name__: str
|
|
1726
|
+
|
|
1633
1727
|
def __init__(self) -> None:
|
|
1634
1728
|
warnings.warn(
|
|
1635
1729
|
"The schema 'number' is deprecated. Use 'float' instead.",
|
|
@@ -1646,14 +1740,20 @@ class number(compiled_schema):
|
|
|
1646
1740
|
if isinstance(obj, (int, float)):
|
|
1647
1741
|
return ""
|
|
1648
1742
|
else:
|
|
1649
|
-
return _wrong_type_message(obj, name,
|
|
1743
|
+
return _wrong_type_message(obj, name, self.__name__)
|
|
1650
1744
|
|
|
1651
1745
|
|
|
1746
|
+
@_set__name__
|
|
1652
1747
|
class float_(compiled_schema):
|
|
1653
1748
|
"""
|
|
1654
1749
|
Schema that only matches floats. Not ints.
|
|
1655
1750
|
"""
|
|
1656
1751
|
|
|
1752
|
+
__name__: str
|
|
1753
|
+
|
|
1754
|
+
def __init__(self) -> None:
|
|
1755
|
+
pass
|
|
1756
|
+
|
|
1657
1757
|
def __validate__(
|
|
1658
1758
|
self,
|
|
1659
1759
|
obj: object,
|
|
@@ -1664,9 +1764,10 @@ class float_(compiled_schema):
|
|
|
1664
1764
|
if isinstance(obj, float):
|
|
1665
1765
|
return ""
|
|
1666
1766
|
else:
|
|
1667
|
-
return _wrong_type_message(obj, name,
|
|
1767
|
+
return _wrong_type_message(obj, name, self.__name__)
|
|
1668
1768
|
|
|
1669
1769
|
|
|
1770
|
+
@_set__name__
|
|
1670
1771
|
class email(compiled_schema):
|
|
1671
1772
|
"""
|
|
1672
1773
|
Checks if the object is a valid email address. This uses the package
|
|
@@ -1675,6 +1776,7 @@ class email(compiled_schema):
|
|
|
1675
1776
|
"""
|
|
1676
1777
|
|
|
1677
1778
|
kw: dict[str, Any]
|
|
1779
|
+
__name__: str
|
|
1678
1780
|
|
|
1679
1781
|
def __init__(self, **kw: Any) -> None:
|
|
1680
1782
|
"""
|
|
@@ -1695,14 +1797,17 @@ class email(compiled_schema):
|
|
|
1695
1797
|
subs: Mapping[str, object] = {},
|
|
1696
1798
|
) -> str:
|
|
1697
1799
|
if not isinstance(obj, str):
|
|
1698
|
-
return _wrong_type_message(
|
|
1800
|
+
return _wrong_type_message(
|
|
1801
|
+
obj, name, self.__name__, f"{_c(obj)} is not a string"
|
|
1802
|
+
)
|
|
1699
1803
|
try:
|
|
1700
1804
|
email_validator.validate_email(obj, **self.kw)
|
|
1701
1805
|
return ""
|
|
1702
1806
|
except Exception as e:
|
|
1703
|
-
return _wrong_type_message(obj, name,
|
|
1807
|
+
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
1704
1808
|
|
|
1705
1809
|
|
|
1810
|
+
@_set__name__
|
|
1706
1811
|
class ip_address(compiled_schema):
|
|
1707
1812
|
"""
|
|
1708
1813
|
Matches ip addresses of the specified version which can be 4, 6 or None.
|
|
@@ -1719,10 +1824,7 @@ class ip_address(compiled_schema):
|
|
|
1719
1824
|
"""
|
|
1720
1825
|
if version is not None and version not in (4, 6):
|
|
1721
1826
|
raise SchemaError("version is not 4 or 6")
|
|
1722
|
-
|
|
1723
|
-
self.__name__ = "ip_address"
|
|
1724
|
-
else:
|
|
1725
|
-
self.__name__ = f"ip_address(version={version})"
|
|
1827
|
+
|
|
1726
1828
|
if version == 4:
|
|
1727
1829
|
self.method = ipaddress.IPv4Address
|
|
1728
1830
|
elif version == 6:
|
|
@@ -1738,7 +1840,12 @@ class ip_address(compiled_schema):
|
|
|
1738
1840
|
subs: Mapping[str, object] = {},
|
|
1739
1841
|
) -> str:
|
|
1740
1842
|
if not isinstance(obj, (int, str, bytes)):
|
|
1741
|
-
return _wrong_type_message(
|
|
1843
|
+
return _wrong_type_message(
|
|
1844
|
+
obj,
|
|
1845
|
+
name,
|
|
1846
|
+
self.__name__,
|
|
1847
|
+
explanation=f"{_c(obj)} is not a string, an int or bytes",
|
|
1848
|
+
)
|
|
1742
1849
|
try:
|
|
1743
1850
|
self.method(obj)
|
|
1744
1851
|
except ValueError as e:
|
|
@@ -1746,6 +1853,7 @@ class ip_address(compiled_schema):
|
|
|
1746
1853
|
return ""
|
|
1747
1854
|
|
|
1748
1855
|
|
|
1856
|
+
@_set__name__
|
|
1749
1857
|
class regex_pattern(compiled_schema):
|
|
1750
1858
|
"""
|
|
1751
1859
|
Matches valid regular expression patterns
|
|
@@ -1754,7 +1862,7 @@ class regex_pattern(compiled_schema):
|
|
|
1754
1862
|
__name__: str
|
|
1755
1863
|
|
|
1756
1864
|
def __init__(self) -> None:
|
|
1757
|
-
|
|
1865
|
+
pass
|
|
1758
1866
|
|
|
1759
1867
|
def __validate__(
|
|
1760
1868
|
self,
|
|
@@ -1764,7 +1872,9 @@ class regex_pattern(compiled_schema):
|
|
|
1764
1872
|
subs: Mapping[str, object] = {},
|
|
1765
1873
|
) -> str:
|
|
1766
1874
|
if not isinstance(obj, str):
|
|
1767
|
-
return _wrong_type_message(
|
|
1875
|
+
return _wrong_type_message(
|
|
1876
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
1877
|
+
)
|
|
1768
1878
|
try:
|
|
1769
1879
|
re.compile(obj)
|
|
1770
1880
|
except re.error as e:
|
|
@@ -1772,11 +1882,60 @@ class regex_pattern(compiled_schema):
|
|
|
1772
1882
|
return ""
|
|
1773
1883
|
|
|
1774
1884
|
|
|
1885
|
+
@_set__name__
|
|
1886
|
+
class unique(compiled_schema):
|
|
1887
|
+
"""
|
|
1888
|
+
Matches containers whose entries do not repeat. We first attempt to convert the
|
|
1889
|
+
object to a set and check its size. If this does not work then we check the
|
|
1890
|
+
entries of the object one by one (this is a quadratic algorithm).
|
|
1891
|
+
"""
|
|
1892
|
+
|
|
1893
|
+
__name__: str
|
|
1894
|
+
|
|
1895
|
+
def __init__(self) -> None:
|
|
1896
|
+
pass
|
|
1897
|
+
|
|
1898
|
+
def __validate__(
|
|
1899
|
+
self,
|
|
1900
|
+
obj: object,
|
|
1901
|
+
name: str = "object",
|
|
1902
|
+
strict: bool = True,
|
|
1903
|
+
subs: Mapping[str, object] = {},
|
|
1904
|
+
) -> str:
|
|
1905
|
+
if not isinstance(obj, Iterable):
|
|
1906
|
+
return _wrong_type_message(
|
|
1907
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not iterable"
|
|
1908
|
+
)
|
|
1909
|
+
try:
|
|
1910
|
+
if isinstance(obj, Sized):
|
|
1911
|
+
if len(set(obj)) == len(obj):
|
|
1912
|
+
return ""
|
|
1913
|
+
except Exception:
|
|
1914
|
+
pass
|
|
1915
|
+
try:
|
|
1916
|
+
object_list = []
|
|
1917
|
+
for o in obj:
|
|
1918
|
+
if o in object_list:
|
|
1919
|
+
return _wrong_type_message(
|
|
1920
|
+
obj, name, self.__name__, explanation=f"{_c(o)} is repeated"
|
|
1921
|
+
)
|
|
1922
|
+
object_list.append(o)
|
|
1923
|
+
except Exception as e:
|
|
1924
|
+
return _wrong_type_message(obj, name, self.__name__, explanation=str(e))
|
|
1925
|
+
return ""
|
|
1926
|
+
|
|
1927
|
+
|
|
1928
|
+
@_set__name__
|
|
1775
1929
|
class url(compiled_schema):
|
|
1776
1930
|
"""
|
|
1777
1931
|
Matches valid urls.
|
|
1778
1932
|
"""
|
|
1779
1933
|
|
|
1934
|
+
__name__: str
|
|
1935
|
+
|
|
1936
|
+
def __init__(self) -> None:
|
|
1937
|
+
pass
|
|
1938
|
+
|
|
1780
1939
|
def __validate__(
|
|
1781
1940
|
self,
|
|
1782
1941
|
obj: object,
|
|
@@ -1785,13 +1944,16 @@ class url(compiled_schema):
|
|
|
1785
1944
|
subs: Mapping[str, object] = {},
|
|
1786
1945
|
) -> str:
|
|
1787
1946
|
if not isinstance(obj, str):
|
|
1788
|
-
return _wrong_type_message(
|
|
1947
|
+
return _wrong_type_message(
|
|
1948
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
1949
|
+
)
|
|
1789
1950
|
result = urllib.parse.urlparse(obj)
|
|
1790
1951
|
if all([result.scheme, result.netloc]):
|
|
1791
1952
|
return ""
|
|
1792
|
-
return _wrong_type_message(obj, name,
|
|
1953
|
+
return _wrong_type_message(obj, name, self.__name__)
|
|
1793
1954
|
|
|
1794
1955
|
|
|
1956
|
+
@_set__name__
|
|
1795
1957
|
class date_time(compiled_schema):
|
|
1796
1958
|
"""
|
|
1797
1959
|
Without argument this represents an ISO 8601 date-time. The `format`
|
|
@@ -1806,10 +1968,6 @@ class date_time(compiled_schema):
|
|
|
1806
1968
|
:param format: format string for `strftime`
|
|
1807
1969
|
"""
|
|
1808
1970
|
self.format = format
|
|
1809
|
-
if format is not None:
|
|
1810
|
-
self.__name__ = f"date_time({repr(format)})"
|
|
1811
|
-
else:
|
|
1812
|
-
self.__name__ = "date_time"
|
|
1813
1971
|
|
|
1814
1972
|
def __validate__(
|
|
1815
1973
|
self,
|
|
@@ -1819,7 +1977,9 @@ class date_time(compiled_schema):
|
|
|
1819
1977
|
subs: Mapping[str, object] = {},
|
|
1820
1978
|
) -> str:
|
|
1821
1979
|
if not isinstance(obj, str):
|
|
1822
|
-
return _wrong_type_message(
|
|
1980
|
+
return _wrong_type_message(
|
|
1981
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
1982
|
+
)
|
|
1823
1983
|
if self.format is not None:
|
|
1824
1984
|
try:
|
|
1825
1985
|
datetime.datetime.strptime(obj, self.format)
|
|
@@ -1833,11 +1993,17 @@ class date_time(compiled_schema):
|
|
|
1833
1993
|
return ""
|
|
1834
1994
|
|
|
1835
1995
|
|
|
1996
|
+
@_set__name__
|
|
1836
1997
|
class date(compiled_schema):
|
|
1837
1998
|
"""
|
|
1838
1999
|
Matches an ISO 8601 date.
|
|
1839
2000
|
"""
|
|
1840
2001
|
|
|
2002
|
+
__name__: str
|
|
2003
|
+
|
|
2004
|
+
def __init__(self) -> None:
|
|
2005
|
+
pass
|
|
2006
|
+
|
|
1841
2007
|
def __validate__(
|
|
1842
2008
|
self,
|
|
1843
2009
|
obj: object,
|
|
@@ -1846,19 +2012,27 @@ class date(compiled_schema):
|
|
|
1846
2012
|
subs: Mapping[str, object] = {},
|
|
1847
2013
|
) -> str:
|
|
1848
2014
|
if not isinstance(obj, str):
|
|
1849
|
-
return _wrong_type_message(
|
|
2015
|
+
return _wrong_type_message(
|
|
2016
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
2017
|
+
)
|
|
1850
2018
|
try:
|
|
1851
2019
|
datetime.date.fromisoformat(obj)
|
|
1852
2020
|
except Exception as e:
|
|
1853
|
-
return _wrong_type_message(obj, name,
|
|
2021
|
+
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
1854
2022
|
return ""
|
|
1855
2023
|
|
|
1856
2024
|
|
|
2025
|
+
@_set__name__
|
|
1857
2026
|
class time(compiled_schema):
|
|
1858
2027
|
"""
|
|
1859
2028
|
Matches an ISO 8601 time.
|
|
1860
2029
|
"""
|
|
1861
2030
|
|
|
2031
|
+
__name__: str
|
|
2032
|
+
|
|
2033
|
+
def __init__(self) -> None:
|
|
2034
|
+
pass
|
|
2035
|
+
|
|
1862
2036
|
def __validate__(
|
|
1863
2037
|
self,
|
|
1864
2038
|
obj: object,
|
|
@@ -1867,19 +2041,27 @@ class time(compiled_schema):
|
|
|
1867
2041
|
subs: Mapping[str, object] = {},
|
|
1868
2042
|
) -> str:
|
|
1869
2043
|
if not isinstance(obj, str):
|
|
1870
|
-
return _wrong_type_message(
|
|
2044
|
+
return _wrong_type_message(
|
|
2045
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
2046
|
+
)
|
|
1871
2047
|
try:
|
|
1872
2048
|
datetime.time.fromisoformat(obj)
|
|
1873
2049
|
except Exception as e:
|
|
1874
|
-
return _wrong_type_message(obj, name,
|
|
2050
|
+
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
1875
2051
|
return ""
|
|
1876
2052
|
|
|
1877
2053
|
|
|
2054
|
+
@_set__name__
|
|
1878
2055
|
class nothing(compiled_schema):
|
|
1879
2056
|
"""
|
|
1880
2057
|
Matches nothing.
|
|
1881
2058
|
"""
|
|
1882
2059
|
|
|
2060
|
+
__name__: str
|
|
2061
|
+
|
|
2062
|
+
def __init__(self) -> None:
|
|
2063
|
+
pass
|
|
2064
|
+
|
|
1883
2065
|
def __validate__(
|
|
1884
2066
|
self,
|
|
1885
2067
|
obj: object,
|
|
@@ -1887,14 +2069,20 @@ class nothing(compiled_schema):
|
|
|
1887
2069
|
strict: bool = True,
|
|
1888
2070
|
subs: Mapping[str, object] = {},
|
|
1889
2071
|
) -> str:
|
|
1890
|
-
return _wrong_type_message(obj, name,
|
|
2072
|
+
return _wrong_type_message(obj, name, self.__name__)
|
|
1891
2073
|
|
|
1892
2074
|
|
|
2075
|
+
@_set__name__
|
|
1893
2076
|
class anything(compiled_schema):
|
|
1894
2077
|
"""
|
|
1895
2078
|
Matchess anything.
|
|
1896
2079
|
"""
|
|
1897
2080
|
|
|
2081
|
+
__name__: str
|
|
2082
|
+
|
|
2083
|
+
def __init__(self) -> None:
|
|
2084
|
+
pass
|
|
2085
|
+
|
|
1898
2086
|
def __validate__(
|
|
1899
2087
|
self,
|
|
1900
2088
|
obj: object,
|
|
@@ -1905,6 +2093,7 @@ class anything(compiled_schema):
|
|
|
1905
2093
|
return ""
|
|
1906
2094
|
|
|
1907
2095
|
|
|
2096
|
+
@_set__name__
|
|
1908
2097
|
class domain_name(compiled_schema):
|
|
1909
2098
|
"""
|
|
1910
2099
|
Checks if the object is a valid domain name.
|
|
@@ -1923,16 +2112,6 @@ class domain_name(compiled_schema):
|
|
|
1923
2112
|
self.re_ascii = re.compile(r"[\x00-\x7F]*")
|
|
1924
2113
|
self.ascii_only = ascii_only
|
|
1925
2114
|
self.resolve = resolve
|
|
1926
|
-
arg_string = ""
|
|
1927
|
-
if not ascii_only:
|
|
1928
|
-
arg_string += ", ascii_only=False"
|
|
1929
|
-
if resolve:
|
|
1930
|
-
arg_string += ", resolve=True"
|
|
1931
|
-
if arg_string != "":
|
|
1932
|
-
arg_string = arg_string[2:]
|
|
1933
|
-
self.__name__ = (
|
|
1934
|
-
"domain_name" if not arg_string else f"domain_name({arg_string})"
|
|
1935
|
-
)
|
|
1936
2115
|
|
|
1937
2116
|
def __validate__(
|
|
1938
2117
|
self,
|
|
@@ -1942,7 +2121,9 @@ class domain_name(compiled_schema):
|
|
|
1942
2121
|
subs: Mapping[str, object] = {},
|
|
1943
2122
|
) -> str:
|
|
1944
2123
|
if not isinstance(obj, str):
|
|
1945
|
-
return _wrong_type_message(
|
|
2124
|
+
return _wrong_type_message(
|
|
2125
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
2126
|
+
)
|
|
1946
2127
|
if self.ascii_only:
|
|
1947
2128
|
if not self.re_ascii.fullmatch(obj):
|
|
1948
2129
|
return _wrong_type_message(
|
|
@@ -1961,6 +2142,7 @@ class domain_name(compiled_schema):
|
|
|
1961
2142
|
return ""
|
|
1962
2143
|
|
|
1963
2144
|
|
|
2145
|
+
@_set__name__
|
|
1964
2146
|
class at_least_one_of(compiled_schema):
|
|
1965
2147
|
"""
|
|
1966
2148
|
This represents a dictionary with a least one key among a collection of
|
|
@@ -1975,8 +2157,6 @@ class at_least_one_of(compiled_schema):
|
|
|
1975
2157
|
:param args: a collection of keys
|
|
1976
2158
|
"""
|
|
1977
2159
|
self.args = args
|
|
1978
|
-
args_s = [repr(a) for a in args]
|
|
1979
|
-
self.__name__ = f"{self.__class__.__name__}({','.join(args_s)})"
|
|
1980
2160
|
|
|
1981
2161
|
def __validate__(
|
|
1982
2162
|
self,
|
|
@@ -1986,7 +2166,9 @@ class at_least_one_of(compiled_schema):
|
|
|
1986
2166
|
subs: Mapping[str, object] = {},
|
|
1987
2167
|
) -> str:
|
|
1988
2168
|
if not isinstance(obj, Mapping):
|
|
1989
|
-
return _wrong_type_message(
|
|
2169
|
+
return _wrong_type_message(
|
|
2170
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a Mapping"
|
|
2171
|
+
)
|
|
1990
2172
|
try:
|
|
1991
2173
|
if any([a in obj for a in self.args]):
|
|
1992
2174
|
return ""
|
|
@@ -1996,6 +2178,7 @@ class at_least_one_of(compiled_schema):
|
|
|
1996
2178
|
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
1997
2179
|
|
|
1998
2180
|
|
|
2181
|
+
@_set__name__
|
|
1999
2182
|
class at_most_one_of(compiled_schema):
|
|
2000
2183
|
"""
|
|
2001
2184
|
This represents an dictionary with at most one key among a collection of
|
|
@@ -2010,8 +2193,6 @@ class at_most_one_of(compiled_schema):
|
|
|
2010
2193
|
:param args: a collection of keys
|
|
2011
2194
|
"""
|
|
2012
2195
|
self.args = args
|
|
2013
|
-
args_s = [repr(a) for a in args]
|
|
2014
|
-
self.__name__ = f"{self.__class__.__name__}({','.join(args_s)})"
|
|
2015
2196
|
|
|
2016
2197
|
def __validate__(
|
|
2017
2198
|
self,
|
|
@@ -2021,7 +2202,9 @@ class at_most_one_of(compiled_schema):
|
|
|
2021
2202
|
subs: Mapping[str, object] = {},
|
|
2022
2203
|
) -> str:
|
|
2023
2204
|
if not isinstance(obj, Mapping):
|
|
2024
|
-
return _wrong_type_message(
|
|
2205
|
+
return _wrong_type_message(
|
|
2206
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a Mapping"
|
|
2207
|
+
)
|
|
2025
2208
|
try:
|
|
2026
2209
|
if sum([a in obj for a in self.args]) <= 1:
|
|
2027
2210
|
return ""
|
|
@@ -2031,6 +2214,7 @@ class at_most_one_of(compiled_schema):
|
|
|
2031
2214
|
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
2032
2215
|
|
|
2033
2216
|
|
|
2217
|
+
@_set__name__
|
|
2034
2218
|
class one_of(compiled_schema):
|
|
2035
2219
|
"""
|
|
2036
2220
|
This represents a dictionary with exactly one key among a collection of
|
|
@@ -2045,8 +2229,6 @@ class one_of(compiled_schema):
|
|
|
2045
2229
|
:param args: a collection of keys
|
|
2046
2230
|
"""
|
|
2047
2231
|
self.args = args
|
|
2048
|
-
args_s = [repr(a) for a in args]
|
|
2049
|
-
self.__name__ = f"{self.__class__.__name__}({','.join(args_s)})"
|
|
2050
2232
|
|
|
2051
2233
|
def __validate__(
|
|
2052
2234
|
self,
|
|
@@ -2056,7 +2238,9 @@ class one_of(compiled_schema):
|
|
|
2056
2238
|
subs: Mapping[str, object] = {},
|
|
2057
2239
|
) -> str:
|
|
2058
2240
|
if not isinstance(obj, Mapping):
|
|
2059
|
-
return _wrong_type_message(
|
|
2241
|
+
return _wrong_type_message(
|
|
2242
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a Mapping"
|
|
2243
|
+
)
|
|
2060
2244
|
try:
|
|
2061
2245
|
if sum([a in obj for a in self.args]) == 1:
|
|
2062
2246
|
return ""
|
|
@@ -2066,6 +2250,7 @@ class one_of(compiled_schema):
|
|
|
2066
2250
|
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
2067
2251
|
|
|
2068
2252
|
|
|
2253
|
+
@_set__name__
|
|
2069
2254
|
class keys(compiled_schema):
|
|
2070
2255
|
"""
|
|
2071
2256
|
This represents a dictionary containing all the keys in a collection of
|
|
@@ -2073,6 +2258,7 @@ class keys(compiled_schema):
|
|
|
2073
2258
|
"""
|
|
2074
2259
|
|
|
2075
2260
|
args: tuple[object, ...]
|
|
2261
|
+
__name__: str
|
|
2076
2262
|
|
|
2077
2263
|
def __init__(self, *args: object) -> None:
|
|
2078
2264
|
"""
|
|
@@ -2088,7 +2274,9 @@ class keys(compiled_schema):
|
|
|
2088
2274
|
subs: Mapping[str, object] = {},
|
|
2089
2275
|
) -> str:
|
|
2090
2276
|
if not isinstance(obj, Mapping):
|
|
2091
|
-
return _wrong_type_message(
|
|
2277
|
+
return _wrong_type_message(
|
|
2278
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a Mapping"
|
|
2279
|
+
)
|
|
2092
2280
|
for k in self.args:
|
|
2093
2281
|
if k not in obj:
|
|
2094
2282
|
return f"{name}[{repr(k)}] is missing"
|
|
@@ -2268,6 +2456,7 @@ class _fields(compiled_schema):
|
|
|
2268
2456
|
return ""
|
|
2269
2457
|
|
|
2270
2458
|
|
|
2459
|
+
@_set__name__
|
|
2271
2460
|
class fields(wrapper, Generic[StringKeyType]):
|
|
2272
2461
|
"""
|
|
2273
2462
|
`d` is a dictionary `{"field1": schema1, ...}`.
|
|
@@ -2277,6 +2466,7 @@ class fields(wrapper, Generic[StringKeyType]):
|
|
|
2277
2466
|
"""
|
|
2278
2467
|
|
|
2279
2468
|
d: Mapping[StringKeyType, object]
|
|
2469
|
+
__name__: str
|
|
2280
2470
|
|
|
2281
2471
|
def __init__(self, d: Mapping[StringKeyType, object]) -> None:
|
|
2282
2472
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vtjson
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.8
|
|
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
|
|
@@ -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=Fj74tRDCniPjuaCUdwRbTmBJEeS9yaXiD2M7d03Q-wE,91767
|
|
4
|
+
vtjson-2.2.8.dist-info/licenses/AUTHORS,sha256=qmxaXxaIO-YPNHJAZ0dcCrnPCs1x9ocbtMksiy4i80M,21
|
|
5
|
+
vtjson-2.2.8.dist-info/licenses/LICENSE,sha256=n7xW-zX8xBLHzCdqWIMRuMzBD_ACLcNCwio0LEkKt1o,1077
|
|
6
|
+
vtjson-2.2.8.dist-info/METADATA,sha256=GyByXqMU-lqhEeolMZt4LlN3KIizRRrGfbP4AiP3AN8,3980
|
|
7
|
+
vtjson-2.2.8.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
8
|
+
vtjson-2.2.8.dist-info/top_level.txt,sha256=9DlSF3l63igcvnYPcj117F2hzOW4Nx0N-JBoW3jjBZM,7
|
|
9
|
+
vtjson-2.2.8.dist-info/RECORD,,
|
vtjson-2.2.6.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=yUD2ojGUUlDZ-KVF5Tzhle6VRoMZx8HVODhWMFFJrZc,87751
|
|
4
|
-
vtjson-2.2.6.dist-info/licenses/AUTHORS,sha256=qmxaXxaIO-YPNHJAZ0dcCrnPCs1x9ocbtMksiy4i80M,21
|
|
5
|
-
vtjson-2.2.6.dist-info/licenses/LICENSE,sha256=n7xW-zX8xBLHzCdqWIMRuMzBD_ACLcNCwio0LEkKt1o,1077
|
|
6
|
-
vtjson-2.2.6.dist-info/METADATA,sha256=yHpR0TUruUh51sZEtYuCveijFPlTtB-ju2WfYYRXR-g,3980
|
|
7
|
-
vtjson-2.2.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
-
vtjson-2.2.6.dist-info/top_level.txt,sha256=9DlSF3l63igcvnYPcj117F2hzOW4Nx0N-JBoW3jjBZM,7
|
|
9
|
-
vtjson-2.2.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|