schemathesis 3.22.1__py3-none-any.whl → 3.23.1__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.
@@ -134,6 +134,12 @@ def add_examples(test: Callable, operation: APIOperation, hook_dispatcher: HookD
134
134
 
135
135
 
136
136
  def get_single_example(strategy: st.SearchStrategy[Case]) -> Case:
137
+ examples: list[Case] = []
138
+ add_single_example(strategy, examples)
139
+ return examples[0]
140
+
141
+
142
+ def add_single_example(strategy: st.SearchStrategy[Case], examples: list[Case]) -> None:
137
143
  @hypothesis.given(strategy) # type: ignore
138
144
  @hypothesis.settings( # type: ignore
139
145
  database=None,
@@ -146,6 +152,4 @@ def get_single_example(strategy: st.SearchStrategy[Case]) -> Case:
146
152
  def example_generating_inner_function(ex: Case) -> None:
147
153
  examples.append(ex)
148
154
 
149
- examples: list[Case] = []
150
155
  example_generating_inner_function()
151
- return examples[0]
@@ -165,6 +165,11 @@ class GroupedOption(click.Option):
165
165
  self.group = group
166
166
 
167
167
 
168
+ with_request_proxy = click.option(
169
+ "--request-proxy",
170
+ help="Set the proxy for all network requests.",
171
+ type=str,
172
+ )
168
173
  with_request_tls_verify = click.option(
169
174
  "--request-tls-verify",
170
175
  help="Configures TLS certificate verification for server requests. Can specify path to CA_BUNDLE for custom certs.",
@@ -398,6 +403,7 @@ REPORT_TO_SERVICE = ReportToService()
398
403
  type=click.IntRange(1),
399
404
  default=DEFAULT_RESPONSE_TIMEOUT,
400
405
  )
406
+ @with_request_proxy
401
407
  @with_request_tls_verify
402
408
  @with_request_cert
403
409
  @with_request_cert_key
@@ -542,6 +548,14 @@ The report data, consisting of a tar gz file with multiple JSON files, is subjec
542
548
  default=False,
543
549
  show_default=True,
544
550
  )
551
+ @click.option(
552
+ "--contrib-openapi-fill-missing-examples",
553
+ "contrib_openapi_fill_missing_examples",
554
+ help="Enables generation of random examples for API operations that do not have explicit examples defined.",
555
+ is_flag=True,
556
+ default=False,
557
+ show_default=True,
558
+ )
545
559
  @click.option(
546
560
  "--hypothesis-database",
547
561
  help="Configures storage for examples discovered by Hypothesis. "
@@ -637,6 +651,7 @@ The report data, consisting of a tar gz file with multiple JSON files, is subjec
637
651
  help="Specifies the codec used for generating strings.",
638
652
  type=str,
639
653
  default="utf-8",
654
+ callback=callbacks.validate_generation_codec,
640
655
  )
641
656
  @click.option(
642
657
  "--schemathesis-io-token",
@@ -690,6 +705,7 @@ def run(
690
705
  request_tls_verify: bool = True,
691
706
  request_cert: str | None = None,
692
707
  request_cert_key: str | None = None,
708
+ request_proxy: str | None = None,
693
709
  validate_schema: bool = True,
694
710
  skip_deprecated_operations: bool = False,
695
711
  junit_xml: click.utils.LazyFile | None = None,
@@ -709,6 +725,7 @@ def run(
709
725
  sanitize_output: bool = True,
710
726
  contrib_unique_data: bool = False,
711
727
  contrib_openapi_formats_uuid: bool = False,
728
+ contrib_openapi_fill_missing_examples: bool = False,
712
729
  hypothesis_database: str | None = None,
713
730
  hypothesis_deadline: int | NotSet | None = None,
714
731
  hypothesis_derandomize: bool | None = None,
@@ -842,6 +859,8 @@ def run(
842
859
  contrib.unique_data.install()
843
860
  if contrib_openapi_formats_uuid:
844
861
  contrib.openapi.formats.uuid.install()
862
+ if contrib_openapi_fill_missing_examples:
863
+ contrib.openapi.fill_missing_examples.install()
845
864
 
846
865
  hypothesis_settings = prepare_hypothesis_settings(
847
866
  database=hypothesis_database,
@@ -863,6 +882,7 @@ def run(
863
882
  data_generation_methods=data_generation_methods,
864
883
  force_schema_version=force_schema_version,
865
884
  request_tls_verify=request_tls_verify,
885
+ request_proxy=request_proxy,
866
886
  request_cert=prepare_request_cert(request_cert, request_cert_key),
867
887
  wait_for_schema=wait_for_schema,
868
888
  auth=auth,
@@ -936,6 +956,7 @@ class LoaderConfig:
936
956
  data_generation_methods: tuple[DataGenerationMethod, ...]
937
957
  force_schema_version: str | None
938
958
  request_tls_verify: bool | str
959
+ request_proxy: str | None
939
960
  request_cert: RequestCert | None
940
961
  wait_for_schema: float | None
941
962
  rate_limit: str | None
@@ -961,6 +982,7 @@ def into_event_stream(
961
982
  data_generation_methods: tuple[DataGenerationMethod, ...],
962
983
  force_schema_version: str | None,
963
984
  request_tls_verify: bool | str,
985
+ request_proxy: str | None,
964
986
  request_cert: RequestCert | None,
965
987
  # Network request parameters
966
988
  auth: tuple[str, str] | None,
@@ -1000,6 +1022,7 @@ def into_event_stream(
1000
1022
  skip_deprecated_operations=skip_deprecated_operations,
1001
1023
  data_generation_methods=data_generation_methods,
1002
1024
  force_schema_version=force_schema_version,
1025
+ request_proxy=request_proxy,
1003
1026
  request_tls_verify=request_tls_verify,
1004
1027
  request_cert=request_cert,
1005
1028
  wait_for_schema=wait_for_schema,
@@ -1020,6 +1043,7 @@ def into_event_stream(
1020
1043
  headers=headers,
1021
1044
  request_timeout=request_timeout,
1022
1045
  request_tls_verify=request_tls_verify,
1046
+ request_proxy=request_proxy,
1023
1047
  request_cert=request_cert,
1024
1048
  seed=seed,
1025
1049
  exit_first=exit_first,
@@ -1073,7 +1097,7 @@ def _try_load_schema(config: LoaderConfig, first: Loader, second: Loader) -> Bas
1073
1097
  try:
1074
1098
  return first(config)
1075
1099
  except SchemaError as exc:
1076
- if should_try_more(exc):
1100
+ if config.force_schema_version is None and should_try_more(exc):
1077
1101
  try:
1078
1102
  return second(config)
1079
1103
  except Exception as second_exc:
@@ -1088,6 +1112,8 @@ def is_specific_exception(loader: Loader, exc: Exception) -> bool:
1088
1112
  loader is _load_graphql_schema
1089
1113
  and isinstance(exc, SchemaError)
1090
1114
  and exc.type == SchemaErrorType.GRAPHQL_INVALID_SCHEMA
1115
+ # In some cases it is not clear that the schema is even supposed to be GraphQL, e.g. an empty input
1116
+ and "Syntax Error: Unexpected <EOF>." not in exc.extras
1091
1117
  )
1092
1118
 
1093
1119
 
@@ -1417,6 +1443,7 @@ def get_exit_code(event: events.ExecutionEvent) -> int:
1417
1443
  @click.option("--force-color", help="Explicitly tells to enable ANSI color escape codes.", type=bool, is_flag=True)
1418
1444
  @click.option("--verbosity", "-v", help="Increase verbosity of the output.", count=True)
1419
1445
  @with_request_tls_verify
1446
+ @with_request_proxy
1420
1447
  @with_request_cert
1421
1448
  @with_request_cert_key
1422
1449
  @click.pass_context
@@ -1432,6 +1459,7 @@ def replay(
1432
1459
  request_tls_verify: bool = True,
1433
1460
  request_cert: str | None = None,
1434
1461
  request_cert_key: str | None = None,
1462
+ request_proxy: str | None = None,
1435
1463
  force_color: bool = False,
1436
1464
  ) -> None:
1437
1465
  """Replay a cassette.
@@ -1455,6 +1483,7 @@ def replay(
1455
1483
  method=method,
1456
1484
  request_tls_verify=request_tls_verify,
1457
1485
  request_cert=prepare_request_cert(request_cert, request_cert_key),
1486
+ request_proxy=request_proxy,
1458
1487
  ):
1459
1488
  click.secho(f" {bold('ID')} : {replayed.interaction['id']}")
1460
1489
  click.secho(f" {bold('URI')} : {replayed.interaction['request']['uri']}")
@@ -1,4 +1,6 @@
1
1
  from __future__ import annotations
2
+
3
+ import codecs
2
4
  import enum
3
5
  import os
4
6
  import re
@@ -137,6 +139,14 @@ def validate_base_url(ctx: click.core.Context, param: click.core.Parameter, raw_
137
139
  return raw_value
138
140
 
139
141
 
142
+ def validate_generation_codec(ctx: click.core.Context, param: click.core.Parameter, raw_value: str) -> str:
143
+ try:
144
+ codecs.getencoder(raw_value)
145
+ except LookupError as exc:
146
+ raise click.UsageError(f"Codec `{raw_value}` is unknown") from exc
147
+ return raw_value
148
+
149
+
140
150
  def validate_rate_limit(ctx: click.core.Context, param: click.core.Parameter, raw_value: str | None) -> str | None:
141
151
  if raw_value is None:
142
152
  return raw_value
@@ -290,6 +290,7 @@ def replay(
290
290
  method: str | None = None,
291
291
  request_tls_verify: bool = True,
292
292
  request_cert: RequestCert | None = None,
293
+ request_proxy: str | None = None,
293
294
  ) -> Generator[Replayed, None, None]:
294
295
  """Replay saved interactions."""
295
296
  import requests
@@ -297,9 +298,12 @@ def replay(
297
298
  session = requests.Session()
298
299
  session.verify = request_tls_verify
299
300
  session.cert = request_cert
301
+ kwargs = {}
302
+ if request_proxy is not None:
303
+ kwargs["proxies"] = {"all": request_proxy}
300
304
  for interaction in filter_cassette(cassette["http_interactions"], id_, status, uri, method):
301
305
  request = get_prepared_request(interaction["request"])
302
- response = session.send(request) # type: ignore
306
+ response = session.send(request, **kwargs) # type: ignore
303
307
  yield Replayed(interaction, response)
304
308
 
305
309
 
@@ -1,9 +1,11 @@
1
- from . import formats
1
+ from . import formats, fill_missing_examples
2
2
 
3
3
 
4
4
  def install() -> None:
5
5
  formats.install()
6
+ fill_missing_examples.install()
6
7
 
7
8
 
8
9
  def uninstall() -> None:
9
10
  formats.uninstall()
11
+ fill_missing_examples.uninstall()
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+ from typing import TYPE_CHECKING
3
+ from ...hooks import HookContext, register, unregister
4
+
5
+ if TYPE_CHECKING:
6
+ from ...models import Case
7
+
8
+
9
+ def install() -> None:
10
+ register(before_add_examples)
11
+
12
+
13
+ def uninstall() -> None:
14
+ unregister(before_add_examples)
15
+
16
+
17
+ def before_add_examples(context: HookContext, examples: list[Case]) -> None:
18
+ if not examples and context.operation is not None:
19
+ from ..._hypothesis import add_single_example
20
+
21
+ strategy = context.operation.as_strategy()
22
+ add_single_example(strategy, examples)
@@ -51,7 +51,7 @@ def make_unique_by_key(
51
51
 
52
52
 
53
53
  def deduplicate_failed_checks(
54
- checks: list[CheckFailed | AssertionError]
54
+ checks: list[CheckFailed | AssertionError],
55
55
  ) -> Generator[CheckFailed | AssertionError, None, None]:
56
56
  """Keep only unique failed checks."""
57
57
  seen = set()
@@ -462,7 +462,10 @@ def extract_requests_exception_details(exc: RequestException) -> tuple[str, list
462
462
  message = "Connection failed"
463
463
  inner = exc.args[0]
464
464
  if isinstance(inner, MaxRetryError) and inner.reason is not None:
465
- _, reason = inner.reason.args[0].split(":", maxsplit=1)
465
+ if ":" not in inner.reason.args[0]:
466
+ reason = inner.reason.args[0]
467
+ else:
468
+ _, reason = inner.reason.args[0].split(":", maxsplit=1)
466
469
  extra = [reason.strip()]
467
470
  else:
468
471
  extra = [" ".join(map(str, inner.args))]
schemathesis/models.py CHANGED
@@ -79,11 +79,7 @@ class CaseSource:
79
79
  elapsed: float
80
80
 
81
81
  def partial_deepcopy(self) -> CaseSource:
82
- from .transports.responses import copy_response
83
-
84
- return self.__class__(
85
- case=self.case.partial_deepcopy(), response=copy_response(self.response), elapsed=self.elapsed
86
- )
82
+ return self.__class__(case=self.case.partial_deepcopy(), response=self.response, elapsed=self.elapsed)
87
83
 
88
84
 
89
85
  def cant_serialize(media_type: str) -> NoReturn: # type: ignore
@@ -461,7 +457,7 @@ class Case:
461
457
  """
462
458
  __tracebackhide__ = True
463
459
  from .checks import ALL_CHECKS
464
- from .transports.responses import get_payload, copy_response, get_reason
460
+ from .transports.responses import get_payload, get_reason
465
461
 
466
462
  checks = checks or ALL_CHECKS
467
463
  checks = tuple(check for check in checks if check not in excluded_checks)
@@ -469,9 +465,8 @@ class Case:
469
465
  failed_checks = []
470
466
  for check in chain(checks, additional_checks):
471
467
  copied_case = self.partial_deepcopy()
472
- copied_response = copy_response(response)
473
468
  try:
474
- check(copied_response, copied_case)
469
+ check(response, copied_case)
475
470
  except AssertionError as exc:
476
471
  maybe_set_assertion_message(exc, check.__name__)
477
472
  failed_checks.append(exc)
@@ -323,6 +323,7 @@ def from_schema(
323
323
  headers: dict[str, Any] | None = None,
324
324
  request_timeout: int | None = None,
325
325
  request_tls_verify: bool | str = True,
326
+ request_proxy: str | None = None,
326
327
  request_cert: RequestCert | None = None,
327
328
  seed: int | None = None,
328
329
  exit_first: bool = False,
@@ -373,6 +374,7 @@ def from_schema(
373
374
  workers_num=workers_num,
374
375
  request_timeout=request_timeout,
375
376
  request_tls_verify=request_tls_verify,
377
+ request_proxy=request_proxy,
376
378
  request_cert=request_cert,
377
379
  exit_first=exit_first,
378
380
  max_failures=max_failures,
@@ -442,6 +444,7 @@ def from_schema(
442
444
  seed=seed,
443
445
  request_timeout=request_timeout,
444
446
  request_tls_verify=request_tls_verify,
447
+ request_proxy=request_proxy,
445
448
  request_cert=request_cert,
446
449
  exit_first=exit_first,
447
450
  max_failures=max_failures,
@@ -40,7 +40,6 @@ from ...internal.result import Ok
40
40
  from ...models import APIOperation, Case, Check, CheckFunction, Status, TestResult, TestResultSet
41
41
  from ...runner import events
42
42
  from ...internal.datetime import current_datetime
43
- from ...transports.responses import copy_response
44
43
  from ...schemas import BaseSchema
45
44
  from ...stateful import Feedback, Stateful
46
45
  from ...targets import Target, TargetContext
@@ -520,16 +519,15 @@ def run_checks(
520
519
  context = error.context
521
520
  else:
522
521
  context = None
523
- check_results.append(result.add_failure(check_name, copied_case, copied_response, elapsed_time, msg, context))
522
+ check_results.append(result.add_failure(check_name, copied_case, response, elapsed_time, msg, context))
524
523
 
525
524
  for check in checks:
526
525
  check_name = check.__name__
527
526
  copied_case = case.partial_deepcopy()
528
- copied_response = copy_response(response)
529
527
  try:
530
- skip_check = check(copied_response, copied_case)
528
+ skip_check = check(response, copied_case)
531
529
  if not skip_check:
532
- check_result = result.add_success(check_name, copied_case, copied_response, elapsed_time)
530
+ check_result = result.add_success(check_name, copied_case, response, elapsed_time)
533
531
  check_results.append(check_result)
534
532
  except AssertionError as exc:
535
533
  add_single_failure(exc)
@@ -621,6 +619,7 @@ def network_test(
621
619
  session: requests.Session,
622
620
  request_timeout: int | None,
623
621
  request_tls_verify: bool,
622
+ request_proxy: str | None,
624
623
  request_cert: RequestCert | None,
625
624
  store_interactions: bool,
626
625
  headers: dict[str, Any] | None,
@@ -649,6 +648,7 @@ def network_test(
649
648
  headers,
650
649
  feedback,
651
650
  request_tls_verify,
651
+ request_proxy,
652
652
  request_cert,
653
653
  max_response_time,
654
654
  )
@@ -667,6 +667,7 @@ def _network_test(
667
667
  headers: dict[str, Any] | None,
668
668
  feedback: Feedback,
669
669
  request_tls_verify: bool,
670
+ request_proxy: str | None,
670
671
  request_cert: RequestCert | None,
671
672
  max_response_time: int | None,
672
673
  ) -> requests.Response:
@@ -680,6 +681,8 @@ def _network_test(
680
681
  "verify": request_tls_verify,
681
682
  "cert": request_cert,
682
683
  }
684
+ if request_proxy is not None:
685
+ kwargs["proxies"] = {"all": request_proxy}
683
686
  hooks.dispatch("process_call_kwargs", hook_context, case, kwargs)
684
687
  response = case.call(**kwargs)
685
688
  except CheckFailed as exc:
@@ -15,6 +15,7 @@ class SingleThreadRunner(BaseRunner):
15
15
  """Fast runner that runs tests sequentially in the main thread."""
16
16
 
17
17
  request_tls_verify: bool | str = True
18
+ request_proxy: str | None = None
18
19
  request_cert: RequestCert | None = None
19
20
 
20
21
  def _execute(
@@ -42,6 +43,7 @@ class SingleThreadRunner(BaseRunner):
42
43
  headers=self.headers,
43
44
  request_timeout=self.request_timeout,
44
45
  request_tls_verify=self.request_tls_verify,
46
+ request_proxy=self.request_proxy,
45
47
  request_cert=self.request_cert,
46
48
  store_interactions=self.store_interactions,
47
49
  dry_run=self.dry_run,
@@ -224,6 +224,7 @@ class ThreadPoolRunner(BaseRunner):
224
224
 
225
225
  workers_num: int = 2
226
226
  request_tls_verify: bool | str = True
227
+ request_proxy: str | None = None
227
228
  request_cert: RequestCert | None = None
228
229
 
229
230
  def _execute(
@@ -330,6 +331,7 @@ class ThreadPoolRunner(BaseRunner):
330
331
  "kwargs": {
331
332
  "request_timeout": self.request_timeout,
332
333
  "request_tls_verify": self.request_tls_verify,
334
+ "request_proxy": self.request_proxy,
333
335
  "request_cert": self.request_cert,
334
336
  "store_interactions": self.store_interactions,
335
337
  "max_response_time": self.max_response_time,
schemathesis/schemas.py CHANGED
@@ -434,7 +434,7 @@ class BaseSchema(Mapping):
434
434
 
435
435
 
436
436
  def operations_to_dict(
437
- operations: Generator[Result[APIOperation, OperationSchemaError], None, None]
437
+ operations: Generator[Result[APIOperation, OperationSchemaError], None, None],
438
438
  ) -> dict[str, MethodsDict]:
439
439
  output: dict[str, MethodsDict] = {}
440
440
  for result in operations:
@@ -7,6 +7,7 @@ import requests
7
7
  from hypothesis.strategies import SearchStrategy
8
8
 
9
9
  from ...constants import DEFAULT_RESPONSE_TIMEOUT
10
+ from ...internal.copy import fast_deepcopy
10
11
  from ...models import APIOperation, Case
11
12
  from ._hypothesis import PARAMETERS, get_case_strategy
12
13
  from .constants import LOCATION_TO_CONTAINER
@@ -109,7 +110,13 @@ def get_static_parameters_from_example(operation: APIOperation) -> dict[str, Any
109
110
 
110
111
  def get_static_parameters_from_examples(operation: APIOperation, examples_field: str) -> list[dict[str, Any]]:
111
112
  """Get static parameters from OpenAPI examples keyword."""
112
- operation_definition = operation.definition.resolved
113
+ operation_definition = fast_deepcopy(operation.definition.resolved)
114
+ # Add shared parameters excluding body
115
+ for parameter in operation.definition.parameters:
116
+ parameters = operation_definition.setdefault("parameters", [])
117
+ if parameter.location == "body" or parameter.name in {parameter["name"] for parameter in parameters}:
118
+ continue
119
+ parameters.append(parameter.definition)
113
120
  return merge_examples(
114
121
  get_parameter_examples(operation_definition, examples_field),
115
122
  get_request_body_examples(operation_definition, examples_field),
@@ -184,6 +184,7 @@ def from_uri(
184
184
  )
185
185
 
186
186
 
187
+ SCHEMA_INVALID_ERROR = "The provided API schema does not appear to be a valid OpenAPI schema"
187
188
  SCHEMA_LOADING_ERROR = "Received unsupported content while expecting a JSON or YAML payload for Open API"
188
189
  SCHEMA_SYNTAX_ERROR = "API schema does not appear syntactically valid"
189
190
 
@@ -304,6 +305,8 @@ def from_dict(
304
305
  """
305
306
  from .schemas import OpenApi30, SwaggerV20
306
307
 
308
+ if not isinstance(raw_schema, dict):
309
+ raise SchemaError(SchemaErrorType.OPEN_API_INVALID_SCHEMA, SCHEMA_INVALID_ERROR)
307
310
  _code_sample_style = CodeSampleStyle.from_str(code_sample_style)
308
311
  hook_context = HookContext()
309
312
  is_openapi_31 = raw_schema.get("openapi", "").startswith("3.1")
@@ -435,7 +438,7 @@ def _maybe_validate_schema(
435
438
  except ValidationError as exc:
436
439
  raise SchemaError(
437
440
  SchemaErrorType.OPEN_API_INVALID_SCHEMA,
438
- "The provided API schema does not appear to be a valid OpenAPI schema",
441
+ SCHEMA_INVALID_ERROR,
439
442
  extras=[entry for entry in str(exc).splitlines() if entry],
440
443
  ) from exc
441
444
 
@@ -11,7 +11,7 @@ MapFunction = Callable[[Generated], Generated]
11
11
 
12
12
 
13
13
  def make_serializer(
14
- func: Callable[[DefinitionList], Generator[Callable | None, None, None]]
14
+ func: Callable[[DefinitionList], Generator[Callable | None, None, None]],
15
15
  ) -> Callable[[DefinitionList], Callable | None]:
16
16
  """A maker function to avoid code duplication."""
17
17
 
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import sys
4
- from copy import deepcopy, copy
5
4
  from json import JSONDecodeError
6
5
  from typing import Union, TYPE_CHECKING, NoReturn
7
6
  from .._compat import JSONMixin
@@ -31,31 +30,6 @@ def get_payload(response: GenericResponse) -> str:
31
30
  return response.get_data(as_text=True)
32
31
 
33
32
 
34
- def copy_response(response: GenericResponse) -> GenericResponse:
35
- """Create a copy of the given response as far as it makes sense."""
36
- from requests import Response
37
-
38
- if isinstance(response, Response):
39
- # Hooks are not copyable. Keep them out and copy the rest
40
- hooks = None
41
- if response.request is not None:
42
- hooks = response.request.hooks["response"]
43
- response.request.hooks["response"] = []
44
- copied_response = deepcopy(response)
45
- if hooks is not None:
46
- copied_response.request.hooks["response"] = hooks
47
- copied_response.raw = response.raw
48
- copied_response.verify = getattr(response, "verify", True) # type: ignore[union-attr]
49
- return copied_response
50
-
51
- # Can't deepcopy WSGI response due to generators inside (`response.freeze` doesn't completely help)
52
- if isinstance(response, WSGIResponse):
53
- response.freeze()
54
- copied_response = copy(response)
55
- copied_response.request = deepcopy(response.request)
56
- return copied_response
57
-
58
-
59
33
  def get_reason(status_code: int) -> str:
60
34
  if sys.version_info < (3, 9) and status_code == 418:
61
35
  # Python 3.8 does not have 418 status in the `HTTPStatus` enum
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schemathesis
3
- Version: 3.22.1
3
+ Version: 3.23.1
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
@@ -28,6 +28,7 @@ Classifier: Programming Language :: Python :: 3.12
28
28
  Classifier: Programming Language :: Python :: Implementation :: CPython
29
29
  Classifier: Topic :: Software Development :: Testing
30
30
  Requires-Python: >=3.8
31
+ Requires-Dist: anyio<4
31
32
  Requires-Dist: backoff<3.0,>=2.1.2
32
33
  Requires-Dist: click<9.0,>=7.0
33
34
  Requires-Dist: colorama<1.0,>=0.4
@@ -42,7 +43,7 @@ Requires-Dist: pytest-subtests<0.8.0,>=0.2.1
42
43
  Requires-Dist: pytest<8,>=4.6.4
43
44
  Requires-Dist: pyyaml<7.0,>=5.1
44
45
  Requires-Dist: requests<3,>=2.22
45
- Requires-Dist: starlette-testclient==0.2.0
46
+ Requires-Dist: starlette-testclient<1
46
47
  Requires-Dist: starlette<1,>=0.13
47
48
  Requires-Dist: tomli-w<2.0,>=1.0.0
48
49
  Requires-Dist: tomli<3.0,>=2.0.1
@@ -1,33 +1,33 @@
1
1
  schemathesis/__init__.py,sha256=WW1NBZxmc5jRR0c24xz-ZtTkJMUQG5MOw1MGVRRGc1s,1970
2
2
  schemathesis/_compat.py,sha256=VizWR0QAVj4l7WZautNe_zmo3AJ7WBl2zrJQOfJAQtk,1837
3
3
  schemathesis/_dependency_versions.py,sha256=P8f-zHGGUb1RRBIwg_QqMLzVTuey8dKKHSeVVmZi6TM,505
4
- schemathesis/_hypothesis.py,sha256=Hd-cbvabDNfqx3KuGL1XOXwRDrx3ajtXx4_Tv8dzU3Y,6676
4
+ schemathesis/_hypothesis.py,sha256=e0H4Z8qeLbL6H638ubxvGUntWnCoVBlubvZmWEuqjWQ,6810
5
5
  schemathesis/_lazy_import.py,sha256=LTki2tM168fCcXet1e6qDoQq8SLgInUA3xjXgi7cXJk,469
6
6
  schemathesis/_xml.py,sha256=1ILe404GO6sfUjFqzy44EvYMYvbBirjTH7-b4QiAEik,6781
7
7
  schemathesis/auths.py,sha256=09tlGuNGpl3rrsU3ua3UI3rIefqUIpaVtG89U5P6rJo,14731
8
8
  schemathesis/checks.py,sha256=jB7E6PfdeLSwMhjLVGmC3WoGCw4DXug_TYP7o0ETrGQ,1572
9
9
  schemathesis/code_samples.py,sha256=QFwyA7dmc_ij2FRwfbe0uMRm6j2yeofQ8zXynZV3SZI,4122
10
10
  schemathesis/constants.py,sha256=sDvVBhNW1TIvNXFMxicHyNgNTxlng877KZsaS7K_L2Y,2085
11
- schemathesis/exceptions.py,sha256=grrVZPTKlSndXunXz0jXExtHGFNRJacJUjFSpk3qjbY,16598
11
+ schemathesis/exceptions.py,sha256=MySsK-H8ZpxJK251avsQlaLsjZCrmLI19tzcU1AQWm8,16715
12
12
  schemathesis/failures.py,sha256=cWPaIzou8nv8ioUXImvgT_JyCaj9MOJJS_Nbc6fvhxU,5191
13
13
  schemathesis/filters.py,sha256=oaNrVA6VWCSy85k9CkB9JdaVpHFFTcJ831gPnfW3-PU,9334
14
14
  schemathesis/graphql.py,sha256=YkoKWY5K8lxp7H3ikAs-IsoDbiPwJvChG7O8p3DgwtI,229
15
15
  schemathesis/hooks.py,sha256=cNJgCh7SyLWT1sYDKF5ncDC80ld08CinvKo2IqLMV4g,12396
16
16
  schemathesis/lazy.py,sha256=JTXoL5QMFc-_h4OsilVV20jTkXEp8pcW5KmJU1UL-QQ,13302
17
17
  schemathesis/loaders.py,sha256=RJnrbf-3vZ7KXmRBkmr3uqWyg0eHzOnONABuudWcTIg,4586
18
- schemathesis/models.py,sha256=2-gU4PInUiwcgoIeBG5bfksq_VR4Rtntcvl47Tcvc7o,45875
18
+ schemathesis/models.py,sha256=OgisrUHFg4x79nDJ5A54QYNp0kf9AwqR-fUEKqOv1ew,45705
19
19
  schemathesis/parameters.py,sha256=oSsXRpujndiv5_1lWUnBZQEJajqd9AQ8sMxVcxtr7rY,2685
20
20
  schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  schemathesis/sanitization.py,sha256=WSV_MB5YRrYkp1pQRPHrzsidqsKcqYZiq64N9grKobo,8956
22
- schemathesis/schemas.py,sha256=3GhjXZ0zHdyHp7R3wCuTcRjVr2k-MZuYG4wSdV7ORqA,16365
22
+ schemathesis/schemas.py,sha256=VaO3Mb9bx8n1Ia57Epyr1Ah-8loOs6HNXAnmHe_H9ig,16366
23
23
  schemathesis/serializers.py,sha256=c-LkIJuuc4D5owoJREm7KQQd3AgcsENPIXEEyiNcevY,11109
24
24
  schemathesis/targets.py,sha256=tzp7VZ2-7g2nZHCooRgFzTMtOVcbl0rvtNR421hQthA,1162
25
25
  schemathesis/throttling.py,sha256=QQcS7TFpXHavUjm0kdFaCcCRhAGlgQ4y3XIbkdRoW20,1079
26
26
  schemathesis/types.py,sha256=AglR5M0bce-YXeDRkweToXTP0GjNOWVjS_mIsxLobwc,919
27
27
  schemathesis/utils.py,sha256=tjH1jkMseEXV6vYg8ylJpYd7sRprnpbmXqdWg20ZaGE,4939
28
- schemathesis/cli/__init__.py,sha256=2J8mFM82HHGedequClJvxiOPGbtTjeh2R4wtkyb370U,59150
29
- schemathesis/cli/callbacks.py,sha256=fviiaR9QSrvd7l8GP81q_L0fgj6oYi8JLvdilk7W6W8,12472
30
- schemathesis/cli/cassettes.py,sha256=-tRi8JBV6a2Ol8lotTydm_7hvU2ueRmb5Rg9Nq6qJHE,12839
28
+ schemathesis/cli/__init__.py,sha256=mLAjbvhkrRwooGJ74BihfLcO241pbRnx3u12GRkjUZY,60312
29
+ schemathesis/cli/callbacks.py,sha256=UAlHDW_zYUzuVlpA01GarsApOtij4PaKJpPp4lboqJk,12770
30
+ schemathesis/cli/cassettes.py,sha256=gPPvcuIj1WnoP-yqqvGCJNe49SWlDFu8OdQkOmY453A,12988
31
31
  schemathesis/cli/constants.py,sha256=x9zrVVFBTOO1HogPeqRO5Mvdgs3y1kiah9R5nPRTIyw,1347
32
32
  schemathesis/cli/context.py,sha256=QrNr-5-7Z8TWGNzlD87hJZau6wU--ZboYHN92cyg82k,1652
33
33
  schemathesis/cli/debug.py,sha256=PDEa-oHyz5bZ8aYjRYARwQaCv_AC6HM_L43LJfe4vUM,657
@@ -40,7 +40,8 @@ schemathesis/cli/output/default.py,sha256=g2SBeZWRspBRlSqYkDrQvkFVVVosfthbaGa2wM
40
40
  schemathesis/cli/output/short.py,sha256=Ui21Ko7eY5igs4CyNFb88-KRXKmMjz776l9aCHpYq8o,1628
41
41
  schemathesis/contrib/__init__.py,sha256=FH8NL8NXgSKBFOF8Jy_EB6T4CJEaiM-tmDhz16B2o4k,187
42
42
  schemathesis/contrib/unique_data.py,sha256=XttUSDVzD7-231jC7kqMi-9Xmu2aP8ljjDYINMOoHJk,736
43
- schemathesis/contrib/openapi/__init__.py,sha256=9jG6b909V2ediVl-yVIIfNqfbNcqLpEMWh20EiDXCdU,120
43
+ schemathesis/contrib/openapi/__init__.py,sha256=YMj_b2f3ohGwEt8QQXlxBT60wqvdCFS6516I4EHWVNM,217
44
+ schemathesis/contrib/openapi/fill_missing_examples.py,sha256=dY1ygG41PWmITOegdv2uwpDm-UiBcyDSOuGCZMGxYAg,582
44
45
  schemathesis/contrib/openapi/formats/__init__.py,sha256=OpHWPW8MkTLVv83QXPYY1HVLflhmSH49hSVefm1oVV0,111
45
46
  schemathesis/contrib/openapi/formats/uuid.py,sha256=SsTH_bInSXnlGLNyYLmwUfvafVnVOTHdmhmKytQVoUQ,390
46
47
  schemathesis/experimental/__init__.py,sha256=vWj64BquX0mbCSd9iDBlwMb1dfm3zHJjAWBQiozRnxw,2474
@@ -61,13 +62,13 @@ schemathesis/internal/jsonschema.py,sha256=eQEkBLTdJ__U7Z0XYXB_RVBQJ4texfFO0AaOo
61
62
  schemathesis/internal/result.py,sha256=Og_ZfwwQ6JFmW79ExC1ndjVMIOHJB7o9XtrfhYIjOOs,461
62
63
  schemathesis/internal/transformation.py,sha256=ZNEtL8ezryLdP9-of4eSRBMSjjV_lBQ5DZZfoPGZFEU,449
63
64
  schemathesis/internal/validation.py,sha256=ZCUrjB_QFriyMKo4V2HgZknMnywOtpwlcEADQiWRJFs,591
64
- schemathesis/runner/__init__.py,sha256=1p7-9Snb9hib2qBf0lesBfiE7vKYCg8s_Nrgk3G2fgQ,19823
65
+ schemathesis/runner/__init__.py,sha256=hbdrQojyIWMZo0e2VgJzJjvjWMPM-qwRLamFXofaQ94,19947
65
66
  schemathesis/runner/events.py,sha256=whpHGXcT7esnJ2bNsFirUrrELI3GtDAAoJ7VVTty2mc,9416
66
67
  schemathesis/runner/serialization.py,sha256=MHgSlsqIWAHqzXtpZABEEr3ARfd7sdE-GRaNP-r7L8Y,15495
67
68
  schemathesis/runner/impl/__init__.py,sha256=1E2iME8uthYPBh9MjwVBCTFV-P3fi7AdphCCoBBspjs,199
68
- schemathesis/runner/impl/core.py,sha256=T3IRLw01LLHbvajEgHM7wTxkXhOXHRlezsn4Y1mUc9g,32986
69
- schemathesis/runner/impl/solo.py,sha256=-_Ux8WpFccx0pTNn6lNiAQf7G2zO65DmR6XlBxwIp-s,3271
70
- schemathesis/runner/impl/threadpool.py,sha256=oHGfBvSvXKPqowON_cOa7vYbejix_z1slP0JojPGLIY,14983
69
+ schemathesis/runner/impl/core.py,sha256=34n0qaV1ktfesO5ljLNrs3U14q7RVCaY_pSKNNQ8Ogg,33051
70
+ schemathesis/runner/impl/solo.py,sha256=Y_tNhVBVxcuxv65hN0FjxLlVSC41ebHMOM1xSzVrNk8,3358
71
+ schemathesis/runner/impl/threadpool.py,sha256=2-2Wvw7msezZtenZY5vU_x3FGLLVlH-ywvhU9hTwAAo,15073
71
72
  schemathesis/service/__init__.py,sha256=cDVTCFD1G-vvhxZkJUwiToTAEQ-0ByIoqwXvJBCf_V8,472
72
73
  schemathesis/service/auth.py,sha256=AiZXvSNwz1Hi3fn-OCp6XD-E4GAMDlfcX8fORJ8_dLo,445
73
74
  schemathesis/service/ci.py,sha256=Nke_GHtUlbJtZA-7JmjD1Nu4aKBCtkUo8AwFwm38qpk,6781
@@ -92,16 +93,16 @@ schemathesis/specs/openapi/checks.py,sha256=1WB_UGNqptfJThWLUNbds1Q-IzOGbbHCOYPI
92
93
  schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
93
94
  schemathesis/specs/openapi/converter.py,sha256=rhzGRJNW6o9CeKLanVm_VIlXJQEWCpQ60XZobSpnplY,2677
94
95
  schemathesis/specs/openapi/definitions.py,sha256=t5xffHLBnSgptBdDkSqYN1OfT-DaXoeUw2tIgNEe2q8,94057
95
- schemathesis/specs/openapi/examples.py,sha256=S_c5YmaSADc8II2QRq15f2K9pZkaTWxuz08bcith3u0,9070
96
+ schemathesis/specs/openapi/examples.py,sha256=QIwFrciKUFz-cxbrXqBdsKCLt01XZo8p3z8m3JK28XI,9475
96
97
  schemathesis/specs/openapi/filters.py,sha256=Ei-QTFcGCvGSIunT-GYQrtqzB-kqvUePOcUuC7B7mT8,1436
97
98
  schemathesis/specs/openapi/formats.py,sha256=ZT-10kOWE4Xcc_OXchjhPxpjA2iq4SXG2a75Lnib03w,1146
98
99
  schemathesis/specs/openapi/links.py,sha256=YryI35djHOhTikRV3FLafy_jhYFypF7E8Yb6dg9ksWc,14575
99
- schemathesis/specs/openapi/loaders.py,sha256=l3H8T4GgolysRgrxpjYK_vOB2xyPIHNbKPX3_FrLq-M,23439
100
+ schemathesis/specs/openapi/loaders.py,sha256=2s9pF8HdIRcz4GwSLy3XJli_FZaeo9zontbat-SFOws,23613
100
101
  schemathesis/specs/openapi/parameters.py,sha256=GbvxMQ0vg2-HvLrKr1dBtOwSNEXkAF6Hj-hqX9qdTNs,15014
101
102
  schemathesis/specs/openapi/references.py,sha256=pnn0aQbP2Kz0xwZE0gVa9nYGyJkXA2jRYoNMFcRf3TQ,8656
102
103
  schemathesis/specs/openapi/schemas.py,sha256=s81MBsGVoc3WILCYR8DjNvmN6OotSsg27YFK5iqtdt8,46220
103
104
  schemathesis/specs/openapi/security.py,sha256=lNRD4RSYe341f_ayhl_bQuYlFbGzx4luhXi6qJwzrOY,6495
104
- schemathesis/specs/openapi/serialization.py,sha256=pHp5rlJhKXpCSAcM4JQtfqIN-CaD17wol4P7OIfqtLk,11382
105
+ schemathesis/specs/openapi/serialization.py,sha256=jajqowTIiyEVWEx-Gy4ZinXZewNg0n_ipsGzz7JXP7c,11383
105
106
  schemathesis/specs/openapi/utils.py,sha256=gmW4v6o6sZQifajfPquhFeWmZWGQM89mOOBYZvjnE7g,741
106
107
  schemathesis/specs/openapi/validation.py,sha256=UJWtW7VTRyMbbBHMRhMwNSUn92k1Hnp4p7IIVqCvqiI,998
107
108
  schemathesis/specs/openapi/expressions/__init__.py,sha256=7TZeRPpCPt0Bjzs5L--AkQnnIbDgTRnpkgYeJKma5Bc,660
@@ -122,9 +123,9 @@ schemathesis/transports/__init__.py,sha256=Wix_WnOxZlDFD_XFqPMIqz_3TAc7Xda6UGicO
122
123
  schemathesis/transports/auth.py,sha256=ZKFku9gjhIG6445qNC2p_64Yt9Iz_4azbvja8AMptBk,404
123
124
  schemathesis/transports/content_types.py,sha256=bgep10TeCT9e0GfOxVFBOFmrmdZ3t4tG8MLE0SJN5D0,1297
124
125
  schemathesis/transports/headers.py,sha256=EDxpm8su0AuhyqZUkMex-OFZMAJN_5NHah7fDT2HDZE,989
125
- schemathesis/transports/responses.py,sha256=K9eUaU3SqTFsMWegITWWENH3qrlNoT9OgU1aSc2oZ7I,2428
126
- schemathesis-3.22.1.dist-info/METADATA,sha256=cbIrQGwAfZdZqFRgaQQup8bxSNcP8eVUV2gIN8frJ0Y,15593
127
- schemathesis-3.22.1.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
128
- schemathesis-3.22.1.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
129
- schemathesis-3.22.1.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
130
- schemathesis-3.22.1.dist-info/RECORD,,
126
+ schemathesis/transports/responses.py,sha256=w-l0bQrPuAXKURtDazm9ptuGVcJgEW-QYWYpYblFEyM,1347
127
+ schemathesis-3.23.1.dist-info/METADATA,sha256=HJD__7N6XCehhfzauNlzscwE42RpyoyPC3l4Tpzue24,15611
128
+ schemathesis-3.23.1.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
129
+ schemathesis-3.23.1.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
130
+ schemathesis-3.23.1.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
131
+ schemathesis-3.23.1.dist-info/RECORD,,