Skip to content

Commit fe55453

Browse files
author
Sergii Kozak
committed
- invalid usage of super() when having multi-baseclass inheritance: use direct basecls.__init__() to avoid nasty side effect of calling 'wrong' base class __init__(). Particularly in this case, openapi_core.validation.request.BaseRequestUnmarshaller got 'extra_format_unmarshallers' property reset to None after BaseRequestValidator.__init__() call
1 parent 707b1e1 commit fe55453

File tree

3 files changed

+133
-2
lines changed

3 files changed

+133
-2
lines changed

openapi_core/unmarshalling/unmarshallers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ def __init__(
6060
schema_validators_factory = (
6161
schema_unmarshallers_factory.schema_validators_factory
6262
)
63-
super().__init__(
63+
BaseValidator.__init__(
64+
self,
6465
spec,
6566
base_url=base_url,
6667
style_deserializers_factory=style_deserializers_factory,

openapi_core/validation/request/validators.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ def __init__(
8484
] = None,
8585
security_provider_factory: SecurityProviderFactory = security_provider_factory,
8686
):
87-
super().__init__(
87+
88+
BaseValidator.__init__(
89+
self,
8890
spec,
8991
base_url=base_url,
9092
style_deserializers_factory=style_deserializers_factory,
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import enum
2+
import pytest
3+
from jsonschema_path import SchemaPath
4+
5+
from openapi_core import V30RequestUnmarshaller, V31RequestUnmarshaller
6+
from openapi_core.datatypes import Parameters
7+
from openapi_core.testing import MockRequest
8+
9+
10+
class Colors(enum.Enum):
11+
12+
YELLOW = "yellow"
13+
BLUE = "blue"
14+
RED = "red"
15+
16+
@classmethod
17+
def of(cls, v: str):
18+
for it in cls:
19+
if it.value == v:
20+
return it
21+
raise ValueError(f"Invalid value: {v}")
22+
23+
24+
class TestRequestUnmarshaller:
25+
26+
@pytest.fixture(scope="session")
27+
def spec_dict(self):
28+
return {
29+
"openapi": "3.1.0",
30+
"info": {
31+
"title": "Test request body unmarshaller",
32+
"version": "0.1",
33+
},
34+
"paths": {
35+
"/resources": {
36+
"post": {
37+
"description": "POST resources test request",
38+
"requestBody": {
39+
"description": "",
40+
"content": {
41+
"application/json": {
42+
"schema": {
43+
"$ref": "#/components/schemas/createResource"
44+
}
45+
}
46+
}
47+
},
48+
"responses": {
49+
"201": {
50+
"description": "Resource was created."
51+
}
52+
}
53+
},
54+
"get": {
55+
"description": "POST resources test request",
56+
"parameters": [
57+
{
58+
"name": "color",
59+
"in": "query",
60+
"required": False,
61+
"schema": {
62+
"$ref": "#/components/schemas/colors"
63+
},
64+
},
65+
],
66+
"responses": {
67+
"default": {
68+
"description": "Returned resources matching request."
69+
}
70+
}
71+
}
72+
}
73+
},
74+
"components": {
75+
"schemas": {
76+
"colors": {
77+
"type": "string",
78+
"enum": ["yellow", "blue", "red"],
79+
"format": "enum_Colors"
80+
},
81+
"createResource": {
82+
"type": "object",
83+
"properties": {
84+
"resId": {
85+
"type": "integer"
86+
},
87+
"color": {
88+
"$ref": "#/components/schemas/colors"
89+
}
90+
},
91+
"required": ["resId", "color"]
92+
}
93+
}
94+
}
95+
}
96+
97+
@pytest.fixture(scope="session")
98+
def spec(self, spec_dict):
99+
return SchemaPath.from_dict(spec_dict)
100+
101+
@pytest.mark.parametrize("req_unmarshaller_cls", [V30RequestUnmarshaller, V31RequestUnmarshaller])
102+
def test_request_body_extra_unmarshaller(self, spec, req_unmarshaller_cls):
103+
ru = req_unmarshaller_cls(spec=spec, extra_format_unmarshallers={
104+
"enum_Colors": Colors.of
105+
})
106+
request = MockRequest(host_url="http://example.com",
107+
method="post",
108+
path="/resources",
109+
data=b'{"resId": 23498572, "color": "blue"}')
110+
result = ru.unmarshal(request)
111+
112+
assert not result.errors
113+
assert result.body == {"resId": 23498572, "color": Colors.BLUE}
114+
assert result.parameters == Parameters()
115+
116+
@pytest.mark.parametrize("req_unmarshaller_cls", [V30RequestUnmarshaller, V31RequestUnmarshaller])
117+
def test_request_param_extra_unmarshaller(self, spec, req_unmarshaller_cls):
118+
ru = req_unmarshaller_cls(spec=spec, extra_format_unmarshallers={
119+
"enum_Colors": Colors.of
120+
})
121+
request = MockRequest(host_url="http://example.com",
122+
method="get",
123+
path="/resources",
124+
args={"color": "blue"})
125+
result = ru.unmarshal(request)
126+
127+
assert not result.errors
128+
assert result.parameters == Parameters(query=dict(color=Colors.BLUE))

0 commit comments

Comments
 (0)