schemathesis 4.0.0a7__py3-none-any.whl → 4.0.0a8__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/__init__.py CHANGED
@@ -8,6 +8,8 @@ from schemathesis.core.version import SCHEMATHESIS_VERSION
8
8
  from schemathesis.generation import GenerationConfig, GenerationMode, HeaderConfig
9
9
  from schemathesis.generation.case import Case
10
10
  from schemathesis.generation.targets import TargetContext, TargetFunction, target
11
+ from schemathesis.hooks import HookContext
12
+ from schemathesis.schemas import BaseSchema
11
13
 
12
14
  __version__ = SCHEMATHESIS_VERSION
13
15
 
@@ -26,6 +28,8 @@ __all__ = [
26
28
  "Response",
27
29
  "TargetContext",
28
30
  "TargetFunction",
31
+ "HookContext",
32
+ "BaseSchema",
29
33
  "__version__",
30
34
  "auth",
31
35
  "check",
@@ -251,7 +251,7 @@ class FailureGroup(BaseExceptionGroup):
251
251
  return super().__new__(cls, message, list(failures))
252
252
 
253
253
 
254
- class MessageBlock(Enum):
254
+ class MessageBlock(str, Enum):
255
255
  CASE_ID = "case_id"
256
256
  FAILURE = "failure"
257
257
  STATUS = "status"
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
10
10
  from schemathesis.engine.events import EventGenerator
11
11
 
12
12
 
13
- class PhaseName(enum.Enum):
13
+ class PhaseName(str, enum.Enum):
14
14
  """Available execution phases."""
15
15
 
16
16
  PROBING = "API probing"
@@ -51,43 +51,48 @@ def execute(engine: EngineContext, phase: Phase) -> events.EventGenerator:
51
51
  status = None
52
52
  is_executed = False
53
53
 
54
- with WorkerPool(
55
- workers_num=workers_num,
56
- producer=producer,
57
- worker_factory=worker_task,
58
- ctx=engine,
59
- mode=mode,
60
- phase=phase.name,
61
- suite_id=suite_started.id,
62
- ) as pool:
63
- try:
64
- while True:
65
- try:
66
- event = pool.events_queue.get(timeout=WORKER_TIMEOUT)
67
- is_executed = True
68
- if engine.is_interrupted:
69
- raise KeyboardInterrupt
70
- yield event
71
- if isinstance(event, events.NonFatalError):
72
- status = Status.ERROR
73
- if isinstance(event, events.ScenarioFinished):
74
- if event.status != Status.SKIP and (status is None or status < event.status):
75
- status = event.status
76
- if event.status in (Status.ERROR, Status.FAILURE):
77
- engine.control.count_failure()
78
- if isinstance(event, events.Interrupted) or engine.is_interrupted:
79
- status = Status.INTERRUPTED
80
- engine.stop()
81
- if engine.has_to_stop:
82
- break # type: ignore[unreachable]
83
- except queue.Empty:
84
- if all(not worker.is_alive() for worker in pool.workers):
85
- break
86
- continue
87
- except KeyboardInterrupt:
88
- engine.stop()
89
- status = Status.INTERRUPTED
90
- yield events.Interrupted(phase=phase.name)
54
+ try:
55
+ with WorkerPool(
56
+ workers_num=workers_num,
57
+ producer=producer,
58
+ worker_factory=worker_task,
59
+ ctx=engine,
60
+ mode=mode,
61
+ phase=phase.name,
62
+ suite_id=suite_started.id,
63
+ ) as pool:
64
+ try:
65
+ while True:
66
+ try:
67
+ event = pool.events_queue.get(timeout=WORKER_TIMEOUT)
68
+ is_executed = True
69
+ if engine.is_interrupted:
70
+ raise KeyboardInterrupt
71
+ yield event
72
+ if isinstance(event, events.NonFatalError):
73
+ status = Status.ERROR
74
+ if isinstance(event, events.ScenarioFinished):
75
+ if event.status != Status.SKIP and (status is None or status < event.status):
76
+ status = event.status
77
+ if event.status in (Status.ERROR, Status.FAILURE):
78
+ engine.control.count_failure()
79
+ if isinstance(event, events.Interrupted) or engine.is_interrupted:
80
+ status = Status.INTERRUPTED
81
+ engine.stop()
82
+ if engine.has_to_stop:
83
+ break # type: ignore[unreachable]
84
+ except queue.Empty:
85
+ if all(not worker.is_alive() for worker in pool.workers):
86
+ break
87
+ continue
88
+ except KeyboardInterrupt:
89
+ # Soft stop, waiting for workers to terminate
90
+ engine.stop()
91
+ status = Status.INTERRUPTED
92
+ yield events.Interrupted(phase=phase.name)
93
+ except KeyboardInterrupt:
94
+ # Hard stop, don't wait for worker threads
95
+ pass
91
96
 
92
97
  if not is_executed:
93
98
  phase.skip_reason = PhaseSkipReason.NOTHING_TO_TEST
@@ -150,7 +150,7 @@ class CoverageContext:
150
150
 
151
151
  def is_valid_for_location(self, value: Any) -> bool:
152
152
  if self.location in ("header", "cookie") and isinstance(value, str):
153
- return is_latin_1_encodable(value) and not has_invalid_characters("", value)
153
+ return not value or (is_latin_1_encodable(value) and not has_invalid_characters("", value))
154
154
  return True
155
155
 
156
156
  def generate_from(self, strategy: st.SearchStrategy) -> Any:
@@ -437,6 +437,36 @@ def cover_schema_iter(
437
437
  elif key == "required":
438
438
  template = template or ctx.generate_from_schema(_get_template_schema(schema, "object"))
439
439
  yield from _negative_required(ctx, template, value)
440
+ elif key == "maxItems" and isinstance(value, int) and value < BUFFER_SIZE:
441
+ try:
442
+ # Force the array to have one more item than allowed
443
+ new_schema = {**schema, "minItems": value + 1, "maxItems": value + 1, "type": "array"}
444
+ array_value = ctx.generate_from_schema(new_schema)
445
+ k = _to_hashable_key(array_value)
446
+ if k not in seen:
447
+ yield NegativeValue(
448
+ array_value,
449
+ description="Array with more items than allowed by maxItems",
450
+ location=ctx.current_path,
451
+ )
452
+ seen.add(k)
453
+ except (InvalidArgument, Unsatisfiable):
454
+ pass
455
+ elif key == "minItems" and isinstance(value, int) and value > 0:
456
+ try:
457
+ # Force the array to have one less item than the minimum
458
+ new_schema = {**schema, "minItems": value - 1, "maxItems": value - 1, "type": "array"}
459
+ array_value = ctx.generate_from_schema(new_schema)
460
+ k = _to_hashable_key(array_value)
461
+ if k not in seen:
462
+ yield NegativeValue(
463
+ array_value,
464
+ description="Array with fewer items than allowed by minItems",
465
+ location=ctx.current_path,
466
+ )
467
+ seen.add(k)
468
+ except (InvalidArgument, Unsatisfiable):
469
+ pass
440
470
  elif (
441
471
  key == "additionalProperties"
442
472
  and not value
@@ -770,7 +800,12 @@ def _negative_enum(
770
800
  _hashed = _to_hashable_key(x)
771
801
  return _hashed not in seen
772
802
 
773
- strategy = (st.none() | st.booleans() | NUMERIC_STRATEGY | st.text()).filter(is_not_in_value)
803
+ strategy = (
804
+ st.text(alphabet=st.characters(min_codepoint=65, max_codepoint=122, categories=["L"]), min_size=3)
805
+ | st.none()
806
+ | st.booleans()
807
+ | NUMERIC_STRATEGY
808
+ ).filter(is_not_in_value)
774
809
  value = ctx.generate_from(strategy)
775
810
  yield NegativeValue(value, description="Invalid enum value", location=ctx.current_path)
776
811
  hashed = _to_hashable_key(value)
@@ -1,9 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import asyncio
3
4
  from dataclasses import dataclass, field
4
5
  from enum import Enum
5
6
  from functools import wraps
6
7
  from itertools import combinations
8
+ import os
7
9
  from time import perf_counter
8
10
  from typing import Any, Callable, Generator, Mapping
9
11
 
@@ -15,7 +17,7 @@ from jsonschema.exceptions import SchemaError
15
17
 
16
18
  from schemathesis import auths
17
19
  from schemathesis.auths import AuthStorage, AuthStorageMark
18
- from schemathesis.core import NOT_SET, NotSet, SpecificationFeature, media_types
20
+ from schemathesis.core import NOT_SET, NotSet, SpecificationFeature, media_types, string_to_boolean
19
21
  from schemathesis.core.errors import InvalidSchema, SerializationNotPossible
20
22
  from schemathesis.core.marks import Mark
21
23
  from schemathesis.core.transport import prepare_urlencoded
@@ -38,7 +40,7 @@ from schemathesis.schemas import APIOperation, ParameterSet
38
40
  setup()
39
41
 
40
42
 
41
- class HypothesisTestMode(Enum):
43
+ class HypothesisTestMode(str, Enum):
42
44
  EXAMPLES = "examples"
43
45
  COVERAGE = "coverage"
44
46
  FUZZING = "fuzzing"
@@ -120,8 +122,11 @@ def create_test(
120
122
  ):
121
123
  hypothesis_test = add_examples(hypothesis_test, operation, hook_dispatcher=hook_dispatcher, **strategy_kwargs)
122
124
 
125
+ disable_coverage = string_to_boolean(os.getenv("SCHEMATHESIS_DISABLE_COVERAGE", ""))
126
+
123
127
  if (
124
- HypothesisTestMode.COVERAGE in config.modes
128
+ not disable_coverage
129
+ and HypothesisTestMode.COVERAGE in config.modes
125
130
  and Phase.explicit in settings.phases
126
131
  and specification.supports_feature(SpecificationFeature.COVERAGE)
127
132
  and not config.given_args
@@ -158,7 +163,24 @@ def create_base_test(
158
163
  __tracebackhide__ = True
159
164
  return test_function(*args, **kwargs)
160
165
 
161
- return hypothesis.given(*args, **{**kwargs, "case": strategy})(test_wrapper)
166
+ funcobj = hypothesis.given(*args, **{**kwargs, "case": strategy})(test_wrapper)
167
+
168
+ if asyncio.iscoroutinefunction(test_function):
169
+ funcobj.hypothesis.inner_test = make_async_test(test_function) # type: ignore
170
+ return funcobj
171
+
172
+
173
+ def make_async_test(test: Callable) -> Callable:
174
+ def async_run(*args: Any, **kwargs: Any) -> None:
175
+ try:
176
+ loop = asyncio.get_event_loop()
177
+ except RuntimeError:
178
+ loop = asyncio.new_event_loop()
179
+ coro = test(*args, **kwargs)
180
+ future = asyncio.ensure_future(coro, loop=loop)
181
+ loop.run_until_complete(future)
182
+
183
+ return async_run
162
184
 
163
185
 
164
186
  def add_examples(
schemathesis/hooks.py CHANGED
@@ -21,7 +21,7 @@ HookDispatcherMark = Mark["HookDispatcher"](attr_name="hook_dispatcher")
21
21
 
22
22
 
23
23
  @unique
24
- class HookScope(Enum):
24
+ class HookScope(int, Enum):
25
25
  GLOBAL = 1
26
26
  SCHEMA = 2
27
27
  TEST = 3
@@ -108,7 +108,12 @@ class SchemathesisCase(PyCollector):
108
108
  This implementation is based on the original one in pytest, but with slight adjustments
109
109
  to produce tests out of hypothesis ones.
110
110
  """
111
- from schemathesis.generation.hypothesis.builder import HypothesisTestConfig, HypothesisTestMode, create_test
111
+ from schemathesis.generation.hypothesis.builder import (
112
+ HypothesisTestConfig,
113
+ HypothesisTestMode,
114
+ create_test,
115
+ make_async_test,
116
+ )
112
117
 
113
118
  is_trio_test = False
114
119
  for mark in getattr(self.test_function, "pytestmark", []):
@@ -221,19 +226,6 @@ class SchemathesisCase(PyCollector):
221
226
  pytest.fail("Error during collection")
222
227
 
223
228
 
224
- def make_async_test(test: Callable) -> Callable:
225
- def async_run(*args: Any, **kwargs: Any) -> None:
226
- try:
227
- loop = asyncio.get_event_loop()
228
- except RuntimeError:
229
- loop = asyncio.new_event_loop()
230
- coro = test(*args, **kwargs)
231
- future = asyncio.ensure_future(coro, loop=loop)
232
- loop.run_until_complete(future)
233
-
234
- return async_run
235
-
236
-
237
229
  @hookimpl(hookwrapper=True) # type:ignore
238
230
  def pytest_pycollect_makeitem(collector: nodes.Collector, name: str, obj: Any) -> Generator[None, Any, None]:
239
231
  """Switch to a different collector if the test is parametrized marked by schemathesis."""
schemathesis/schemas.py CHANGED
@@ -14,7 +14,7 @@ from typing import (
14
14
  NoReturn,
15
15
  TypeVar,
16
16
  )
17
- from urllib.parse import quote, unquote, urljoin, urlsplit, urlunsplit
17
+ from urllib.parse import quote, unquote, urljoin, urlparse, urlsplit, urlunsplit
18
18
 
19
19
  from schemathesis import transport
20
20
  from schemathesis.core import NOT_SET, NotSet
@@ -436,6 +436,8 @@ class BaseSchema(Mapping):
436
436
  app: Any | NotSet = NOT_SET,
437
437
  ) -> Self:
438
438
  if not isinstance(base_url, NotSet):
439
+ if base_url is not None:
440
+ validate_base_url(base_url)
439
441
  self.base_url = base_url
440
442
  if not isinstance(location, NotSet):
441
443
  self.location = location
@@ -453,6 +455,21 @@ class BaseSchema(Mapping):
453
455
  return self
454
456
 
455
457
 
458
+ INVALID_BASE_URL_MESSAGE = (
459
+ "The provided base URL is invalid. This URL serves as a prefix for all API endpoints you want to test. "
460
+ "Make sure it is a properly formatted URL."
461
+ )
462
+
463
+
464
+ def validate_base_url(value: str) -> None:
465
+ try:
466
+ netloc = urlparse(value).netloc
467
+ except ValueError as exc:
468
+ raise ValueError(INVALID_BASE_URL_MESSAGE) from exc
469
+ if value and not netloc:
470
+ raise ValueError(INVALID_BASE_URL_MESSAGE)
471
+
472
+
456
473
  @dataclass
457
474
  class APIOperationMap(Mapping):
458
475
  _schema: BaseSchema
@@ -460,7 +460,7 @@ def ensure_resource_availability(ctx: CheckContext, response: Response, case: Ca
460
460
  )
461
461
 
462
462
 
463
- class AuthKind(enum.Enum):
463
+ class AuthKind(str, enum.Enum):
464
464
  EXPLICIT = "explicit"
465
465
  GENERATED = "generated"
466
466
 
@@ -6,7 +6,7 @@ from typing import Callable, Generator
6
6
 
7
7
 
8
8
  @unique
9
- class TokenType(Enum):
9
+ class TokenType(int, Enum):
10
10
  VARIABLE = 1
11
11
  STRING = 2
12
12
  POINTER = 3
@@ -25,7 +25,7 @@ class Node:
25
25
 
26
26
 
27
27
  @unique
28
- class NodeType(Enum):
28
+ class NodeType(str, Enum):
29
29
  URL = "$url"
30
30
  METHOD = "$method"
31
31
  STATUS_CODE = "$statusCode"
@@ -20,7 +20,7 @@ from .utils import can_negate
20
20
  T = TypeVar("T")
21
21
 
22
22
 
23
- class MutationResult(enum.Enum):
23
+ class MutationResult(int, enum.Enum):
24
24
  """The result of applying some mutation to some schema.
25
25
 
26
26
  Failing to mutate something means that by applying some mutation, it is not possible to change
@@ -134,6 +134,7 @@ class OpenAPI20Parameter(OpenAPIParameter):
134
134
  "multipleOf",
135
135
  "example",
136
136
  "examples",
137
+ "default",
137
138
  )
138
139
 
139
140
 
@@ -178,6 +179,7 @@ class OpenAPI30Parameter(OpenAPIParameter):
178
179
  "format",
179
180
  "example",
180
181
  "examples",
182
+ "default",
181
183
  )
182
184
 
183
185
  def from_open_api_to_json_schema(self, operation: APIOperation, open_api_schema: dict[str, Any]) -> dict[str, Any]:
@@ -230,6 +232,7 @@ class OpenAPI20Body(OpenAPIBody, OpenAPI20Parameter):
230
232
  "additionalProperties",
231
233
  "example",
232
234
  "examples",
235
+ "default",
233
236
  )
234
237
  # NOTE. For Open API 2.0 bodies, we still give `x-example` precedence over the schema-level `example` field to keep
235
238
  # the precedence rules consistent.
@@ -139,7 +139,10 @@ class ConvertingResolver(InliningResolver):
139
139
  def resolve(self, ref: str) -> tuple[str, Any]:
140
140
  url, document = super().resolve(ref)
141
141
  document = to_json_schema_recursive(
142
- document, nullable_name=self.nullable_name, is_response_schema=self.is_response_schema
142
+ document,
143
+ nullable_name=self.nullable_name,
144
+ is_response_schema=self.is_response_schema,
145
+ update_quantifiers=False,
143
146
  )
144
147
  return url, document
145
148
 
@@ -1022,24 +1022,30 @@ class SwaggerV20(BaseOpenAPISchema):
1022
1022
  content_types = self.get_request_payload_content_types(operation)
1023
1023
  is_multipart = "multipart/form-data" in content_types
1024
1024
 
1025
- def add_file(file_value: Any) -> None:
1026
- if isinstance(file_value, list):
1027
- for item in file_value:
1028
- files.append((name, (None, item)))
1029
- else:
1030
- files.append((name, file_value))
1025
+ known_fields: dict[str, dict] = {}
1031
1026
 
1032
1027
  for parameter in operation.body:
1033
1028
  if isinstance(parameter, OpenAPI20CompositeBody):
1034
1029
  for form_parameter in parameter.definition:
1035
- name = form_parameter.name
1036
- # It might be not in `form_data`, if the parameter is optional
1037
- if name in form_data:
1038
- value = form_data[name]
1039
- if form_parameter.definition.get("type") == "file" or is_multipart:
1040
- add_file(value)
1041
- else:
1042
- data[name] = value
1030
+ known_fields[form_parameter.name] = form_parameter.definition
1031
+
1032
+ def add_file(name: str, value: Any) -> None:
1033
+ if isinstance(value, list):
1034
+ for item in value:
1035
+ files.append((name, (None, item)))
1036
+ else:
1037
+ files.append((name, value))
1038
+
1039
+ for name, value in form_data.items():
1040
+ param_def = known_fields.get(name)
1041
+ if param_def:
1042
+ if param_def.get("type") == "file" or is_multipart:
1043
+ add_file(name, value)
1044
+ else:
1045
+ data[name] = value
1046
+ else:
1047
+ # Unknown field — treat it as a file (safe default under multipart/form-data)
1048
+ add_file(name, value)
1043
1049
  # `None` is the default value for `files` and `data` arguments in `requests.request`
1044
1050
  return files or None, data or None
1045
1051
 
@@ -1202,14 +1208,19 @@ class OpenApi30(SwaggerV20):
1202
1208
  break
1203
1209
  else:
1204
1210
  raise InternalError("No 'multipart/form-data' media type found in the schema")
1205
- for name, property_schema in (schema or {}).get("properties", {}).items():
1206
- if name in form_data:
1207
- if isinstance(form_data[name], list):
1208
- files.extend([(name, item) for item in form_data[name]])
1211
+ for name, value in form_data.items():
1212
+ property_schema = (schema or {}).get("properties", {}).get(name)
1213
+ if property_schema:
1214
+ if isinstance(value, list):
1215
+ files.extend([(name, item) for item in value])
1209
1216
  elif property_schema.get("format") in ("binary", "base64"):
1210
- files.append((name, form_data[name]))
1217
+ files.append((name, value))
1211
1218
  else:
1212
- files.append((name, (None, form_data[name])))
1219
+ files.append((name, (None, value)))
1220
+ elif isinstance(value, list):
1221
+ files.extend([(name, item) for item in value])
1222
+ else:
1223
+ files.append((name, (None, value)))
1213
1224
  # `None` is the default value for `files` and `data` arguments in `requests.request`
1214
1225
  return files or None, None
1215
1226
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: schemathesis
3
- Version: 4.0.0a7
3
+ Version: 4.0.0a8
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
@@ -1,11 +1,11 @@
1
- schemathesis/__init__.py,sha256=ggp1CxctLo__wwFwlDhvtrexxDXGSbRjFKzXw_Twi7k,1139
1
+ schemathesis/__init__.py,sha256=S9MD8cGyXWihyQikye9mSBpvrfUJbOItD5yr65vkx6A,1263
2
2
  schemathesis/auths.py,sha256=t-YuPyoLqL7jlRUH-45JxO7Ir3pYxpe31CRmNIJh7rI,15423
3
3
  schemathesis/checks.py,sha256=B5-ROnjvvwpaqgj_iQ7eCjGqvRRVT30eWNPLKmwdrM8,5084
4
4
  schemathesis/errors.py,sha256=VSZ-h9Bt7QvrvywOGB-MoHCshR8OWJegYlBxfVh5Vuw,899
5
5
  schemathesis/filters.py,sha256=CzVPnNSRLNgvLlU5_WssPEC0wpdQi0dMvDpHSQbAlkE,13577
6
- schemathesis/hooks.py,sha256=jTdN5GJbxHRMshxgcuI_th9ouuL32CN4m2Jt0pmT_bs,13148
6
+ schemathesis/hooks.py,sha256=ZSGEnsLJ7UVezf4CcaJebVkjEpvwgJolJFZo5fjQNDc,13153
7
7
  schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- schemathesis/schemas.py,sha256=Hs2pJTUa2Od3x5YRprrKYIfE7ndpKbAqeDylAWkB6yM,27407
8
+ schemathesis/schemas.py,sha256=A2qAs1PY9wbRWk6PFnslWyIqzchAhu5oo_MsKL7uF8w,27952
9
9
  schemathesis/cli/__init__.py,sha256=U9gjzWWpiFhaqevPjZbwyTNjABdpvXETI4HgwdGKnvs,877
10
10
  schemathesis/cli/__main__.py,sha256=MWaenjaUTZIfNPFzKmnkTiawUri7DVldtg3mirLwzU8,92
11
11
  schemathesis/cli/constants.py,sha256=rUixnqorraUFDtOu3Nmm1x_k0qbgmW9xW96kQB_fBCQ,338
@@ -40,7 +40,7 @@ schemathesis/core/control.py,sha256=IzwIc8HIAEMtZWW0Q0iXI7T1niBpjvcLlbuwOSmy5O8,
40
40
  schemathesis/core/curl.py,sha256=yuaCe_zHLGwUjEeloQi6W3tOA3cGdnHDNI17-5jia0o,1723
41
41
  schemathesis/core/deserialization.py,sha256=ygIj4fNaOd0mJ2IvTsn6bsabBt_2AbSLCz-z9UqfpdQ,2406
42
42
  schemathesis/core/errors.py,sha256=97Fk3udsMaS5xZrco7ZaShqe4W6g2aZ55J7d58HPRac,15881
43
- schemathesis/core/failures.py,sha256=jbbxOXB8LDYoLI97YrLCKi9XLuSqVqFJSLeeixVJPRU,8828
43
+ schemathesis/core/failures.py,sha256=nt_KJAQnachw4Ey-rZ__P8q6nGJ_YekZiSLc6-PfFW0,8833
44
44
  schemathesis/core/fs.py,sha256=ItQT0_cVwjDdJX9IiI7EnU75NI2H3_DCEyyUjzg_BgI,472
45
45
  schemathesis/core/lazy_import.py,sha256=aMhWYgbU2JOltyWBb32vnWBb6kykOghucEzI_F70yVE,470
46
46
  schemathesis/core/loaders.py,sha256=SQQ-8m64-D2FaOgvwKZLyTtLJuzP3RPo7Ud2BERK1c0,3404
@@ -63,24 +63,24 @@ schemathesis/engine/core.py,sha256=DfulRMVTivmZj-wwLekIhuSzLsFnuVPtSg7j9HyWdz0,5
63
63
  schemathesis/engine/errors.py,sha256=8PHYsuq2qIEJHm2FDf_UnWa4IDc-DRFTPckLAr22yhE,16895
64
64
  schemathesis/engine/events.py,sha256=gslRAWQKMPqBCQzLDS4wAbsKcVuONSy5SPqimJJJYT4,6250
65
65
  schemathesis/engine/recorder.py,sha256=K3HfMARrT5mPWXPnYebjjcq5CcsBRhMrtZwEL9_Lvtg,8432
66
- schemathesis/engine/phases/__init__.py,sha256=3p_T3JYBFOtrwtgmMM7J-6a41QJgk83dUtm7NKcVl3o,2490
66
+ schemathesis/engine/phases/__init__.py,sha256=CuTBMaQIsGdtWw400maiwqfIbMyVv5_vHXV-SY5A5NI,2495
67
67
  schemathesis/engine/phases/probes.py,sha256=3M9g3E7CXbDDK_8inuvkRZibCCcoO2Ce5U3lnyTeWXQ,5131
68
68
  schemathesis/engine/phases/stateful/__init__.py,sha256=lWo2RLrutNblHvohTzofQqL22GORwBRA8bf6jvLuGPg,2391
69
69
  schemathesis/engine/phases/stateful/_executor.py,sha256=m1ZMqFUPc4Hdql10l0gF3tpP4JOImSA-XeBd4jg3Ll8,12443
70
70
  schemathesis/engine/phases/stateful/context.py,sha256=SKWsok-tlWbUDagiUmP7cLNW6DsgFDc_Afv0vQfWv6c,2964
71
- schemathesis/engine/phases/unit/__init__.py,sha256=LcBQpGNPeEFB9XPGpcHBcH-C7nF-e8bZNPop9PIfiKA,7861
71
+ schemathesis/engine/phases/unit/__init__.py,sha256=QmtzIgP9KWLo-IY1kMyBqYXPMxFQz-WF2eVTWewqUfI,8174
72
72
  schemathesis/engine/phases/unit/_executor.py,sha256=buMEr7e01SFSeNuEQNGMf4hoiLxX9_sp0JhH4LBAk9M,12928
73
73
  schemathesis/engine/phases/unit/_pool.py,sha256=9OgmFd-ov1AAvcZGquK40PXkGLp7f2qCjZoPZuoZl4A,2529
74
74
  schemathesis/experimental/__init__.py,sha256=jYY3Mq6okqTRTMudPzcaT0JVjzJW5IN_ZVJdGU0stBs,2011
75
75
  schemathesis/generation/__init__.py,sha256=sWTRPTh-qDNkSfpM9rYI3v8zskH8_wFKUuPRg18fZI8,1627
76
76
  schemathesis/generation/case.py,sha256=Rt5MCUtPVYVQzNyjUx8magocPJpHV1svyuqQSTwUE-I,7306
77
- schemathesis/generation/coverage.py,sha256=hyDb465tBoCWE7nI-ZJjhTUzk7f2WDufaadWdSAkdr0,39276
77
+ schemathesis/generation/coverage.py,sha256=vv2dbj_KAaqo8PCwMdyDWLyyAssk-YL5oTU3aCkgB1s,41185
78
78
  schemathesis/generation/meta.py,sha256=36h6m4E7jzLGa8TCvl7eBl_xUWLiRul3qxzexl5cB58,2515
79
79
  schemathesis/generation/modes.py,sha256=t_EvKr2aOXYMsEfdMu4lLF4KCGcX1LVVyvzTkcpJqhk,663
80
80
  schemathesis/generation/overrides.py,sha256=FhqcFoliEvgW6MZyFPYemfLgzKt3Miy8Cud7OMOCb7g,3045
81
81
  schemathesis/generation/targets.py,sha256=_rN2qgxTE2EfvygiN-Fy3WmDnRH0ERohdx3sKRDaYhU,2120
82
82
  schemathesis/generation/hypothesis/__init__.py,sha256=Rl7QwvMBMJI7pBqTydplX6bXC420n0EGQHVm-vZgaYQ,1204
83
- schemathesis/generation/hypothesis/builder.py,sha256=6U4BaTx0VMVRXhmKrEakDSnHunIdEMQiBZfr89pdpP4,29618
83
+ schemathesis/generation/hypothesis/builder.py,sha256=cSgFWQG-apIHNdW-PpIBDBjLw4RorihfZ4e_Ln3j2-w,30341
84
84
  schemathesis/generation/hypothesis/examples.py,sha256=6eGaKUEC3elmKsaqfKj1sLvM8EHc-PWT4NRBq4NI0Rs,1409
85
85
  schemathesis/generation/hypothesis/given.py,sha256=sTZR1of6XaHAPWtHx2_WLlZ50M8D5Rjux0GmWkWjDq4,2337
86
86
  schemathesis/generation/hypothesis/reporting.py,sha256=uDVow6Ya8YFkqQuOqRsjbzsbyP4KKfr3jA7ZaY4FuKY,279
@@ -99,7 +99,7 @@ schemathesis/pytest/__init__.py,sha256=7W0q-Thcw03IAQfXE_Mo8JPZpUdHJzfu85fjK1Zdf
99
99
  schemathesis/pytest/control_flow.py,sha256=F8rAPsPeNv_sJiJgbZYtTpwKWjauZmqFUaKroY2GmQI,217
100
100
  schemathesis/pytest/lazy.py,sha256=g7DpOeQNsjXC03FCG5e1L65iz3zE48qAyaqG81HzCZY,12028
101
101
  schemathesis/pytest/loaders.py,sha256=oQJ78yyuIm3Ye9X7giVjDB1vYfaW5UY5YuhaTLm_ZFU,266
102
- schemathesis/pytest/plugin.py,sha256=RDOuT25Uotese7W-SD3Pu-nb7zdnaPbyPOoJSkJKSoQ,12379
102
+ schemathesis/pytest/plugin.py,sha256=TxbESQy9JPZBaIwUP4BHiIGFzPd2oMWwq_4VqFS_UfI,12067
103
103
  schemathesis/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
104
  schemathesis/python/asgi.py,sha256=5PyvuTBaivvyPUEi3pwJni91K1kX5Zc0u9c6c1D8a1Q,287
105
105
  schemathesis/python/wsgi.py,sha256=uShAgo_NChbfYaV1117e6UHp0MTg7jaR0Sy_to3Jmf8,219
@@ -113,28 +113,28 @@ schemathesis/specs/graphql/validation.py,sha256=-W1Noc1MQmTb4RX-gNXMeU2qkgso4mzV
113
113
  schemathesis/specs/openapi/__init__.py,sha256=C5HOsfuDJGq_3mv8CRBvRvb0Diy1p0BFdqyEXMS-loE,238
114
114
  schemathesis/specs/openapi/_cache.py,sha256=HpglmETmZU0RCHxp3DO_sg5_B_nzi54Zuw9vGzzYCxY,4295
115
115
  schemathesis/specs/openapi/_hypothesis.py,sha256=n_39iyz1rt2EdSe-Lyr-3sOIEyJIthnCVR4tGUUvH1c,21328
116
- schemathesis/specs/openapi/checks.py,sha256=m3n5N3_iZcS7inJojW47FF6dfbUQzrBH-bXwsCAOyhM,27737
116
+ schemathesis/specs/openapi/checks.py,sha256=i4tVVkK1wLthdmG-zu7EaQLkBxJ2T3FkuHqw0dA4qlA,27742
117
117
  schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
118
118
  schemathesis/specs/openapi/converter.py,sha256=lil8IewM5j8tvt4lpA9g_KITvIwx1M96i45DNSHNjoc,3505
119
119
  schemathesis/specs/openapi/definitions.py,sha256=8htclglV3fW6JPBqs59lgM4LnA25Mm9IptXBPb_qUT0,93949
120
120
  schemathesis/specs/openapi/examples.py,sha256=Xvjp60QUcLaeGsJRbi2i6XM15_4uO0ceVoClIaJehiE,21062
121
121
  schemathesis/specs/openapi/formats.py,sha256=ViVF3aFeFI1ctwGQbiRDXhU3so82P0BCaF2aDDbUUm8,2816
122
122
  schemathesis/specs/openapi/media_types.py,sha256=ADedOaNWjbAtAekyaKmNj9fY6zBTeqcNqBEjN0EWNhI,1014
123
- schemathesis/specs/openapi/parameters.py,sha256=hv1reNpSjVuzFbtMpSTwWZ75zcWTOy5ZE0ah6AVEqAo,14565
123
+ schemathesis/specs/openapi/parameters.py,sha256=tVL61gDe9A8_jwoVKZZvpXKPerMyq7vkAvwdMsi44TI,14622
124
124
  schemathesis/specs/openapi/patterns.py,sha256=NLnGybcana_kYLVKVEjkEyAzdClAV0xKe4Oy4NVayMI,12834
125
- schemathesis/specs/openapi/references.py,sha256=YjD1xMlaYS7xLt6PrrVS20R72ZWHuFZFTa8Llzf54Rg,8808
126
- schemathesis/specs/openapi/schemas.py,sha256=VSeacEAVJJ6EKJ-llwOaX4aalzUTXyWP8s4wbxTqtWc,54720
125
+ schemathesis/specs/openapi/references.py,sha256=c8Ufa8hp6Dyf-gPn5lpmyqF_GtqXIBWoKkj3bk3WaPA,8871
126
+ schemathesis/specs/openapi/schemas.py,sha256=zfGPFWnaI9_W8F8E8qCTzuYQRE5yDuGx7WGW4EH-QgI,55020
127
127
  schemathesis/specs/openapi/security.py,sha256=6UWYMhL-dPtkTineqqBFNKca1i4EuoTduw-EOLeE0aQ,7149
128
128
  schemathesis/specs/openapi/serialization.py,sha256=VdDLmeHqxlWM4cxQQcCkvrU6XurivolwEEaT13ohelA,11972
129
129
  schemathesis/specs/openapi/utils.py,sha256=ER4vJkdFVDIE7aKyxyYatuuHVRNutytezgE52pqZNE8,900
130
130
  schemathesis/specs/openapi/expressions/__init__.py,sha256=hfuRtXD75tQFhzSo6QgDZ3zByyWeZRKevB8edszAVj4,2272
131
131
  schemathesis/specs/openapi/expressions/errors.py,sha256=YLVhps-sYcslgVaahfcUYxUSHlIfWL-rQMeT5PZSMZ8,219
132
132
  schemathesis/specs/openapi/expressions/extractors.py,sha256=Py3of3_vBACP4ljiZIcgd-xQCrWIpcMsfQFc0EtAUoA,470
133
- schemathesis/specs/openapi/expressions/lexer.py,sha256=LeVE6fgYT9-fIsXrv0-YrRHnI4VPisbwsexyh9Q5YU0,3982
134
- schemathesis/specs/openapi/expressions/nodes.py,sha256=YvpbAi8OFdb6RqqrqReGBeADpAmFaoyWN-lGiyYOXTc,4072
133
+ schemathesis/specs/openapi/expressions/lexer.py,sha256=KFA8Z-Kh1IYUpKgwAnDtEucN9YLLpnFR1GQl8KddWlA,3987
134
+ schemathesis/specs/openapi/expressions/nodes.py,sha256=63LC4mQHy3a0_tKiGIVWaUHu9L9IWilq6R004GLpjyY,4077
135
135
  schemathesis/specs/openapi/expressions/parser.py,sha256=e-ZxshrGE_5CVbgcZLYgdGSjdifgyzgKkLQp0dI0cJY,4503
136
136
  schemathesis/specs/openapi/negative/__init__.py,sha256=60QqVBTXPTsAojcf7GDs7v8WbOE_k3g_VC_DBeQUqBw,3749
137
- schemathesis/specs/openapi/negative/mutations.py,sha256=7jTjD9rt5vxWSVBL5Hx8Avj4WhTA63frDQiFMKysrUU,19248
137
+ schemathesis/specs/openapi/negative/mutations.py,sha256=MIFVSWbZHW92KhpWruJT3XLisgc-rFnvYasRtwMmExs,19253
138
138
  schemathesis/specs/openapi/negative/types.py,sha256=a7buCcVxNBG6ILBM3A7oNTAX0lyDseEtZndBuej8MbI,174
139
139
  schemathesis/specs/openapi/negative/utils.py,sha256=ozcOIuASufLqZSgnKUACjX-EOZrrkuNdXX0SDnLoGYA,168
140
140
  schemathesis/specs/openapi/stateful/__init__.py,sha256=0pu_iGjRiKuqUDN3ewz1zUOt6f1SdvSxVtHC5uK-CYw,14750
@@ -146,8 +146,8 @@ schemathesis/transport/prepare.py,sha256=qQ6zXBw5NN2AIM0bzLAc5Ryc3dmMb0R6xN14lnR
146
146
  schemathesis/transport/requests.py,sha256=j5wI1Uo_PnVuP1eV8l6ddsXosyxAPQ1mLSyWEZmTI9I,8747
147
147
  schemathesis/transport/serialization.py,sha256=jIMra1LqRGav0OX3Hx7mvORt38ll4cd2DKit2D58FN0,10531
148
148
  schemathesis/transport/wsgi.py,sha256=RWSuUXPrl91GxAy8a4jyNNozOWVMRBxKx_tljlWA_Lo,5697
149
- schemathesis-4.0.0a7.dist-info/METADATA,sha256=l_31cA1530vqN9M094EGpnFezX2Sk-YyJDq8_pSWcro,10427
150
- schemathesis-4.0.0a7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
151
- schemathesis-4.0.0a7.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
152
- schemathesis-4.0.0a7.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
153
- schemathesis-4.0.0a7.dist-info/RECORD,,
149
+ schemathesis-4.0.0a8.dist-info/METADATA,sha256=hdJd_ASqgZ75dZ1EW27p3mL6CAG179nTb-cm1zVtQqk,10427
150
+ schemathesis-4.0.0a8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
151
+ schemathesis-4.0.0a8.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
152
+ schemathesis-4.0.0a8.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
153
+ schemathesis-4.0.0a8.dist-info/RECORD,,