schemathesis 3.28.0__py3-none-any.whl → 3.28.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.
@@ -4,22 +4,22 @@ Based on https://swagger.io/docs/specification/links/
4
4
  """
5
5
 
6
6
  from __future__ import annotations
7
+
7
8
  from dataclasses import dataclass, field
8
9
  from difflib import get_close_matches
9
- from typing import Any, Generator, NoReturn, Sequence, Union, TYPE_CHECKING
10
+ from typing import TYPE_CHECKING, Any, Generator, NoReturn, Sequence, Union
10
11
 
12
+ from ...constants import NOT_SET
13
+ from ...internal.copy import fast_deepcopy
11
14
  from ...models import APIOperation, Case
12
15
  from ...parameters import ParameterSet
13
- from ...stateful import ParsedData, StatefulTest
16
+ from ...stateful import ParsedData, StatefulTest, UnresolvableLink
14
17
  from ...stateful.state_machine import Direction
15
18
  from ...types import NotSet
16
-
17
- from ...constants import NOT_SET
18
- from ...internal.copy import fast_deepcopy
19
19
  from . import expressions
20
20
  from .constants import LOCATION_TO_CONTAINER
21
21
  from .parameters import OpenAPI20Body, OpenAPI30Body, OpenAPIParameter
22
-
22
+ from .references import Unresolvable
23
23
 
24
24
  if TYPE_CHECKING:
25
25
  from ...transports.responses import GenericResponse
@@ -61,16 +61,17 @@ class Link(StatefulTest):
61
61
  def parse(self, case: Case, response: GenericResponse) -> ParsedData:
62
62
  """Parse data into a structure expected by links definition."""
63
63
  context = expressions.ExpressionContext(case=case, response=response)
64
- parameters = {
65
- parameter: expressions.evaluate(expression, context) for parameter, expression in self.parameters.items()
66
- }
67
- return ParsedData(
68
- parameters=parameters,
69
- # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#link-object
70
- # > A literal value or {expression} to use as a request body when calling the target operation.
71
- # In this case all literals will be passed as is, and expressions will be evaluated
72
- body=expressions.evaluate(self.request_body, context),
73
- )
64
+ parameters = {}
65
+ for parameter, expression in self.parameters.items():
66
+ evaluated = expressions.evaluate(expression, context)
67
+ if isinstance(evaluated, Unresolvable):
68
+ raise UnresolvableLink(f"Unresolvable reference in the link: {expression}")
69
+ parameters[parameter] = evaluated
70
+ # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#link-object
71
+ # > A literal value or {expression} to use as a request body when calling the target operation.
72
+ # In this case all literals will be passed as is, and expressions will be evaluated
73
+ body = expressions.evaluate(self.request_body, context)
74
+ return ParsedData(parameters=parameters, body=body)
74
75
 
75
76
  def make_operation(self, collected: list[ParsedData]) -> APIOperation:
76
77
  """Create a modified version of the original API operation with additional data merged in."""
@@ -524,7 +524,7 @@ class BaseOpenAPISchema(BaseSchema):
524
524
  if operation == source.path:
525
525
  # Methods should be completely resolved now, otherwise they might miss a resolving scope when
526
526
  # they will be fully resolved later
527
- methods = self.resolver.resolve_all(methods)
527
+ methods = self.resolver.resolve_all(methods, RECURSION_DEPTH_LIMIT - 8)
528
528
  found = False
529
529
  for method, definition in methods.items():
530
530
  if method.upper() == source.method.upper():
@@ -1066,11 +1066,11 @@ class OpenApi30(SwaggerV20):
1066
1066
  for media_type, entry in content.items():
1067
1067
  main, sub = parse_content_type(media_type)
1068
1068
  if main in ("*", "multipart") and sub in ("*", "form-data", "mixed"):
1069
- schema = entry["schema"]
1069
+ schema = entry.get("schema")
1070
1070
  break
1071
1071
  else:
1072
1072
  raise InternalError("No 'multipart/form-data' media type found in the schema")
1073
- for name, property_schema in schema.get("properties", {}).items():
1073
+ for name, property_schema in (schema or {}).get("properties", {}).items():
1074
1074
  if name in form_data:
1075
1075
  if isinstance(form_data[name], list):
1076
1076
  files.extend([(name, item) for item in form_data[name]])
@@ -10,8 +10,7 @@ from ....internal.result import Ok
10
10
  from ....stateful.state_machine import APIStateMachine, Direction, StepResult
11
11
  from ....utils import combine_strategies
12
12
  from .. import expressions
13
- from . import links
14
- from .links import APIOperationConnections, Connection, _convert_strategy, apply, make_response_filter
13
+ from .links import APIOperationConnections, Connection, apply
15
14
 
16
15
  if TYPE_CHECKING:
17
16
  from ....models import APIOperation, Case
@@ -16,6 +16,10 @@ if TYPE_CHECKING:
16
16
  from .state_machine import APIStateMachine
17
17
 
18
18
 
19
+ class UnresolvableLink(Exception):
20
+ """Raised when a link cannot be resolved."""
21
+
22
+
19
23
  @enum.unique
20
24
  class Stateful(enum.Enum):
21
25
  none = 1
@@ -70,8 +74,12 @@ class StatefulData:
70
74
 
71
75
  def store(self, case: Case, response: GenericResponse) -> None:
72
76
  """Parse and store data for a stateful test."""
73
- parsed = self.stateful_test.parse(case, response)
74
- self.container.append(parsed)
77
+ try:
78
+ parsed = self.stateful_test.parse(case, response)
79
+ self.container.append(parsed)
80
+ except UnresolvableLink:
81
+ # For now, ignore if a link cannot be resolved
82
+ pass
75
83
 
76
84
 
77
85
  @dataclass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: schemathesis
3
- Version: 3.28.0
3
+ Version: 3.28.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
@@ -103,12 +103,12 @@ schemathesis/specs/openapi/definitions.py,sha256=t5xffHLBnSgptBdDkSqYN1OfT-DaXoe
103
103
  schemathesis/specs/openapi/examples.py,sha256=igLDfMpNhRMAk7mYBqi93CtVRQTZCWjCJ2KxlQFotdA,14932
104
104
  schemathesis/specs/openapi/filters.py,sha256=Ei-QTFcGCvGSIunT-GYQrtqzB-kqvUePOcUuC7B7mT8,1436
105
105
  schemathesis/specs/openapi/formats.py,sha256=JmmkQWNAj5XreXb7Edgj4LADAf4m86YulR_Ec8evpJ4,1220
106
- schemathesis/specs/openapi/links.py,sha256=FUjqEf6Sv6PeS0UX7CLL5p2VHa9vA1MGDPhx2pfYg1s,14576
106
+ schemathesis/specs/openapi/links.py,sha256=Afju0IzRzvDypD3_V_SauhpKuMICczck6tLqezEapYY,14794
107
107
  schemathesis/specs/openapi/loaders.py,sha256=QoEFJ7fxJz5XcGTEWV_ZGXARiektmyyT_xmVtcHco6Q,24131
108
108
  schemathesis/specs/openapi/media_types.py,sha256=dNTxpRQbY3SubdVjh4Cjb38R6Bc9MF9BsRQwPD87x0g,1017
109
109
  schemathesis/specs/openapi/parameters.py,sha256=5jMZQZFsZNBFjG22Bqot-Rc65emiSA4E95rIzwImThk,13610
110
110
  schemathesis/specs/openapi/references.py,sha256=zEDzoJbUAwVYTy9CtJ9w1E1Xzp60CVsjebDkFjMXnno,8982
111
- schemathesis/specs/openapi/schemas.py,sha256=oFRfFucQ3Sf5iZvnVCGJDW0MH7lyA1pSAn7S7bnaSmQ,50466
111
+ schemathesis/specs/openapi/schemas.py,sha256=k6tcZrSwDAC8LA_hmRv2PvQ7epNxVs9wIZ-lkquCZcs,50505
112
112
  schemathesis/specs/openapi/security.py,sha256=nCUIaZTzI6t26HAfd8YTHW6mFxXAPN9Ds-P9UnXxmNA,6628
113
113
  schemathesis/specs/openapi/serialization.py,sha256=jajqowTIiyEVWEx-Gy4ZinXZewNg0n_ipsGzz7JXP7c,11383
114
114
  schemathesis/specs/openapi/utils.py,sha256=gmW4v6o6sZQifajfPquhFeWmZWGQM89mOOBYZvjnE7g,741
@@ -123,17 +123,17 @@ schemathesis/specs/openapi/negative/__init__.py,sha256=Nhe6qeSCnlgf5l-Fu6yHvL--3
123
123
  schemathesis/specs/openapi/negative/mutations.py,sha256=SQjQR5aK-LpbSWzwrtbFX3PQ2xb5hzJV7eZXw6MlRJo,18643
124
124
  schemathesis/specs/openapi/negative/types.py,sha256=a7buCcVxNBG6ILBM3A7oNTAX0lyDseEtZndBuej8MbI,174
125
125
  schemathesis/specs/openapi/negative/utils.py,sha256=ozcOIuASufLqZSgnKUACjX-EOZrrkuNdXX0SDnLoGYA,168
126
- schemathesis/specs/openapi/stateful/__init__.py,sha256=R8RhPJD3rDzqL4eA9jSnUwh9Q_Mv27ka1C5FdRuyusY,4509
126
+ schemathesis/specs/openapi/stateful/__init__.py,sha256=XpPBe0JLK2LUPUTiLn0UE0aWrNwVsbzlhqejVXRGXJM,4448
127
127
  schemathesis/specs/openapi/stateful/links.py,sha256=cSIwho2Hroty6au-gyCD-OwqnuCcIpnIIHU6FvF0SwA,3533
128
- schemathesis/stateful/__init__.py,sha256=T7rvhzftfl3wumEsir33DBBzCTK2PtRp9CxBxMLdMSE,4693
128
+ schemathesis/stateful/__init__.py,sha256=uo0UuLPuNsf7dK401BaNA8AqvlGXn2cb2FZlhzHmXYk,4909
129
129
  schemathesis/stateful/state_machine.py,sha256=ZcKpbvEl1QGhVOYnA7Ow6zkuFHtEPDAyCjroPrj-FgU,11343
130
130
  schemathesis/transports/__init__.py,sha256=vQ5pyMefhVpbl0FFXtivGsFHWX-7V1PXNwvqCKMJHoI,11423
131
131
  schemathesis/transports/auth.py,sha256=ZKFku9gjhIG6445qNC2p_64Yt9Iz_4azbvja8AMptBk,404
132
132
  schemathesis/transports/content_types.py,sha256=xU8RZWxz-CyWRqQTI2fGYQacB7KasoY7LL_bxPQdyPY,2144
133
133
  schemathesis/transports/headers.py,sha256=EDxpm8su0AuhyqZUkMex-OFZMAJN_5NHah7fDT2HDZE,989
134
134
  schemathesis/transports/responses.py,sha256=j_-udvWbmi6XtEYmpdX8WoFnlrQ6-i3PSBizfozRjQI,1673
135
- schemathesis-3.28.0.dist-info/METADATA,sha256=42KfcWW6Hsnb65TECi8kVUb_lTES715x93ei2OjJNgs,17376
136
- schemathesis-3.28.0.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
137
- schemathesis-3.28.0.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
138
- schemathesis-3.28.0.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
139
- schemathesis-3.28.0.dist-info/RECORD,,
135
+ schemathesis-3.28.1.dist-info/METADATA,sha256=0gIx1YbzeUCbaEjNYgoVWpn92YEgfL87fr6H1ft3rG8,17376
136
+ schemathesis-3.28.1.dist-info/WHEEL,sha256=hKi7AIIx6qfnsRbr087vpeJnrVUuDokDHZacPPMW7-Y,87
137
+ schemathesis-3.28.1.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
138
+ schemathesis-3.28.1.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
139
+ schemathesis-3.28.1.dist-info/RECORD,,