schemathesis 3.30.1__py3-none-any.whl → 3.30.3__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.
@@ -59,8 +59,6 @@ class ExecutionContext:
59
59
  probes: list[ProbeRun] | None = None
60
60
  analysis: Result[AnalysisResult, Exception] | None = None
61
61
  output_config: OutputConfig = field(default_factory=OutputConfig)
62
- # Special flag to display a warning about Windows-specific encoding issue
63
- encountered_windows_encoding_issue: bool = False
64
62
  state_machine_sink: StateMachineSink | None = None
65
63
 
66
64
  @deprecated_property(removed_in="4.0", replacement="show_trace")
@@ -46,6 +46,7 @@ if TYPE_CHECKING:
46
46
  import requests
47
47
 
48
48
  SPINNER_REPETITION_NUMBER = 10
49
+ IO_ENCODING = os.getenv("PYTHONIOENCODING", "utf-8")
49
50
 
50
51
 
51
52
  def get_terminal_width() -> int:
@@ -280,6 +281,18 @@ def display_failures(context: ExecutionContext, event: events.Finished) -> None:
280
281
  display_failures_for_single_test(context, result)
281
282
 
282
283
 
284
+ if IO_ENCODING != "utf-8":
285
+
286
+ def _secho(text: str, **kwargs: Any) -> None:
287
+ text = text.encode(IO_ENCODING, errors="replace").decode("utf-8")
288
+ click.secho(text, **kwargs)
289
+
290
+ else:
291
+
292
+ def _secho(text: str, **kwargs: Any) -> None:
293
+ click.secho(text, **kwargs)
294
+
295
+
283
296
  def display_failures_for_single_test(context: ExecutionContext, result: SerializedTestResult) -> None:
284
297
  """Display a failure for a single method / path."""
285
298
  from ...transports.responses import get_reason
