vtjson 2.2.5__py3-none-any.whl → 2.2.7__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 +289 -75
- {vtjson-2.2.5.dist-info → vtjson-2.2.7.dist-info}/METADATA +1 -1
- vtjson-2.2.7.dist-info/RECORD +9 -0
- {vtjson-2.2.5.dist-info → vtjson-2.2.7.dist-info}/WHEEL +1 -1
- vtjson-2.2.5.dist-info/RECORD +0 -9
- {vtjson-2.2.5.dist-info → vtjson-2.2.7.dist-info}/licenses/AUTHORS +0 -0
- {vtjson-2.2.5.dist-info → vtjson-2.2.7.dist-info}/licenses/LICENSE +0 -0
- {vtjson-2.2.5.dist-info → vtjson-2.2.7.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.7"
|
|
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")
|
|
257
288
|
|
|
258
|
-
|
|
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__)
|
|
320
|
+
|
|
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
|
|
|
@@ -823,6 +899,7 @@ class set_name(wrapper):
|
|
|
823
899
|
)
|
|
824
900
|
|
|
825
901
|
|
|
902
|
+
@_set__name__
|
|
826
903
|
class regex(compiled_schema):
|
|
827
904
|
"""
|
|
828
905
|
This matches the strings which match the given pattern.
|
|
@@ -857,10 +934,6 @@ class regex(compiled_schema):
|
|
|
857
934
|
if not isinstance(name, str):
|
|
858
935
|
raise SchemaError(f"The regex name {_c(name)} is not a string")
|
|
859
936
|
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
937
|
|
|
865
938
|
try:
|
|
866
939
|
self.pattern = re.compile(regex, flags)
|
|
@@ -878,7 +951,9 @@ class regex(compiled_schema):
|
|
|
878
951
|
subs: Mapping[str, object] = {},
|
|
879
952
|
) -> str:
|
|
880
953
|
if not isinstance(obj, str):
|
|
881
|
-
return _wrong_type_message(
|
|
954
|
+
return _wrong_type_message(
|
|
955
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
956
|
+
)
|
|
882
957
|
try:
|
|
883
958
|
if self.fullmatch and self.pattern.fullmatch(obj):
|
|
884
959
|
return ""
|
|
@@ -889,6 +964,7 @@ class regex(compiled_schema):
|
|
|
889
964
|
return _wrong_type_message(obj, name, self.__name__)
|
|
890
965
|
|
|
891
966
|
|
|
967
|
+
@_set__name__
|
|
892
968
|
class glob(compiled_schema):
|
|
893
969
|
"""
|
|
894
970
|
Unix style filename matching. This is implemented using
|
|
@@ -910,9 +986,7 @@ class glob(compiled_schema):
|
|
|
910
986
|
|
|
911
987
|
self.pattern = pattern
|
|
912
988
|
|
|
913
|
-
if name is None:
|
|
914
|
-
self.__name__ = f"glob({repr(pattern)})"
|
|
915
|
-
else:
|
|
989
|
+
if name is not None:
|
|
916
990
|
self.__name__ = name
|
|
917
991
|
|
|
918
992
|
try:
|
|
@@ -931,7 +1005,9 @@ class glob(compiled_schema):
|
|
|
931
1005
|
subs: Mapping[str, object] = {},
|
|
932
1006
|
) -> str:
|
|
933
1007
|
if not isinstance(obj, str):
|
|
934
|
-
return _wrong_type_message(
|
|
1008
|
+
return _wrong_type_message(
|
|
1009
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
1010
|
+
)
|
|
935
1011
|
try:
|
|
936
1012
|
if pathlib.PurePath(obj).match(self.pattern):
|
|
937
1013
|
return ""
|
|
@@ -941,6 +1017,7 @@ class glob(compiled_schema):
|
|
|
941
1017
|
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
942
1018
|
|
|
943
1019
|
|
|
1020
|
+
@_set__name__
|
|
944
1021
|
class magic(compiled_schema):
|
|
945
1022
|
"""
|
|
946
1023
|
Checks if a buffer (for example a string or a byte array) has the given
|
|
@@ -966,9 +1043,7 @@ class magic(compiled_schema):
|
|
|
966
1043
|
|
|
967
1044
|
self.mime_type = mime_type
|
|
968
1045
|
|
|
969
|
-
if name is None:
|
|
970
|
-
self.__name__ = f"magic({repr(mime_type)})"
|
|
971
|
-
else:
|
|
1046
|
+
if name is not None:
|
|
972
1047
|
self.__name__ = name
|
|
973
1048
|
|
|
974
1049
|
def __validate__(
|
|
@@ -979,7 +1054,12 @@ class magic(compiled_schema):
|
|
|
979
1054
|
subs: Mapping[str, object] = {},
|
|
980
1055
|
) -> str:
|
|
981
1056
|
if not isinstance(obj, (str, bytes)):
|
|
982
|
-
return _wrong_type_message(
|
|
1057
|
+
return _wrong_type_message(
|
|
1058
|
+
obj,
|
|
1059
|
+
name,
|
|
1060
|
+
self.__name__,
|
|
1061
|
+
explanation=f"{_c(obj)} is not a string nor bytes",
|
|
1062
|
+
)
|
|
983
1063
|
try:
|
|
984
1064
|
objmime_type = magic_.from_buffer(obj, mime=True)
|
|
985
1065
|
except Exception as e:
|
|
@@ -994,6 +1074,7 @@ class magic(compiled_schema):
|
|
|
994
1074
|
return ""
|
|
995
1075
|
|
|
996
1076
|
|
|
1077
|
+
@_set__name__
|
|
997
1078
|
class div(compiled_schema):
|
|
998
1079
|
"""
|
|
999
1080
|
This matches the integers `x` such that `(x - remainder) % divisor` == 0.
|
|
@@ -1024,13 +1105,7 @@ class div(compiled_schema):
|
|
|
1024
1105
|
self.divisor = divisor
|
|
1025
1106
|
self.remainder = remainder
|
|
1026
1107
|
|
|
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:
|
|
1108
|
+
if name is not None:
|
|
1034
1109
|
self.__name__ = name
|
|
1035
1110
|
|
|
1036
1111
|
def __validate__(
|
|
@@ -1041,13 +1116,16 @@ class div(compiled_schema):
|
|
|
1041
1116
|
subs: Mapping[str, object] = {},
|
|
1042
1117
|
) -> str:
|
|
1043
1118
|
if not isinstance(obj, int):
|
|
1044
|
-
return _wrong_type_message(
|
|
1119
|
+
return _wrong_type_message(
|
|
1120
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not an integer"
|
|
1121
|
+
)
|
|
1045
1122
|
elif (obj - self.remainder) % self.divisor == 0:
|
|
1046
1123
|
return ""
|
|
1047
1124
|
else:
|
|
1048
1125
|
return _wrong_type_message(obj, name, self.__name__)
|
|
1049
1126
|
|
|
1050
1127
|
|
|
1128
|
+
@_set__name__
|
|
1051
1129
|
class close_to(compiled_schema):
|
|
1052
1130
|
"""
|
|
1053
1131
|
This matches the real numbers that are close to `x` in the sense of
|
|
@@ -1087,9 +1165,6 @@ class close_to(compiled_schema):
|
|
|
1087
1165
|
)
|
|
1088
1166
|
self.kw["abs_tol"] = abs_tol
|
|
1089
1167
|
|
|
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
1168
|
self.x = x
|
|
1094
1169
|
|
|
1095
1170
|
def __validate__(
|
|
@@ -1100,19 +1175,23 @@ class close_to(compiled_schema):
|
|
|
1100
1175
|
subs: Mapping[str, object] = {},
|
|
1101
1176
|
) -> str:
|
|
1102
1177
|
if not isinstance(obj, (float, int)):
|
|
1103
|
-
return _wrong_type_message(
|
|
1178
|
+
return _wrong_type_message(
|
|
1179
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not an integer"
|
|
1180
|
+
)
|
|
1104
1181
|
elif math.isclose(obj, self.x, **self.kw):
|
|
1105
1182
|
return ""
|
|
1106
1183
|
else:
|
|
1107
1184
|
return _wrong_type_message(obj, name, self.__name__)
|
|
1108
1185
|
|
|
1109
1186
|
|
|
1187
|
+
@_set__name__
|
|
1110
1188
|
class gt(compiled_schema):
|
|
1111
1189
|
"""
|
|
1112
1190
|
This checks if `object > lb`.
|
|
1113
1191
|
"""
|
|
1114
1192
|
|
|
1115
1193
|
lb: comparable
|
|
1194
|
+
__name__: str
|
|
1116
1195
|
|
|
1117
1196
|
def __init__(self, lb: comparable) -> None:
|
|
1118
1197
|
"""
|
|
@@ -1148,12 +1227,14 @@ class gt(compiled_schema):
|
|
|
1148
1227
|
return f"{self.message(name, obj)}: {str(e)}"
|
|
1149
1228
|
|
|
1150
1229
|
|
|
1230
|
+
@_set__name__
|
|
1151
1231
|
class ge(compiled_schema):
|
|
1152
1232
|
"""
|
|
1153
1233
|
This checks if `object >= lb`.
|
|
1154
1234
|
"""
|
|
1155
1235
|
|
|
1156
1236
|
lb: comparable
|
|
1237
|
+
__name__: str
|
|
1157
1238
|
|
|
1158
1239
|
def __init__(self, lb: comparable) -> None:
|
|
1159
1240
|
"""
|
|
@@ -1189,12 +1270,14 @@ class ge(compiled_schema):
|
|
|
1189
1270
|
return f"{self.message(name, obj)}: {str(e)}"
|
|
1190
1271
|
|
|
1191
1272
|
|
|
1273
|
+
@_set__name__
|
|
1192
1274
|
class lt(compiled_schema):
|
|
1193
1275
|
"""
|
|
1194
1276
|
This checks if `object < ub`.
|
|
1195
1277
|
"""
|
|
1196
1278
|
|
|
1197
1279
|
ub: comparable
|
|
1280
|
+
__name__: str
|
|
1198
1281
|
|
|
1199
1282
|
def __init__(self, ub: comparable) -> None:
|
|
1200
1283
|
"""
|
|
@@ -1230,12 +1313,14 @@ class lt(compiled_schema):
|
|
|
1230
1313
|
return f"{self.message(name, obj)}: {str(e)}"
|
|
1231
1314
|
|
|
1232
1315
|
|
|
1316
|
+
@_set__name__
|
|
1233
1317
|
class le(compiled_schema):
|
|
1234
1318
|
"""
|
|
1235
1319
|
This checks if `object <= ub`.
|
|
1236
1320
|
"""
|
|
1237
1321
|
|
|
1238
1322
|
ub: comparable
|
|
1323
|
+
__name__: str
|
|
1239
1324
|
|
|
1240
1325
|
def __init__(self, ub: comparable) -> None:
|
|
1241
1326
|
"""
|
|
@@ -1271,6 +1356,7 @@ class le(compiled_schema):
|
|
|
1271
1356
|
return f"{self.message(name, obj)}: {str(e)}"
|
|
1272
1357
|
|
|
1273
1358
|
|
|
1359
|
+
@_set__name__
|
|
1274
1360
|
class interval(compiled_schema):
|
|
1275
1361
|
"""
|
|
1276
1362
|
This checks if `lb <= object <= ub`, provided the comparisons make sense.
|
|
@@ -1278,6 +1364,7 @@ class interval(compiled_schema):
|
|
|
1278
1364
|
|
|
1279
1365
|
lb_s: str
|
|
1280
1366
|
ub_s: str
|
|
1367
|
+
__name__: str
|
|
1281
1368
|
|
|
1282
1369
|
def __init__(
|
|
1283
1370
|
self,
|
|
@@ -1346,6 +1433,7 @@ class interval(compiled_schema):
|
|
|
1346
1433
|
setattr(self, "__validate__", anything().__validate__)
|
|
1347
1434
|
|
|
1348
1435
|
|
|
1436
|
+
@_set__name__
|
|
1349
1437
|
class size(compiled_schema):
|
|
1350
1438
|
"""
|
|
1351
1439
|
Matches the objects (which support `len()` such as strings or lists) whose
|
|
@@ -1353,6 +1441,7 @@ class size(compiled_schema):
|
|
|
1353
1441
|
"""
|
|
1354
1442
|
|
|
1355
1443
|
interval_: interval
|
|
1444
|
+
__name__: str
|
|
1356
1445
|
|
|
1357
1446
|
def __init__(self, lb: int, ub: int | types.EllipsisType | None = None) -> None:
|
|
1358
1447
|
"""
|
|
@@ -1625,11 +1714,14 @@ def validate(
|
|
|
1625
1714
|
# Some predefined schemas
|
|
1626
1715
|
|
|
1627
1716
|
|
|
1717
|
+
@_set__name__
|
|
1628
1718
|
class number(compiled_schema):
|
|
1629
1719
|
"""
|
|
1630
1720
|
A deprecated alias for `float`.
|
|
1631
1721
|
"""
|
|
1632
1722
|
|
|
1723
|
+
__name__: str
|
|
1724
|
+
|
|
1633
1725
|
def __init__(self) -> None:
|
|
1634
1726
|
warnings.warn(
|
|
1635
1727
|
"The schema 'number' is deprecated. Use 'float' instead.",
|
|
@@ -1646,14 +1738,20 @@ class number(compiled_schema):
|
|
|
1646
1738
|
if isinstance(obj, (int, float)):
|
|
1647
1739
|
return ""
|
|
1648
1740
|
else:
|
|
1649
|
-
return _wrong_type_message(obj, name,
|
|
1741
|
+
return _wrong_type_message(obj, name, self.__name__)
|
|
1650
1742
|
|
|
1651
1743
|
|
|
1744
|
+
@_set__name__
|
|
1652
1745
|
class float_(compiled_schema):
|
|
1653
1746
|
"""
|
|
1654
1747
|
Schema that only matches floats. Not ints.
|
|
1655
1748
|
"""
|
|
1656
1749
|
|
|
1750
|
+
__name__: str
|
|
1751
|
+
|
|
1752
|
+
def __init__(self) -> None:
|
|
1753
|
+
pass
|
|
1754
|
+
|
|
1657
1755
|
def __validate__(
|
|
1658
1756
|
self,
|
|
1659
1757
|
obj: object,
|
|
@@ -1664,9 +1762,10 @@ class float_(compiled_schema):
|
|
|
1664
1762
|
if isinstance(obj, float):
|
|
1665
1763
|
return ""
|
|
1666
1764
|
else:
|
|
1667
|
-
return _wrong_type_message(obj, name,
|
|
1765
|
+
return _wrong_type_message(obj, name, self.__name__)
|
|
1668
1766
|
|
|
1669
1767
|
|
|
1768
|
+
@_set__name__
|
|
1670
1769
|
class email(compiled_schema):
|
|
1671
1770
|
"""
|
|
1672
1771
|
Checks if the object is a valid email address. This uses the package
|
|
@@ -1675,6 +1774,7 @@ class email(compiled_schema):
|
|
|
1675
1774
|
"""
|
|
1676
1775
|
|
|
1677
1776
|
kw: dict[str, Any]
|
|
1777
|
+
__name__: str
|
|
1678
1778
|
|
|
1679
1779
|
def __init__(self, **kw: Any) -> None:
|
|
1680
1780
|
"""
|
|
@@ -1695,14 +1795,17 @@ class email(compiled_schema):
|
|
|
1695
1795
|
subs: Mapping[str, object] = {},
|
|
1696
1796
|
) -> str:
|
|
1697
1797
|
if not isinstance(obj, str):
|
|
1698
|
-
return _wrong_type_message(
|
|
1798
|
+
return _wrong_type_message(
|
|
1799
|
+
obj, name, self.__name__, f"{_c(obj)} is not a string"
|
|
1800
|
+
)
|
|
1699
1801
|
try:
|
|
1700
1802
|
email_validator.validate_email(obj, **self.kw)
|
|
1701
1803
|
return ""
|
|
1702
1804
|
except Exception as e:
|
|
1703
|
-
return _wrong_type_message(obj, name,
|
|
1805
|
+
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
1704
1806
|
|
|
1705
1807
|
|
|
1808
|
+
@_set__name__
|
|
1706
1809
|
class ip_address(compiled_schema):
|
|
1707
1810
|
"""
|
|
1708
1811
|
Matches ip addresses of the specified version which can be 4, 6 or None.
|
|
@@ -1719,10 +1822,7 @@ class ip_address(compiled_schema):
|
|
|
1719
1822
|
"""
|
|
1720
1823
|
if version is not None and version not in (4, 6):
|
|
1721
1824
|
raise SchemaError("version is not 4 or 6")
|
|
1722
|
-
|
|
1723
|
-
self.__name__ = "ip_address"
|
|
1724
|
-
else:
|
|
1725
|
-
self.__name__ = f"ip_address(version={version})"
|
|
1825
|
+
|
|
1726
1826
|
if version == 4:
|
|
1727
1827
|
self.method = ipaddress.IPv4Address
|
|
1728
1828
|
elif version == 6:
|
|
@@ -1738,7 +1838,12 @@ class ip_address(compiled_schema):
|
|
|
1738
1838
|
subs: Mapping[str, object] = {},
|
|
1739
1839
|
) -> str:
|
|
1740
1840
|
if not isinstance(obj, (int, str, bytes)):
|
|
1741
|
-
return _wrong_type_message(
|
|
1841
|
+
return _wrong_type_message(
|
|
1842
|
+
obj,
|
|
1843
|
+
name,
|
|
1844
|
+
self.__name__,
|
|
1845
|
+
explanation=f"{_c(obj)} is not a string, an int or bytes",
|
|
1846
|
+
)
|
|
1742
1847
|
try:
|
|
1743
1848
|
self.method(obj)
|
|
1744
1849
|
except ValueError as e:
|
|
@@ -1746,11 +1851,89 @@ class ip_address(compiled_schema):
|
|
|
1746
1851
|
return ""
|
|
1747
1852
|
|
|
1748
1853
|
|
|
1854
|
+
@_set__name__
|
|
1855
|
+
class regex_pattern(compiled_schema):
|
|
1856
|
+
"""
|
|
1857
|
+
Matches valid regular expression patterns
|
|
1858
|
+
"""
|
|
1859
|
+
|
|
1860
|
+
__name__: str
|
|
1861
|
+
|
|
1862
|
+
def __init__(self) -> None:
|
|
1863
|
+
pass
|
|
1864
|
+
|
|
1865
|
+
def __validate__(
|
|
1866
|
+
self,
|
|
1867
|
+
obj: object,
|
|
1868
|
+
name: str = "object",
|
|
1869
|
+
strict: bool = True,
|
|
1870
|
+
subs: Mapping[str, object] = {},
|
|
1871
|
+
) -> str:
|
|
1872
|
+
if not isinstance(obj, str):
|
|
1873
|
+
return _wrong_type_message(
|
|
1874
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
1875
|
+
)
|
|
1876
|
+
try:
|
|
1877
|
+
re.compile(obj)
|
|
1878
|
+
except re.error as e:
|
|
1879
|
+
return _wrong_type_message(obj, name, self.__name__, explanation=str(e))
|
|
1880
|
+
return ""
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
@_set__name__
|
|
1884
|
+
class unique(compiled_schema):
|
|
1885
|
+
"""
|
|
1886
|
+
Matches containers whose entries do not repeat. We first attempt to convert the
|
|
1887
|
+
object to a set and check its size. If this does not work then we check the
|
|
1888
|
+
entries of the object one by one (this is a quadratic algorithm).
|
|
1889
|
+
"""
|
|
1890
|
+
|
|
1891
|
+
__name__: str
|
|
1892
|
+
|
|
1893
|
+
def __init__(self) -> None:
|
|
1894
|
+
pass
|
|
1895
|
+
|
|
1896
|
+
def __validate__(
|
|
1897
|
+
self,
|
|
1898
|
+
obj: object,
|
|
1899
|
+
name: str = "object",
|
|
1900
|
+
strict: bool = True,
|
|
1901
|
+
subs: Mapping[str, object] = {},
|
|
1902
|
+
) -> str:
|
|
1903
|
+
if not isinstance(obj, Iterable):
|
|
1904
|
+
return _wrong_type_message(
|
|
1905
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not iterable"
|
|
1906
|
+
)
|
|
1907
|
+
try:
|
|
1908
|
+
if isinstance(obj, Sized):
|
|
1909
|
+
if len(set(obj)) == len(obj):
|
|
1910
|
+
return ""
|
|
1911
|
+
except Exception:
|
|
1912
|
+
pass
|
|
1913
|
+
try:
|
|
1914
|
+
object_list = []
|
|
1915
|
+
for o in obj:
|
|
1916
|
+
if o in object_list:
|
|
1917
|
+
return _wrong_type_message(
|
|
1918
|
+
obj, name, self.__name__, explanation=f"{_c(o)} is repeated"
|
|
1919
|
+
)
|
|
1920
|
+
object_list.append(o)
|
|
1921
|
+
except Exception as e:
|
|
1922
|
+
return _wrong_type_message(obj, name, self.__name__, explanation=str(e))
|
|
1923
|
+
return ""
|
|
1924
|
+
|
|
1925
|
+
|
|
1926
|
+
@_set__name__
|
|
1749
1927
|
class url(compiled_schema):
|
|
1750
1928
|
"""
|
|
1751
1929
|
Matches valid urls.
|
|
1752
1930
|
"""
|
|
1753
1931
|
|
|
1932
|
+
__name__: str
|
|
1933
|
+
|
|
1934
|
+
def __init__(self) -> None:
|
|
1935
|
+
pass
|
|
1936
|
+
|
|
1754
1937
|
def __validate__(
|
|
1755
1938
|
self,
|
|
1756
1939
|
obj: object,
|
|
@@ -1759,13 +1942,16 @@ class url(compiled_schema):
|
|
|
1759
1942
|
subs: Mapping[str, object] = {},
|
|
1760
1943
|
) -> str:
|
|
1761
1944
|
if not isinstance(obj, str):
|
|
1762
|
-
return _wrong_type_message(
|
|
1945
|
+
return _wrong_type_message(
|
|
1946
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
1947
|
+
)
|
|
1763
1948
|
result = urllib.parse.urlparse(obj)
|
|
1764
1949
|
if all([result.scheme, result.netloc]):
|
|
1765
1950
|
return ""
|
|
1766
|
-
return _wrong_type_message(obj, name,
|
|
1951
|
+
return _wrong_type_message(obj, name, self.__name__)
|
|
1767
1952
|
|
|
1768
1953
|
|
|
1954
|
+
@_set__name__
|
|
1769
1955
|
class date_time(compiled_schema):
|
|
1770
1956
|
"""
|
|
1771
1957
|
Without argument this represents an ISO 8601 date-time. The `format`
|
|
@@ -1780,10 +1966,6 @@ class date_time(compiled_schema):
|
|
|
1780
1966
|
:param format: format string for `strftime`
|
|
1781
1967
|
"""
|
|
1782
1968
|
self.format = format
|
|
1783
|
-
if format is not None:
|
|
1784
|
-
self.__name__ = f"date_time({repr(format)})"
|
|
1785
|
-
else:
|
|
1786
|
-
self.__name__ = "date_time"
|
|
1787
1969
|
|
|
1788
1970
|
def __validate__(
|
|
1789
1971
|
self,
|
|
@@ -1793,7 +1975,9 @@ class date_time(compiled_schema):
|
|
|
1793
1975
|
subs: Mapping[str, object] = {},
|
|
1794
1976
|
) -> str:
|
|
1795
1977
|
if not isinstance(obj, str):
|
|
1796
|
-
return _wrong_type_message(
|
|
1978
|
+
return _wrong_type_message(
|
|
1979
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
1980
|
+
)
|
|
1797
1981
|
if self.format is not None:
|
|
1798
1982
|
try:
|
|
1799
1983
|
datetime.datetime.strptime(obj, self.format)
|
|
@@ -1807,11 +1991,17 @@ class date_time(compiled_schema):
|
|
|
1807
1991
|
return ""
|
|
1808
1992
|
|
|
1809
1993
|
|
|
1994
|
+
@_set__name__
|
|
1810
1995
|
class date(compiled_schema):
|
|
1811
1996
|
"""
|
|
1812
1997
|
Matches an ISO 8601 date.
|
|
1813
1998
|
"""
|
|
1814
1999
|
|
|
2000
|
+
__name__: str
|
|
2001
|
+
|
|
2002
|
+
def __init__(self) -> None:
|
|
2003
|
+
pass
|
|
2004
|
+
|
|
1815
2005
|
def __validate__(
|
|
1816
2006
|
self,
|
|
1817
2007
|
obj: object,
|
|
@@ -1820,19 +2010,27 @@ class date(compiled_schema):
|
|
|
1820
2010
|
subs: Mapping[str, object] = {},
|
|
1821
2011
|
) -> str:
|
|
1822
2012
|
if not isinstance(obj, str):
|
|
1823
|
-
return _wrong_type_message(
|
|
2013
|
+
return _wrong_type_message(
|
|
2014
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
2015
|
+
)
|
|
1824
2016
|
try:
|
|
1825
2017
|
datetime.date.fromisoformat(obj)
|
|
1826
2018
|
except Exception as e:
|
|
1827
|
-
return _wrong_type_message(obj, name,
|
|
2019
|
+
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
1828
2020
|
return ""
|
|
1829
2021
|
|
|
1830
2022
|
|
|
2023
|
+
@_set__name__
|
|
1831
2024
|
class time(compiled_schema):
|
|
1832
2025
|
"""
|
|
1833
2026
|
Matches an ISO 8601 time.
|
|
1834
2027
|
"""
|
|
1835
2028
|
|
|
2029
|
+
__name__: str
|
|
2030
|
+
|
|
2031
|
+
def __init__(self) -> None:
|
|
2032
|
+
pass
|
|
2033
|
+
|
|
1836
2034
|
def __validate__(
|
|
1837
2035
|
self,
|
|
1838
2036
|
obj: object,
|
|
@@ -1841,19 +2039,27 @@ class time(compiled_schema):
|
|
|
1841
2039
|
subs: Mapping[str, object] = {},
|
|
1842
2040
|
) -> str:
|
|
1843
2041
|
if not isinstance(obj, str):
|
|
1844
|
-
return _wrong_type_message(
|
|
2042
|
+
return _wrong_type_message(
|
|
2043
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
2044
|
+
)
|
|
1845
2045
|
try:
|
|
1846
2046
|
datetime.time.fromisoformat(obj)
|
|
1847
2047
|
except Exception as e:
|
|
1848
|
-
return _wrong_type_message(obj, name,
|
|
2048
|
+
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
1849
2049
|
return ""
|
|
1850
2050
|
|
|
1851
2051
|
|
|
2052
|
+
@_set__name__
|
|
1852
2053
|
class nothing(compiled_schema):
|
|
1853
2054
|
"""
|
|
1854
2055
|
Matches nothing.
|
|
1855
2056
|
"""
|
|
1856
2057
|
|
|
2058
|
+
__name__: str
|
|
2059
|
+
|
|
2060
|
+
def __init__(self) -> None:
|
|
2061
|
+
pass
|
|
2062
|
+
|
|
1857
2063
|
def __validate__(
|
|
1858
2064
|
self,
|
|
1859
2065
|
obj: object,
|
|
@@ -1861,14 +2067,20 @@ class nothing(compiled_schema):
|
|
|
1861
2067
|
strict: bool = True,
|
|
1862
2068
|
subs: Mapping[str, object] = {},
|
|
1863
2069
|
) -> str:
|
|
1864
|
-
return _wrong_type_message(obj, name,
|
|
2070
|
+
return _wrong_type_message(obj, name, self.__name__)
|
|
1865
2071
|
|
|
1866
2072
|
|
|
2073
|
+
@_set__name__
|
|
1867
2074
|
class anything(compiled_schema):
|
|
1868
2075
|
"""
|
|
1869
2076
|
Matchess anything.
|
|
1870
2077
|
"""
|
|
1871
2078
|
|
|
2079
|
+
__name__: str
|
|
2080
|
+
|
|
2081
|
+
def __init__(self) -> None:
|
|
2082
|
+
pass
|
|
2083
|
+
|
|
1872
2084
|
def __validate__(
|
|
1873
2085
|
self,
|
|
1874
2086
|
obj: object,
|
|
@@ -1879,6 +2091,7 @@ class anything(compiled_schema):
|
|
|
1879
2091
|
return ""
|
|
1880
2092
|
|
|
1881
2093
|
|
|
2094
|
+
@_set__name__
|
|
1882
2095
|
class domain_name(compiled_schema):
|
|
1883
2096
|
"""
|
|
1884
2097
|
Checks if the object is a valid domain name.
|
|
@@ -1897,16 +2110,6 @@ class domain_name(compiled_schema):
|
|
|
1897
2110
|
self.re_ascii = re.compile(r"[\x00-\x7F]*")
|
|
1898
2111
|
self.ascii_only = ascii_only
|
|
1899
2112
|
self.resolve = resolve
|
|
1900
|
-
arg_string = ""
|
|
1901
|
-
if not ascii_only:
|
|
1902
|
-
arg_string += ", ascii_only=False"
|
|
1903
|
-
if resolve:
|
|
1904
|
-
arg_string += ", resolve=True"
|
|
1905
|
-
if arg_string != "":
|
|
1906
|
-
arg_string = arg_string[2:]
|
|
1907
|
-
self.__name__ = (
|
|
1908
|
-
"domain_name" if not arg_string else f"domain_name({arg_string})"
|
|
1909
|
-
)
|
|
1910
2113
|
|
|
1911
2114
|
def __validate__(
|
|
1912
2115
|
self,
|
|
@@ -1916,7 +2119,9 @@ class domain_name(compiled_schema):
|
|
|
1916
2119
|
subs: Mapping[str, object] = {},
|
|
1917
2120
|
) -> str:
|
|
1918
2121
|
if not isinstance(obj, str):
|
|
1919
|
-
return _wrong_type_message(
|
|
2122
|
+
return _wrong_type_message(
|
|
2123
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a string"
|
|
2124
|
+
)
|
|
1920
2125
|
if self.ascii_only:
|
|
1921
2126
|
if not self.re_ascii.fullmatch(obj):
|
|
1922
2127
|
return _wrong_type_message(
|
|
@@ -1935,6 +2140,7 @@ class domain_name(compiled_schema):
|
|
|
1935
2140
|
return ""
|
|
1936
2141
|
|
|
1937
2142
|
|
|
2143
|
+
@_set__name__
|
|
1938
2144
|
class at_least_one_of(compiled_schema):
|
|
1939
2145
|
"""
|
|
1940
2146
|
This represents a dictionary with a least one key among a collection of
|
|
@@ -1949,8 +2155,6 @@ class at_least_one_of(compiled_schema):
|
|
|
1949
2155
|
:param args: a collection of keys
|
|
1950
2156
|
"""
|
|
1951
2157
|
self.args = args
|
|
1952
|
-
args_s = [repr(a) for a in args]
|
|
1953
|
-
self.__name__ = f"{self.__class__.__name__}({','.join(args_s)})"
|
|
1954
2158
|
|
|
1955
2159
|
def __validate__(
|
|
1956
2160
|
self,
|
|
@@ -1960,7 +2164,9 @@ class at_least_one_of(compiled_schema):
|
|
|
1960
2164
|
subs: Mapping[str, object] = {},
|
|
1961
2165
|
) -> str:
|
|
1962
2166
|
if not isinstance(obj, Mapping):
|
|
1963
|
-
return _wrong_type_message(
|
|
2167
|
+
return _wrong_type_message(
|
|
2168
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a Mapping"
|
|
2169
|
+
)
|
|
1964
2170
|
try:
|
|
1965
2171
|
if any([a in obj for a in self.args]):
|
|
1966
2172
|
return ""
|
|
@@ -1970,6 +2176,7 @@ class at_least_one_of(compiled_schema):
|
|
|
1970
2176
|
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
1971
2177
|
|
|
1972
2178
|
|
|
2179
|
+
@_set__name__
|
|
1973
2180
|
class at_most_one_of(compiled_schema):
|
|
1974
2181
|
"""
|
|
1975
2182
|
This represents an dictionary with at most one key among a collection of
|
|
@@ -1984,8 +2191,6 @@ class at_most_one_of(compiled_schema):
|
|
|
1984
2191
|
:param args: a collection of keys
|
|
1985
2192
|
"""
|
|
1986
2193
|
self.args = args
|
|
1987
|
-
args_s = [repr(a) for a in args]
|
|
1988
|
-
self.__name__ = f"{self.__class__.__name__}({','.join(args_s)})"
|
|
1989
2194
|
|
|
1990
2195
|
def __validate__(
|
|
1991
2196
|
self,
|
|
@@ -1995,7 +2200,9 @@ class at_most_one_of(compiled_schema):
|
|
|
1995
2200
|
subs: Mapping[str, object] = {},
|
|
1996
2201
|
) -> str:
|
|
1997
2202
|
if not isinstance(obj, Mapping):
|
|
1998
|
-
return _wrong_type_message(
|
|
2203
|
+
return _wrong_type_message(
|
|
2204
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a Mapping"
|
|
2205
|
+
)
|
|
1999
2206
|
try:
|
|
2000
2207
|
if sum([a in obj for a in self.args]) <= 1:
|
|
2001
2208
|
return ""
|
|
@@ -2005,6 +2212,7 @@ class at_most_one_of(compiled_schema):
|
|
|
2005
2212
|
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
2006
2213
|
|
|
2007
2214
|
|
|
2215
|
+
@_set__name__
|
|
2008
2216
|
class one_of(compiled_schema):
|
|
2009
2217
|
"""
|
|
2010
2218
|
This represents a dictionary with exactly one key among a collection of
|
|
@@ -2019,8 +2227,6 @@ class one_of(compiled_schema):
|
|
|
2019
2227
|
:param args: a collection of keys
|
|
2020
2228
|
"""
|
|
2021
2229
|
self.args = args
|
|
2022
|
-
args_s = [repr(a) for a in args]
|
|
2023
|
-
self.__name__ = f"{self.__class__.__name__}({','.join(args_s)})"
|
|
2024
2230
|
|
|
2025
2231
|
def __validate__(
|
|
2026
2232
|
self,
|
|
@@ -2030,7 +2236,9 @@ class one_of(compiled_schema):
|
|
|
2030
2236
|
subs: Mapping[str, object] = {},
|
|
2031
2237
|
) -> str:
|
|
2032
2238
|
if not isinstance(obj, Mapping):
|
|
2033
|
-
return _wrong_type_message(
|
|
2239
|
+
return _wrong_type_message(
|
|
2240
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a Mapping"
|
|
2241
|
+
)
|
|
2034
2242
|
try:
|
|
2035
2243
|
if sum([a in obj for a in self.args]) == 1:
|
|
2036
2244
|
return ""
|
|
@@ -2040,6 +2248,7 @@ class one_of(compiled_schema):
|
|
|
2040
2248
|
return _wrong_type_message(obj, name, self.__name__, str(e))
|
|
2041
2249
|
|
|
2042
2250
|
|
|
2251
|
+
@_set__name__
|
|
2043
2252
|
class keys(compiled_schema):
|
|
2044
2253
|
"""
|
|
2045
2254
|
This represents a dictionary containing all the keys in a collection of
|
|
@@ -2047,6 +2256,7 @@ class keys(compiled_schema):
|
|
|
2047
2256
|
"""
|
|
2048
2257
|
|
|
2049
2258
|
args: tuple[object, ...]
|
|
2259
|
+
__name__: str
|
|
2050
2260
|
|
|
2051
2261
|
def __init__(self, *args: object) -> None:
|
|
2052
2262
|
"""
|
|
@@ -2062,7 +2272,9 @@ class keys(compiled_schema):
|
|
|
2062
2272
|
subs: Mapping[str, object] = {},
|
|
2063
2273
|
) -> str:
|
|
2064
2274
|
if not isinstance(obj, Mapping):
|
|
2065
|
-
return _wrong_type_message(
|
|
2275
|
+
return _wrong_type_message(
|
|
2276
|
+
obj, name, self.__name__, explanation=f"{_c(obj)} is not a Mapping"
|
|
2277
|
+
)
|
|
2066
2278
|
for k in self.args:
|
|
2067
2279
|
if k not in obj:
|
|
2068
2280
|
return f"{name}[{repr(k)}] is missing"
|
|
@@ -2242,6 +2454,7 @@ class _fields(compiled_schema):
|
|
|
2242
2454
|
return ""
|
|
2243
2455
|
|
|
2244
2456
|
|
|
2457
|
+
@_set__name__
|
|
2245
2458
|
class fields(wrapper, Generic[StringKeyType]):
|
|
2246
2459
|
"""
|
|
2247
2460
|
`d` is a dictionary `{"field1": schema1, ...}`.
|
|
@@ -2251,6 +2464,7 @@ class fields(wrapper, Generic[StringKeyType]):
|
|
|
2251
2464
|
"""
|
|
2252
2465
|
|
|
2253
2466
|
d: Mapping[StringKeyType, object]
|
|
2467
|
+
__name__: str
|
|
2254
2468
|
|
|
2255
2469
|
def __init__(self, d: Mapping[StringKeyType, object]) -> None:
|
|
2256
2470
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vtjson
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.7
|
|
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=AZOYnkjYeefa6agUiU7FUl7_fk8tUAxGBsqc6a1Hee0,91671
|
|
4
|
+
vtjson-2.2.7.dist-info/licenses/AUTHORS,sha256=qmxaXxaIO-YPNHJAZ0dcCrnPCs1x9ocbtMksiy4i80M,21
|
|
5
|
+
vtjson-2.2.7.dist-info/licenses/LICENSE,sha256=n7xW-zX8xBLHzCdqWIMRuMzBD_ACLcNCwio0LEkKt1o,1077
|
|
6
|
+
vtjson-2.2.7.dist-info/METADATA,sha256=Rvm5_Z2otxfFfcf8StFHpZAIOuNmqXu-GQNFflf7MRs,3980
|
|
7
|
+
vtjson-2.2.7.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
8
|
+
vtjson-2.2.7.dist-info/top_level.txt,sha256=9DlSF3l63igcvnYPcj117F2hzOW4Nx0N-JBoW3jjBZM,7
|
|
9
|
+
vtjson-2.2.7.dist-info/RECORD,,
|
vtjson-2.2.5.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=AQIoyST4Qfpc6apLbIg4plWEh-z0VlvbAjr03JVr924,87109
|
|
4
|
-
vtjson-2.2.5.dist-info/licenses/AUTHORS,sha256=qmxaXxaIO-YPNHJAZ0dcCrnPCs1x9ocbtMksiy4i80M,21
|
|
5
|
-
vtjson-2.2.5.dist-info/licenses/LICENSE,sha256=n7xW-zX8xBLHzCdqWIMRuMzBD_ACLcNCwio0LEkKt1o,1077
|
|
6
|
-
vtjson-2.2.5.dist-info/METADATA,sha256=4TSessIW50S0gojL08Xhj8k6kze022XbfQrMrIIWUE0,3980
|
|
7
|
-
vtjson-2.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
-
vtjson-2.2.5.dist-info/top_level.txt,sha256=9DlSF3l63igcvnYPcj117F2hzOW4Nx0N-JBoW3jjBZM,7
|
|
9
|
-
vtjson-2.2.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|