Skip to content

Commit 208aa24

Browse files
author
vyuroshchin
committed
add ruff, drop black/isort/flynt
1 parent 3c71e8c commit 208aa24

File tree

19 files changed

+257
-460
lines changed

19 files changed

+257
-460
lines changed

.pre-commit-config.yaml

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,29 @@ default_stages: [pre-commit, pre-push]
33
default_language_version:
44
# force all unspecified python hooks to run python3
55
python: python3
6-
minimum_pre_commit_version: "1.20.0"
6+
minimum_pre_commit_version: "4.5.1"
77
repos:
88
- repo: meta
99
hooks:
1010
- id: check-hooks-apply
1111

12-
- repo: https://github.com/asottile/pyupgrade
13-
rev: v2.38.4
14-
hooks:
15-
- id: pyupgrade
16-
args: ["--py36-plus"]
17-
1812
- repo: local
1913
hooks:
20-
- id: flynt
21-
name: Convert to f-strings with flynt
22-
entry: flynt
23-
language: python
24-
additional_dependencies: ['flynt==0.76']
25-
26-
- id: black
27-
name: black
28-
entry: black
14+
- id: ruff-format
15+
name: ruff format
16+
entry: ruff
17+
args:
18+
- format
19+
types: [ python ]
2920
language: system
30-
require_serial: true
31-
types: [python]
3221

33-
- id: isort
34-
name: isort
35-
entry: isort
36-
args: ['--filter-files']
22+
- id: ruff-check
23+
name: ruff check
24+
entry: ruff
25+
args:
26+
- check
27+
- --fix
28+
- --exit-non-zero-on-fix
29+
- --show-fixes
30+
types: [ python ]
3731
language: system
38-
require_serial: true
39-
types: [python]

AGENTS.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Use this as the default operating playbook when making changes.
1010
- Runtime package: `openapi_schema_validator/`.
1111
- Tests: `pytest` in `tests/unit` and `tests/integration`.
1212
- Type checking: `mypy` with `strict = true`.
13-
- Formatting and imports: `black` and `isort`.
13+
- Formatting and imports: `ruff`.
1414
- Extra static analysis: `deptry`.
1515
- Supported Python versions: 3.10, 3.11, 3.12, 3.13, 3.14.
1616

@@ -68,9 +68,8 @@ Run commands from repository root.
6868

6969
- Full pre-commit run: `poetry run pre-commit run -a`
7070
- Staged files pre-commit run: `poetry run pre-commit run`
71-
- Format explicitly: `poetry run black .`
72-
- Sort imports explicitly: `poetry run isort .`
73-
- Convert to f-strings where safe: `poetry run flynt .`
71+
- Format explicitly: `poetry run ruff format .`
72+
- Lint code: `poetry run ruff check .`
7473
- Dependency hygiene: `poetry run deptry .`
7574

7675
### Build package / docs

benchmarks/cases.py

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -117,30 +117,14 @@ def build_cases() -> list[BenchmarkCase]:
117117
},
118118
"Route": {
119119
"oneOf": [
120-
{
121-
"$ref": (
122-
"#/components/schemas/"
123-
"MountainHiking"
124-
)
125-
},
126-
{
127-
"$ref": (
128-
"#/components/schemas/"
129-
"AlpineClimbing"
130-
)
131-
},
120+
{"$ref": ("#/components/schemas/MountainHiking")},
121+
{"$ref": ("#/components/schemas/AlpineClimbing")},
132122
],
133123
"discriminator": {
134124
"propertyName": "discipline",
135125
"mapping": {
136-
"mountain_hiking": (
137-
"#/components/schemas/"
138-
"MountainHiking"
139-
),
140-
"alpine_climbing": (
141-
"#/components/schemas/"
142-
"AlpineClimbing"
143-
),
126+
"mountain_hiking": ("#/components/schemas/MountainHiking"),
127+
"alpine_climbing": ("#/components/schemas/AlpineClimbing"),
144128
},
145129
},
146130
},

