Skip to content

Commit 73e59fa

Browse files
authored
Merge pull request #456 from python-openapi/feature/python-3.9-drop
Python 3.9 drop
2 parents c419b07 + 0c323a2 commit 73e59fa

File tree

15 files changed

+80
-206
lines changed

15 files changed

+80
-206
lines changed

.github/workflows/python-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
runs-on: ${{ matrix.os }}
1515
strategy:
1616
matrix:
17-
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
17+
python-version: ['3.10', '3.11', '3.12', '3.13']
1818
os: [windows-latest, ubuntu-latest]
1919
fail-fast: false
2020
steps:

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ repos:
1313
rev: v3.21.2
1414
hooks:
1515
- id: pyupgrade
16-
args: ["--py39-plus"]
16+
args: ["--py310-plus"]
1717

1818
- repo: https://github.com/psf/black-pre-commit-mirror
1919
rev: 25.12.0

openapi_spec_validator/__main__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import sys
33
from argparse import ArgumentParser
44
from collections.abc import Sequence
5-
from typing import Optional
65

76
from jsonschema.exceptions import ValidationError
87
from jsonschema.exceptions import best_match
@@ -51,7 +50,7 @@ def print_validationerror(
5150
)
5251

5352

54-
def main(args: Optional[Sequence[str]] = None) -> None:
53+
def main(args: Sequence[str] | None = None) -> None:
5554
parser = ArgumentParser()
5655
parser.add_argument(
5756
"file",
@@ -78,7 +77,7 @@ def main(args: Optional[Sequence[str]] = None) -> None:
7877
for filename in args_parsed.file:
7978
# choose source
8079
reader = read_from_filename
81-
if filename in ["-", "/-"]:
80+
if filename in {"-", "/-"}:
8281
filename = "stdin"
8382
reader = read_from_stdin
8483

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
from typing import Union
2-
31
from jsonschema_path.paths import SchemaPath
42
from jsonschema_path.typing import Schema
53

6-
AnySchema = Union[Schema, SchemaPath]
4+
AnySchema = Schema | SchemaPath

openapi_spec_validator/shortcuts.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import warnings
44
from collections.abc import Mapping
5-
from typing import Optional
65

76
from jsonschema_path import SchemaPath
87
from jsonschema_path.handlers import all_urls_handler
@@ -39,7 +38,7 @@ def get_validator_cls(spec: Schema) -> SpecValidatorType:
3938
def validate(
4039
spec: Schema,
4140
base_uri: str = "",
42-
cls: Optional[SpecValidatorType] = None,
41+
cls: SpecValidatorType | None = None,
4342
) -> None:
4443
if cls is None:
4544
cls = get_validator_cls(spec)
@@ -50,7 +49,7 @@ def validate(
5049

5150
def validate_url(
5251
spec_url: str,
53-
cls: Optional[type[SpecValidator]] = None,
52+
cls: type[SpecValidator] | None = None,
5453
) -> None:
5554
spec = all_urls_handler(spec_url)
5655
return validate(spec, base_uri=spec_url, cls=cls)
@@ -59,9 +58,9 @@ def validate_url(
5958
def validate_spec(
6059
spec: Schema,
6160
base_uri: str = "",
62-
validator: Optional[SupportsValidation] = None,
63-
cls: Optional[SpecValidatorType] = None,
64-
spec_url: Optional[str] = None,
61+
validator: SupportsValidation | None = None,
62+
cls: SpecValidatorType | None = None,
63+
spec_url: str | None = None,
6564
) -> None:
6665
warnings.warn(
6766
"validate_spec shortcut is deprecated. Use validate instead.",
@@ -81,8 +80,8 @@ def validate_spec(
8180

8281
def validate_spec_url(
8382
spec_url: str,
84-
validator: Optional[SupportsValidation] = None,
85-
cls: Optional[type[SpecValidator]] = None,
83+
validator: SupportsValidation | None = None,
84+
cls: type[SpecValidator] | None = None,
8685
) -> None:
8786
warnings.warn(
8887
"validate_spec_url shortcut is deprecated. Use validate_url instead.",

openapi_spec_validator/validation/decorators.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
"""OpenAPI spec validator validation decorators module."""
22

33
import logging
4+
from collections.abc import Callable
45
from collections.abc import Iterable
56
from collections.abc import Iterator
67
from functools import wraps
7-
from typing import Any
8-
from typing import Callable
8+
from typing import ParamSpec
99
from typing import TypeVar
1010

1111
from jsonschema.exceptions import ValidationError
1212

1313
from openapi_spec_validator.validation.caches import CachedIterable
1414
from openapi_spec_validator.validation.exceptions import OpenAPIValidationError
1515

16-
Args = TypeVar("Args")
16+
P = ParamSpec("P")
1717
T = TypeVar("T")
1818

1919
log = logging.getLogger(__name__)
2020

2121

2222
def wraps_errors(
23-
func: Callable[..., Any],
24-
) -> Callable[..., Iterator[ValidationError]]:
23+
func: Callable[P, Iterator[ValidationError]],
24+
) -> Callable[P, Iterator[ValidationError]]:
2525
@wraps(func)
26-
def wrapper(*args: Any, **kwds: Any) -> Iterator[ValidationError]:
26+
def wrapper(*args: P.args, **kwds: P.kwargs) -> Iterator[ValidationError]:
2727
errors = func(*args, **kwds)
2828
for err in errors:
2929
if not isinstance(err, OpenAPIValidationError):
@@ -36,21 +36,21 @@ def wrapper(*args: Any, **kwds: Any) -> Iterator[ValidationError]:
3636

3737

3838
def wraps_cached_iter(
39-
func: Callable[[Args], Iterator[T]],
40-
) -> Callable[[Args], CachedIterable[T]]:
39+
func: Callable[P, Iterator[T]],
40+
) -> Callable[P, CachedIterable[T]]:
4141
@wraps(func)
42-
def wrapper(*args: Any, **kwargs: Any) -> CachedIterable[T]:
42+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> CachedIterable[T]:
4343
result = func(*args, **kwargs)
4444
return CachedIterable(result)
4545

4646
return wrapper
4747

4848

4949
def unwraps_iter(
50-
func: Callable[[Args], Iterable[T]],
51-
) -> Callable[[Args], Iterator[T]]:
50+
func: Callable[P, Iterable[T]],
51+
) -> Callable[P, Iterator[T]]:
5252
@wraps(func)
53-
def wrapper(*args: Any, **kwargs: Any) -> Iterator[T]:
53+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> Iterator[T]:
5454
result = func(*args, **kwargs)
5555
return iter(result)
5656

openapi_spec_validator/validation/keywords.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import string
22
from collections.abc import Iterator
3+
from collections.abc import Callable
34
from collections.abc import Sequence
45
from typing import TYPE_CHECKING
56
from typing import Any
6-
from typing import Optional
77
from typing import cast
88

99
from jsonschema._format import FormatChecker
@@ -38,7 +38,7 @@ def __init__(self, registry: "KeywordValidatorRegistry"):
3838

3939

4040
class ValueValidator(KeywordValidator):
41-
value_validator_cls: Validator = NotImplemented
41+
value_validator_cls: Callable[..., Validator] = NotImplemented
4242
value_validator_format_checker: FormatChecker = NotImplemented
4343

4444
def __call__(
@@ -67,7 +67,7 @@ class SchemaValidator(KeywordValidator):
6767
def __init__(self, registry: "KeywordValidatorRegistry"):
6868
super().__init__(registry)
6969

70-
self.schema_ids_registry: Optional[list[int]] = []
70+
self.schema_ids_registry: list[int] | None = []
7171

7272
@property
7373
def default_validator(self) -> ValueValidator:
@@ -309,7 +309,7 @@ class OperationValidator(KeywordValidator):
309309
def __init__(self, registry: "KeywordValidatorRegistry"):
310310
super().__init__(registry)
311311

312-
self.operation_ids_registry: Optional[list[str]] = []
312+
self.operation_ids_registry: list[str] | None = []
313313

314314
@property
315315
def responses_validator(self) -> ResponsesValidator:
@@ -324,7 +324,7 @@ def __call__(
324324
url: str,
325325
name: str,
326326
operation: SchemaPath,
327-
path_parameters: Optional[SchemaPath],
327+
path_parameters: SchemaPath | None,
328328
) -> Iterator[ValidationError]:
329329
assert self.operation_ids_registry is not None
330330

openapi_spec_validator/validation/protocols.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from collections.abc import Iterator
2-
from typing import Optional
32
from typing import Protocol
43
from typing import runtime_checkable
54

@@ -16,12 +15,12 @@ def iter_errors(
1615
self,
1716
instance: Schema,
1817
base_uri: str = "",
19-
spec_url: Optional[str] = None,
18+
spec_url: str | None = None,
2019
) -> Iterator[OpenAPIValidationError]: ...
2120

2221
def validate(
2322
self,
2423
instance: Schema,
2524
base_uri: str = "",
26-
spec_url: Optional[str] = None,
25+
spec_url: str | None = None,
2726
) -> None: ...

openapi_spec_validator/validation/proxies.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
import warnings
44
from collections.abc import Iterator
55
from collections.abc import Mapping
6-
from typing import Optional
76

87
from jsonschema.exceptions import ValidationError
98
from jsonschema_path.typing import Schema
109

11-
from openapi_spec_validator.validation.exceptions import OpenAPIValidationError
1210
from openapi_spec_validator.validation.exceptions import ValidatorDetectError
1311
from openapi_spec_validator.validation.types import SpecValidatorType
1412

@@ -18,7 +16,7 @@ def __init__(
1816
self,
1917
cls: SpecValidatorType,
2018
deprecated: str = "SpecValidator",
21-
use: Optional[str] = None,
19+
use: str | None = None,
2220
):
2321
self.cls = cls
2422

@@ -29,7 +27,7 @@ def validate(
2927
self,
3028
schema: Schema,
3129
base_uri: str = "",
32-
spec_url: Optional[str] = None,
30+
spec_url: str | None = None,
3331
) -> None:
3432
for err in self.iter_errors(
3533
schema,
@@ -46,7 +44,7 @@ def iter_errors(
4644
self,
4745
schema: Schema,
4846
base_uri: str = "",
49-
spec_url: Optional[str] = None,
47+
spec_url: str | None = None,
5048
) -> Iterator[ValidationError]:
5149
warnings.warn(
5250
f"{self.deprecated} is deprecated. Use {self.use} instead.",
@@ -70,7 +68,7 @@ def validate(
7068
self,
7169
instance: Schema,
7270
base_uri: str = "",
73-
spec_url: Optional[str] = None,
71+
spec_url: str | None = None,
7472
) -> None:
7573
validator = self.detect(instance)
7674
for err in validator.iter_errors(
@@ -87,8 +85,8 @@ def iter_errors(
8785
self,
8886
instance: Schema,
8987
base_uri: str = "",
90-
spec_url: Optional[str] = None,
91-
) -> Iterator[OpenAPIValidationError]:
88+
spec_url: str | None = None,
89+
) -> Iterator[ValidationError]:
9290
warnings.warn(
9391
"openapi_spec_validator_proxy is deprecated.",
9492
DeprecationWarning,

openapi_spec_validator/validation/registries.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
from __future__ import annotations
2-
1+
from collections import defaultdict
32
from collections.abc import Mapping
4-
from typing import DefaultDict
53

64
from openapi_spec_validator.validation.keywords import KeywordValidator
75

86

9-
class KeywordValidatorRegistry(DefaultDict[str, KeywordValidator]):
7+
class KeywordValidatorRegistry(defaultdict[str, KeywordValidator]):
108
def __init__(
119
self, keyword_validators: Mapping[str, type[KeywordValidator]]
1210
):

0 commit comments

Comments
 (0)