Skip to content

Commit 251ce3d

Browse files
committed
Formats raise error for other types fix
1 parent c35b702 commit 251ce3d

File tree

2 files changed

+91
-8
lines changed

2 files changed

+91
-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, so ensure bools aren't reported as ints
31+
if isinstance(instance, bool):
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, so ensure bools aren't reported as ints
40+
if isinstance(instance, bool):
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

+60
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,43 @@ 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+
("int64", "test"),
43+
("int64", True),
44+
("float", "test"),
45+
("float", True),
46+
("double", "test"),
47+
("double", True),
48+
("password", 3.12),
49+
("password", True),
50+
],
51+
)
52+
def test_formats_ignored(
53+
self, format, value, validator_class, format_checker
54+
):
55+
schema = {"format": format}
56+
validator = validator_class(schema, format_checker=format_checker)
57+
58+
result = validator.validate(value)
59+
60+
assert result is None
61+
62+
@pytest.mark.parametrize("format", ["float", "double"])
63+
@pytest.mark.parametrize("value", [3.14, 1.0])
64+
def test_number_float_and_double_valid(
65+
self, format, value, validator_class, format_checker
66+
):
67+
schema = {"type": "number", "format": format}
68+
validator = validator_class(schema, format_checker=format_checker)
69+
70+
result = validator.validate(value)
71+
72+
assert result is None
73+
3774
@pytest.mark.parametrize("value", ["test"])
3875
def test_string(self, validator_class, value):
3976
schema = {"type": "string"}
@@ -61,6 +98,29 @@ def validator_class(self):
6198
def format_checker(self):
6299
return oas30_format_checker
63100

101+
@pytest.mark.parametrize(
102+
"format,value",
103+
[
104+
("binary", True),
105+
("binary", 3),
106+
("binary", 3.12),
107+
("binary", ["test"]),
108+
("byte", True),
109+
("byte", 3),
110+
("byte", 3.12),
111+
("byte", ["test"]),
112+
],
113+
)
114+
def test_oas30_formats_ignored(
115+
self, format, value, validator_class, format_checker
116+
):
117+
schema = {"format": format}
118+
validator = validator_class(schema, format_checker=format_checker)
119+
120+
result = validator.validate(value)
121+
122+
assert result is None
123+
64124
@pytest.mark.xfail(reason="OAS 3.0 string type checker allows byte")
65125
@pytest.mark.parametrize("value", [b"test"])
66126
def test_string_disallow_binary(self, validator_class, value):

0 commit comments

Comments
 (0)