Skip to content

Commit 92d8511

Browse files
committed
Merge branch 'main' into stubs-package-data
2 parents a01aaed + 012a10c commit 92d8511

40 files changed

Lines changed: 422 additions & 178 deletions

.github/workflows/ci.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ jobs:
3030
outputs:
3131
wheel-distribution: ${{ steps.wheel-distribution.outputs.path }}
3232
steps:
33-
- uses: actions/checkout@v5
33+
- uses: actions/checkout@v6
3434
with: {fetch-depth: 0} # deep clone for setuptools-scm
3535
- uses: actions/setup-python@v6
3636
with: {python-version: "3.x"}
37-
- uses: astral-sh/setup-uv@v6
37+
- uses: astral-sh/setup-uv@v7
3838
- name: Run static analysis and format checkers
3939
run: >-
4040
uvx --with tox-uv
@@ -49,15 +49,15 @@ jobs:
4949
- name: Store the distribution files for use in other stages
5050
# `tests` and `publish` will use the same pre-built distributions,
5151
# so we make sure to release the exact same package that was tested
52-
uses: actions/upload-artifact@v4
52+
uses: actions/upload-artifact@v5
5353
with:
5454
name: python-distribution-files
5555
path: dist/
5656
retention-days: 1
5757
- name: Download files used for testing
5858
run: python tools/cache_urls_for_tests.py
5959
- name: Store downloaded files
60-
uses: actions/upload-artifact@v4
60+
uses: actions/upload-artifact@v5
6161
with:
6262
name: test-download-files
6363
path: ${{ env.VALIDATE_PYPROJECT_CACHE_REMOTE }}
@@ -79,17 +79,17 @@ jobs:
7979
- windows-latest
8080
runs-on: ${{ matrix.platform }}
8181
steps:
82-
- uses: actions/checkout@v5
82+
- uses: actions/checkout@v6
8383
- uses: actions/setup-python@v6
8484
with:
8585
python-version: ${{ matrix.python }}
8686
allow-prereleases: true
87-
- uses: astral-sh/setup-uv@v6
87+
- uses: astral-sh/setup-uv@v7
8888
- name: Retrieve pre-built distribution files
89-
uses: actions/download-artifact@v5
89+
uses: actions/download-artifact@v6
9090
with: {name: python-distribution-files, path: dist/}
9191
- name: Retrieve test download files
92-
uses: actions/download-artifact@v5
92+
uses: actions/download-artifact@v6
9393
with:
9494
name: test-download-files
9595
path: ${{ env.VALIDATE_PYPROJECT_CACHE_REMOTE }}
@@ -124,12 +124,12 @@ jobs:
124124
if: ${{ github.event_name == 'push' && contains(github.ref, 'refs/tags/') }}
125125
runs-on: ubuntu-latest
126126
steps:
127-
- uses: actions/checkout@v5
127+
- uses: actions/checkout@v6
128128
- uses: actions/setup-python@v6
129129
with: {python-version: "3.x"}
130-
- uses: astral-sh/setup-uv@v6
130+
- uses: astral-sh/setup-uv@v7
131131
- name: Retrieve pre-built distribution files
132-
uses: actions/download-artifact@v5
132+
uses: actions/download-artifact@v6
133133
with: {name: python-distribution-files, path: dist/}
134134
- name: Publish Package
135135
env:

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,7 @@ MANIFEST
5252
.venv*/
5353
.conda*/
5454
.python-version
55+
56+
# Lock files
57+
uv.lock
58+
*pylock.toml

.pre-commit-config.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ repos:
2626
args: ["--ignore-words-list=THIRDPARTY", --write-changes]
2727

2828
- repo: https://github.com/astral-sh/ruff-pre-commit
29-
rev: v0.14.1
29+
rev: v0.14.5
3030
hooks:
3131
- id: ruff-check
32-
args: [--exclude=tools/to_schemastore.py, "--ignore=PLC0415,RUF200", --fix, --show-fixes, ]
32+
args: [--fix, --show-fixes]
3333
- id: ruff-format
3434

3535
- repo: https://github.com/adamchainz/blacken-docs
@@ -63,15 +63,15 @@ repos:
6363
- validate-pyproject[all]>=0.13
6464

6565
- repo: https://github.com/python-jsonschema/check-jsonschema
66-
rev: 0.34.1
66+
rev: 0.35.0
6767
hooks:
6868
- id: check-metaschema
6969
files: \.schema\.json$
7070
- id: check-readthedocs
7171
- id: check-github-workflows
7272

7373
- repo: https://github.com/scientific-python/cookie
74-
rev: 2025.10.20
74+
rev: 2025.11.10
7575
hooks:
7676
- id: sp-repo-review
7777
name: Validate Python repository

