schemathesis 3.38.5__py3-none-any.whl → 3.38.6__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.
- schemathesis/_hypothesis.py +26 -11
- schemathesis/generation/coverage.py +17 -7
- schemathesis/specs/openapi/checks.py +2 -2
- schemathesis/specs/openapi/patterns.py +25 -8
- {schemathesis-3.38.5.dist-info → schemathesis-3.38.6.dist-info}/METADATA +2 -3
- {schemathesis-3.38.5.dist-info → schemathesis-3.38.6.dist-info}/RECORD +9 -9
- {schemathesis-3.38.5.dist-info → schemathesis-3.38.6.dist-info}/WHEEL +1 -1
- {schemathesis-3.38.5.dist-info → schemathesis-3.38.6.dist-info}/entry_points.txt +0 -0
- {schemathesis-3.38.5.dist-info → schemathesis-3.38.6.dist-info}/licenses/LICENSE +0 -0
schemathesis/_hypothesis.py
CHANGED
|
@@ -224,6 +224,12 @@ def _iter_coverage_cases(
|
|
|
224
224
|
from .specs.openapi.constants import LOCATION_TO_CONTAINER
|
|
225
225
|
from .specs.openapi.examples import find_in_responses, find_matching_in_responses
|
|
226
226
|
|
|
227
|
+
def _stringify_value(val: Any) -> str:
|
|
228
|
+
if isinstance(val, list):
|
|
229
|
+
# use comma-separated values style for arrays
|
|
230
|
+
return ",".join(json.dumps(sub) for sub in val)
|
|
231
|
+
return json.dumps(val)
|
|
232
|
+
|
|
227
233
|
generators: dict[tuple[str, str], Generator[coverage.GeneratedValue, None, None]] = {}
|
|
228
234
|
template: dict[str, Any] = {}
|
|
229
235
|
responses = find_in_responses(operation)
|
|
@@ -240,8 +246,8 @@ def _iter_coverage_cases(
|
|
|
240
246
|
location = parameter.location
|
|
241
247
|
name = parameter.name
|
|
242
248
|
container = template.setdefault(LOCATION_TO_CONTAINER[location], {})
|
|
243
|
-
if location in ("header", "cookie") and not isinstance(value.value, str):
|
|
244
|
-
container[name] =
|
|
249
|
+
if location in ("header", "cookie", "path") and not isinstance(value.value, str):
|
|
250
|
+
container[name] = _stringify_value(value.value)
|
|
245
251
|
else:
|
|
246
252
|
container[name] = value.value
|
|
247
253
|
generators[(location, name)] = gen
|
|
@@ -286,12 +292,13 @@ def _iter_coverage_cases(
|
|
|
286
292
|
case.data_generation_method = DataGenerationMethod.positive
|
|
287
293
|
case.meta = _make_meta(description="Default positive test case")
|
|
288
294
|
yield case
|
|
295
|
+
|
|
289
296
|
for (location, name), gen in generators.items():
|
|
290
297
|
container_name = LOCATION_TO_CONTAINER[location]
|
|
291
298
|
container = template[container_name]
|
|
292
299
|
for value in gen:
|
|
293
|
-
if location in ("header", "cookie") and not isinstance(value.value, str):
|
|
294
|
-
generated =
|
|
300
|
+
if location in ("header", "cookie", "path") and not isinstance(value.value, str):
|
|
301
|
+
generated = _stringify_value(value.value)
|
|
295
302
|
else:
|
|
296
303
|
generated = value.value
|
|
297
304
|
case = operation.make_case(**{**template, container_name: {**container, name: generated}})
|
|
@@ -340,10 +347,13 @@ def _iter_coverage_cases(
|
|
|
340
347
|
optional = sorted(all_params - required)
|
|
341
348
|
|
|
342
349
|
# Helper function to create and yield a case
|
|
343
|
-
def make_case(
|
|
344
|
-
|
|
350
|
+
def make_case(
|
|
351
|
+
container_values: dict, description: str, _location: str, _container_name: str, _parameter: str | None
|
|
352
|
+
) -> Case:
|
|
353
|
+
if _location in ("header", "cookie", "path"):
|
|
345
354
|
container = {
|
|
346
|
-
name:
|
|
355
|
+
name: _stringify_value(val) if not isinstance(val, str) else val
|
|
356
|
+
for name, val in container_values.items()
|
|
347
357
|
}
|
|
348
358
|
else:
|
|
349
359
|
container = container_values
|
|
@@ -353,6 +363,7 @@ def _iter_coverage_cases(
|
|
|
353
363
|
case.meta = _make_meta(
|
|
354
364
|
description=description,
|
|
355
365
|
location=_location,
|
|
366
|
+
parameter=_parameter,
|
|
356
367
|
parameter_location=_location,
|
|
357
368
|
)
|
|
358
369
|
return case
|
|
@@ -377,12 +388,12 @@ def _iter_coverage_cases(
|
|
|
377
388
|
coverage.CoverageContext(data_generation_methods=[DataGenerationMethod.negative]),
|
|
378
389
|
subschema,
|
|
379
390
|
):
|
|
380
|
-
yield make_case(more.value, more.description, _location, _container_name)
|
|
391
|
+
yield make_case(more.value, more.description, _location, _container_name, more.parameter)
|
|
381
392
|
|
|
382
393
|
# 1. Generate only required properties
|
|
383
394
|
if required and all_params != required:
|
|
384
395
|
only_required = {k: v for k, v in base_container.items() if k in required}
|
|
385
|
-
yield make_case(only_required, "Only required properties", location, container_name)
|
|
396
|
+
yield make_case(only_required, "Only required properties", location, container_name, None)
|
|
386
397
|
if DataGenerationMethod.negative in data_generation_methods:
|
|
387
398
|
subschema = _combination_schema(only_required, required, parameter_set)
|
|
388
399
|
yield from _yield_negative(subschema, location, container_name)
|
|
@@ -391,7 +402,9 @@ def _iter_coverage_cases(
|
|
|
391
402
|
for opt_param in optional:
|
|
392
403
|
combo = {k: v for k, v in base_container.items() if k in required or k == opt_param}
|
|
393
404
|
if combo != base_container:
|
|
394
|
-
yield make_case(
|
|
405
|
+
yield make_case(
|
|
406
|
+
combo, f"All required properties and optional '{opt_param}'", location, container_name, None
|
|
407
|
+
)
|
|
395
408
|
if DataGenerationMethod.negative in data_generation_methods:
|
|
396
409
|
subschema = _combination_schema(combo, required, parameter_set)
|
|
397
410
|
yield from _yield_negative(subschema, location, container_name)
|
|
@@ -402,7 +415,9 @@ def _iter_coverage_cases(
|
|
|
402
415
|
for combination in combinations(optional, size):
|
|
403
416
|
combo = {k: v for k, v in base_container.items() if k in required or k in combination}
|
|
404
417
|
if combo != base_container:
|
|
405
|
-
yield make_case(
|
|
418
|
+
yield make_case(
|
|
419
|
+
combo, f"All required and {size} optional properties", location, container_name, None
|
|
420
|
+
)
|
|
406
421
|
|
|
407
422
|
|
|
408
423
|
def _make_meta(
|
|
@@ -39,7 +39,7 @@ NUMERIC_STRATEGY: st.SearchStrategy = st.integers() | FLOAT_STRATEGY
|
|
|
39
39
|
JSON_STRATEGY: st.SearchStrategy = st.recursive(
|
|
40
40
|
st.none() | st.booleans() | NUMERIC_STRATEGY | st.text(), json_recursive_strategy
|
|
41
41
|
)
|
|
42
|
-
ARRAY_STRATEGY: st.SearchStrategy = st.lists(JSON_STRATEGY)
|
|
42
|
+
ARRAY_STRATEGY: st.SearchStrategy = st.lists(JSON_STRATEGY, min_size=2)
|
|
43
43
|
OBJECT_STRATEGY: st.SearchStrategy = st.dictionaries(st.text(), JSON_STRATEGY)
|
|
44
44
|
|
|
45
45
|
|
|
@@ -63,23 +63,31 @@ class GeneratedValue:
|
|
|
63
63
|
value: Any
|
|
64
64
|
data_generation_method: DataGenerationMethod
|
|
65
65
|
description: str
|
|
66
|
+
parameter: str | None
|
|
66
67
|
location: str | None
|
|
67
68
|
|
|
68
|
-
__slots__ = ("value", "data_generation_method", "description", "location")
|
|
69
|
+
__slots__ = ("value", "data_generation_method", "description", "parameter", "location")
|
|
69
70
|
|
|
70
71
|
@classmethod
|
|
71
72
|
def with_positive(cls, value: Any, *, description: str) -> GeneratedValue:
|
|
72
73
|
return cls(
|
|
73
|
-
value=value,
|
|
74
|
+
value=value,
|
|
75
|
+
data_generation_method=DataGenerationMethod.positive,
|
|
76
|
+
description=description,
|
|
77
|
+
location=None,
|
|
78
|
+
parameter=None,
|
|
74
79
|
)
|
|
75
80
|
|
|
76
81
|
@classmethod
|
|
77
|
-
def with_negative(
|
|
82
|
+
def with_negative(
|
|
83
|
+
cls, value: Any, *, description: str, location: str, parameter: str | None = None
|
|
84
|
+
) -> GeneratedValue:
|
|
78
85
|
return cls(
|
|
79
86
|
value=value,
|
|
80
87
|
data_generation_method=DataGenerationMethod.negative,
|
|
81
88
|
description=description,
|
|
82
89
|
location=location,
|
|
90
|
+
parameter=parameter,
|
|
83
91
|
)
|
|
84
92
|
|
|
85
93
|
|
|
@@ -218,11 +226,11 @@ def _encode(o: Any) -> str:
|
|
|
218
226
|
return "".join(_iterencode(o, 0))
|
|
219
227
|
|
|
220
228
|
|
|
221
|
-
def _to_hashable_key(value: T, _encode: Callable = _encode) ->
|
|
229
|
+
def _to_hashable_key(value: T, _encode: Callable = _encode) -> tuple[type, str | T]:
|
|
222
230
|
if isinstance(value, (dict, list)):
|
|
223
231
|
serialized = _encode(value)
|
|
224
232
|
return (type(value), serialized)
|
|
225
|
-
return value
|
|
233
|
+
return (type(value), value)
|
|
226
234
|
|
|
227
235
|
|
|
228
236
|
def _cover_positive_for_type(
|
|
@@ -425,7 +433,8 @@ def cover_schema_iter(
|
|
|
425
433
|
elif key == "allOf":
|
|
426
434
|
nctx = ctx.with_negative()
|
|
427
435
|
if len(value) == 1:
|
|
428
|
-
|
|
436
|
+
with nctx.location(0):
|
|
437
|
+
yield from cover_schema_iter(nctx, value[0], seen)
|
|
429
438
|
else:
|
|
430
439
|
with _ignore_unfixable():
|
|
431
440
|
canonical = canonicalish(schema)
|
|
@@ -755,6 +764,7 @@ def _negative_properties(
|
|
|
755
764
|
{**template, key: value.value},
|
|
756
765
|
description=f"Object with invalid '{key}' value: {value.description}",
|
|
757
766
|
location=nctx.current_location,
|
|
767
|
+
parameter=key,
|
|
758
768
|
)
|
|
759
769
|
|
|
760
770
|
|
|
@@ -391,14 +391,14 @@ def ignored_auth(ctx: CheckContext, response: GenericResponse, case: Case) -> bo
|
|
|
391
391
|
# Check if invalid auth will give an error
|
|
392
392
|
_remove_auth_from_case(case, security_parameters)
|
|
393
393
|
new_response = case.operation.schema.transport.send(case)
|
|
394
|
-
if
|
|
394
|
+
if new_response.status_code != 401:
|
|
395
395
|
_update_response(response, new_response)
|
|
396
396
|
_raise_no_auth_error(new_response, case.operation.verbose_name, "that requires authentication")
|
|
397
397
|
# Try to set invalid auth and check if it succeeds
|
|
398
398
|
for parameter in security_parameters:
|
|
399
399
|
_set_auth_for_case(case, parameter)
|
|
400
400
|
new_response = case.operation.schema.transport.send(case)
|
|
401
|
-
if
|
|
401
|
+
if new_response.status_code != 401:
|
|
402
402
|
_update_response(response, new_response)
|
|
403
403
|
_raise_no_auth_error(new_response, case.operation.verbose_name, "with any auth")
|
|
404
404
|
_remove_auth_from_case(case, security_parameters)
|
|
@@ -44,21 +44,38 @@ def _handle_parsed_pattern(parsed: list, pattern: str, min_length: int | None, m
|
|
|
44
44
|
if parsed[0][0] == ANCHOR:
|
|
45
45
|
# Starts with an anchor
|
|
46
46
|
op, value = parsed[1]
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
anchor_length = _get_anchor_length(parsed[0][1])
|
|
48
|
+
leading_anchor = pattern[:anchor_length]
|
|
49
|
+
return leading_anchor + _update_quantifier(op, value, pattern[anchor_length:], min_length, max_length)
|
|
49
50
|
if parsed[1][0] == ANCHOR:
|
|
50
51
|
# Ends with an anchor
|
|
51
52
|
op, value = parsed[0]
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
anchor_length = _get_anchor_length(parsed[1][1])
|
|
54
|
+
trailing_anchor = pattern[-anchor_length:]
|
|
55
|
+
return _update_quantifier(op, value, pattern[:-anchor_length], min_length, max_length) + trailing_anchor
|
|
54
56
|
elif len(parsed) == 3 and parsed[0][0] == ANCHOR and parsed[2][0] == ANCHOR:
|
|
55
57
|
op, value = parsed[1]
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
leading_anchor_length = _get_anchor_length(parsed[0][1])
|
|
59
|
+
trailing_anchor_length = _get_anchor_length(parsed[2][1])
|
|
60
|
+
leading_anchor = pattern[:leading_anchor_length]
|
|
61
|
+
trailing_anchor = pattern[-trailing_anchor_length:]
|
|
62
|
+
return (
|
|
63
|
+
leading_anchor
|
|
64
|
+
+ _update_quantifier(
|
|
65
|
+
op, value, pattern[leading_anchor_length:-trailing_anchor_length], min_length, max_length
|
|
66
|
+
)
|
|
67
|
+
+ trailing_anchor
|
|
68
|
+
)
|
|
59
69
|
return pattern
|
|
60
70
|
|
|
61
71
|
|
|
72
|
+
def _get_anchor_length(node_type: int) -> int:
|
|
73
|
+
"""Determine the length of the anchor based on its type."""
|
|
74
|
+
if node_type in {sre.AT_BEGINNING_STRING, sre.AT_END_STRING, sre.AT_BOUNDARY, sre.AT_NON_BOUNDARY}:
|
|
75
|
+
return 2 # \A, \Z, \b, or \B
|
|
76
|
+
return 1 # ^ or $ or their multiline/locale/unicode variants
|
|
77
|
+
|
|
78
|
+
|
|
62
79
|
def _update_quantifier(op: int, value: tuple, pattern: str, min_length: int | None, max_length: int | None) -> str:
|
|
63
80
|
"""Update the quantifier based on the operation type and given constraints."""
|
|
64
81
|
if op in REPEATS:
|
|
@@ -113,7 +130,7 @@ def _strip_quantifier(pattern: str) -> str:
|
|
|
113
130
|
return pattern[:-2]
|
|
114
131
|
if pattern.endswith(("?", "*", "+")):
|
|
115
132
|
pattern = pattern[:-1]
|
|
116
|
-
if pattern.endswith("}"):
|
|
133
|
+
if pattern.endswith("}") and "{" in pattern:
|
|
117
134
|
# Find the start of the exact quantifier and drop everything since that index
|
|
118
135
|
idx = pattern.rfind("{")
|
|
119
136
|
pattern = pattern[:idx]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: schemathesis
|
|
3
|
-
Version: 3.38.
|
|
3
|
+
Version: 3.38.6
|
|
4
4
|
Summary: Property-based testing framework for Open API and GraphQL based apps
|
|
5
5
|
Project-URL: Documentation, https://schemathesis.readthedocs.io/en/stable/
|
|
6
6
|
Project-URL: Changelog, https://schemathesis.readthedocs.io/en/stable/changelog.html
|
|
@@ -9,8 +9,7 @@ Project-URL: Funding, https://github.com/sponsors/Stranger6667
|
|
|
9
9
|
Project-URL: Source Code, https://github.com/schemathesis/schemathesis
|
|
10
10
|
Author-email: Dmitry Dygalo <dmitry@dygalo.dev>
|
|
11
11
|
Maintainer-email: Dmitry Dygalo <dmitry@dygalo.dev>
|
|
12
|
-
License
|
|
13
|
-
License-File: LICENSE
|
|
12
|
+
License: MIT
|
|
14
13
|
Keywords: graphql,hypothesis,openapi,pytest,testing
|
|
15
14
|
Classifier: Development Status :: 5 - Production/Stable
|
|
16
15
|
Classifier: Environment :: Console
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
schemathesis/__init__.py,sha256=UW2Bq8hDDkcBeAAA7PzpBFXkOOxkmHox-mfQwzHDjL0,1914
|
|
2
2
|
schemathesis/_compat.py,sha256=y4RZd59i2NCnZ91VQhnKeMn_8t3SgvLOk2Xm8nymUHY,1837
|
|
3
3
|
schemathesis/_dependency_versions.py,sha256=pjEkkGAfOQJYNb-9UOo84V8nj_lKHr_TGDVdFwY2UU0,816
|
|
4
|
-
schemathesis/_hypothesis.py,sha256=
|
|
4
|
+
schemathesis/_hypothesis.py,sha256=SHFQKVeKsKX55D7Rfb2DTG7gq7h-jLXMGGD8RG81ac4,21339
|
|
5
5
|
schemathesis/_lazy_import.py,sha256=aMhWYgbU2JOltyWBb32vnWBb6kykOghucEzI_F70yVE,470
|
|
6
6
|
schemathesis/_override.py,sha256=TAjYB3eJQmlw9K_xiR9ptt9Wj7if4U7UFlUhGjpBAoM,1625
|
|
7
7
|
schemathesis/_patches.py,sha256=Hsbpn4UVeXUQD2Kllrbq01CSWsTYENWa0VJTyhX5C2k,895
|
|
@@ -61,7 +61,7 @@ schemathesis/fixups/utf8_bom.py,sha256=lWT9RNmJG8i-l5AXIpaCT3qCPUwRgzXPW3eoOjmZE
|
|
|
61
61
|
schemathesis/generation/__init__.py,sha256=29Zys_tD6kfngaC4zHeC6TOBZQcmo7CWm7KDSYsHStQ,1581
|
|
62
62
|
schemathesis/generation/_hypothesis.py,sha256=74fzLPHugZgMQXerWYFAMqCAjtAXz5E4gek7Gnkhli4,1756
|
|
63
63
|
schemathesis/generation/_methods.py,sha256=r8oVlJ71_gXcnEhU-byw2E0R2RswQQFm8U7yGErSqbw,1204
|
|
64
|
-
schemathesis/generation/coverage.py,sha256=
|
|
64
|
+
schemathesis/generation/coverage.py,sha256=6VCaQ8bUtBmbG-DCOS11rXHA-s6hiIzVtbXAB0pYMZU,38604
|
|
65
65
|
schemathesis/internal/__init__.py,sha256=93HcdG3LF0BbQKbCteOsFMa1w6nXl8yTmx87QLNJOik,161
|
|
66
66
|
schemathesis/internal/checks.py,sha256=SBx2gesB-XzgVSMX_u7Mb416jSxJ68eQKtcdkWlkyOo,2441
|
|
67
67
|
schemathesis/internal/copy.py,sha256=DcL56z-d69kKR_5u8mlHvjSL1UTyUKNMAwexrwHFY1s,1031
|
|
@@ -107,7 +107,7 @@ schemathesis/specs/graphql/validation.py,sha256=uINIOt-2E7ZuQV2CxKzwez-7L9tDtqzM
|
|
|
107
107
|
schemathesis/specs/openapi/__init__.py,sha256=HDcx3bqpa6qWPpyMrxAbM3uTo0Lqpg-BUNZhDJSJKnw,279
|
|
108
108
|
schemathesis/specs/openapi/_cache.py,sha256=PAiAu4X_a2PQgD2lG5H3iisXdyg4SaHpU46bRZvfNkM,4320
|
|
109
109
|
schemathesis/specs/openapi/_hypothesis.py,sha256=nU8UDn1PzGCre4IVmwIuO9-CZv1KJe1fYY0d2BojhSo,22981
|
|
110
|
-
schemathesis/specs/openapi/checks.py,sha256=
|
|
110
|
+
schemathesis/specs/openapi/checks.py,sha256=NZwcqmLnINq3rUUUmdof0GGB0AjaqSF5dOQy08nsJPg,23902
|
|
111
111
|
schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
|
|
112
112
|
schemathesis/specs/openapi/converter.py,sha256=Yxw9lS_JKEyi-oJuACT07fm04bqQDlAu-iHwzkeDvE4,3546
|
|
113
113
|
schemathesis/specs/openapi/definitions.py,sha256=WTkWwCgTc3OMxfKsqh6YDoGfZMTThSYrHGp8h0vLAK0,93935
|
|
@@ -117,7 +117,7 @@ schemathesis/specs/openapi/links.py,sha256=C4Uir2P_EcpqME8ee_a1vdUM8Tm3ZcKNn2YsG
|
|
|
117
117
|
schemathesis/specs/openapi/loaders.py,sha256=5B1cgYEBj3h2psPQxzrQ5Xq5owLVGw-u9HsCQIx7yFE,25705
|
|
118
118
|
schemathesis/specs/openapi/media_types.py,sha256=dNTxpRQbY3SubdVjh4Cjb38R6Bc9MF9BsRQwPD87x0g,1017
|
|
119
119
|
schemathesis/specs/openapi/parameters.py,sha256=LUahlWKCDSlp94v2IA1Q90pyeECgO6FmrqbzCU-9Z0Y,14658
|
|
120
|
-
schemathesis/specs/openapi/patterns.py,sha256=
|
|
120
|
+
schemathesis/specs/openapi/patterns.py,sha256=aEOiJeqI_qcE9bE2Viz6TUA8UppiTHm6QFxrLJryag8,5520
|
|
121
121
|
schemathesis/specs/openapi/references.py,sha256=euxM02kQGMHh4Ss1jWjOY_gyw_HazafKITIsvOEiAvI,9831
|
|
122
122
|
schemathesis/specs/openapi/schemas.py,sha256=MLU2h9DrQNCDkk74MFFSj-8BsKjkJsf9lJQHPxLFVps,53845
|
|
123
123
|
schemathesis/specs/openapi/security.py,sha256=Z-6pk2Ga1PTUtBe298KunjVHsNh5A-teegeso7zcPIE,7138
|
|
@@ -153,8 +153,8 @@ schemathesis/transports/auth.py,sha256=urSTO9zgFO1qU69xvnKHPFQV0SlJL3d7_Ojl0tLnZ
|
|
|
153
153
|
schemathesis/transports/content_types.py,sha256=MiKOm-Hy5i75hrROPdpiBZPOTDzOwlCdnthJD12AJzI,2187
|
|
154
154
|
schemathesis/transports/headers.py,sha256=hr_AIDOfUxsJxpHfemIZ_uNG3_vzS_ZeMEKmZjbYiBE,990
|
|
155
155
|
schemathesis/transports/responses.py,sha256=OFD4ZLqwEFpo7F9vaP_SVgjhxAqatxIj38FS4XVq8Qs,1680
|
|
156
|
-
schemathesis-3.38.
|
|
157
|
-
schemathesis-3.38.
|
|
158
|
-
schemathesis-3.38.
|
|
159
|
-
schemathesis-3.38.
|
|
160
|
-
schemathesis-3.38.
|
|
156
|
+
schemathesis-3.38.6.dist-info/METADATA,sha256=CbrAdVVhZVREx6pwkPRARvVXqETpf8YE34flEN3Tr4I,12923
|
|
157
|
+
schemathesis-3.38.6.dist-info/WHEEL,sha256=WJ9WQ4-pUYxfD_tEj5GvKSG9KSULNumqkTQdolV8mME,87
|
|
158
|
+
schemathesis-3.38.6.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
|
|
159
|
+
schemathesis-3.38.6.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
|
|
160
|
+
schemathesis-3.38.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|