1import binascii
2from base64 import b64decode
3from base64 import b64encode
4from numbers import Number
5from typing import Any
6from typing import Union
7
8from jsonschema._format import FormatChecker
9
10
11def is_int32(instance: Any) -> bool:
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
18
19
20def is_int64(instance: Any) -> bool:
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
27
28
29def 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
35 return isinstance(instance, float)
36
37
38def 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
44 # float has double precision in Python
45 # It's double in CPython and Jython
46 return isinstance(instance, float)
47
48
49def is_binary(instance: Any) -> bool:
50 if not isinstance(instance, (str, bytes)):
51 return True
52 if isinstance(instance, str):
53 return False
54 return True
55
56
57def is_byte(instance: Union[str, bytes]) -> bool:
58 if not isinstance(instance, (str, bytes)):
59 return True
60 if isinstance(instance, str):
61 instance = instance.encode()
62
63 encoded = b64encode(b64decode(instance))
64 return encoded == instance
65
66
67def is_password(instance: Any) -> bool:
68 # A hint to UIs to obscure input
69 return True
70
71
72oas30_format_checker = FormatChecker()
73oas30_format_checker.checks("int32")(is_int32)
74oas30_format_checker.checks("int64")(is_int64)
75oas30_format_checker.checks("float")(is_float)
76oas30_format_checker.checks("double")(is_double)
77oas30_format_checker.checks("binary")(is_binary)
78oas30_format_checker.checks("byte", (binascii.Error, TypeError))(is_byte)
79oas30_format_checker.checks("password")(is_password)
80
81oas31_format_checker = FormatChecker()
82oas31_format_checker.checks("int32")(is_int32)
83oas31_format_checker.checks("int64")(is_int64)
84oas31_format_checker.checks("float")(is_float)
85oas31_format_checker.checks("double")(is_double)
86oas31_format_checker.checks("password")(is_password)