.ruff.toml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,52 @@
11
# --- General config ---
22
target-version = "py38"
3+
exclude = ["tools/to_schemastore.py", "tests/invalid-examples"]
34

45
# --- Linting config ---
56
[lint]
67
extend-select = [
8+
"ARG", # flake8-unused-arguments
79
"B", # flake8-bugbear
10+
"BLE", # flake8-blind-except
811
"C4", # flake8-comprehensions
912
"C90", # McCabe cyclomatic complexity
1013
"DTZ", # flake8-datetimez
14+
"EM", # flake8-errmsg
1115
"EXE", # flake8-executable
16+
"FA", # flake8-future-annotations
1217
"FBT", # flake8-boolean-trap
18+
"FLY", # flynt
19+
"FURB", # refurb
1320
"I", # isort
1421
"ICN", # flake8-import-conventions
1522
"INT", # flake8-gettext
23+
"ISC", # flake8-implicit-str-concat
24+
"LOG", # flake8-logging
25+
"PERF", # Perflint
26+
"PGH", # pygrep-hooks
27+
"PIE", # flake8-pie
1628
"PL", # Pylint
29+
"PT", # flake8-pytest-style
1730
"PYI", # flake8-pyi
31+
"Q", # flake8-quotes
1832
"RET", # flake8-return
33+
"RSE", # flake8-raise
1934
"RUF", # Ruff-specific rules
2035
"S", # flake8-bandit
2136
"SIM", # flake8-simplify
37+
"SLOT", # flake8-slots
2238
"T10", # flake8-debugger
39+
"TC", # flake8-type-checking
2340
"TCH", # flake8-type-checking
41+
"TRY", # tryceratops
2442
"UP", # pyupgrade
2543
"YTT", # flake8-2020
2644
]
2745
ignore = [
28-
"SIM105", # contextlib.supress (3.7 feature)
46+
"PLC0415", # import at top of file
47+
"RSE102", # parens on exception raise
48+
"S101", # assert is used by mypy and pytest
49+
"TRY401", # redundant logging message, TODO check
2950
]
3051

3152
[lint.per-file-ignores]

docs/_gendocs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
__location__ = Path(__file__).parent
2020

2121

22-
def gen_stubs(module_dir: str, output_dir: str):
22+
def gen_stubs(module_dir: str, output_dir: str): # noqa: ARG001
2323
shutil.rmtree(output_dir, ignore_errors=True) # Always start fresh
2424
out = Path(output_dir)
2525
out.mkdir(parents=True, exist_ok=True)

