schemathesis 3.37.1__py3-none-any.whl → 3.38.0__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.
@@ -6,15 +6,16 @@ import asyncio
6
6
  import json
7
7
  import warnings
8
8
  from copy import copy
9
+ from functools import wraps
9
10
  from typing import TYPE_CHECKING, Any, Callable, Generator, Mapping
10
11
 
11
12
  import hypothesis
12
13
  from hypothesis import Phase
13
14
  from hypothesis.errors import HypothesisWarning, Unsatisfiable
14
15
  from hypothesis.internal.entropy import deterministic_PRNG
15
- from hypothesis.internal.reflection import proxies
16
16
  from jsonschema.exceptions import SchemaError
17
17
 
18
+ from . import _patches
18
19
  from .auths import get_auth_storage_from_test
19
20
  from .constants import DEFAULT_DEADLINE, NOT_SET
20
21
  from .exceptions import OperationSchemaError, SerializationNotPossible
@@ -29,11 +30,13 @@ from .types import NotSet
29
30
  if TYPE_CHECKING:
30
31
  from .utils import GivenInput
31
32
 
32
- # Forcefully initializes Hypothesis' global PRNG to avoid races that initilize it
33
+ # Forcefully initializes Hypothesis' global PRNG to avoid races that initialize it
33
34
  # if e.g. Schemathesis CLI is used with multiple workers
34
35
  with deterministic_PRNG():
35
36
  pass
36
37
 
38
+ _patches.install()
39
+
37
40
 
