schemathesis 3.26.0__py3-none-any.whl → 3.26.2__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.
@@ -16,3 +16,6 @@ IS_PYTEST_ABOVE_8 = PYTEST_VERSION >= version.parse("8.0.0")
16
16
 
17
17
  HYPOTHESIS_VERSION = version.parse(metadata.version("hypothesis"))
18
18
  HYPOTHESIS_HAS_STATEFUL_NAMING_IMPROVEMENTS = HYPOTHESIS_VERSION >= version.parse("6.98.14")
19
+
20
+ PYRATE_LIMITER_VERSION = version.parse(metadata.version("pyrate-limiter"))
21
+ IS_PYRATE_LIMITER_ABOVE_3 = PYRATE_LIMITER_VERSION >= version.parse("3.0")
@@ -77,7 +77,16 @@ def create_test(
77
77
  wrapped_test.hypothesis.inner_test = make_async_test(test) # type: ignore
78
78
  setup_default_deadline(wrapped_test)
79
79
  if settings is not None:
80
- wrapped_test = settings(wrapped_test)
80
+ existing_settings = _get_hypothesis_settings(wrapped_test)
81
+ if existing_settings is not None:
82
+ # Merge the user-provided settings with the current ones
83
+ default = hypothesis.settings.default
84
+ wrapped_test._hypothesis_internal_use_settings = hypothesis.settings(
85
+ wrapped_test._hypothesis_internal_use_settings,
86
+ **{item: value for item, value in settings.__dict__.items() if value != getattr(default, item)},
87
+ )
88
+ else:
89
+ wrapped_test = settings(wrapped_test)
81
90
  existing_settings = _get_hypothesis_settings(wrapped_test)
82
91
  if existing_settings is not None:
83
92
  existing_settings = remove_explain_phase(existing_settings)
@@ -0,0 +1,6 @@
1
+ from ._dependency_versions import IS_PYRATE_LIMITER_ABOVE_3
2
+
3
+ if IS_PYRATE_LIMITER_ABOVE_3:
4
+ from pyrate_limiter import Limiter, Rate, RateItem
5
+ else:
6
+ from pyrate_limiter import Limiter, RequestRate as Rate
schemathesis/models.py CHANGED
@@ -125,6 +125,8 @@ class Case:
125
125
  """A single test case parameters."""
126
126
 
127
127
  operation: APIOperation
128
+ # Time spent on generation of this test case
129
+ generation_time: float
128
130
  # Unique test case identifier
129
131
  id: str = field(default_factory=generate_random_case_id, compare=False)
130
132
  path_parameters: PathParameters | None = None
@@ -579,6 +581,7 @@ class Case:
579
581
  cookies=fast_deepcopy(self.cookies),
580
582
  query=fast_deepcopy(self.query),
581
583
  body=fast_deepcopy(self.body),
584
+ generation_time=self.generation_time,
582
585
  )
583
586
 
584
587
 
@@ -36,6 +36,7 @@ if TYPE_CHECKING:
36
36
  class SerializedCase:
37
37
  # Case data
38
38
  id: str
39
+ generation_time: float
39
40
  path_parameters: dict[str, Any] | None
40
41
  headers: dict[str, Any] | None
41
42
  cookies: dict[str, Any] | None
@@ -60,6 +61,7 @@ class SerializedCase:
60
61
  serialized_body = _serialize_body(request_data.body)
