From d40d6780fd96cd83ac4c0a2c2b515e7f17cab1c2 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Sat, 18 May 2024 15:37:21 +0200 Subject: [PATCH] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20=20Python=203.9-3.12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 18 +++++++++--------- .readthedocs.yml | 2 +- pyproject.toml | 4 ++-- sphinx_design/_compat.py | 3 ++- sphinx_design/article_info.py | 4 ++-- sphinx_design/badges_buttons.py | 18 +++++++++--------- sphinx_design/cards.py | 12 ++++++------ sphinx_design/grids.py | 16 ++++++++-------- sphinx_design/icons.py | 17 +++++++++-------- sphinx_design/shared.py | 11 ++++++----- sphinx_design/tabs.py | 8 +++----- tests/conftest.py | 4 ++-- tox.ini | 4 ++-- 13 files changed, 61 insertions(+), 60 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f4a939..57b178e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,11 +15,11 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up Python 3.8 + - name: Set up Python 3.9 uses: actions/setup-python@v4 with: - python-version: 3.8 - - uses: pre-commit/action@v3.0.0 + python-version: 3.9 + - uses: pre-commit/action@v3.0.1 tests: @@ -27,17 +27,17 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12"] sphinx-version: ["~=7.0"] include: - os: ubuntu-latest - python-version: 3.8 + python-version: 3.9 sphinx-version: "~=5.0" - os: ubuntu-latest - python-version: 3.8 + python-version: 3.9 sphinx-version: "~=6.0" - os: windows-latest - python-version: 3.8 + python-version: 3.9 sphinx-version: "~=7.0" runs-on: ${{ matrix.os }} @@ -57,7 +57,7 @@ jobs: run: | pytest --cov=sphinx_design --cov-report=xml --cov-report=term-missing - name: Upload to Codecov - if: matrix.python-version == '3.8' && matrix.os == 'ubuntu-latest' + if: matrix.python-version == '3.9' && matrix.os == 'ubuntu-latest' uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -117,7 +117,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: install flit run: | pip install flit~=3.4 diff --git a/.readthedocs.yml b/.readthedocs.yml index 4971637..a418de2 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -3,7 +3,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.8" + python: "3.9" python: install: diff --git a/pyproject.toml b/pyproject.toml index c5ed5d1..c5305f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,10 +15,10 @@ classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", - "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 :: Implementation :: CPython", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Markup", @@ -26,7 +26,7 @@ classifiers = [ "Topic :: Text Processing :: Markup :: reStructuredText", ] keywords = ["sphinx", "extension", "material design", "web components"] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = ["sphinx>=5,<8"] [project.urls] diff --git a/sphinx_design/_compat.py b/sphinx_design/_compat.py index f1bd875..3797c73 100644 --- a/sphinx_design/_compat.py +++ b/sphinx_design/_compat.py @@ -1,7 +1,8 @@ """Helpers for cross compatibility across dependency versions.""" +from collections.abc import Iterable from importlib import resources -from typing import Callable, Iterable +from typing import Callable from docutils.nodes import Element diff --git a/sphinx_design/article_info.py b/sphinx_design/article_info.py index f654be1..9201daf 100644 --- a/sphinx_design/article_info.py +++ b/sphinx_design/article_info.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import Optional from docutils import nodes from docutils.parsers.rst import directives @@ -48,7 +48,7 @@ def _parse_text( output = [para] return output - def run(self) -> List[nodes.Node]: # noqa: PLR0915 + def run(self) -> list[nodes.Node]: # noqa: PLR0915 """Run the directive.""" parse_fields = True # parse field text diff --git a/sphinx_design/badges_buttons.py b/sphinx_design/badges_buttons.py index 8026297..52a46a3 100644 --- a/sphinx_design/badges_buttons.py +++ b/sphinx_design/badges_buttons.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Tuple +from typing import Optional from docutils import nodes from docutils.parsers.rst import directives @@ -45,7 +45,7 @@ def setup_badges_and_buttons(app: Sphinx) -> None: app.add_directive(DIRECTIVE_NAME_BUTTON_REF, ButtonRefDirective) -def create_bdg_classes(color: Optional[str], outline: bool) -> List[str]: +def create_bdg_classes(color: Optional[str], outline: bool) -> list[str]: """Create the badge classes.""" classes = [ "sd-sphinx-override", @@ -68,7 +68,7 @@ def __init__(self, color: Optional[str] = None, *, outline: bool = False) -> Non self.color = color self.outline = outline - def run(self) -> Tuple[List[nodes.Node], List[nodes.system_message]]: + def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]: """Run the role.""" node = nodes.inline( self.rawtext, @@ -87,7 +87,7 @@ def __init__(self, color: Optional[str] = None, *, outline: bool = False) -> Non self.color = color self.outline = outline - def run(self) -> Tuple[List[nodes.Node], List[nodes.system_message]]: + def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]: """Run the role.""" node = nodes.reference( self.rawtext, @@ -110,7 +110,7 @@ def __init__(self, color: Optional[str] = None, *, outline: bool = False) -> Non self.color = color self.outline = outline - def run(self) -> Tuple[List[nodes.Node], List[nodes.system_message]]: + def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]: """Run the role.""" options = { "classes": create_bdg_classes(self.color, self.outline), @@ -150,12 +150,12 @@ class _ButtonDirective(SphinxDirective): } def create_ref_node( - self, rawtext: str, target: str, explicit_title: bool, classes: List[str] + self, rawtext: str, target: str, explicit_title: bool, classes: list[str] ) -> nodes.Node: """Create the reference node.""" raise NotImplementedError - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" rawtext = self.arguments[0] target = directives.uri(rawtext) @@ -205,7 +205,7 @@ class ButtonLinkDirective(_ButtonDirective): """A button directive with an external link.""" def create_ref_node( - self, rawtext: str, target: str, explicit_title: bool, classes: List[str] + self, rawtext: str, target: str, explicit_title: bool, classes: list[str] ) -> nodes.Node: """Create the reference node.""" return nodes.reference( @@ -219,7 +219,7 @@ class ButtonRefDirective(_ButtonDirective): """A button directive with an internal link.""" def create_ref_node( - self, rawtext: str, target: str, explicit_title: bool, classes: List[str] + self, rawtext: str, target: str, explicit_title: bool, classes: list[str] ) -> nodes.Node: """Create the reference node.""" ref_type = self.options.get("ref-type", "any") diff --git a/sphinx_design/cards.py b/sphinx_design/cards.py index b638fc2..a7d2619 100644 --- a/sphinx_design/cards.py +++ b/sphinx_design/cards.py @@ -1,5 +1,5 @@ import re -from typing import List, NamedTuple, Optional, Tuple +from typing import NamedTuple, Optional from docutils import nodes from docutils.parsers.rst import directives @@ -40,9 +40,9 @@ class CardContent(NamedTuple): (offset, content) """ - body: Tuple[int, StringList] - header: Optional[Tuple[int, StringList]] = None - footer: Optional[Tuple[int, StringList]] = None + body: tuple[int, StringList] + header: Optional[tuple[int, StringList]] = None + footer: Optional[tuple[int, StringList]] = None class CardDirective(SphinxDirective): @@ -73,7 +73,7 @@ class CardDirective(SphinxDirective): "class-img-bottom": directives.class_option, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: return [self.create_card(self, self.arguments, self.options)] @classmethod @@ -266,7 +266,7 @@ class CardCarouselDirective(SphinxDirective): "class": directives.class_option, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" self.assert_has_content() try: diff --git a/sphinx_design/grids.py b/sphinx_design/grids.py index ccf2971..a0bab89 100644 --- a/sphinx_design/grids.py +++ b/sphinx_design/grids.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import Optional from docutils import nodes from docutils.parsers.rst import directives @@ -39,7 +39,7 @@ def _media_option( allow_auto: bool = False, min_num: int = 1, max_num: int = 12, -) -> List[str]: +) -> list[str]: """Validate the number of columns (out of 12). One or four integers (for "xs sm md lg") between 1 and 12. @@ -70,7 +70,7 @@ def _media_option( ] -def row_columns_option(argument: Optional[str]) -> List[str]: +def row_columns_option(argument: Optional[str]) -> list[str]: """Validate the number of columns (out of 12) a grid row will have. One or four integers (for "xs sm md lg") between 1 and 12 (or 'auto'). @@ -78,7 +78,7 @@ def row_columns_option(argument: Optional[str]) -> List[str]: return _media_option(argument, "sd-row-cols-", allow_auto=True) -def item_columns_option(argument: Optional[str]) -> List[str]: +def item_columns_option(argument: Optional[str]) -> list[str]: """Validate the number of columns (out of 12) a grid-item will take up. One or four integers (for "xs sm md lg") between 1 and 12 (or 'auto'). @@ -86,7 +86,7 @@ def item_columns_option(argument: Optional[str]) -> List[str]: return _media_option(argument, "sd-col-", allow_auto=True) -def gutter_option(argument: Optional[str]) -> List[str]: +def gutter_option(argument: Optional[str]) -> list[str]: """Validate the gutter size between grid items. One or four integers (for "xs sm md lg") between 0 and 5. @@ -111,7 +111,7 @@ class GridDirective(SphinxDirective): "class-row": directives.class_option, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" try: column_classes = ( @@ -174,7 +174,7 @@ class GridItemDirective(SphinxDirective): "class": directives.class_option, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" if not is_component(self.state_machine.node, "grid-row"): LOGGER.warning( @@ -237,7 +237,7 @@ class GridItemCardDirective(SphinxDirective): "class-img-bottom": directives.class_option, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" if not is_component(self.state_machine.node, "grid-row"): LOGGER.warning( diff --git a/sphinx_design/icons.py b/sphinx_design/icons.py index 2932a86..29e354d 100644 --- a/sphinx_design/icons.py +++ b/sphinx_design/icons.py @@ -1,7 +1,8 @@ +from collections.abc import Sequence from functools import lru_cache import json import re -from typing import Any, Dict, List, Optional, Sequence, Tuple +from typing import Any, Optional from docutils import nodes from docutils.parsers.rst import directives @@ -46,13 +47,13 @@ def setup_icons(app: Sphinx) -> None: @lru_cache(1) -def get_octicon_data() -> Dict[str, Any]: +def get_octicon_data() -> dict[str, Any]: """Load all octicon data.""" content = read_text(compiled, "octicons.json") return json.loads(content) -def list_octicons() -> List[str]: +def list_octicons() -> list[str]: """List available octicon names.""" return list(get_octicon_data().keys()) @@ -120,7 +121,7 @@ class OcticonRole(SphinxRole): Additional classes can be added to the element after a semicolon. """ - def run(self) -> Tuple[List[nodes.Node], List[nodes.system_message]]: + def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]: """Run the role.""" values = self.text.split(";") if ";" in self.text else [self.text] icon = values[0] @@ -151,7 +152,7 @@ class AllOcticons(SphinxDirective): "class": directives.class_option, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" classes = self.options.get("class", []) list_node = nodes.bullet_list() @@ -186,7 +187,7 @@ def __init__(self, style: str) -> None: super().__init__() self.style = style - def run(self) -> Tuple[List[nodes.Node], List[nodes.system_message]]: + def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]: """Run the role.""" icon, classes = self.text.split(";", 1) if ";" in self.text else [self.text, ""] icon = icon.strip() @@ -238,7 +239,7 @@ def visit_fontawesome_warning(self, node: nodes.Element) -> None: @lru_cache(1) -def get_material_icon_data(style: str) -> Dict[str, Any]: +def get_material_icon_data(style: str) -> dict[str, Any]: """Load all octicon data.""" content = read_text(compiled, f"material_{style}.json") return json.loads(content) @@ -309,7 +310,7 @@ def __init__(self, style: str) -> None: super().__init__() self.style = style - def run(self) -> Tuple[List[nodes.Node], List[nodes.system_message]]: + def run(self) -> tuple[list[nodes.Node], list[nodes.system_message]]: """Run the role.""" values = self.text.split(";") if ";" in self.text else [self.text] icon = values[0] diff --git a/sphinx_design/shared.py b/sphinx_design/shared.py index a02bc9b..9b9bd92 100644 --- a/sphinx_design/shared.py +++ b/sphinx_design/shared.py @@ -1,6 +1,7 @@ """Shared constants and functions.""" -from typing import List, Optional, Sequence +from collections.abc import Sequence +from typing import Optional from docutils import nodes from docutils.parsers.rst import directives @@ -55,7 +56,7 @@ def _margin_or_padding_option( argument: Optional[str], class_prefix: str, allowed: Sequence[str], -) -> List[str]: +) -> list[str]: """Validate the margin/padding is one (all) or four (top bottom left right) integers, between 0 and 5 or 'auto'. """ @@ -77,7 +78,7 @@ def _margin_or_padding_option( ) -def margin_option(argument: Optional[str]) -> List[str]: +def margin_option(argument: Optional[str]) -> list[str]: """Validate the margin is one (all) or four (top bottom left right) integers, between 0 and 5 or 'auto'. """ @@ -86,14 +87,14 @@ def margin_option(argument: Optional[str]) -> List[str]: ) -def padding_option(argument: Optional[str]) -> List[str]: +def padding_option(argument: Optional[str]) -> list[str]: """Validate the padding is one (all) or four (top bottom left right) integers, between 0 and 5. """ return _margin_or_padding_option(argument, "sd-p", ("0", "1", "2", "3", "4", "5")) -def text_align(argument: Optional[str]) -> List[str]: +def text_align(argument: Optional[str]) -> list[str]: """Validate the text align is left, right, center or justify.""" value = directives.choice(argument, ["left", "right", "center", "justify"]) return [f"sd-text-{value}"] diff --git a/sphinx_design/tabs.py b/sphinx_design/tabs.py index 96d0f73..5fa915a 100644 --- a/sphinx_design/tabs.py +++ b/sphinx_design/tabs.py @@ -1,5 +1,3 @@ -from typing import List - from docutils import nodes from docutils.parsers.rst import directives from sphinx.application import Sphinx @@ -30,7 +28,7 @@ class TabSetDirective(SphinxDirective): "class": directives.class_option, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" self.assert_has_content() tab_set = create_component( @@ -81,7 +79,7 @@ class TabItemDirective(SphinxDirective): "class-content": directives.class_option, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" self.assert_has_content() if not is_component(self.state_machine.node, "tab-set"): @@ -130,7 +128,7 @@ class TabSetCodeDirective(SphinxDirective): "class-item": directives.class_option, } - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """Run the directive.""" self.assert_has_content() tab_set = create_component( diff --git a/tests/conftest.py b/tests/conftest.py index abc06f1..409f586 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,6 @@ import os from pathlib import Path -from typing import Any, Dict, Optional +from typing import Any, Optional from docutils import nodes import pytest @@ -69,7 +69,7 @@ def get_doctree( @pytest.fixture() def sphinx_builder(tmp_path: Path, make_app, monkeypatch): def _create_project( - buildername: str = "html", conf_kwargs: Optional[Dict[str, Any]] = None + buildername: str = "html", conf_kwargs: Optional[dict[str, Any]] = None ): src_path = tmp_path / "srcdir" src_path.mkdir() diff --git a/tox.ini b/tox.ini index cd3994a..e1bc78c 100644 --- a/tox.ini +++ b/tox.ini @@ -4,12 +4,12 @@ # then run `tox` or `tox -- {pytest args}` # run in parallel using `tox -p` [tox] -envlist = py38 +envlist = py39 [testenv] usedevelop = true -[testenv:py{38,39,310,311}] +[testenv:py{39,310,311,312}] description = Run unit tests with this Python version extras = testing