schemathesis 3.39.7__py3-none-any.whl → 4.0.0a2__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.
Files changed (229) hide show
  1. schemathesis/__init__.py +27 -65
  2. schemathesis/auths.py +26 -68
  3. schemathesis/checks.py +130 -60
  4. schemathesis/cli/__init__.py +5 -2105
  5. schemathesis/cli/commands/__init__.py +37 -0
  6. schemathesis/cli/commands/run/__init__.py +662 -0
  7. schemathesis/cli/commands/run/checks.py +80 -0
  8. schemathesis/cli/commands/run/context.py +117 -0
  9. schemathesis/cli/commands/run/events.py +30 -0
  10. schemathesis/cli/commands/run/executor.py +141 -0
  11. schemathesis/cli/commands/run/filters.py +202 -0
  12. schemathesis/cli/commands/run/handlers/__init__.py +46 -0
  13. schemathesis/cli/commands/run/handlers/base.py +18 -0
  14. schemathesis/cli/{cassettes.py → commands/run/handlers/cassettes.py} +178 -247
  15. schemathesis/cli/commands/run/handlers/junitxml.py +54 -0
  16. schemathesis/cli/commands/run/handlers/output.py +1368 -0
  17. schemathesis/cli/commands/run/hypothesis.py +105 -0
  18. schemathesis/cli/commands/run/loaders.py +129 -0
  19. schemathesis/cli/{callbacks.py → commands/run/validation.py} +59 -175
  20. schemathesis/cli/constants.py +5 -58
  21. schemathesis/cli/core.py +17 -0
  22. schemathesis/cli/ext/fs.py +14 -0
  23. schemathesis/cli/ext/groups.py +55 -0
  24. schemathesis/cli/{options.py → ext/options.py} +37 -16
  25. schemathesis/cli/hooks.py +36 -0
  26. schemathesis/contrib/__init__.py +1 -3
  27. schemathesis/contrib/openapi/__init__.py +1 -3
  28. schemathesis/contrib/openapi/fill_missing_examples.py +3 -7
  29. schemathesis/core/__init__.py +58 -0
  30. schemathesis/core/compat.py +25 -0
  31. schemathesis/core/control.py +2 -0
  32. schemathesis/core/curl.py +58 -0
  33. schemathesis/core/deserialization.py +65 -0
  34. schemathesis/core/errors.py +370 -0
  35. schemathesis/core/failures.py +315 -0
  36. schemathesis/core/fs.py +19 -0
  37. schemathesis/core/loaders.py +104 -0
  38. schemathesis/core/marks.py +66 -0
  39. schemathesis/{transports/content_types.py → core/media_types.py} +14 -12
  40. schemathesis/{internal/output.py → core/output/__init__.py} +1 -0
  41. schemathesis/core/output/sanitization.py +197 -0
  42. schemathesis/{throttling.py → core/rate_limit.py} +16 -17
  43. schemathesis/core/registries.py +31 -0
  44. schemathesis/core/transforms.py +113 -0
  45. schemathesis/core/transport.py +108 -0
  46. schemathesis/core/validation.py +38 -0
  47. schemathesis/core/version.py +7 -0
  48. schemathesis/engine/__init__.py +30 -0
  49. schemathesis/engine/config.py +59 -0
  50. schemathesis/engine/context.py +119 -0
  51. schemathesis/engine/control.py +36 -0
  52. schemathesis/engine/core.py +157 -0
  53. schemathesis/engine/errors.py +394 -0
  54. schemathesis/engine/events.py +243 -0
  55. schemathesis/engine/phases/__init__.py +66 -0
  56. schemathesis/{runner → engine/phases}/probes.py +49 -68
  57. schemathesis/engine/phases/stateful/__init__.py +66 -0
  58. schemathesis/engine/phases/stateful/_executor.py +301 -0
  59. schemathesis/engine/phases/stateful/context.py +85 -0
  60. schemathesis/engine/phases/unit/__init__.py +175 -0
  61. schemathesis/engine/phases/unit/_executor.py +322 -0
  62. schemathesis/engine/phases/unit/_pool.py +74 -0
  63. schemathesis/engine/recorder.py +246 -0
  64. schemathesis/errors.py +31 -0
  65. schemathesis/experimental/__init__.py +9 -40
  66. schemathesis/filters.py +7 -95
  67. schemathesis/generation/__init__.py +3 -3
  68. schemathesis/generation/case.py +190 -0
  69. schemathesis/generation/coverage.py +22 -22
  70. schemathesis/{_patches.py → generation/hypothesis/__init__.py} +15 -6
  71. schemathesis/generation/hypothesis/builder.py +585 -0
  72. schemathesis/generation/{_hypothesis.py → hypothesis/examples.py} +2 -11
  73. schemathesis/generation/hypothesis/given.py +66 -0
  74. schemathesis/generation/hypothesis/reporting.py +14 -0
  75. schemathesis/generation/hypothesis/strategies.py +16 -0
  76. schemathesis/generation/meta.py +115 -0
  77. schemathesis/generation/modes.py +28 -0
  78. schemathesis/generation/overrides.py +96 -0
  79. schemathesis/generation/stateful/__init__.py +20 -0
  80. schemathesis/{stateful → generation/stateful}/state_machine.py +84 -109
  81. schemathesis/generation/targets.py +69 -0
  82. schemathesis/graphql/__init__.py +15 -0
  83. schemathesis/graphql/checks.py +109 -0
  84. schemathesis/graphql/loaders.py +131 -0
  85. schemathesis/hooks.py +17 -62
  86. schemathesis/openapi/__init__.py +13 -0
  87. schemathesis/openapi/checks.py +387 -0
  88. schemathesis/openapi/generation/__init__.py +0 -0
  89. schemathesis/openapi/generation/filters.py +63 -0
  90. schemathesis/openapi/loaders.py +178 -0
  91. schemathesis/pytest/__init__.py +5 -0
  92. schemathesis/pytest/control_flow.py +7 -0
  93. schemathesis/pytest/lazy.py +273 -0
  94. schemathesis/pytest/loaders.py +12 -0
  95. schemathesis/{extra/pytest_plugin.py → pytest/plugin.py} +94 -107
  96. schemathesis/python/__init__.py +0 -0
  97. schemathesis/python/asgi.py +12 -0
  98. schemathesis/python/wsgi.py +12 -0
  99. schemathesis/schemas.py +456 -228
  100. schemathesis/specs/graphql/__init__.py +0 -1
  101. schemathesis/specs/graphql/_cache.py +1 -2
  102. schemathesis/specs/graphql/scalars.py +5 -3
  103. schemathesis/specs/graphql/schemas.py +122 -123
  104. schemathesis/specs/graphql/validation.py +11 -17
  105. schemathesis/specs/openapi/__init__.py +6 -1
  106. schemathesis/specs/openapi/_cache.py +1 -2
  107. schemathesis/specs/openapi/_hypothesis.py +97 -134
  108. schemathesis/specs/openapi/checks.py +238 -219
  109. schemathesis/specs/openapi/converter.py +4 -4
  110. schemathesis/specs/openapi/definitions.py +1 -1
  111. schemathesis/specs/openapi/examples.py +22 -20
  112. schemathesis/specs/openapi/expressions/__init__.py +11 -15
  113. schemathesis/specs/openapi/expressions/extractors.py +1 -4
  114. schemathesis/specs/openapi/expressions/nodes.py +33 -32
  115. schemathesis/specs/openapi/formats.py +3 -2
  116. schemathesis/specs/openapi/links.py +123 -299
  117. schemathesis/specs/openapi/media_types.py +10 -12
  118. schemathesis/specs/openapi/negative/__init__.py +2 -1
  119. schemathesis/specs/openapi/negative/mutations.py +3 -2
  120. schemathesis/specs/openapi/parameters.py +8 -6
  121. schemathesis/specs/openapi/patterns.py +1 -1
  122. schemathesis/specs/openapi/references.py +11 -51
  123. schemathesis/specs/openapi/schemas.py +177 -191
  124. schemathesis/specs/openapi/security.py +1 -1
  125. schemathesis/specs/openapi/serialization.py +10 -6
  126. schemathesis/specs/openapi/stateful/__init__.py +97 -91
  127. schemathesis/transport/__init__.py +104 -0
  128. schemathesis/transport/asgi.py +26 -0
  129. schemathesis/transport/prepare.py +99 -0
  130. schemathesis/transport/requests.py +221 -0
  131. schemathesis/{_xml.py → transport/serialization.py} +69 -7
  132. schemathesis/transport/wsgi.py +165 -0
  133. {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/METADATA +18 -14
  134. schemathesis-4.0.0a2.dist-info/RECORD +151 -0
  135. {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/entry_points.txt +1 -1
  136. schemathesis/_compat.py +0 -74
  137. schemathesis/_dependency_versions.py +0 -19
  138. schemathesis/_hypothesis.py +0 -559
  139. schemathesis/_override.py +0 -50
  140. schemathesis/_rate_limiter.py +0 -7
  141. schemathesis/cli/context.py +0 -75
  142. schemathesis/cli/debug.py +0 -27
  143. schemathesis/cli/handlers.py +0 -19
  144. schemathesis/cli/junitxml.py +0 -124
  145. schemathesis/cli/output/__init__.py +0 -1
  146. schemathesis/cli/output/default.py +0 -936
  147. schemathesis/cli/output/short.py +0 -59
  148. schemathesis/cli/reporting.py +0 -79
  149. schemathesis/cli/sanitization.py +0 -26
  150. schemathesis/code_samples.py +0 -151
  151. schemathesis/constants.py +0 -56
  152. schemathesis/contrib/openapi/formats/__init__.py +0 -9
  153. schemathesis/contrib/openapi/formats/uuid.py +0 -16
  154. schemathesis/contrib/unique_data.py +0 -41
  155. schemathesis/exceptions.py +0 -571
  156. schemathesis/extra/_aiohttp.py +0 -28
  157. schemathesis/extra/_flask.py +0 -13
  158. schemathesis/extra/_server.py +0 -18
  159. schemathesis/failures.py +0 -277
  160. schemathesis/fixups/__init__.py +0 -37
  161. schemathesis/fixups/fast_api.py +0 -41
  162. schemathesis/fixups/utf8_bom.py +0 -28
  163. schemathesis/generation/_methods.py +0 -44
  164. schemathesis/graphql.py +0 -3
  165. schemathesis/internal/__init__.py +0 -7
  166. schemathesis/internal/checks.py +0 -84
  167. schemathesis/internal/copy.py +0 -32
  168. schemathesis/internal/datetime.py +0 -5
  169. schemathesis/internal/deprecation.py +0 -38
  170. schemathesis/internal/diff.py +0 -15
  171. schemathesis/internal/extensions.py +0 -27
  172. schemathesis/internal/jsonschema.py +0 -36
  173. schemathesis/internal/transformation.py +0 -26
  174. schemathesis/internal/validation.py +0 -34
  175. schemathesis/lazy.py +0 -474
  176. schemathesis/loaders.py +0 -122
  177. schemathesis/models.py +0 -1341
  178. schemathesis/parameters.py +0 -90
  179. schemathesis/runner/__init__.py +0 -605
  180. schemathesis/runner/events.py +0 -389
  181. schemathesis/runner/impl/__init__.py +0 -3
  182. schemathesis/runner/impl/context.py +0 -104
  183. schemathesis/runner/impl/core.py +0 -1246
  184. schemathesis/runner/impl/solo.py +0 -80
  185. schemathesis/runner/impl/threadpool.py +0 -391
  186. schemathesis/runner/serialization.py +0 -544
  187. schemathesis/sanitization.py +0 -252
  188. schemathesis/serializers.py +0 -328
  189. schemathesis/service/__init__.py +0 -18
  190. schemathesis/service/auth.py +0 -11
  191. schemathesis/service/ci.py +0 -202
  192. schemathesis/service/client.py +0 -133
  193. schemathesis/service/constants.py +0 -38
  194. schemathesis/service/events.py +0 -61
  195. schemathesis/service/extensions.py +0 -224
  196. schemathesis/service/hosts.py +0 -111
  197. schemathesis/service/metadata.py +0 -71
  198. schemathesis/service/models.py +0 -258
  199. schemathesis/service/report.py +0 -255
  200. schemathesis/service/serialization.py +0 -173
  201. schemathesis/service/usage.py +0 -66
  202. schemathesis/specs/graphql/loaders.py +0 -364
  203. schemathesis/specs/openapi/expressions/context.py +0 -16
  204. schemathesis/specs/openapi/loaders.py +0 -708
  205. schemathesis/specs/openapi/stateful/statistic.py +0 -198
  206. schemathesis/specs/openapi/stateful/types.py +0 -14
  207. schemathesis/specs/openapi/validation.py +0 -26
  208. schemathesis/stateful/__init__.py +0 -147
  209. schemathesis/stateful/config.py +0 -97
  210. schemathesis/stateful/context.py +0 -135
  211. schemathesis/stateful/events.py +0 -274
  212. schemathesis/stateful/runner.py +0 -309
  213. schemathesis/stateful/sink.py +0 -68
  214. schemathesis/stateful/statistic.py +0 -22
  215. schemathesis/stateful/validation.py +0 -100
  216. schemathesis/targets.py +0 -77
  217. schemathesis/transports/__init__.py +0 -359
  218. schemathesis/transports/asgi.py +0 -7
  219. schemathesis/transports/auth.py +0 -38
  220. schemathesis/transports/headers.py +0 -36
  221. schemathesis/transports/responses.py +0 -57
  222. schemathesis/types.py +0 -44
  223. schemathesis/utils.py +0 -164
  224. schemathesis-3.39.7.dist-info/RECORD +0 -160
  225. /schemathesis/{extra → cli/ext}/__init__.py +0 -0
  226. /schemathesis/{_lazy_import.py → core/lazy_import.py} +0 -0
  227. /schemathesis/{internal → core}/result.py +0 -0
  228. {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/WHEEL +0 -0
  229. {schemathesis-3.39.7.dist-info → schemathesis-4.0.0a2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,190 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import TYPE_CHECKING, Any, Mapping
5
+
6
+ from schemathesis.checks import CHECKS, CheckContext, CheckFunction, run_checks
7
+ from schemathesis.core import NOT_SET, SCHEMATHESIS_TEST_CASE_HEADER, NotSet, curl
8
+ from schemathesis.core.failures import FailureGroup, failure_report_title, format_failures
9
+ from schemathesis.core.transport import Response
10
+ from schemathesis.generation import generate_random_case_id
11
+ from schemathesis.generation.meta import CaseMetadata
12
+ from schemathesis.generation.overrides import Override, store_components
13
+ from schemathesis.hooks import HookContext, dispatch
14
+ from schemathesis.transport.prepare import prepare_request
15
+
16
+ if TYPE_CHECKING:
17
+ import requests.auth
18
+ from requests.structures import CaseInsensitiveDict
19
+
20
+ from schemathesis.schemas import APIOperation
21
+
22
+
23
+ @dataclass
24
+ class Case:
25
+ """A single test case parameters."""
26
+
27
+ operation: APIOperation
28
+ method: str
29
+ path: str
30
+ # Unique test case identifier
31
+ id: str = field(default_factory=generate_random_case_id, compare=False)
32
+ path_parameters: dict[str, Any] | None = None
33
+ headers: CaseInsensitiveDict | None = None
34
+ cookies: dict[str, Any] | None = None
35
+ query: dict[str, Any] | None = None
36
+ # By default, there is no body, but we can't use `None` as the default value because it clashes with `null`
37
+ # which is a valid payload.
38
+ body: list | dict[str, Any] | str | int | float | bool | bytes | NotSet = NOT_SET
39
+ # The media type for cases with a payload. For example, "application/json"
40
+ media_type: str | None = None
41
+
42
+ meta: CaseMetadata | None = field(compare=False, default=None)
43
+
44
+ _auth: requests.auth.AuthBase | None = None
45
+ _has_explicit_auth: bool = False
46
+
47
+ def __post_init__(self) -> None:
48
+ self._components = store_components(self)
49
+
50
+ @property
51
+ def _override(self) -> Override:
52
+ return Override.from_components(self._components, self)
53
+
54
+ def __repr__(self) -> str:
55
+ output = f"{self.__class__.__name__}("
56
+ first = True
57
+ for name in ("path_parameters", "headers", "cookies", "query", "body"):
58
+ value = getattr(self, name)
59
+ if value is not None and not isinstance(value, NotSet):
60
+ if first:
61
+ first = False
62
+ else:
63
+ output += ", "
64
+ output += f"{name}={value!r}"
65
+ return f"{output})"
66
+
67
+ def __hash__(self) -> int:
68
+ return hash(self.as_curl_command({SCHEMATHESIS_TEST_CASE_HEADER: "0"}))
69
+
70
+ def _repr_pretty_(self, *args: Any, **kwargs: Any) -> None: ...
71
+
72
+ def as_curl_command(self, headers: Mapping[str, Any] | None = None, verify: bool = True) -> str:
73
+ """Construct a curl command for a given case."""
74
+ request_data = prepare_request(self, headers, self.operation.schema.output_config.sanitize)
75
+ return curl.generate(
76
+ method=str(request_data.method),
77
+ url=str(request_data.url),
78
+ body=request_data.body,
79
+ verify=verify,
80
+ headers=dict(request_data.headers),
81
+ known_generated_headers=dict(self.headers or {}),
82
+ )
83
+
84
+ def as_transport_kwargs(self, base_url: str | None = None, headers: dict[str, str] | None = None) -> dict[str, Any]:
85
+ """Convert the test case into a dictionary acceptable by the underlying transport call."""
86
+ return self.operation.schema.transport.serialize_case(self, base_url=base_url, headers=headers)
87
+
88
+ def call(
89
+ self,
90
+ base_url: str | None = None,
91
+ session: requests.Session | None = None,
92
+ headers: dict[str, Any] | None = None,
93
+ params: dict[str, Any] | None = None,
94
+ cookies: dict[str, Any] | None = None,
95
+ **kwargs: Any,
96
+ ) -> Response:
97
+ hook_context = HookContext(operation=self.operation)
98
+ dispatch("before_call", hook_context, self, **kwargs)
99
+ if self.operation.app is not None:
100
+ kwargs["app"] = self.operation.app
101
+ response = self.operation.schema.transport.send(
102
+ self,
103
+ session=session,
104
+ base_url=base_url,
105
+ headers=headers,
106
+ params=params,
107
+ cookies=cookies,
108
+ **kwargs,
109
+ )
110
+ dispatch("after_call", hook_context, self, response)
111
+ return response
112
+
113
+ def validate_response(
114
+ self,
115
+ response: Response,
116
+ checks: list[CheckFunction] | None = None,
117
+ additional_checks: list[CheckFunction] | None = None,
118
+ excluded_checks: list[CheckFunction] | None = None,
119
+ headers: dict[str, Any] | None = None,
120
+ transport_kwargs: dict[str, Any] | None = None,
121
+ ) -> None:
122
+ """Validate application response.
123
+
124
+ By default, all available checks will be applied.
125
+
126
+ :param response: Application response.
127
+ :param checks: A tuple of check functions that accept ``response`` and ``case``.
128
+ :param additional_checks: A tuple of additional checks that will be executed after ones from the ``checks``
129
+ argument.
130
+ :param excluded_checks: Checks excluded from the default ones.
131
+ """
132
+ __tracebackhide__ = True
133
+ from requests.structures import CaseInsensitiveDict
134
+
135
+ checks = [
136
+ check
137
+ for check in list(checks or CHECKS.get_all()) + list(additional_checks or [])
138
+ if check not in set(excluded_checks or [])
139
+ ]
140
+
141
+ ctx = CheckContext(
142
+ override=self._override,
143
+ auth=None,
144
+ headers=CaseInsensitiveDict(headers) if headers else None,
145
+ config={},
146
+ transport_kwargs=transport_kwargs,
147
+ recorder=None,
148
+ )
149
+ failures = run_checks(
150
+ case=self,
151
+ response=response,
152
+ ctx=ctx,
153
+ checks=checks,
154
+ on_failure=lambda _, collected, failure: collected.add(failure),
155
+ )
156
+ if failures:
157
+ _failures = list(failures)
158
+ message = failure_report_title(_failures) + "\n"
159
+ verify = getattr(response, "verify", True)
160
+ curl = self.as_curl_command(headers=dict(response.request.headers), verify=verify)
161
+ message += format_failures(
162
+ case_id=None,
163
+ response=response,
164
+ failures=_failures,
165
+ curl=curl,
166
+ config=self.operation.schema.output_config,
167
+ )
168
+ raise FailureGroup(_failures, message) from None
169
+
170
+ def call_and_validate(
171
+ self,
172
+ base_url: str | None = None,
173
+ session: requests.Session | None = None,
174
+ headers: dict[str, Any] | None = None,
175
+ checks: list[CheckFunction] | None = None,
176
+ additional_checks: list[CheckFunction] | None = None,
177
+ excluded_checks: list[CheckFunction] | None = None,
178
+ **kwargs: Any,
179
+ ) -> Response:
180
+ __tracebackhide__ = True
181
+ response = self.call(base_url, session, headers, **kwargs)
182
+ self.validate_response(
183
+ response,
184
+ checks,
185
+ headers=headers,
186
+ additional_checks=additional_checks,
187
+ excluded_checks=excluded_checks,
188
+ transport_kwargs=kwargs,
189
+ )
190
+ return response
@@ -16,14 +16,16 @@ from hypothesis_jsonschema import from_schema
16
16
  from hypothesis_jsonschema._canonicalise import canonicalish
17
17
  from hypothesis_jsonschema._from_schema import STRING_FORMATS as BUILT_IN_STRING_FORMATS
18
18
 
19
- from ..constants import NOT_SET
20
- from ..internal.copy import fast_deepcopy
19
+ from schemathesis.core import NOT_SET
20
+ from schemathesis.core.compat import RefResolutionError
21
+ from schemathesis.core.transforms import deepclone
22
+ from schemathesis.core.validation import has_invalid_characters, is_latin_1_encodable
23
+ from schemathesis.generation import GenerationMode
24
+ from schemathesis.generation.hypothesis import examples
25
+
21
26
  from ..specs.openapi.converter import update_pattern_in_schema
22
27
  from ..specs.openapi.formats import STRING_FORMATS, get_default_format_strategies
23
28
  from ..specs.openapi.patterns import update_quantifier
24
- from ..transports.headers import has_invalid_characters, is_latin_1_encodable
25
- from ._hypothesis import get_single_example
26
- from ._methods import DataGenerationMethod
27
29
 
28
30
 
29
31
  def _replace_zero_with_nonzero(x: float) -> float:
@@ -62,18 +64,18 @@ UNKNOWN_PROPERTY_VALUE = 42
62
64
  @dataclass
63
65
  class GeneratedValue:
64
66
  value: Any
65
- data_generation_method: DataGenerationMethod
67
+ generation_mode: GenerationMode
66
68
  description: str
67
69
  parameter: str | None
68
70
  location: str | None
69
71
 
70
- __slots__ = ("value", "data_generation_method", "description", "parameter", "location")
72
+ __slots__ = ("value", "generation_mode", "description", "parameter", "location")
71
73
 
72
74
  @classmethod
73
75
  def with_positive(cls, value: Any, *, description: str) -> GeneratedValue:
74
76
  return cls(
75
77
  value=value,
76
- data_generation_method=DataGenerationMethod.positive,
78
+ generation_mode=GenerationMode.POSITIVE,
77
79
  description=description,
78
80
  location=None,
79
81
  parameter=None,
@@ -85,7 +87,7 @@ class GeneratedValue:
85
87
  ) -> GeneratedValue:
86
88
  return cls(
87
89
  value=value,
88
- data_generation_method=DataGenerationMethod.negative,
90
+ generation_mode=GenerationMode.NEGATIVE,
89
91
  description=description,
90
92
  location=location,
91
93
  parameter=parameter,
@@ -98,28 +100,26 @@ NegativeValue = GeneratedValue.with_negative
98
100
 
99
101
  @lru_cache(maxsize=128)
100
102
  def cached_draw(strategy: st.SearchStrategy) -> Any:
101
- return get_single_example(strategy)
103
+ return examples.generate_one(strategy)
102
104
 
103
105
 
104
106
  @dataclass
105
107
  class CoverageContext:
106
- data_generation_methods: list[DataGenerationMethod]
108
+ generation_modes: list[GenerationMode]
107
109
  location: str
108
110
  path: list[str | int]
109
111
 
110
- __slots__ = ("location", "data_generation_methods", "path")
112
+ __slots__ = ("location", "generation_modes", "path")
111
113
 
112
114
  def __init__(
113
115
  self,
114
116
  *,
115
117
  location: str,
116
- data_generation_methods: list[DataGenerationMethod] | None = None,
118
+ generation_modes: list[GenerationMode] | None = None,
117
119
  path: list[str | int] | None = None,
118
120
  ) -> None:
119
121
  self.location = location
120
- self.data_generation_methods = (
121
- data_generation_methods if data_generation_methods is not None else DataGenerationMethod.all()
122
- )
122
+ self.generation_modes = generation_modes if generation_modes is not None else GenerationMode.all()
123
123
  self.path = path or []
124
124
 
125
125
  @contextmanager
@@ -137,14 +137,14 @@ class CoverageContext:
137
137
  def with_positive(self) -> CoverageContext:
138
138
  return CoverageContext(
139
139
  location=self.location,
140
- data_generation_methods=[DataGenerationMethod.positive],
140
+ generation_modes=[GenerationMode.POSITIVE],
141
141
  path=self.path,
142
142
  )
143
143
 
144
144
  def with_negative(self) -> CoverageContext:
145
145
  return CoverageContext(
146
146
  location=self.location,
147
- data_generation_methods=[DataGenerationMethod.negative],
147
+ generation_modes=[GenerationMode.NEGATIVE],
148
148
  path=self.path,
149
149
  )
150
150
 
@@ -255,7 +255,7 @@ def _cover_positive_for_type(
255
255
  template = ctx.generate_from_schema(template_schema)
256
256
  else:
257
257
  template = None
258
- if DataGenerationMethod.positive in ctx.data_generation_methods:
258
+ if GenerationMode.POSITIVE in ctx.generation_modes:
259
259
  ctx = ctx.with_positive()
260
260
  enum = schema.get("enum", NOT_SET)
261
261
  const = schema.get("const", NOT_SET)
@@ -298,7 +298,7 @@ def _ignore_unfixable(
298
298
  *,
299
299
  # Cache exception types here as `jsonschema` uses a custom `__getattr__` on the module level
300
300
  # and it may cause errors during the interpreter shutdown
301
- ref_error: type[Exception] = jsonschema.RefResolutionError,
301
+ ref_error: type[Exception] = RefResolutionError,
302
302
  schema_error: type[Exception] = jsonschema.SchemaError,
303
303
  ) -> Generator:
304
304
  try:
@@ -333,7 +333,7 @@ def cover_schema_iter(
333
333
  for ty in types:
334
334
  with _ignore_unfixable():
335
335
  yield from _cover_positive_for_type(ctx, schema, ty)
336
- if DataGenerationMethod.negative in ctx.data_generation_methods:
336
+ if GenerationMode.NEGATIVE in ctx.generation_modes:
337
337
  template = None
338
338
  for key, value in schema.items():
339
339
  with _ignore_unfixable(), ctx.at(key):
@@ -467,7 +467,7 @@ def _get_properties(schema: dict | bool) -> dict | bool:
467
467
  return {"enum": schema["examples"]}
468
468
  if schema.get("type") == "object":
469
469
  return _get_template_schema(schema, "object")
470
- _schema = fast_deepcopy(schema)
470
+ _schema = deepclone(schema)
471
471
  update_pattern_in_schema(_schema)
472
472
  return _schema
473
473
  return schema
@@ -1,14 +1,23 @@
1
- """A set of performance-related patches."""
2
-
3
1
  from typing import Any
4
2
 
3
+ # Maximum test running time
4
+ DEFAULT_DEADLINE = 15000
5
+
5
6
 
6
- def install() -> None:
7
+ def setup() -> None:
8
+ from hypothesis.internal.entropy import deterministic_PRNG
7
9
  from hypothesis.internal.reflection import is_first_param_referenced_in_function
8
10
  from hypothesis.strategies._internal import core
9
11
  from hypothesis_jsonschema import _from_schema, _resolve
10
12
 
11
- from .internal.copy import fast_deepcopy
13
+ from schemathesis.core.transforms import deepclone
14
+
15
+ # Forcefully initializes Hypothesis' global PRNG to avoid races that initialize it
16
+ # if e.g. Schemathesis CLI is used with multiple workers
17
+ with deterministic_PRNG():
18
+ pass
19
+
20
+ # A set of performance-related patches
12
21
 
13
22
  # This one is used a lot, and under the hood it re-parses the AST of the same function
14
23
  def _is_first_param_referenced_in_function(f: Any) -> bool:
@@ -17,5 +26,5 @@ def install() -> None:
17
26
  return is_first_param_referenced_in_function(f)
18
27
 
19
28
  core.is_first_param_referenced_in_function = _is_first_param_referenced_in_function # type: ignore
20
- _resolve.deepcopy = fast_deepcopy # type: ignore
21
- _from_schema.deepcopy = fast_deepcopy # type: ignore
29
+ _resolve.deepcopy = deepclone # type: ignore
30
+ _from_schema.deepcopy = deepclone # type: ignore