Skip to content

Commit 769d20d

Browse files
authored
Merge pull request #1125 from python-openapi/fix/deprecated-warnings-only-when-present
Fix deprecation warnings for omitted params and headers
2 parents 9f9cfc8 + afa1fe0 commit 769d20d

File tree

6 files changed

+126
-20
lines changed

6 files changed

+126
-20
lines changed

openapi_core/validation/request/validators.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,16 +202,15 @@ def _get_parameter(
202202
self, parameters: RequestParameters, param: SchemaPath
203203
) -> Any:
204204
name = (param / "name").read_str()
205+
param_location = (param / "in").read_str()
206+
location = parameters[param_location]
205207
deprecated = (param / "deprecated").read_bool(default=False)
206-
if deprecated:
208+
if deprecated and name in location:
207209
warnings.warn(
208210
f"{name} parameter is deprecated",
209211
DeprecationWarning,
210212
)
211213

212-
param_location = (param / "in").read_str()
213-
location = parameters[param_location]
214-
215214
try:
216215
value, _ = self._get_param_or_header_and_schema(param, location)
217216
except KeyError:

openapi_core/validation/response/validators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ def _get_header(
175175
self, headers: Mapping[str, Any], name: str, header: SchemaPath
176176
) -> Any:
177177
deprecated = (header / "deprecated").read_bool(default=False)
178-
if deprecated:
178+
if deprecated and name in headers:
179179
warnings.warn(
180180
f"{name} header is deprecated",
181181
DeprecationWarning,

tests/integration/test_petstore.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -532,18 +532,15 @@ def test_get_pets_raises_missing_required_param(self, spec):
532532
)
533533

534534
with pytest.warns(
535-
DeprecationWarning, match="limit parameter is deprecated"
535+
DeprecationWarning,
536+
match="Use of allowEmptyValue property is deprecated",
536537
):
537-
with pytest.warns(
538-
DeprecationWarning,
539-
match="Use of allowEmptyValue property is deprecated",
540-
):
541-
with pytest.raises(MissingRequiredParameter):
542-
validate_request(
543-
request,
544-
spec=spec,
545-
cls=V30RequestParametersValidator,
546-
)
538+
with pytest.raises(MissingRequiredParameter):
539+
validate_request(
540+
request,
541+
spec=spec,
542+
cls=V30RequestParametersValidator,
543+
)
547544

