From 6191f20c54bb833ca5430c41ce18813d26e70c0d Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sat, 21 Dec 2024 06:05:09 +0100 Subject: [PATCH] =?UTF-8?q?=EF=81=AD=20Drop=20support=20for=20Python=203.6?= =?UTF-8?q?,=203.7,=203.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref: https://endoflife.date/python --- .github/workflows/ci-cd.yml | 36 ---------- .github/workflows/reusable-linters.yml | 10 --- .mypy.ini | 2 +- .pre-commit-config.yaml | 80 +---------------------- docs/change-notes-layout.rst | 2 +- docs/conf.py | 1 - nitpick-style.toml | 3 +- setup.cfg | 8 +-- src/sphinxcontrib/towncrier/_compat.py | 35 ---------- src/sphinxcontrib/towncrier/_towncrier.py | 8 +-- src/sphinxcontrib/towncrier/_version.py | 4 +- src/sphinxcontrib/towncrier/ext.py | 8 +-- tests/units_test.py | 4 +- 13 files changed, 17 insertions(+), 184 deletions(-) delete mode 100644 src/sphinxcontrib/towncrier/_compat.py diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index ab696ad..4f57e74 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -71,7 +71,6 @@ env: PUBLISHING_TO_TESTPYPI_ENABLED: true PY_COLORS: 1 # Recognized by the `py` package, dependency of `pytest` PYTHONIOENCODING: utf-8 - PYTHONLEGACYWINDOWSSTDIO: 1 # Python 3.6 hack PYTHONUTF8: 1 TOX_PARALLEL_NO_SPINNER: 1 # Disable tox's parallel run spinner animation TOX_TESTENV_PASSENV: >- # Make tox-wrapped tools see color requests @@ -574,9 +573,6 @@ jobs: - >- 3.10 - 3.9 - - 3.8 - - 3.7 - - 3.6 os: - ubuntu-24.04 - ubuntu-20.04 @@ -584,28 +580,6 @@ jobs: - macos-13 - windows-latest exclude: - - os: macos-14 - python-version: 3.6 # EOL, only provided for older OSs - - os: macos-14 - python-version: 3.7 # EOL, only provided for older OSs - - os: ubuntu-24.04 - python-version: 3.6 # EOL, only provided for older OSs - - os: ubuntu-24.04 - python-version: 3.7 # EOL, only provided for older OSs - - python-version: 3.6 - towncrier-version: 22.8.0 # Dropped support for Python 3.6 - - python-version: 3.6 - towncrier-version: 22.12.0 # Does not support Python 3.6 - - python-version: 3.6 - towncrier-version: 23.6.0 # Dropped support for Python 3.6 - - python-version: 3.6 - towncrier-version: 23.11.0 # Does not support Python 3.6 - - python-version: 3.7 - towncrier-version: 23.11.0 # Does not support Python 3.7 - - python-version: 3.6 - towncrier-version: 24.8.0 # Does not support Python 3.6 - - python-version: 3.7 - towncrier-version: 24.8.0 # Does not support Python 3.7 - python-version: ~3.12.0-0 towncrier-version: 19.2.0 # Does not support Python 3.12 - python-version: ~3.12.0-0 @@ -690,16 +664,6 @@ jobs: run: | python -m pip freeze --all - - name: Patch tox.ini for Python 3.6 under Windows - if: >- - runner.os == 'Windows' - && matrix.python-version == '3.6' - run: >- - sed -i - 's/^package_env\(\s\)\?=.*/package_env = py36-win-dummy/g' - tox.ini - shell: bash - - name: Initialize tox envs run: >- python diff --git a/.github/workflows/reusable-linters.yml b/.github/workflows/reusable-linters.yml index fe81e4d..5b155c0 100644 --- a/.github/workflows/reusable-linters.yml +++ b/.github/workflows/reusable-linters.yml @@ -25,7 +25,6 @@ jobs: - >- 3.10 - 3.9 - - 3.8 os: - ubuntu-latest toxenv: @@ -33,15 +32,6 @@ jobs: - build-dists skipped-pre-commit-check: - '' - exclude: - - toxenv: lint - python-version: 3.8 # WPS does not work under Python 3.8 - skipped-pre-commit-check: '' - include: - - toxenv: lint - os: ubuntu-latest - python-version: 3.8 # WPS does not work under Python 3.8 - skipped-pre-commit-check: flake8 env: PY_COLORS: 1 diff --git a/.mypy.ini b/.mypy.ini index 3a71ce2..6a70f52 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -1,5 +1,5 @@ [mypy] -python_version = 3.6 +python_version = 3.8 color_output = true error_summary = true files = diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 83177d8..bad8769 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,36 +42,6 @@ repos: language: system files: >- ^tests/__init__\.py$ - - id: enforced-versions - name: Verify that enforced hook versions stay unchanged - description: >- - This is a sanity check and fixer that makes sure that - the some hook versions in this file remain matching the - corresponding request in the `# enforce-version` comment. - # Using Python here because using - # shell test does not always work in CIs: - entry: >- - python -c 'import pathlib, re, sys; - pre_commit_config = pathlib.Path(sys.argv[1]); - cfg_txt = pre_commit_config.read_text(); - new_cfg_txt = re.sub( - r"(?P\s+)rev:\s+(?:v?\d+\.\d+\.\d+)\s+" - r"#\s+enforce-version:\s(?Pv?\d+\.\d+\.\d+)" - r"[ \t\f\v]*", - r"\grev: \g " - r"# enforce-version: \g", - cfg_txt, - ); - cfg_txt != new_cfg_txt and - pre_commit_config.write_text(new_cfg_txt) and - sys.exit(1) - ' - pass_filenames: true - language: system - files: >- - ^\.pre-commit-config\.ya?ml$ - types: - - yaml - repo: https://github.com/asottile/add-trailing-comma.git rev: v3.1.0 @@ -79,11 +49,11 @@ repos: - id: add-trailing-comma - repo: https://github.com/asottile/pyupgrade.git - rev: v3.16.0 + rev: v3.19.1 hooks: - id: pyupgrade args: - - --py36-plus + - --py38-plus - repo: https://github.com/PyCQA/isort.git rev: 5.13.2 @@ -287,51 +257,5 @@ repos: - --cobertura-xml-report=.tox/.tmp/.test-results/mypy--py-3.9 - --html-report=.tox/.tmp/.test-results/mypy--py-3.9 pass_filenames: false -- repo: https://github.com/pre-commit/mirrors-mypy.git - # NOTE: This is kept at v1.5.1 until we stop supporting Python 3.6. - rev: v1.5.1 # enforce-version: v1.5.1 - hooks: - - id: mypy - alias: mypy-py37 - name: MyPy, for Python 3.7 - additional_dependencies: - - importlib_metadata - - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` - - pytest ~= 7.4.4 # last to have Python 3.6-compatible syntax - - Sphinx >= 3.1.2, < 6 - - types-colorama - - types-Pillow - - types-Pygments - - types-pytz - - types-setuptools - - types-typed-ast - - typing-extensions # Literal - args: - - --python-version=3.7 - - --txt-report=.tox/.tmp/.test-results/mypy--py-3.7 - - --cobertura-xml-report=.tox/.tmp/.test-results/mypy--py-3.7 - - --html-report=.tox/.tmp/.test-results/mypy--py-3.7 - pass_filenames: false - - id: mypy - alias: mypy-py36 - name: MyPy, for Python 3.6 - additional_dependencies: - - importlib_metadata - - lxml # dep of `--txt-report`, `--cobertura-xml-report` & `--html-report` - - pytest ~= 7.4.4 # last to have Python 3.6-compatible syntax - - Sphinx >= 3.1.2, < 6 - - types-colorama - - types-Pillow - - types-Pygments - - types-pytz - - types-setuptools - - types-typed-ast - - typing-extensions # Literal - args: - - --python-version=3.6 - - --txt-report=.tox/.tmp/.test-results/mypy--py-3.6 - - --cobertura-xml-report=.tox/.tmp/.test-results/mypy--py-3.6 - - --html-report=.tox/.tmp/.test-results/mypy--py-3.6 - pass_filenames: false ... diff --git a/docs/change-notes-layout.rst b/docs/change-notes-layout.rst index 3de4479..c197c23 100644 --- a/docs/change-notes-layout.rst +++ b/docs/change-notes-layout.rst @@ -324,7 +324,7 @@ like failing the build on any warnings and having nice URLs. image: latest python: - version: 3.8 + version: 3.13 install: - requirements: docs/requirements.txt ... diff --git a/docs/conf.py b/docs/conf.py index 187406d..dc2baeb 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,4 @@ # pylint: disable=invalid-name -# Requires Python 3.6+ # Ref: https://www.sphinx-doc.org/en/master/usage/configuration.html """Configuration for the Sphinx documentation generator.""" diff --git a/nitpick-style.toml b/nitpick-style.toml index 2189f89..47de6a3 100644 --- a/nitpick-style.toml +++ b/nitpick-style.toml @@ -6,8 +6,7 @@ include = [ # "py://nitpick/resources/python/flake8", # "py://nitpick/resources/python/github-workflow", - "gh://andreoliwa/nitpick@8a1d2bd0/src/nitpick/resources/python/hooks.toml", # NOTE: Needed for as long as Python 3.6 remains supported - # "py://nitpick/resources/python/pre-commit-hooks", # FIXME: Uncomment as soon as Python 3.6 support is dropped + # "py://nitpick/resources/python/pre-commit-hooks", # "py://nitpick/resources/python/isort", # Requires config to be in `setup.cfg` so not for us # "py://nitpick/resources/python/mypy", # Requires CLI args but we have that in `mypy.ini` # "py://nitpick/resources/python/pylint", # Makes several bad suggestions diff --git a/setup.cfg b/setup.cfg index 35195d0..d3d27c1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,7 +3,7 @@ # NOTE: tag "py2.py3" which implies (and tricks pip into thinking) that this # NOTE: wheel contains Python 2 compatible code. This is not true and conflicts # NOTE: with the "Requires-Python" field in the metadata that says that we only -# NOTE: support Python 3.6+. +# NOTE: support Python 3.9+. # NOTE: We need to keep it at "0" which will produce wheels tagged with "py3" # NOTE: when built under Python 3. # Ref: https://github.com/pypa/packaging.python.org/issues/726 @@ -37,9 +37,6 @@ classifiers = Operating System :: OS Independent - Programming Language :: Python :: 3.6 - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 @@ -54,13 +51,12 @@ classifiers = [options] include_package_data = True install_requires = - importlib-metadata >= 4; python_version < '3.8' sphinx towncrier >= 19.2 package_dir = = src packages = find_namespace: -python_requires = >=3.6 +python_requires = >= 3.9 zip_safe = True [options.packages.find] diff --git a/src/sphinxcontrib/towncrier/_compat.py b/src/sphinxcontrib/towncrier/_compat.py deleted file mode 100644 index 8ebc8c2..0000000 --- a/src/sphinxcontrib/towncrier/_compat.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Cross-Python compatibility helpers.""" - -import sys -from typing import Iterable - - -if sys.version_info >= (3, 8): - from importlib.metadata import ( # noqa: WPS433 - version as importlib_metadata_get_version, - ) - from shlex import join as shlex_join # noqa: WPS433 -else: - # Python 3.7 and lower: - from shlex import quote as _shlex_quote # noqa: WPS433 - - # pylint: disable-next=line-too-long - from importlib_metadata import ( # type: ignore[no-redef, unused-ignore] # noqa: B950, LN002, WPS433, WPS440 # `unused-ignore` is only needed under Python 3.6 - version as importlib_metadata_get_version, - ) - - def shlex_join(split_command: Iterable[str]) -> str: # noqa: WPS440 - """Return a shell-escaped string from *split_command*.""" - return ' '.join(_shlex_quote(arg) for arg in split_command) - - -if sys.version_info[:2] < (3, 8): - from typing_extensions import Literal # noqa: WPS433 -else: - from typing import Literal # noqa: WPS433, WPS440 - -__all__ = ( # noqa: WPS410 - 'importlib_metadata_get_version', - 'Literal', - 'shlex_join', -) diff --git a/src/sphinxcontrib/towncrier/_towncrier.py b/src/sphinxcontrib/towncrier/_towncrier.py index ecba95e..db5c436 100644 --- a/src/sphinxcontrib/towncrier/_towncrier.py +++ b/src/sphinxcontrib/towncrier/_towncrier.py @@ -1,16 +1,10 @@ """Towncrier related shims.""" -from contextlib import suppress as _suppress_exception +from dataclasses import asdict as _dataclass_to_dict from pathlib import Path from typing import Any, Dict, Union -with _suppress_exception(ImportError): - # NOTE: This will not raise an exception under Python >= 3.7, and is only - # NOTE: needed for Towncrier >= 22.12.0rc1 which doesn't support Python 3.6 - from dataclasses import asdict as _dataclass_to_dict # noqa: WPS433 - - try: # Towncrier >= 22.8.0rc1 # pylint: disable=import-error,no-name-in-module diff --git a/src/sphinxcontrib/towncrier/_version.py b/src/sphinxcontrib/towncrier/_version.py index 86a5e5e..28aba91 100644 --- a/src/sphinxcontrib/towncrier/_version.py +++ b/src/sphinxcontrib/towncrier/_version.py @@ -4,7 +4,9 @@ # pylint: disable=unused-import from ._scm_version import version as __version__ # noqa: WPS433, WPS436 except ImportError: - from ._compat import importlib_metadata_get_version # noqa: WPS433, WPS436 + from importlib.metadata import ( # noqa: WPS433, WPS436 + version as importlib_metadata_get_version, + ) __version__ = importlib_metadata_get_version( # noqa: WPS440 'sphinxcontrib-towncrier', diff --git a/src/sphinxcontrib/towncrier/ext.py b/src/sphinxcontrib/towncrier/ext.py index cc574c5..1a21877 100644 --- a/src/sphinxcontrib/towncrier/ext.py +++ b/src/sphinxcontrib/towncrier/ext.py @@ -1,12 +1,13 @@ """Sphinx extension for injecting an unreleased changelog into docs.""" +import shlex import subprocess # noqa: S404 import sys from contextlib import suppress as suppress_exceptions from functools import lru_cache from pathlib import Path -from typing import Dict, List, Optional, Set, Tuple, Union +from typing import Dict, List, Literal, Optional, Set, Tuple, Union from sphinx.application import Sphinx from sphinx.config import Config as SphinxConfig @@ -24,7 +25,6 @@ from docutils import statemachine # pylint: disable=wrong-import-order from docutils.parsers.rst.states import RSTState -from ._compat import Literal, shlex_join # noqa: WPS436 from ._data_transformers import ( # noqa: WPS436 escape_project_version_rst_substitution, ) @@ -68,11 +68,11 @@ def _get_changelog_draft_entries( TOWNCRIER_DRAFT_CMD + extra_cli_args, cwd=str(working_dir) if working_dir else None, stderr=subprocess.PIPE, - universal_newlines=True, # a "text" alias exists since Python 3.7 + text=True, ).strip() except subprocess.CalledProcessError as proc_exc: - cmd = shlex_join(proc_exc.cmd) + cmd = shlex.join(proc_exc.cmd) stdout = proc_exc.stdout or '[No output]' stderr = proc_exc.stderr or '[No output]' raise RuntimeError( diff --git a/tests/units_test.py b/tests/units_test.py index ab5c1bc..092ba9f 100644 --- a/tests/units_test.py +++ b/tests/units_test.py @@ -1,11 +1,11 @@ """Unit tests of the extension bits.""" +import shlex import sys import typing import pytest -from sphinxcontrib.towncrier._compat import shlex_join from sphinxcontrib.towncrier.ext import _get_changelog_draft_entries @@ -78,7 +78,7 @@ def test_towncrier_draft_generation_failure_msg( ) escaped_failing_cmd = ( # This is necessary because it's used in a regexp - shlex_join(failing_cmd). + shlex.join(failing_cmd). replace('\\', r'\\'). replace('(', r'\('). replace(')', r'\)')