38
41
  def create_test(
39
42
  *,
@@ -72,7 +75,7 @@ def create_test(
72
75
  # tests in multiple threads because Hypothesis stores some internal attributes on function objects and re-writing
73
76
  # them from different threads may lead to unpredictable side-effects.
74
77
 
75
- @proxies(test) # type: ignore
78
+ @wraps(test)
76
79
  def test_function(*args: Any, **kwargs: Any) -> Any:
77
80
  __tracebackhide__ = True
78
81
  return test(*args, **kwargs)
@@ -220,7 +223,6 @@ def _iter_coverage_cases(
220
223
  from .specs.openapi.constants import LOCATION_TO_CONTAINER
221
224
  from .specs.openapi.examples import find_in_responses, find_matching_in_responses
222
225
 
223
- ctx = coverage.CoverageContext(data_generation_methods=data_generation_methods)
224
226
  meta = GenerationMetadata(
225
227
  query=None,
226
228
  path_parameters=None,
@@ -229,15 +231,18 @@ def _iter_coverage_cases(
229
231
  body=None,
230
232
  phase=TestPhase.COVERAGE,
231
233
  description=None,
234
+ location=None,
232
235
  )
233
236
  generators: dict[tuple[str, str], Generator[coverage.GeneratedValue, None, None]] = {}
234
237
  template: dict[str, Any] = {}
235
238
  responses = find_in_responses(operation)
236
239
  for parameter in operation.iter_parameters():
237
- schema = parameter.as_json_schema(operation)
240
+ schema = parameter.as_json_schema(operation, update_quantifiers=False)
238
241
  for value in find_matching_in_responses(responses, parameter.name):
239
242
  schema.setdefault("examples", []).append(value)
240
- gen = coverage.cover_schema_iter(ctx, schema)
243
+ gen = coverage.cover_schema_iter(
244
+ coverage.CoverageContext(data_generation_methods=data_generation_methods), schema
245
+ )
241
246
  value = next(gen, NOT_SET)
242
247
  if isinstance(value, NotSet):
243
248
  continue
@@ -251,13 +256,15 @@ def _iter_coverage_cases(
251
256
  generators[(location, name)] = gen
252
257
  if operation.body:
253
258
  for body in operation.body:
254
- schema = body.as_json_schema(operation)
259
+ schema = body.as_json_schema(operation, update_quantifiers=False)
255
260
  # Definition could be a list for Open API 2.0
256
261
  definition = body.definition if isinstance(body.definition, dict) else {}
257
262
  examples = [example["value"] for example in definition.get("examples", {}).values() if "value" in example]
258
263
  if examples:
259
264
  schema.setdefault("examples", []).extend(examples)
260
- gen = coverage.cover_schema_iter(ctx, schema)
265
+ gen = coverage.cover_schema_iter(
266
+ coverage.CoverageContext(data_generation_methods=data_generation_methods), schema
267
+ )
261
268
  value = next(gen, NOT_SET)
262
269
  if isinstance(value, NotSet):
263
270
  continue
@@ -268,12 +275,14 @@ def _iter_coverage_cases(
268
275
  case.data_generation_method = value.data_generation_method
269
276
  case.meta = copy(meta)
270
277
  case.meta.description = value.description
278
+ case.meta.location = value.location
271
279
  yield case
272
280
  for next_value in gen:
273
281
  case = operation.make_case(**{**template, "body": next_value.value, "media_type": body.media_type})
274
282
  case.data_generation_method = next_value.data_generation_method
275
283
  case.meta = copy(meta)
276
284
  case.meta.description = next_value.description
285
+ case.meta.location = next_value.location
277
286
  yield case
278
287
  elif DataGenerationMethod.positive in data_generation_methods:
279
288
  case = operation.make_case(**template)
@@ -292,6 +301,7 @@ def _iter_coverage_cases(
292
301
  case.data_generation_method = value.data_generation_method
293
302
  case.meta = copy(meta)
294
303
  case.meta.description = value.description
304
+ case.meta.location = value.location
295
305
  yield case
296
306
 
297
307
 
@@ -0,0 +1,21 @@
1
+ """A set of performance-related patches."""
2
+
3
+ from typing import Any
4
+
5
+
6
+ def install() -> None:
7
+ from hypothesis.internal.reflection import is_first_param_referenced_in_function
8
+ from hypothesis.strategies._internal import core
9
+ from hypothesis_jsonschema import _from_schema, _resolve
10
+
11
+ from .internal.copy import fast_deepcopy
12
+
13
+ # This one is used a lot, and under the hood it re-parses the AST of the same function
14
+ def _is_first_param_referenced_in_function(f: Any) -> bool:
15
+ if f.__name__ == "from_object_schema" and f.__module__ == "hypothesis_jsonschema._from_schema":
16
+ return True
17
+ return is_first_param_referenced_in_function(f)
18
+
19
+ 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
@@ -36,7 +36,7 @@ from ..filters import FilterSet, expression_to_filter_function, is_deprecated
36
36
  from ..fixups import ALL_FIXUPS
37
37
  from ..generation import DEFAULT_DATA_GENERATION_METHODS, DataGenerationMethod
38
38
  from ..hooks import GLOBAL_HOOK_DISPATCHER, HookContext, HookDispatcher, HookScope
39
- from ..internal.checks import CheckConfig, PositiveDataAcceptanceConfig
39
+ from ..internal.checks import CheckConfig
40
40
  from ..internal.datetime import current_datetime
41
41
  from ..internal.output import OutputConfig
42
42
  from ..internal.validation import file_exists
@@ -244,6 +244,12 @@ http_interactions:"""
244
244
  write_double_quoted(stream, interaction.description)
245
245
  else:
246
246
  stream.write("null")
247
+ stream.write("\n location: ")
248
+
249
+ if interaction.location is not None:
250
+ write_double_quoted(stream, interaction.location)
251
+ else:
252
+ stream.write("null")
247
253
  stream.write(
248
254
  f"""
249
255
  phase: {phase}
@@ -200,7 +200,7 @@ class SchemathesisCase(PyCollector):
200
200
  kwargs["_ispytest"] = True
201
201
  metafunc = Metafunc(definition, fixtureinfo, self.config, **kwargs)
202
202
  methods = []
203
- if hasattr(module, "pytest_generate_tests"):
203
+ if module is not None and hasattr(module, "pytest_generate_tests"):
204
204
  methods.append(module.pytest_generate_tests)
205
205
  if hasattr(cls, "pytest_generate_tests"):
206
206
  cls = cast(Type, cls)
@@ -43,6 +43,8 @@ def add_single_example(strategy: st.SearchStrategy[T], examples: list[T]) -> Non
43
43
  def example_generating_inner_function(ex: T) -> None:
44
44
  examples.append(ex)
45
45
 
46
+ example_generating_inner_function._hypothesis_internal_database_key = b"" # type: ignore
47
+
46
48
  if SCHEMATHESIS_BENCHMARK_SEED is not None:
47
49
  example_generating_inner_function = seed(SCHEMATHESIS_BENCHMARK_SEED)(example_generating_inner_function)
48
50