@@ -298,7 +311,7 @@ def display_failures_for_single_test(context: ExecutionContext, result: Serializ
298
311
  click.secho(f"\n- {check.title}", fg="red", bold=True)
299
312
  message = check.formatted_message
300
313
  if message:
301
- click.secho(f"\n{message}", fg="red")
314
+ _secho(f"\n{message}", fg="red")
302
315
  if check_idx + 1 == len(checks):
303
316
  if check.response is not None:
304
317
  status_code = check.response.status_code
@@ -319,24 +332,7 @@ def display_failures_for_single_test(context: ExecutionContext, result: Serializ
319
332
  click.echo(payload)
320
333
  except UnicodeDecodeError:
321
334
  click.echo("\n <BINARY>")
322
-
323
- try:
324
- click.echo(
325
- f"\n{bold('Reproduce with')}: \n\n {code_sample}\n",
326
- )
327
- except UnicodeEncodeError:
328
- # On Windows it may fail when redirecting the output to a file
329
- # because it uses a different encoding than the console encoding and the default
330
- # is cp1252, which doesn't support some Unicode characters.
331
- # In this case, display a stub message and set a flag to display a warning at the end
332
- if platform.system() != "Windows":
333
- raise
334
- click.echo(
335
- f"\n{bold('Reproduce with')}: \n\n"
336
- " CAN NOT DISPLAY THIS CODE SAMPLE DUE TO TERMINAL LIMITATIONS.\n"
337
- " SEE DETAILS AT THE END OF THE OUTPUT\n",
338
- )
339
- context.encountered_windows_encoding_issue = True
335
+ _secho(f"\n{bold('Reproduce with')}: \n\n {code_sample}\n")
340
336
 
341
337
 
342
338
  def display_application_logs(context: ExecutionContext, event: events.Finished) -> None:
@@ -485,17 +481,6 @@ def display_statistic(context: ExecutionContext, event: events.Finished) -> None
485
481
  seed_option = f"`--hypothesis-seed={context.seed}`"
486
482
  click.secho(f"\n{bold('Note')}: To replicate these test failures, rerun with {bold(seed_option)}")
487
483
 
488
- if context.encountered_windows_encoding_issue:
489
- click.echo()
490
- title = click.style("WARNING:", bold=True, fg="yellow")
491
- name = click.style("PYTHONIOENCODING", bold=True)
492
- value = click.style("utf8", bold=True)
493
- warning = (
494
- "Some code samples could not be displayed due to terminal limitations on Windows.\n"
495
- f"To resolve this set the '{name}' environment variable to '{value}' and rerun your command."
496
- )
497
- click.secho(f"{title} {warning}")
498
-
499
484
  if context.report is not None and not context.is_interrupted:
500
485
  if isinstance(context.report, FileReportContext):
501
486
  click.echo()
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from itertools import groupby
4
- from typing import Callable, Generator
4
+ from typing import Callable, Generator, Iterator
5
5
 
6
6
  import click
7
7
 
@@ -14,20 +14,25 @@ TEST_CASE_ID_TITLE = "Test Case ID"
14
14
 
15
15
  def group_by_case(
16
16
  checks: list[SerializedCheck], code_sample_style: CodeSampleStyle
17
- ) -> Generator[tuple[str, Generator[SerializedCheck, None, None]], None, None]:
17
+ ) -> Generator[tuple[str, Iterator[SerializedCheck]], None, None]:
18
18
  checks = deduplicate_failures(checks)
19
- checks = sorted(checks, key=lambda c: _by_unique_code_sample(c, code_sample_style))
20
- yield from groupby(checks, lambda c: _by_unique_code_sample(c, code_sample_style))
21
-
22
-
23
- def _by_unique_code_sample(check: SerializedCheck, code_sample_style: CodeSampleStyle) -> str:
24
- return code_sample_style.generate(
25
- method=check.example.method,
26
- url=check.example.url,
27
- body=check.example.deserialize_body(),
28
- headers=check.example.headers,
29
- verify=check.example.verify,
30
- extra_headers=check.example.extra_headers,
19
+ checks = sorted(checks, key=lambda c: _by_unique_key(c, code_sample_style))
20
+ for (sample, _, _), gen in groupby(checks, lambda c: _by_unique_key(c, code_sample_style)):
21
+ yield (sample, gen)
22
+
23
+
24
+ def _by_unique_key(check: SerializedCheck, code_sample_style: CodeSampleStyle) -> tuple[str, int | None, str | None]:
25
+ return (
26
+ code_sample_style.generate(
27
+ method=check.example.method,
28
+ url=check.example.url,
29
+ body=check.example.deserialize_body(),
30
+ headers=check.example.headers,
31
+ verify=check.example.verify,
32
+ extra_headers=check.example.extra_headers,
33
+ ),
34
+ None if not check.response else check.response.status_code,
35
+ None if not check.response else check.response.body,
31
36
  )
32
37
 
33
38
 
@@ -6,6 +6,7 @@ import threading
6
6
  import time
7
7
  import unittest
8
8
  import uuid
9
+ import warnings
9
10
  from contextlib import contextmanager
10
11
  from dataclasses import dataclass, field
11
12
  from types import TracebackType
@@ -20,6 +21,7 @@ from hypothesis_jsonschema._canonicalise import HypothesisRefResolutionError
20
21
  from jsonschema.exceptions import SchemaError as JsonSchemaError
21
22
  from jsonschema.exceptions import ValidationError
22
23
  from requests.auth import HTTPDigestAuth, _basic_auth_str
24
+ from urllib3.exceptions import InsecureRequestWarning
23
25
 
24
26
  from ... import experimental, failures, hooks
25
27
  from ..._compat import MultipleFailures
@@ -192,6 +194,7 @@ class BaseRunner:
192
194
  return
193
195
 
194
196
  try:
197
+ warnings.simplefilter("ignore", InsecureRequestWarning)
195
198
  if not experimental.STATEFUL_ONLY.is_enabled:
196
199
  yield from self._execute(results, stop_event)
197
200
  yield from self._run_stateful_tests(results)
@@ -79,7 +79,12 @@ def content_type_conformance(response: GenericResponse, case: Case) -> bool | No
79
79
  received_main, received_sub = parse_content_type(content_type)
80
80
  except ValueError as exc:
81
81
  _reraise_malformed_media_type(case, exc, "Response", content_type, option)
82
- if (expected_main, expected_sub) == (received_main, received_sub):
82
+ if (
83
+ (expected_main == "*" and expected_sub == "*")
84
+ or (expected_main == received_main and expected_sub == "*")
85
+ or (expected_main == "*" and expected_sub == received_sub)
86
+ or (expected_main == received_main and expected_sub == received_sub)
87
+ ):
83
88
  return None
84
89
  exc_class = get_response_type_error(
85
90
  case.operation.verbose_name, f"{expected_main}_{expected_sub}", f"{received_main}_{received_sub}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schemathesis
3
- Version: 3.30.1
3
+ Version: 3.30.3
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
@@ -32,15 +32,15 @@ schemathesis/cli/__main__.py,sha256=MWaenjaUTZIfNPFzKmnkTiawUri7DVldtg3mirLwzU8,
32
32
  schemathesis/cli/callbacks.py,sha256=tZSe6EIyc1fdKZ8xGaE0w0LuGCMtT7m9cW41Rd0Nah0,14949
33
33
  schemathesis/cli/cassettes.py,sha256=WLt2svZm23vZX5buQWmWO94QwQEC8OM2g8yH50rfatE,12990
34
34
  schemathesis/cli/constants.py,sha256=ogSuZs68KvzHNKF0yaiBkxLcGbo8IVR3xaIfsy1H1IQ,1546
35
- schemathesis/cli/context.py,sha256=BsaKvfmh9LmiDU3D7wixSzBjk9KWNRWJwYA3Xa3d35I,2223
35
+ schemathesis/cli/context.py,sha256=EMeyAbU9mRujR46anc43yr6ab4rGYtIDaHC3cV9Qa-Q,2092
36
36
  schemathesis/cli/debug.py,sha256=_YA-bX1ujHl4bqQDEum7M-I2XHBTEGbvgkhvcvKhmgU,658
37
37
  schemathesis/cli/handlers.py,sha256=RjvogPCqqFTiyVYWrGG6euw9-6h-7uSeFvS-ouU8eWs,389
38
38
  schemathesis/cli/junitxml.py,sha256=yWacOIrTC9UI-IlgZnu8nfSmpkxfMT22NqJ3L1SZa3w,4743
39
39
  schemathesis/cli/options.py,sha256=DY5PUzpUNyYgpcqqFTeZjmVUykpbaI9fbN44QIWNOfA,2559
40
- schemathesis/cli/reporting.py,sha256=_Jh8sJMfOf_CUHdbTpG5VRsfW8INtXQjtk1njmGWEnY,3298
40
+ schemathesis/cli/reporting.py,sha256=AT8ZjSUeH0S9Dl1ZhvTw0CJPy1JdIIRuRWxsJXfFpjc,3521
41
41
  schemathesis/cli/sanitization.py,sha256=pVlQnVDC1_Ugp0oe1LEkRorFdBRDHqr_NWWKaOaNdY0,728
42
42
  schemathesis/cli/output/__init__.py,sha256=AXaUzQ1nhQ-vXhW4-X-91vE2VQtEcCOrGtQXXNN55iQ,29
43
- schemathesis/cli/output/default.py,sha256=0zFolpo2HS2NH-IzRqEIZqfa_6Vk4jEHpfykLQ7apAM,39755
43
+ schemathesis/cli/output/default.py,sha256=xG1R3f-s8xy-eqH42kL_ZSaADLkc6Fc0WqmcDbQTVVo,38775
44
44
  schemathesis/cli/output/short.py,sha256=CL6-Apxr5tuZ3BL1vecV1MiRY1wDt21g0wiUwZu6mLM,2607
45
45
  schemathesis/contrib/__init__.py,sha256=FH8NL8NXgSKBFOF8Jy_EB6T4CJEaiM-tmDhz16B2o4k,187
46
46
  schemathesis/contrib/unique_data.py,sha256=_ElPRLNp0XhdETiZ-aplKln4hgU04jxR17kmjAEWf1I,1318
@@ -72,7 +72,7 @@ schemathesis/runner/events.py,sha256=PJceb_jC-2BKEdMIrH8mSCtt8lbPPq6Gs5qjPicwxmU
72
72
  schemathesis/runner/probes.py,sha256=J-TT0hOKu9j4htWKBcYKmsomcRxmvOl4WpmnKLVXu8M,5546
73
73
  schemathesis/runner/serialization.py,sha256=J8fuG8MSJq3rE3IJs73U1YXWFrNa05k7PGd5Bvq1uec,17356
74
74
  schemathesis/runner/impl/__init__.py,sha256=1E2iME8uthYPBh9MjwVBCTFV-P3fi7AdphCCoBBspjs,199
75
- schemathesis/runner/impl/core.py,sha256=vlq4TWf-s5As49wSmiATTK8N7vf2PFjJtsDoH_rrTrc,41896
75
+ schemathesis/runner/impl/core.py,sha256=u56WvKOJY96ShHj5MoAcwys_th3DAxLAAoipx7wvWm8,42034
76
76
  schemathesis/runner/impl/solo.py,sha256=MatxThgqKsY2tX_hVwjy78oKFeKejb6dFJoX3kGzW4U,3359
77
77
  schemathesis/runner/impl/threadpool.py,sha256=fj2QYoWxIJIxpTCcJQyM_VCRO1YDnW9XQJJnNVFVQxY,15253
78
78
  schemathesis/service/__init__.py,sha256=cDVTCFD1G-vvhxZkJUwiToTAEQ-0ByIoqwXvJBCf_V8,472
@@ -99,7 +99,7 @@ schemathesis/specs/graphql/validation.py,sha256=uINIOt-2E7ZuQV2CxKzwez-7L9tDtqzM
99
99
  schemathesis/specs/openapi/__init__.py,sha256=HDcx3bqpa6qWPpyMrxAbM3uTo0Lqpg-BUNZhDJSJKnw,279
100
100
  schemathesis/specs/openapi/_cache.py,sha256=PAiAu4X_a2PQgD2lG5H3iisXdyg4SaHpU46bRZvfNkM,4320
101
101
  schemathesis/specs/openapi/_hypothesis.py,sha256=9O8gTVWtq17UezgvlxHxjTHGVmggQ2mxwAnVIvZKgsk,23619
102
- schemathesis/specs/openapi/checks.py,sha256=8dy65jSYKtzaUMR0GWQU3omWkbeol4r8ztKAP23zzoQ,9132
102
+ schemathesis/specs/openapi/checks.py,sha256=1Fu3Kgai9ySCoGtCrx99Q9oVCEWXgkqHd1gTqG_569s,9364
103
103
  schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
104
104
  schemathesis/specs/openapi/converter.py,sha256=TaYgc5BBHPdkN-n0lqpbeVgLu3eL3L8Wu3y_Vo3TJaQ,2800
105
105
  schemathesis/specs/openapi/definitions.py,sha256=Z186F0gNBSCmPg-Kk7Q-n6XxEZHIOzgUyeqixlC62XE,94058
@@ -144,8 +144,8 @@ schemathesis/transports/auth.py,sha256=4z7c-K7lfyyVqgR6X1v4yiE8ewR_ViAznWFTAsCL0
144
144
  schemathesis/transports/content_types.py,sha256=VrcRQvF5T_TUjrCyrZcYF2LOwKfs3IrLcMtkVSp1ImI,2189
145
145
  schemathesis/transports/headers.py,sha256=hr_AIDOfUxsJxpHfemIZ_uNG3_vzS_ZeMEKmZjbYiBE,990
146
146
  schemathesis/transports/responses.py,sha256=6-gvVcRK0Ho_lSydUysBNFWoJwZEiEgf6Iv-GWkQGd8,1675
147
- schemathesis-3.30.1.dist-info/METADATA,sha256=zpOkWoX0pEVKQ1smDJgZMR5cg29onY26c5P8t4ukbnE,17671
148
- schemathesis-3.30.1.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
149
- schemathesis-3.30.1.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
150
- schemathesis-3.30.1.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
151
- schemathesis-3.30.1.dist-info/RECORD,,
147
+ schemathesis-3.30.3.dist-info/METADATA,sha256=EJGm-5rC8P8sk_GgBDOfehfb5MdK4a9O6pU7jISsbTU,17671
148
+ schemathesis-3.30.3.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
149
+ schemathesis-3.30.3.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
150
+ schemathesis-3.30.3.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
151
+ schemathesis-3.30.3.dist-info/RECORD,,