Skip to content

Commit 1e233ae

Browse files
authored
Merge pull request #60 from p1c2u/fix/format-checkers-assigned-to-validators
format checkers assigned to validators
2 parents 38ca847 + 30f791a commit 1e233ae

File tree

5 files changed

+58
-390
lines changed

5 files changed

+58
-390
lines changed

Diff for: .github/workflows/python-test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848
run: timeout 10s poetry run pip --version || rm -rf .venv
4949

5050
- name: Install dependencies
51-
run: poetry install -E rfc3339-validator -E strict-rfc3339 -E isodate
51+
run: poetry install -E rfc3339-validator
5252

5353
- name: Test
5454
env:

Diff for: openapi_schema_validator/_format.py

+19-111
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,10 @@
11
import binascii
22
from base64 import b64decode
33
from base64 import b64encode
4-
from datetime import datetime
54
from typing import Any
6-
from typing import Tuple
75
from typing import Union
8-
from uuid import UUID
96

107
from jsonschema._format import FormatChecker
11-
from jsonschema.exceptions import FormatError
12-
13-
DATETIME_HAS_RFC3339_VALIDATOR = False
14-
DATETIME_HAS_STRICT_RFC3339 = False
15-
DATETIME_HAS_ISODATE = False
16-
DATETIME_RAISES: Tuple[Exception, ...] = ()
17-
18-
try:
19-
import isodate
20-
except ImportError:
21-
pass
22-
else:
23-
DATETIME_HAS_ISODATE = True
24-
DATETIME_RAISES += (ValueError, isodate.ISO8601Error)
25-
26-
try:
27-
from rfc3339_validator import validate_rfc3339
28-
except ImportError:
29-
pass
30-
else:
31-
DATETIME_HAS_RFC3339_VALIDATOR = True
32-
DATETIME_RAISES += (ValueError, TypeError)
33-
34-
try:
35-
import strict_rfc3339
36-
except ImportError:
37-
pass
38-
else:
39-
DATETIME_HAS_STRICT_RFC3339 = True
40-
DATETIME_RAISES += (ValueError, TypeError)
418

429

4310
def is_int32(instance: Any) -> bool:
@@ -65,91 +32,32 @@ def is_binary(instance: Any) -> bool:
6532
def is_byte(instance: Union[str, bytes]) -> bool:
6633
if isinstance(instance, str):
6734
instance = instance.encode()
68-
69-
try:
70-
encoded = b64encode(b64decode(instance))
71-
except TypeError:
72-
return False
73-
else:
74-
return encoded == instance
75-
76-
77-
def is_datetime(instance: str) -> bool:
78-
if not isinstance(instance, (bytes, str)):
79-
return False
80-
81-
if DATETIME_HAS_RFC3339_VALIDATOR:
82-
return bool(validate_rfc3339(instance))
83-
84-
if DATETIME_HAS_STRICT_RFC3339:
85-
return bool(strict_rfc3339.validate_rfc3339(instance))
86-
87-
if DATETIME_HAS_ISODATE:
88-
return bool(isodate.parse_datetime(instance))
89-
90-
return True
91-
92-
93-
def is_date(instance: Any) -> bool:
94-
if not isinstance(instance, (bytes, str)):
35+
if not isinstance(instance, bytes):
9536
return False
9637

97-
if isinstance(instance, bytes):
98-
instance = instance.decode()
99-
100-
return bool(datetime.strptime(instance, "%Y-%m-%d"))
38+
encoded = b64encode(b64decode(instance))
39+
return encoded == instance
10140

10241

103-
def is_uuid(instance: Any) -> bool:
42+
def is_password(instance: Any) -> bool:
10443
if not isinstance(instance, (bytes, str)):
10544
return False
10645

107-
if isinstance(instance, bytes):
108-
instance = instance.decode()
109-
110-
return str(UUID(instance)).lower() == instance.lower()
111-
112-
113-
def is_password(instance: Any) -> bool:
11446
return True
11547

11648