548545
result = unmarshal_request(
549546
request, spec=spec, cls=V30RequestBodyUnmarshaller
@@ -2165,10 +2162,7 @@ def test_delete_tags_raises_missing_required_response_header(
21652162
data = None
21662163
response = MockResponse(data, status_code=200)
21672164

2168-
with pytest.warns(DeprecationWarning):
2169-
response_result = response_unmarshaller.unmarshal(
2170-
request, response
2171-
)
2165+
response_result = response_unmarshaller.unmarshal(request, response)
21722166

21732167
assert response_result.errors == [
21742168
MissingRequiredHeader(name="x-delete-confirm"),

tests/integration/unmarshalling/test_response_unmarshaller.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from openapi_core.validation.response.exceptions import InvalidData
2020
from openapi_core.validation.response.exceptions import InvalidHeader
2121
from openapi_core.validation.response.exceptions import MissingData
22+
from openapi_core.validation.response.exceptions import MissingRequiredHeader
2223
from openapi_core.validation.schemas.exceptions import InvalidSchemaValue
2324

2425

@@ -173,6 +174,35 @@ def test_invalid_header(self, response_unmarshaller):
173174
assert result.data is None
174175
assert result.headers == {"x-delete-confirm": True}
175176

177+
def test_missing_deprecated_required_header(self, response_unmarshaller):
178+
request = MockRequest(
179+
self.host_url,
180+
"delete",
181+
"/v1/tags",
182+
path_pattern="/v1/tags",
183+
)
184+
response_json = {
185+
"data": [
186+
{
187+
"id": 1,
188+
"name": "Sparky",
189+
"ears": {
190+
"healthy": True,
191+
},
192+
},
193+
],
194+
}
195+
response_data = json.dumps(response_json).encode()
196+
response = MockResponse(response_data)
197+
198+
result = response_unmarshaller.unmarshal(request, response)
199+
200+
assert result.errors == [
201+
MissingRequiredHeader(name="x-delete-confirm")
202+
]
203+
assert result.data is None
204+
assert result.headers == {}
205+
176206
def test_get_pets(self, response_unmarshaller):
177207
request = MockRequest(self.host_url, "get", "/v1/pets")
178208
response_json = {

tests/integration/validation/test_request_validators.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44

5+
from openapi_core import OpenAPI
56
from openapi_core import V30RequestValidator
67
from openapi_core.templating.media_types.exceptions import MediaTypeNotFound
78
from openapi_core.templating.paths.exceptions import OperationNotFound
@@ -63,6 +64,61 @@ def test_missing_parameter(self, request_validator):
6364
with pytest.warns(DeprecationWarning):
6465
request_validator.validate(request)
6566

67+
def test_omitted_required_deprecated_parameter(self):
68+
spec = OpenAPI.from_dict(
69+
{
70+
"openapi": "3.1.0",
71+
"info": {"version": "0", "title": "test"},
72+
"paths": {
73+
"/test": {
74+
"get": {
75+
"parameters": [
76+
{
77+
"name": "foo",
78+
"in": "query",
79+
"schema": {},
80+
"deprecated": True,
81+
"required": True,
82+
},
83+
]
84+
}
85+
}
86+
},
87+
}
88+
)
89+
90+
request = MockRequest("http://localhost", "get", "/test")
91+
92+
with pytest.raises(MissingRequiredParameter):
93+
spec.validate_request(request)
94+
95+
def test_omitted_optional_deprecated_parameter(self):
96+
spec = OpenAPI.from_dict(
97+
{
98+
"openapi": "3.1.0",
99+
"info": {"version": "0", "title": "test"},
100+
"paths": {
101+
"/test": {
102+
"get": {
103+
"parameters": [
104+
{
105+
"name": "foo",
106+
"in": "query",
107+
"schema": {},
108+
"deprecated": True,
109+
},
110+
]
111+
}
112+
}
113+
},
114+
}
115+
)
116+
117+
request = MockRequest("http://localhost", "get", "/test")
118+
result = spec.validate_request(request)
119+
120+
assert result is None
121+
66122
def test_security_not_found(self, request_validator):
67123
request = MockRequest(
68124
self.host_url,

tests/integration/validation/test_response_validators.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from openapi_core.validation.response.exceptions import InvalidData
1717
from openapi_core.validation.response.exceptions import InvalidHeader
1818
from openapi_core.validation.response.exceptions import MissingData
19+
from openapi_core.validation.response.exceptions import MissingRequiredHeader
1920
from openapi_core.validation.schemas.exceptions import InvalidSchemaValue
2021

2122

@@ -135,6 +136,32 @@ def test_invalid_header(self, response_validator):
135136
with pytest.warns(DeprecationWarning):
136137
response_validator.validate(request, response)
137138

139+
def test_missing_deprecated_required_header(self, response_validator):
140+
request = MockRequest(
141+
self.host_url,
142+
"delete",
143+
"/v1/tags",
144+
path_pattern="/v1/tags",
145+
)
146+
response_json = {
147+
"data": [
148+
{
149+
"id": 1,
150+
"name": "Sparky",
151+
"ears": {
152+
"healthy": True,
153+
},
154+
},
155+
],
156+
}
157+
response_data = json.dumps(response_json).encode()
158+
response = MockResponse(response_data)
159+
160+
with pytest.raises(MissingRequiredHeader) as exc_info:
161+
response_validator.validate(request, response)
162+
163+
assert exc_info.value == MissingRequiredHeader(name="x-delete-confirm")
164+
138165
def test_valid(self, response_validator):
139166
request = MockRequest(self.host_url, "get", "/v1/pets")
140167
response_json = {

0 commit comments

Comments
 (0)