benchmarks/compare.py

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ def _parse_args() -> argparse.Namespace:
4545
"--regression-threshold",
4646
type=float,
4747
default=0.0,
48-
help=(
49-
"Percent threshold for regressions. "
50-
"Example: 5 means fail only when regression exceeds 5%%."
51-
),
48+
help="Percent threshold for regressions. Example: 5 means fail only when regression exceeds 5%%.",
5249
)
5350
parser.add_argument(
5451
"--fail-on-regression",
@@ -102,9 +99,7 @@ def _compare_reports(
10299

103100
for case_name in sorted(baseline_cases):
104101
if case_name not in candidate_cases:
105-
regressions.append(
106-
f"Missing case in candidate report: {case_name}"
107-
)
102+
regressions.append(f"Missing case in candidate report: {case_name}")
108103
continue
109104

110105
report_lines.append(f"Case: {case_name}")
@@ -119,19 +114,14 @@ def _compare_reports(
119114
status = _format_status(regression, change)
120115

121116
report_lines.append(
122-
" "
123-
f"{metric}: baseline={baseline_value:.6f} "
124-
f"candidate={candidate_value:.6f} -> {status}"
117+
f" {metric}: baseline={baseline_value:.6f} candidate={candidate_value:.6f} -> {status}"
125118
)
126119

127120
if regression and abs(change) > regression_threshold:
128-
regressions.append(
129-
f"{case_name} {metric} regressed by {abs(change):.2f}%"
130-
)
121+
regressions.append(f"{case_name} {metric} regressed by {abs(change):.2f}%")
131122

132123
extra_candidate_cases = set(candidate_cases).difference(baseline_cases)
133-
for case_name in sorted(extra_candidate_cases):
134-
report_lines.append(f"Case present only in candidate: {case_name}")
124+
report_lines.extend(f"Case present only in candidate: {case_name}" for case_name in sorted(extra_candidate_cases))
135125

136126
return report_lines, regressions
137127

@@ -146,15 +136,12 @@ def main() -> int:
146136
args.regression_threshold,
147137
)
148138

149-
print(
150-
f"Comparing candidate {args.candidate} "
151-
f"against baseline {args.baseline}"
152-
)
153-
print("")
139+
print(f"Comparing candidate {args.candidate} against baseline {args.baseline}")
140+
print()
154141
print("\n".join(report_lines))
155142

156143
if regressions:
157-
print("")
144+
print()
158145
print("Regressions above threshold:")
159146
for regression in regressions:
160147
print(f"- {regression}")

docs/conf.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ def _read_project_version() -> str:
6161
"scheme": "slate",
6262
"primary": "lime",
6363
"accent": "amber",
64-
"scheme": "slate",
6564
"toggle": {
6665
"icon": "material/toggle-switch",
6766
"name": "Switch to light mode",

openapi_schema_validator/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,17 @@
1919
__license__ = "3-clause BSD License"
2020

2121
__all__ = [
22-
"validate",
22+
"OAS31_BASE_DIALECT_ID",
23+
"OAS32_BASE_DIALECT_ID",
2324
"OAS30ReadValidator",
2425
"OAS30StrictValidator",
25-
"OAS30WriteValidator",
2626
"OAS30Validator",
27+
"OAS30WriteValidator",
28+
"OAS31Validator",
29+
"OAS32Validator",
2730
"oas30_format_checker",
2831
"oas30_strict_format_checker",
29-
"OAS31Validator",
3032
"oas31_format_checker",
31-
"OAS32Validator",
3233
"oas32_format_checker",
33-
"OAS31_BASE_DIALECT_ID",
34-
"OAS32_BASE_DIALECT_ID",
34+
"validate",
3535
]

openapi_schema_validator/_caches.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from collections import OrderedDict
2+
from collections.abc import Hashable
3+
from collections.abc import Mapping
24
from dataclasses import dataclass
35
from threading import RLock
46
from typing import Any
5-
from typing import Hashable
6-
from typing import Mapping
77

88
from jsonschema.protocols import Validator
99

@@ -23,12 +23,7 @@ def __init__(self) -> None:
2323

2424
def _freeze_value(self, value: Any) -> Hashable:
2525
if isinstance(value, dict):
26-
return tuple(
27-
sorted(
28-
(str(key), self._freeze_value(item))
29-
for key, item in value.items()
30-
)
31-
)
26+
return tuple(sorted((str(key), self._freeze_value(item)) for key, item in value.items()))
3227
if isinstance(value, list):
3328
return tuple(self._freeze_value(item) for item in value)
3429
if isinstance(value, tuple):

openapi_schema_validator/_dialects.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22

33
from jsonschema.validators import validates
44

5-
from openapi_schema_validator._specifications import (
6-
REGISTRY as OPENAPI_SPECIFICATIONS,
7-
)
5+
from openapi_schema_validator._specifications import REGISTRY as OPENAPI_SPECIFICATIONS
86

97
__all__ = [
108
"OAS31_BASE_DIALECT_ID",

openapi_schema_validator/_format.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import binascii
22
from base64 import b64decode
3-
from base64 import b64encode
43
from numbers import Number
54

65
from jsonschema._format import FormatChecker
@@ -106,9 +105,7 @@ def is_regex(instance: object) -> bool:
106105
oas30_strict_format_checker.checks("float")(is_float)
107106
oas30_strict_format_checker.checks("double")(is_double)
108107
oas30_strict_format_checker.checks("binary")(is_binary_strict)
109-
oas30_strict_format_checker.checks("byte", (binascii.Error, TypeError))(
110-
is_byte
111-
)
108+
oas30_strict_format_checker.checks("byte", (binascii.Error, TypeError))(is_byte)
112109
oas30_strict_format_checker.checks("password")(is_password)
113110
oas30_strict_format_checker.checks("regex")(is_regex)
114111

openapi_schema_validator/_keywords.py

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
from collections.abc import Iterator
2+
from collections.abc import Mapping
13
from typing import Any
2-
from typing import Iterator
3-
from typing import Mapping
44
from typing import cast
55

66
from jsonschema._keywords import allOf as _allOf
@@ -18,9 +18,7 @@
1818
from openapi_schema_validator._regex import search as regex_search
1919

2020

21-
def handle_discriminator(
22-
validator: Any, _: Any, instance: Any, schema: Mapping[str, Any]
23-
) -> Iterator[ValidationError]:
21+
def handle_discriminator(validator: Any, _: Any, instance: Any, schema: Mapping[str, Any]) -> Iterator[ValidationError]:
2422
"""
2523
Handle presence of discriminator in anyOf, oneOf and allOf.
2624
The behaviour is the same in all 3 cases because at most 1 schema will match.
@@ -29,9 +27,7 @@ def handle_discriminator(
2927
prop_name = discriminator["propertyName"]
3028

3129
if not validator.is_type(instance, "object"):
32-
yield ValidationError(
33-
f"{instance!r} is not of type 'object'", context=[]
34-
)
30+
yield ValidationError(f"{instance!r} is not of type 'object'", context=[])
3531
return
3632

3733
prop_value = instance.get(prop_name)
@@ -44,10 +40,7 @@ def handle_discriminator(
4440
return
4541

4642
# Use explicit mapping if available, otherwise try implicit value
47-
ref = (
48-
discriminator.get("mapping", {}).get(prop_value)
49-
or f"#/components/schemas/{prop_value}"
50-
)
43+
ref = discriminator.get("mapping", {}).get(prop_value) or f"#/components/schemas/{prop_value}"
5144

5245
if not isinstance(ref, str):
5346
# this is a schema error
@@ -132,11 +125,7 @@ def type(
132125
yield ValidationError("None for not nullable")
133126

134127
# Pragmatic: allow bytes for binary format (common in Python use cases)
135-
if (
136-
data_type == "string"
137-
and schema.get("format") == "binary"
138-
and isinstance(instance, bytes)
139-
):
128+
if data_type == "string" and schema.get("format") == "binary" and isinstance(instance, bytes):
140129
return
141130

142131
if not validator.is_type(instance, data_type):
@@ -183,9 +172,7 @@ def pattern(
183172
try:
184173
matches = regex_search(patrn, instance)
185174
except ECMARegexSyntaxError as exc:
186-
yield ValidationError(
187-
f"{patrn!r} is not a valid regular expression ({exc})"
188-
)
175+
yield ValidationError(f"{patrn!r} is not a valid regular expression ({exc})")
189176
return
190177

191178
if not matches:
@@ -235,11 +222,8 @@ def required(
235222
if prop_schema:
236223
read_only = prop_schema.get("readOnly", False)
237224
write_only = prop_schema.get("writeOnly", False)
238-
if (
239-
getattr(validator, "write", True)
240-
and read_only
241-
or getattr(validator, "read", True)
242-
and write_only
225+
if (getattr(validator, "write", True) and read_only) or (
226+
getattr(validator, "read", True) and write_only
243227
):
244228
continue
245229
yield ValidationError(f"{property!r} is a required property")
@@ -299,10 +283,9 @@ def additionalProperties(
299283
for extra in extras:
300284
for error in validator.descend(instance[extra], aP, path=extra):
301285
yield error
302-
elif validator.is_type(aP, "boolean"):
303-
if not aP:
304-
error = "Additional properties are not allowed (%s %s unexpected)"
305-
yield ValidationError(error % extras_msg(extras))
286+
elif validator.is_type(aP, "boolean") and not aP:
287+
error = "Additional properties are not allowed (%s %s unexpected)"
288+
yield ValidationError(error % extras_msg(extras))
306289

307290

308291
def write_readOnly(

0 commit comments

Comments
 (0)