117-
class OASFormatChecker(FormatChecker): # type: ignore
118-
119-
checkers = {
120-
"int32": (is_int32, ()),
121-
"int64": (is_int64, ()),
122-
"float": (is_float, ()),
123-
"double": (is_double, ()),
124-
"byte": (is_byte, (binascii.Error, TypeError)),
125-
"binary": (is_binary, ()),
126-
"date": (is_date, (ValueError,)),
127-
"date-time": (is_datetime, DATETIME_RAISES),
128-
"password": (is_password, ()),
129-
# non standard
130-
"uuid": (is_uuid, (AttributeError, ValueError)),
131-
}
132-
133-
def check(self, instance: Any, format: str) -> Any:
134-
if format not in self.checkers:
135-
raise FormatError(
136-
f"Format checker for {format!r} format not found"
137-
)
138-
139-
func, raises = self.checkers[format]
140-
result, cause = None, None
141-
try:
142-
result = func(instance)
143-
except raises as e: # type: ignore
144-
cause = e
145-
146-
if not result:
147-
raise FormatError(
148-
f"{instance!r} is not a {format!r}",
149-
cause=cause,
150-
)
151-
return result
152-
153-
154-
oas30_format_checker = OASFormatChecker()
155-
oas31_format_checker = oas30_format_checker
49+
oas30_format_checker = FormatChecker()
50+
oas30_format_checker.checks("int32")(is_int32)
51+
oas30_format_checker.checks("int64")(is_int64)
52+
oas30_format_checker.checks("float")(is_float)
53+
oas30_format_checker.checks("double")(is_double)
54+
oas30_format_checker.checks("binary")(is_binary)
55+
oas30_format_checker.checks("byte", (binascii.Error, TypeError))(is_byte)
56+
oas30_format_checker.checks("password")(is_password)
57+
58+
oas31_format_checker = FormatChecker()
59+
oas31_format_checker.checks("int32")(is_int32)
60+
oas31_format_checker.checks("int64")(is_int64)
61+
oas31_format_checker.checks("float")(is_float)
62+
oas31_format_checker.checks("double")(is_double)
63+
oas31_format_checker.checks("password")(is_password)

Diff for: openapi_schema_validator/validators.py

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from jsonschema.validators import create
1111
from jsonschema.validators import extend
1212

13+
from openapi_schema_validator import _format as oas_format
1314
from openapi_schema_validator import _types as oas_types
1415
from openapi_schema_validator import _validators as oas_validators
1516
from openapi_schema_validator._types import oas31_type_checker
@@ -55,6 +56,7 @@
5556
"deprecated": oas_validators.not_implemented,
5657
},
5758
type_checker=oas_types.oas30_type_checker,
59+
format_checker=oas_format.oas30_format_checker,
5860
# NOTE: version causes conflict with global jsonschema validator
5961
# See https://github.com/p1c2u/openapi-schema-validator/pull/12
6062
# version="oas30",
@@ -94,6 +96,7 @@
9496
"example": oas_validators.not_implemented,
9597
},
9698
type_checker=oas31_type_checker,
99+
format_checker=oas_format.oas31_format_checker,
97100
)
98101

99102

Diff for: pyproject.toml

-12
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,10 @@ strict = true
1717
module = "jsonschema.*"
1818
ignore_missing_imports = true
1919

20-
[[tool.mypy.overrides]]
21-
module = "isodate"
22-
ignore_missing_imports = true
23-
2420
[[tool.mypy.overrides]]
2521
module = "rfc3339_validator"
2622
ignore_missing_imports = true
2723

28-
[[tool.mypy.overrides]]
29-
module = "strict_rfc3339"
30-
ignore_missing_imports = true
31-
3224
[tool.poetry]
3325
name = "openapi-schema-validator"
3426
version = "0.4.1"
@@ -54,13 +46,9 @@ classifiers = [
5446
python = "^3.7.0"
5547
jsonschema = "^4.0.0"
5648
rfc3339-validator = {version = "*", optional = true}
57-
strict-rfc3339 = {version = "*", optional = true}
58-
isodate = {version = "*", optional = true}
5949

6050
[tool.poetry.extras]
6151
rfc3339-validator = ["rfc3339-validator"]
62-
strict-rfc3339 = ["strict-rfc3339"]
63-
isodate = ["isodate"]
6452

6553
[tool.poetry.dev-dependencies]
6654
black = "^22.0.0"

0 commit comments

Comments
 (0)