Skip to content

Commit d4a0500

Browse files
committed
Fix deprecation warnings for omitted params and headers
1 parent 9f9cfc8 commit d4a0500

File tree

5 files changed

+125
-14
lines changed

5 files changed

+125
-14
lines changed

openapi_core/validation/request/validators.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,6 @@ def _get_parameter(
202202
self, parameters: RequestParameters, param: SchemaPath
203203
) -> Any:
204204
name = (param / "name").read_str()
205-
deprecated = (param / "deprecated").read_bool(default=False)
206-
if deprecated:
207-
warnings.warn(
208-
f"{name} parameter is deprecated",
209-
DeprecationWarning,
210-
)
211-
212205
param_location = (param / "in").read_str()
213206
location = parameters[param_location]
214207

@@ -219,6 +212,12 @@ def _get_parameter(
219212
raise MissingRequiredParameter(name, param_location)
220213
raise MissingParameter(name, param_location)
221214
else:
215+
deprecated = (param / "deprecated").read_bool(default=False)
216+
if deprecated:
217+
warnings.warn(
218+
f"{name} parameter is deprecated",
219+
DeprecationWarning,
220+
)
222221
return value
223222

224223
@ValidationErrorWrapper(SecurityValidationError, InvalidSecurity)

openapi_core/validation/response/validators.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -174,13 +174,6 @@ def _get_headers(
174174
def _get_header(
175175
self, headers: Mapping[str, Any], name: str, header: SchemaPath
176176
) -> Any:
177-
deprecated = (header / "deprecated").read_bool(default=False)
178-
if deprecated:
179-
warnings.warn(
180-
f"{name} header is deprecated",
181-
DeprecationWarning,
182-
)
183-
184177
try:
185178
value, _ = self._get_param_or_header_and_schema(
186179
header, headers, name=name
@@ -191,6 +184,12 @@ def _get_header(
191184
raise MissingRequiredHeader(name)
192185
raise MissingHeader(name)
193186
else:
187+
deprecated = (header / "deprecated").read_bool(default=False)
188+
if deprecated:
189+
warnings.warn(
190+
f"{name} header is deprecated",
191+
DeprecationWarning,
192+
)
194193
return value
195194

196195

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)