diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e7e040f..e9cbb44 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,10 +1,10 @@ repos: - repo: https://github.com/tox-dev/pyproject-fmt - rev: "2.2.1" + rev: "2.3.0" hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.1 + rev: v0.6.9 hooks: - id: ruff-format - id: ruff diff --git a/README.md b/README.md index 7137f1b..5cfb880 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Open Source Initiative Approved License logo [![CI](https://github.com/kpfleming/jinjanator-plugins/workflows/CI%20checks/badge.svg)](https://github.com/kpfleming/jinjanator-plugins/actions?query=workflow%3ACI%20checks) -[![Python](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/release/python-3812/) +[![Python](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/release/python-3920/) [![License - Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-9400d3.svg)](https://spdx.org/licenses/Apache-2.0.html) [![Code Style - Black](https://img.shields.io/badge/Code%20Style-Black-000000.svg)](https://github.com/psf/black) [![Types - Mypy](https://img.shields.io/badge/Types-Mypy-blue.svg)](https://github.com/python/mypy) diff --git a/changelog.d/+e1c61bf0.breaking.md b/changelog.d/+e1c61bf0.breaking.md new file mode 100644 index 0000000..88e0c80 --- /dev/null +++ b/changelog.d/+e1c61bf0.breaking.md @@ -0,0 +1 @@ +Added support for Python 3.13, and removed support for Python 3.8. diff --git a/plugin_example/jinjanator_plugin_example.py b/plugin_example/jinjanator_plugin_example.py index 9f8001d..1296213 100644 --- a/plugin_example/jinjanator_plugin_example.py +++ b/plugin_example/jinjanator_plugin_example.py @@ -1,8 +1,7 @@ -from __future__ import annotations - import codecs -from typing import Iterable, Mapping +from collections.abc import Iterable, Mapping +from typing import Optional from jinjanator_plugins import ( Extensions, @@ -31,10 +30,10 @@ def is_len12_test(value: str) -> bool: class SpamFormat: name = "spam" - suffixes: Iterable[str] | None = (".spam",) - option_names: Iterable[str] | None = ("ham",) + suffixes: Optional[Iterable[str]] = (".spam",) + option_names: Optional[Iterable[str]] = ("ham",) - def __init__(self, options: Iterable[str] | None) -> None: + def __init__(self, options: Optional[Iterable[str]]) -> None: self.ham = False if options: diff --git a/plugin_example/pyproject.toml b/plugin_example/pyproject.toml index ca9d060..d7edd26 100644 --- a/plugin_example/pyproject.toml +++ b/plugin_example/pyproject.toml @@ -7,14 +7,14 @@ requires = [ [project] name = "jinjanator-plugin-example" version = "0.0.0" -requires-python = ">=3.8" +requires-python = ">=3.9" classifiers = [ "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] dependencies = [ diff --git a/plugin_example/tests/test_plugin.py b/plugin_example/tests/test_plugin.py index 66d2a24..dabafe1 100644 --- a/plugin_example/tests/test_plugin.py +++ b/plugin_example/tests/test_plugin.py @@ -1,5 +1,3 @@ -from __future__ import annotations - import jinjanator_plugin_example as plugin # type: ignore[import-not-found] import pytest diff --git a/plugin_example/tests/test_plugin_discovery.py b/plugin_example/tests/test_plugin_discovery.py index a6a55c6..6755f69 100644 --- a/plugin_example/tests/test_plugin_discovery.py +++ b/plugin_example/tests/test_plugin_discovery.py @@ -1,5 +1,3 @@ -from __future__ import annotations - from typing import cast import jinjanator_plugin_example as plugin # type: ignore[import-not-found] diff --git a/plugin_example/tests/test_plugin_discovery_entrypoint.py b/plugin_example/tests/test_plugin_discovery_entrypoint.py index 1257c39..fa0ee8a 100644 --- a/plugin_example/tests/test_plugin_discovery_entrypoint.py +++ b/plugin_example/tests/test_plugin_discovery_entrypoint.py @@ -1,5 +1,3 @@ -from __future__ import annotations - from typing import cast import pluggy diff --git a/pyproject.toml b/pyproject.toml index cb72219..f60b981 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ license = { text = "Apache-2.0" } authors = [ { name = "Kevin P. Fleming", email = "jinjanator@kevin.km6g.us" }, ] -requires-python = ">=3.8" +requires-python = ">=3.9" classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Console", @@ -22,11 +22,11 @@ classifiers = [ "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Typing :: Typed", ] dynamic = [ @@ -36,6 +36,7 @@ dynamic = [ dependencies = [ "attrs", "pluggy", + "typing-extensions", ] urls."Bug Tracker" = "https://github.com/kpfleming/jinjanator-plugins/issues" urls."Homepage" = "https://github.com/kpfleming/jinjanator-plugins" @@ -122,7 +123,6 @@ dependencies = [ [[tool.hatch.envs.ci.matrix]] python = [ - "3.8", "3.9", "3.10", "3.11", @@ -189,6 +189,7 @@ lint.ignore = [ "C901", # Leave complexity to me. "COM812", # conflicts with formatter "D", # We have different ideas about docstrings. + "FA100", # Intentionally not using '__future__' for annotations "ISC001", # conflicts with formatter "PLR0912", # Leave complexity to me. "TRY301", # Raise in try blocks can totally make sense. @@ -271,7 +272,7 @@ name = "Fixes" showcontent = true [tool.mypy] -python_version = 3.8 +python_version = 3.9 namespace_packages = true explicit_package_bases = true check_untyped_defs = true diff --git a/src/jinjanator_plugins/__init__.py b/src/jinjanator_plugins/__init__.py index 0aa20d9..2760114 100644 --- a/src/jinjanator_plugins/__init__.py +++ b/src/jinjanator_plugins/__init__.py @@ -1,36 +1,33 @@ -from __future__ import annotations - +from collections.abc import Iterable, Mapping from typing import ( - TYPE_CHECKING, Any, Callable, - Iterable, - Mapping, + Optional, Protocol, - Type, TypeVar, + Union, cast, ) import pluggy - -if TYPE_CHECKING: # pragma: no cover - from typing_extensions import TypeAlias +from typing_extensions import ( + TypeAlias, +) class Format(Protocol): name: str - suffixes: Iterable[str] | None - option_names: Iterable[str] | None + suffixes: Optional[Iterable[str]] + option_names: Optional[Iterable[str]] - def __init__(self, options: Iterable[str] | None) -> None: ... # pragma: no cover + def __init__(self, options: Optional[Iterable[str]]) -> None: ... # pragma: no cover def parse(self, data_string: str) -> Mapping[str, Any]: ... # pragma: no cover class FormatOptionUnknownError(Exception): - def __init__(self, fmt: type[Format] | Format, option: str): + def __init__(self, fmt: Union[type[Format], Format], option: str): self.fmt = fmt self.option = option @@ -48,7 +45,7 @@ def __str__(self) -> str: class FormatOptionUnsupportedError(Exception): - def __init__(self, fmt: type[Format] | Format, option: str, message: str): + def __init__(self, fmt: Union[type[Format], Format], option: str, message: str): self.fmt = fmt self.option = option self.message = message @@ -58,7 +55,7 @@ def __str__(self) -> str: class FormatOptionValueError(Exception): - def __init__(self, fmt: type[Format] | Format, option: str, value: str, message: str): + def __init__(self, fmt: Union[type[Format], Format], option: str, value: str, message: str): self.fmt = fmt self.option = option self.message = message @@ -75,7 +72,7 @@ def __str__(self) -> str: hookspec = cast(Callable[[F], F], pluggy.HookspecMarker("jinjanator")) Identity: TypeAlias = str -Formats: TypeAlias = Mapping[str, Type[Format]] +Formats: TypeAlias = Mapping[str, type[Format]] Filters: TypeAlias = Mapping[str, Callable[..., Any]] Globals: TypeAlias = Mapping[str, Callable[..., Any]] Tests: TypeAlias = Mapping[str, Callable[..., Any]] diff --git a/tests/test_format_error_output.py b/tests/test_format_error_output.py index ef34187..2113439 100644 --- a/tests/test_format_error_output.py +++ b/tests/test_format_error_output.py @@ -1,6 +1,5 @@ -from __future__ import annotations - -from typing import Iterable, Mapping +from collections.abc import Iterable, Mapping +from typing import Optional from jinjanator_plugins import ( FormatOptionUnknownError, @@ -11,10 +10,10 @@ class FormatNoOptions: name = "test" - suffixes: Iterable[str] | None = () - option_names: Iterable[str] | None = () + suffixes: Optional[Iterable[str]] = () + option_names: Optional[Iterable[str]] = () - def __init__(self, options: Iterable[str] | None) -> None: + def __init__(self, options: Optional[Iterable[str]]) -> None: pass def parse( @@ -26,10 +25,10 @@ def parse( class FormatOptions: name = "test" - suffixes: Iterable[str] | None = () - option_names: Iterable[str] | None = ("bart",) + suffixes: Optional[Iterable[str]] = () + option_names: Optional[Iterable[str]] = ("bart",) - def __init__(self, options: Iterable[str] | None) -> None: + def __init__(self, options: Optional[Iterable[str]]) -> None: pass def parse( diff --git a/workflow-support/versions.json b/workflow-support/versions.json index 2dc44cb..5fdb6f0 100644 --- a/workflow-support/versions.json +++ b/workflow-support/versions.json @@ -1 +1 @@ -versions={"python": ["3.8", "3.9", "3.10", "3.11", "3.12"]} +versions={"python": ["3.9", "3.10", "3.11", "3.12"]}