61
62
  return cls(
62
63
  id=case.id,
64
+ generation_time=case.generation_time,
63
65
  path_parameters=case.path_parameters,
64
66
  headers=dict(case.headers) if case.headers is not None else None,
65
67
  cookies=case.cookies,
schemathesis/schemas.py CHANGED
@@ -40,6 +40,7 @@ from .generation import (
40
40
  DataGenerationMethodInput,
41
41
  GenerationConfig,
42
42
  )
43
+ from ._dependency_versions import IS_PYRATE_LIMITER_ABOVE_3
43
44
  from .exceptions import OperationSchemaError, UsageError
44
45
  from .hooks import HookContext, HookDispatcher, HookScope, dispatch
45
46
  from .internal.result import Result, Ok
@@ -423,7 +424,10 @@ class BaseSchema(Mapping):
423
424
  """Limit the rate of sending generated requests."""
424
425
  label = urlparse(self.base_url).netloc
425
426
  if self.rate_limiter is not None:
426
- return self.rate_limiter.ratelimit(label, delay=True, max_delay=0)
427
+ if IS_PYRATE_LIMITER_ABOVE_3:
428
+ self.rate_limiter.try_acquire(label)
429
+ else:
430
+ return self.rate_limiter.ratelimit(label, delay=True, max_delay=0)
427
431
  return nullcontext()
428
432
 
429
433
  def _get_payload_schema(self, definition: dict[str, Any], media_type: str) -> dict[str, Any] | None:
@@ -60,6 +60,8 @@ def serialize_before_execution(event: events.BeforeExecution) -> dict[str, Any]
60
60
 
61
61
  def _serialize_case(case: SerializedCase) -> dict[str, Any]:
62
62
  return {
63
+ "id": case.id,
64
+ "generation_time": case.generation_time,
63
65
  "verbose_name": case.verbose_name,
64
66
  "path_template": case.path_template,
65
67
  "path_parameters": stringify_path_parameters(case.path_parameters),
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import enum
4
+ import time
4
5
  from dataclasses import dataclass, field
5
6
  from difflib import get_close_matches
6
7
  from enum import unique
@@ -287,6 +288,7 @@ class GraphQLSchema(BaseSchema):
287
288
  query=query,
288
289
  body=body,
289
290
  media_type=media_type,
291
+ generation_time=0.0,
290
292
  )
291
293
 
292
294
  def get_tags(self, operation: APIOperation) -> list[str] | None:
@@ -337,6 +339,7 @@ def get_case_strategy(
337
339
  generation_config: GenerationConfig | None = None,
338
340
  **kwargs: Any,
339
341
  ) -> Any:
342
+ start = time.monotonic()
340
343
  definition = cast(GraphQLOperationDefinition, operation.definition)
341
344
  strategy_factory = {
342
345
  RootType.QUERY: gql_st.queries,
@@ -369,6 +372,7 @@ def get_case_strategy(
369
372
  body=body,
370
373
  operation=operation,
371
374
  data_generation_method=data_generation_method,
375
+ generation_time=time.monotonic() - start,
372
376
  ) # type: ignore
373
377
  context = auths.AuthContext(
374
378
  operation=operation,
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
  import string
3
+ import time
3
4
  from base64 import b64encode
4
5
  from contextlib import suppress
5
6
  from dataclasses import dataclass
@@ -42,7 +43,9 @@ StrategyFactory = Callable[[Dict[str, Any], str, str, Optional[str], GenerationC
42
43
 
43
44
 
44
45
  def header_values(blacklist_characters: str = "\n\r") -> st.SearchStrategy[str]:
45
- return st.text(alphabet=st.characters(min_codepoint=0, max_codepoint=255, blacklist_characters="\n\r"))
46
+ return st.text(
47
+ alphabet=st.characters(min_codepoint=0, max_codepoint=255, blacklist_characters=blacklist_characters)
48
+ )
46
49
 
47
50
 
48
51
  @lru_cache
@@ -131,6 +134,7 @@ def get_case_strategy(
131
134
  The primary purpose of this behavior is to prevent sending incomplete explicit examples by generating missing parts
132
135
  as it works with `body`.
133
136
  """
137
+ start = time.monotonic()
134
138
  strategy_factory = DATA_GENERATION_METHOD_TO_STRATEGY_FACTORY[generator]
135
139
 
136
140
  context = HookContext(operation)
@@ -193,6 +197,7 @@ def get_case_strategy(
193
197
  reject()
194
198
  instance = Case(
195
199
  operation=operation,
200
+ generation_time=time.monotonic() - start,
196
201
  media_type=media_type,
197
202
  path_parameters=path_parameters_.value,
198
203
  headers=CaseInsensitiveDict(headers_.value) if headers_.value is not None else headers_.value,
@@ -953,6 +953,7 @@ class SwaggerV20(BaseOpenAPISchema):
953
953
  query=query,
954
954
  body=body,
955
955
  media_type=media_type,
956
+ generation_time=0.0,
956
957
  )
957
958
 
958
959
  def _get_consumes_for_operation(self, definition: dict[str, Any]) -> list[str]:
@@ -34,8 +34,8 @@ def invalid_rate(value: str) -> UsageError:
34
34
 
35
35
 
36
36
  def build_limiter(rate: str) -> Limiter:
37
- from pyrate_limiter import Limiter, RequestRate
37
+ from ._rate_limiter import Limiter, Rate
38
38
 
39
39
  limit, interval = parse_units(rate)
40
- rate = RequestRate(limit, interval)
40
+ rate = Rate(limit, interval)
41
41
  return Limiter(rate)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schemathesis
3
- Version: 3.26.0
3
+ Version: 3.26.2
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
@@ -39,7 +39,7 @@ Requires-Dist: hypothesis<7,>=6.84.3; python_version > '3.8'
39
39
  Requires-Dist: hypothesis[zoneinfo]<7,>=6.84.3; python_version == '3.8'
40
40
  Requires-Dist: jsonschema<5.0,>=4.18.0
41
41
  Requires-Dist: junit-xml<2.0,>=1.9
42
- Requires-Dist: pyrate-limiter<3.0,>=2.10
42
+ Requires-Dist: pyrate-limiter<4.0,>=2.10
43
43
  Requires-Dist: pytest-subtests<0.8.0,>=0.2.1
44
44
  Requires-Dist: pytest<9,>=4.6.4
45
45
  Requires-Dist: pyyaml<7.0,>=5.1
@@ -1,9 +1,10 @@
1
1
  schemathesis/__init__.py,sha256=WW1NBZxmc5jRR0c24xz-ZtTkJMUQG5MOw1MGVRRGc1s,1970
2
2
  schemathesis/_compat.py,sha256=VizWR0QAVj4l7WZautNe_zmo3AJ7WBl2zrJQOfJAQtk,1837
3
- schemathesis/_dependency_versions.py,sha256=sLlY3jGtnjIg2JRMbVt89lYKiD3K2zl1A5QF0_5_O08,728
4
- schemathesis/_hypothesis.py,sha256=9qqO4xlNRXm8lYJaYN53N5HoQTHKljjZ1M3jzWKKnbU,10244
3
+ schemathesis/_dependency_versions.py,sha256=InIv6MZmuRVHc_9FxAiRg7_dY-vuF0jT69FBxrBLK6U,879
4
+ schemathesis/_hypothesis.py,sha256=O3rfMbT0rChFONMUsYmMEGV9nPG5cHd_6v9NhWDI_IQ,10763
5
5
  schemathesis/_lazy_import.py,sha256=LTki2tM168fCcXet1e6qDoQq8SLgInUA3xjXgi7cXJk,469
6
6
  schemathesis/_override.py,sha256=oetGCvMGqP8plf2Suvql2E0n3P-PU9SIySKwlBjzuR4,1629
7
+ schemathesis/_rate_limiter.py,sha256=t0uUB4kz5lG1ogfLHwIImunOaP88jFkCf-zzzxOM3cs,212
7
8
  schemathesis/_xml.py,sha256=5AMZuno3fS4YWPqBlrv5V-f-BmawkdwmpD3GpAsaxnA,6922
8
9
  schemathesis/auths.py,sha256=tUuaHvXO96HJr22Gu9OmlSpL2wbAqKZr3TRbb9dVyA4,14732
9
10
  schemathesis/checks.py,sha256=SYts1Teecg-5kSHBo32Pzhh7YQ4a1Y7DIfldd-0VTj8,2155
@@ -16,14 +17,14 @@ schemathesis/graphql.py,sha256=YkoKWY5K8lxp7H3ikAs-IsoDbiPwJvChG7O8p3DgwtI,229
16
17
  schemathesis/hooks.py,sha256=cNJgCh7SyLWT1sYDKF5ncDC80ld08CinvKo2IqLMV4g,12396
17
18
  schemathesis/lazy.py,sha256=CivWpvesh4iYLSkatXbQPTEOruWmXvuZQ29gng5p9wM,14846
18
19
  schemathesis/loaders.py,sha256=RJnrbf-3vZ7KXmRBkmr3uqWyg0eHzOnONABuudWcTIg,4586
19
- schemathesis/models.py,sha256=F2aWZW_BqCFzgv9s7KFkRt-EGQTimhKbYaehRtqC6Lw,46757
20
+ schemathesis/models.py,sha256=Rcgm2VX7oQN3HN-ThZlqWmBuNsV1Hrd2_xbvh0K6KQY,46883
20
21
  schemathesis/parameters.py,sha256=VheEffVzoSfYaSEcG7KhPlA4ypifosG8biiHifzwL8g,2257
21
22
  schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
23
  schemathesis/sanitization.py,sha256=WSV_MB5YRrYkp1pQRPHrzsidqsKcqYZiq64N9grKobo,8956
23
- schemathesis/schemas.py,sha256=rtlbHoEmZt5sF31E7Mn_MJdfcaCRUejVAkxFicrq3c0,18252
24
+ schemathesis/schemas.py,sha256=H13rs5X-FkNcGIB9W__oolu-AM-vIyYEiArXpg-rKU0,18429
24
25
  schemathesis/serializers.py,sha256=_xoebWkVrgbGbPjPgTgwuN-fN4YT004aj7kImyPComY,11619
25
26
  schemathesis/targets.py,sha256=tzp7VZ2-7g2nZHCooRgFzTMtOVcbl0rvtNR421hQthA,1162
26
- schemathesis/throttling.py,sha256=QQcS7TFpXHavUjm0kdFaCcCRhAGlgQ4y3XIbkdRoW20,1079
27
+ schemathesis/throttling.py,sha256=uwhL4XWPWAU8HECg0NhibfCMn5dT7NElTx3fdL3Mmcc,1065
27
28
  schemathesis/types.py,sha256=AglR5M0bce-YXeDRkweToXTP0GjNOWVjS_mIsxLobwc,919
28
29
  schemathesis/utils.py,sha256=4HXvHysnHp-Uz2HfNgLfW5F5VjL-mtixrjjzRCEJhYo,5233
29
30
  schemathesis/cli/__init__.py,sha256=MSdz9Xt2qvey-3HbWj5nfwV2nZ-rdV05u_Eh_Be9m0c,64909
@@ -66,7 +67,7 @@ schemathesis/internal/validation.py,sha256=G7i8jIMUpAeOnDsDF_eWYvRZe_yMprRswx0QA
66
67
  schemathesis/runner/__init__.py,sha256=kkqjC_5G2Mrq00syLNUDHP3sXqwiId8_cusKtIlOyXM,21419
67
68
  schemathesis/runner/events.py,sha256=eZc4TT8C8mWCMr9h4JvlijvQQ-x8wFry8LntdsYIL-A,10200
68
69
  schemathesis/runner/probes.py,sha256=t_B38-ljy-p3Odw-dqcZUVIjYTPwBvac8KE5GaLnz4M,5546
69
- schemathesis/runner/serialization.py,sha256=SOyEvO87ZtGCG_zfYW5uaKZBiXbVtEM7yGDuVp0wrI8,16003
70
+ schemathesis/runner/serialization.py,sha256=JgkZrbELi2rL7iCsQ0yySOADwxSNF96gd_DOHVANPVU,16080
70
71
  schemathesis/runner/impl/__init__.py,sha256=1E2iME8uthYPBh9MjwVBCTFV-P3fi7AdphCCoBBspjs,199
71
72
  schemathesis/runner/impl/core.py,sha256=vaw6OBgYOVT44-gR2t_EiWLArX2RmtAxITR3WZWCX8k,39558
72
73
  schemathesis/runner/impl/solo.py,sha256=Y_tNhVBVxcuxv65hN0FjxLlVSC41ebHMOM1xSzVrNk8,3358
@@ -82,17 +83,17 @@ schemathesis/service/hosts.py,sha256=Qxa-BGV56z9pRHl8kUm8LNZQiW3fALDYVcgZqUMh4qQ
82
83
  schemathesis/service/metadata.py,sha256=ajiDb2VDquXRoYl7h9LGDoj9GWq6pKv5nN-WVtTnCIE,2086
83
84
  schemathesis/service/models.py,sha256=45J7lugoFP1QbQFAEFCi9aj-yuTBKKHtil9vA8BWnfk,6577
84
85
  schemathesis/service/report.py,sha256=ua1-cfa-TgGshZgimUQ3-YQqykhZqMHCkEificBKncM,8294
85
- schemathesis/service/serialization.py,sha256=si3NF9_nN7l2f2EPnVGWNN07Oc9lFh_ZhaqhO78qtWg,8305
86
+ schemathesis/service/serialization.py,sha256=OjWG7FfihEl4LtpOD8N-fmjOTzSPUm6A4x6sypt2nW4,8377
86
87
  schemathesis/service/usage.py,sha256=Z-GCwFcW1pS6YdC-ziEOynikqgOttxp2Uyj_dfK5Q7A,2437
87
88
  schemathesis/specs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
89
  schemathesis/specs/graphql/__init__.py,sha256=fgyHtvWNUVWismBTOqxQtgLoTighTfvMv6v6QCD_Oyc,85
89
90
  schemathesis/specs/graphql/loaders.py,sha256=16fGT4rSqVF91DPY90cKDaFsbtRb9_ZdLnlGY1Gb_vg,11391
90
91
  schemathesis/specs/graphql/nodes.py,sha256=7F5jbk96uTZZXK9Ulr86KpCAn8z6LKMBcrLrdJHggH0,540
91
92
  schemathesis/specs/graphql/scalars.py,sha256=W5oj6AcjiXpR-Z6eSSp1oPWl0mjH2NF-w87nRFhrHHg,1805
92
- schemathesis/specs/graphql/schemas.py,sha256=pbonjYD2neMujoMZZMM_MXFJt-gk1qsW59Qkfed9Ltg,13967
93
+ schemathesis/specs/graphql/schemas.py,sha256=XK-zbR_d8zER2HLU3zH-BrKnfoV9hb0VXvDueryp8Y0,14091
93
94
  schemathesis/specs/graphql/validation.py,sha256=SqQbj9uymGUQxlHXc8HkQccIq25uwP5CvLF1zReb1Xg,1636
94
95
  schemathesis/specs/openapi/__init__.py,sha256=HDcx3bqpa6qWPpyMrxAbM3uTo0Lqpg-BUNZhDJSJKnw,279
95
- schemathesis/specs/openapi/_hypothesis.py,sha256=Z-Zapvv734eBrZVdKukhJ-fDXqPDIPez5OOgvSCI5Sg,22716
96
+ schemathesis/specs/openapi/_hypothesis.py,sha256=o1ssS7JJZ45l750ogoZ3gXoedzLmRsXqpPb1LCZXikY,22835
96
97
  schemathesis/specs/openapi/checks.py,sha256=1WB_UGNqptfJThWLUNbds1Q-IzOGbbHCOYPIhBYk-zs,5411
97
98
  schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
98
99
  schemathesis/specs/openapi/converter.py,sha256=9TKeKvNi9MVvoNMfqoPz_cODO8oNrMSTXTOwLLfjD_Q,2799
@@ -105,7 +106,7 @@ schemathesis/specs/openapi/loaders.py,sha256=Jm37MTUmbVVkOxoRAJOo_T_Ex-tWu2ir7YG
105
106
  schemathesis/specs/openapi/media_types.py,sha256=dNTxpRQbY3SubdVjh4Cjb38R6Bc9MF9BsRQwPD87x0g,1017
106
107
  schemathesis/specs/openapi/parameters.py,sha256=5jMZQZFsZNBFjG22Bqot-Rc65emiSA4E95rIzwImThk,13610
107
108
  schemathesis/specs/openapi/references.py,sha256=YGunHAGubYPKbMqQtpFWZm1D4AGxB8wLuiVhE6T6cWo,8978
108
- schemathesis/specs/openapi/schemas.py,sha256=mIoJkuaQeF5fcrjBFGuudglQJz93vbaMc0wFVJjdVTg,50424
109
+ schemathesis/specs/openapi/schemas.py,sha256=BuBKfToNYIsQ1RIh3EedNaB948-33wLSrjSi1lBV0F0,50457
109
110
  schemathesis/specs/openapi/security.py,sha256=nCUIaZTzI6t26HAfd8YTHW6mFxXAPN9Ds-P9UnXxmNA,6628
110
111
  schemathesis/specs/openapi/serialization.py,sha256=jajqowTIiyEVWEx-Gy4ZinXZewNg0n_ipsGzz7JXP7c,11383
111
112
  schemathesis/specs/openapi/utils.py,sha256=gmW4v6o6sZQifajfPquhFeWmZWGQM89mOOBYZvjnE7g,741
@@ -129,8 +130,8 @@ schemathesis/transports/auth.py,sha256=ZKFku9gjhIG6445qNC2p_64Yt9Iz_4azbvja8AMpt
129
130
  schemathesis/transports/content_types.py,sha256=xU8RZWxz-CyWRqQTI2fGYQacB7KasoY7LL_bxPQdyPY,2144
130
131
  schemathesis/transports/headers.py,sha256=EDxpm8su0AuhyqZUkMex-OFZMAJN_5NHah7fDT2HDZE,989
131
132
  schemathesis/transports/responses.py,sha256=U6z1VW5w19c9qRRoyf2ljkuXR2smTfWikmrTGqlgl18,1619
132
- schemathesis-3.26.0.dist-info/METADATA,sha256=hx0GrhFy5iphwAsc2_2SZZhNYFtr1hXSjL_xY8J_AEo,16257
133
- schemathesis-3.26.0.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
134
- schemathesis-3.26.0.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
135
- schemathesis-3.26.0.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
136
- schemathesis-3.26.0.dist-info/RECORD,,
133
+ schemathesis-3.26.2.dist-info/METADATA,sha256=6ILqISo9c7aYKJCwsxMgNop39oJl1ZPz2qtbhLD_1nc,16257
134
+ schemathesis-3.26.2.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
135
+ schemathesis-3.26.2.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
136
+ schemathesis-3.26.2.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
137
+ schemathesis-3.26.2.dist-info/RECORD,,