pyproject.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ validate_pyproject = "validate_pyproject.repo_review:repo_review_families"
5252
[dependency-groups]
5353
dev = [
5454
{ include-group = "test" },
55+
"validate_pyproject[all]",
5556
]
5657
docs = [
5758
"furo>=2023.08.17",
@@ -79,9 +80,6 @@ typecheck = [
7980
environments = [
8081
"python_version >= '3.9'",
8182
]
82-
dev-dependencies = [
83-
"validate_pyproject[all]",
84-
]
8583

8684
[tool.setuptools_scm]
8785
version_scheme = "no-guess-dev"
@@ -97,7 +95,7 @@ addopts = """
9795
"""
9896
norecursedirs = ["dist", "build", ".*"]
9997
testpaths = ["src", "tests"]
100-
log_cli_level = "info"
98+
log_level = "INFO"
10199

102100
[tool.mypy]
103101
python_version = "3.8"

src/validate_pyproject/_tomllib.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
)
1313
from toml import loads # type: ignore[no-redef]
1414
except ImportError as ex:
15-
raise ImportError("Please install `tomli` (TOML parser)") from ex
15+
msg = "Please install `tomli` (TOML parser)"
16+
raise ImportError(msg) from ex
1617

1718

1819
__all__ = [

src/validate_pyproject/api.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Retrieve JSON schemas for validating dicts representing a ``pyproject.toml`` file.
33
"""
44

5+
from __future__ import annotations
6+
57
import json
68
import logging
79
import sys
@@ -11,14 +13,10 @@
1113
from types import MappingProxyType, ModuleType
1214
from typing import (
1315
Callable,
14-
Dict,
1516
Iterator,
1617
Mapping,
17-
Optional,
1818
Sequence,
19-
Tuple,
2019
TypeVar,
21-
Union,
2220
)
2321

2422
import fastjsonschema as FJS
@@ -37,7 +35,7 @@
3735
if sys.version_info >= (3, 9): # pragma: no cover
3836
from importlib.resources import files
3937

40-
def read_text(package: Union[str, ModuleType], resource: str) -> str:
38+
def read_text(package: str | ModuleType, resource: str) -> str:
4139
""":meta private:"""
4240
return files(package).joinpath(resource).read_text(encoding="utf-8")
4341

@@ -94,8 +92,8 @@ class SchemaRegistry(Mapping[str, Schema]):
9492
:meta private: (low level detail)
9593
"""
9694

97-
def __init__(self, plugins: Sequence["PluginProtocol"] = ()):
98-
self._schemas: Dict[str, Tuple[str, str, Schema]] = {}
95+
def __init__(self, plugins: Sequence[PluginProtocol] = ()):
96+
self._schemas: dict[str, tuple[str, str, Schema]] = {}
9997
# (which part of the TOML, who defines, schema)
10098

10199
top_level = typing.cast("dict", load(TOP_LEVEL_SCHEMA)) # Make it mutable
@@ -114,7 +112,7 @@ def __init__(self, plugins: Sequence["PluginProtocol"] = ()):
114112
# Add tools using Plugins
115113
for plugin in plugins:
116114
if plugin.tool:
117-
allow_overwrite: Optional[str] = None
115+
allow_overwrite: str | None = None
118116
if plugin.tool in tool_properties:
119117
_logger.warning(f"{plugin} overwrites `tool.{plugin.tool}` schema")
120118
allow_overwrite = plugin.schema.get("$id")
@@ -150,7 +148,7 @@ def _ensure_compatibility(
150148
self,
151149
reference: str,
152150
schema: Schema,
153-
allow_overwrite: Optional[str] = None,
151+
allow_overwrite: str | None = None,
154152
) -> Schema:
155153
if "$id" not in schema or not schema["$id"]:
156154
raise errors.SchemaMissingId(reference or "<extra>")
@@ -208,19 +206,19 @@ def __getitem__(self, key: str) -> Callable[[str], Schema]:
208206

209207

210208
class Validator:
211-
_plugins: Sequence["PluginProtocol"]
209+
_plugins: Sequence[PluginProtocol]
212210

213211
def __init__(
214212
self,
215-
plugins: Union[Sequence["PluginProtocol"], AllPlugins] = ALL_PLUGINS,
213+
plugins: Sequence[PluginProtocol] | AllPlugins = ALL_PLUGINS,
216214
format_validators: Mapping[str, FormatValidationFn] = FORMAT_FUNCTIONS,
217215
extra_validations: Sequence[ValidationFn] = EXTRA_VALIDATIONS,
218216
*,
219-
extra_plugins: Sequence["PluginProtocol"] = (),
217+
extra_plugins: Sequence[PluginProtocol] = (),
220218
):
221-
self._code_cache: Optional[str] = None
222-
self._cache: Optional[ValidationFn] = None
223-
self._schema: Optional[Schema] = None
219+
self._code_cache: str | None = None
220+
self._cache: ValidationFn | None = None
221+
self._schema: Schema | None = None
224222

225223
# Let's make the following options readonly
226224
self._format_validators = MappingProxyType(format_validators)

src/validate_pyproject/caching.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
# This module is intentionally kept minimal,
22
# so that it can be imported without triggering imports outside stdlib.
3+
from __future__ import annotations
4+
35
import hashlib
4-
import io
56
import logging
67
import os
78
from pathlib import Path
8-
from typing import Callable, Optional, Union
9+
from typing import TYPE_CHECKING, Callable, Union
10+
11+
if TYPE_CHECKING:
12+
import io
913

1014
PathLike = Union[str, "os.PathLike[str]"]
1115
_logger = logging.getLogger(__name__)
@@ -14,8 +18,8 @@
1418
def as_file(
1519
fn: Callable[[str], io.StringIO],
1620
arg: str,
17-
cache_dir: Optional[PathLike] = None,
18-
) -> Union[io.StringIO, io.BufferedReader]:
21+
cache_dir: PathLike | None = None,
22+
) -> io.StringIO | io.BufferedReader:
1923
"""
2024
Cache the result of calling ``fn(arg)`` into a file inside ``cache_dir``.
2125
The file name is derived from ``arg``.
@@ -36,7 +40,7 @@ def as_file(
3640
return open(cache_path, "rb")
3741

3842

39-
def path_for(arbitrary_id: str, cache: Optional[PathLike] = None) -> Optional[Path]:
43+
def path_for(arbitrary_id: str, cache: PathLike | None = None) -> Path | None:
4044
cache_dir = cache or os.getenv("VALIDATE_PYPROJECT_CACHE_REMOTE")
4145
if not cache_dir:
4246
return None

0 commit comments

Comments
 (0)