Skip to content

Commit 45aa702

Browse files
committed
Formats raise error for other types fix
1 parent c35b702 commit 45aa702

File tree

2 files changed

+101
-8
lines changed

2 files changed

+101
-8
lines changed

Diff for: openapi_schema_validator/_format.py

+31-8
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,71 @@
11
import binascii
22
from base64 import b64decode
33
from base64 import b64encode
4+
from numbers import Number
45
from typing import Any
56
from typing import Union
67

78
from jsonschema._format import FormatChecker
89

910

1011
def is_int32(instance: Any) -> bool:
11-
return isinstance(instance, int)
12+
# bool inherits from int, so ensure bools aren't reported as ints
13+
if isinstance(instance, bool):
14+
return True
15+
if not isinstance(instance, int):
16+
return True
17+
return ~(1 << 31) < instance < 1 << 31
1218

1319

1420
def is_int64(instance: Any) -> bool:
15-
return isinstance(instance, int)
21+
# bool inherits from int, so ensure bools aren't reported as ints
22+
if isinstance(instance, bool):
23+
return True
24+
if not isinstance(instance, int):
25+
return True
26+
return ~(1 << 63) < instance < 1 << 63
1627

1728

1829
def is_float(instance: Any) -> bool:
30+
# bool inherits from int
31+
if isinstance(instance, int):
32+
return True
33+
if not isinstance(instance, Number):
34+
return True
1935
return isinstance(instance, float)
2036

2137

2238
def is_double(instance: Any) -> bool:
39+
# bool inherits from int
40+
if isinstance(instance, int):
41+
return True
42+
if not isinstance(instance, Number):
43+
return True
2344
# float has double precision in Python
2445
# It's double in CPython and Jython
2546
return isinstance(instance, float)
2647

2748

2849
def is_binary(instance: Any) -> bool:
29-
return isinstance(instance, bytes)
50+
if not isinstance(instance, (str, bytes)):
51+
return True
52+
if isinstance(instance, str):
53+
return False
54+
return True
3055

3156

3257
def is_byte(instance: Union[str, bytes]) -> bool:
58+
if not isinstance(instance, (str, bytes)):
59+
return True
3360
if isinstance(instance, str):
3461
instance = instance.encode()
35-
if not isinstance(instance, bytes):
36-
return False
3762

3863
encoded = b64encode(b64decode(instance))
3964
return encoded == instance
4065

4166

4267
def is_password(instance: Any) -> bool:
43-
if not isinstance(instance, (bytes, str)):
44-
return False
45-
68+
# A hint to UIs to obscure input
4669
return True
4770

4871

Diff for: tests/integration/test_validators.py

+70
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,53 @@ def test_required_checkers(self, format_checker):
3434

3535

3636
class BaseTestOASValidatorValidate:
37+
@pytest.mark.parametrize(
38+
"format,value",
39+
[
40+
("int32", "test"),
41+
("int32", True),
42+
("int32", 3.12),
43+
("int32", ["test"]),
44+
("int64", "test"),
45+
("int64", True),
46+
("int64", 3.12),
47+
("int64", ["test"]),
48+
("float", "test"),
49+
("float", 3),
50+
("float", True),
51+
("float", ["test"]),
52+
("double", "test"),
53+
("double", 3),
54+
("double", True),
55+
("double", ["test"]),
56+
("password", 3.12),
57+
("password", True),
58+
("password", 3),
59+
("password", ["test"]),
60+
],
61+
)
62+
def test_formats_ignored(
63+
self, format, value, validator_class, format_checker
64+
):
65+
schema = {"format": format}
66+
validator = validator_class(schema, format_checker=format_checker)
67+
68+
result = validator.validate(value)
69+
70+
assert result is None
71+
72+
@pytest.mark.parametrize("format", ["float", "double"])
73+
@pytest.mark.parametrize("value", [3, 3.14, 1.0])
74+
def test_number_float_and_double_valid(
75+
self, format, value, validator_class, format_checker
76+
):
77+
schema = {"type": "number", "format": format}
78+
validator = validator_class(schema, format_checker=format_checker)
79+
80+
result = validator.validate(value)
81+
82+
assert result is None
83+
3784
@pytest.mark.parametrize("value", ["test"])
3885
def test_string(self, validator_class, value):
3986
schema = {"type": "string"}
@@ -61,6 +108,29 @@ def validator_class(self):
61108
def format_checker(self):
62109
return oas30_format_checker
63110

111+
@pytest.mark.parametrize(
112+
"format,value",
113+
[
114+
("binary", True),
115+
("binary", 3),
116+
("binary", 3.12),
117+
("binary", ["test"]),
118+
("byte", True),
119+
("byte", 3),
120+
("byte", 3.12),
121+
("byte", ["test"]),
122+
],
123+
)
124+
def test_oas30_formats_ignored(
125+
self, format, value, validator_class, format_checker
126+
):
127+
schema = {"format": format}
128+
validator = validator_class(schema, format_checker=format_checker)
129+
130+
result = validator.validate(value)
131+
132+
assert result is None
133+
64134
@pytest.mark.xfail(reason="OAS 3.0 string type checker allows byte")
65135
@pytest.mark.parametrize("value", [b"test"])
66136
def test_string_disallow_binary(self, validator_class, value):

0 commit comments

Comments
 (0)