Skip to content

Commit 6586c93

Browse files
committed
Formats raise error for other types fix
1 parent c35b702 commit 6586c93

File tree

2 files changed

+99
-8
lines changed

2 files changed

+99
-8
lines changed

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

tests/integration/test_validators.py

+68
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,51 @@ 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", True),
50+
("float", ["test"]),
51+
("double", "test"),
52+
("double", True),
53+
("double", ["test"]),
54+
("password", 3.12),
55+
("password", True),
56+
("password", 3),
57+
("password", ["test"]),
58+
],
59+
)
60+
def test_formats_ignored(
61+
self, format, value, validator_class, format_checker
62+
):
63+
schema = {"format": format}
64+
validator = validator_class(schema, format_checker=format_checker)
65+
66+
result = validator.validate(value)
67+
68+
assert result is None
69+
70+
@pytest.mark.parametrize("format", ["float", "double"])
71+
@pytest.mark.parametrize("value", [3, 3.14, 1.0])
72+
def test_number_float_and_double_valid(
73+
self, format, value, validator_class, format_checker
74+
):
75+
schema = {"type": "number", "format": format}
76+
validator = validator_class(schema, format_checker=format_checker)
77+
78+
result = validator.validate(value)
79+
80+
assert result is None
81+
3782
@pytest.mark.parametrize("value", ["test"])
3883
def test_string(self, validator_class, value):
3984
schema = {"type": "string"}
@@ -61,6 +106,29 @@ def validator_class(self):
61106
def format_checker(self):
62107
return oas30_format_checker
63108

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

0 commit comments

Comments
 (0)