diff --git a/.cirrus.yml b/.cirrus.yml index 57c953b..8dcda21 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -85,7 +85,7 @@ check_task: name: check (Linux - 3.10) alias: check depends_on: [build] - container: {image: "python:3.10-bullseye"} # most recent => better types + container: {image: "python:3.10-bullseye"} # 3.11+ don't understand some code paths dist_cache: {folder: dist, fingerprint_script: echo $CIRRUS_BUILD_ID} # download <<: *task-template install_script: pip install tox @@ -93,11 +93,6 @@ check_task: linux_task: matrix: - - name: test (Linux - 3.6) - container: {image: "python:3.6-bullseye"} - allow_failures: true # EoL - - name: test (Linux - 3.7) - container: {image: "python:3.7-bullseye"} - name: test (Linux - 3.8) container: {image: "python:3.8-bullseye"} - name: test (Linux - 3.9) @@ -107,7 +102,7 @@ linux_task: - name: test (Linux - 3.11) container: {image: "python:3.11-bullseye"} - name: test (Linux - 3.12) - container: {image: "python:3.12-rc-bullseye"} + container: {image: "python:3.12-bullseye"} allow_failures: true # Experimental install_script: - python -m pip install --upgrade pip tox pipx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0304b23..5c0ffb1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,8 @@ on: # relevant branches and tags. Other branches can be checked via PRs. # branches: [main] tags: ['v[0-9]*', '[0-9]+.[0-9]+*'] # Match tags that resemble a version - # pull_request: # Run in every PR + pull_request: + paths: ['.github/workflows/ci.yml'] # On PRs only when this file itself is changed workflow_dispatch: # Allow manually triggering the workflow schedule: # Run roughly every 15 days at 00:00 UTC @@ -62,8 +63,8 @@ jobs: strategy: matrix: python: - - "3.7" # oldest Python supported by PSF - - "3.11" # newest Python that is stable + - "3.8" # oldest Python supported by PSF + - "3.12" # newest Python that is stable platform: - ubuntu-latest - macos-13 diff --git a/.ruff.toml b/.ruff.toml index e2fce3b..a36942a 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -1,6 +1,6 @@ # --- General config --- src = ["src"] -target-version = "py37" +target-version = "py38" # --- Linting config --- [lint] diff --git a/setup.cfg b/setup.cfg index ad38f9b..2863019 100644 --- a/setup.cfg +++ b/setup.cfg @@ -47,15 +47,13 @@ package_dir = =src # Require a min/specific Python version (comma-separated conditions) -python_requires = >=3.6 +python_requires = >=3.8 # Add here dependencies of your project (line-separated), e.g. requests>=2.2,<3.0. # Version specifiers like >=2.2,<3.0 avoid problems due to API changes in # new major versions. This works if the required packages follow Semantic Versioning. # For more information, check out https://semver.org/. install_requires = - importlib-metadata; python_version<"3.8" - importlib-resources; python_version<"3.7" fastjsonschema>=2.16.2,<=3 diff --git a/src/validate_pyproject/__init__.py b/src/validate_pyproject/__init__.py index fbaff2e..be9fa4e 100644 --- a/src/validate_pyproject/__init__.py +++ b/src/validate_pyproject/__init__.py @@ -1,10 +1,4 @@ -import sys - -if sys.version_info[:2] >= (3, 8): - # TODO: Import directly (no need for conditional) when `python_requires = >= 3.8` - from importlib.metadata import PackageNotFoundError, version # pragma: no cover -else: - from importlib_metadata import PackageNotFoundError, version # pragma: no cover +from importlib.metadata import PackageNotFoundError, version # pragma: no cover try: # Change here if project is renamed and does not equal the package name diff --git a/src/validate_pyproject/api.py b/src/validate_pyproject/api.py index 2c88ef2..887eaf7 100644 --- a/src/validate_pyproject/api.py +++ b/src/validate_pyproject/api.py @@ -4,7 +4,6 @@ import json import logging -import sys import typing from enum import Enum from functools import partial, reduce @@ -35,14 +34,11 @@ try: # pragma: no cover - if sys.version_info[:2] < (3, 7) or typing.TYPE_CHECKING: # See #22 - from importlib_resources import files - else: - from importlib.resources import files + from importlib.resources import files def read_text(package: Union[str, ModuleType], resource: str) -> str: """:meta private:""" - return files(package).joinpath(resource).read_text(encoding="utf-8") # type: ignore[no-any-return] + return files(package).joinpath(resource).read_text(encoding="utf-8") except ImportError: # pragma: no cover from importlib.resources import read_text diff --git a/src/validate_pyproject/plugins/__init__.py b/src/validate_pyproject/plugins/__init__.py index 16393eb..f39175d 100644 --- a/src/validate_pyproject/plugins/__init__.py +++ b/src/validate_pyproject/plugins/__init__.py @@ -5,29 +5,14 @@ .. _entry point: https://setuptools.readthedocs.io/en/latest/userguide/entry_point.html """ -import sys import typing +from importlib.metadata import EntryPoint, entry_points from string import Template from textwrap import dedent -from typing import Any, Callable, Iterable, List, Optional +from typing import Any, Callable, Iterable, List, Optional, Protocol from .. import __version__ - -if sys.version_info[:2] >= (3, 8): # pragma: no cover - # TODO: Import directly (no need for conditional) when `python_requires = >= 3.8` - from importlib.metadata import EntryPoint, entry_points -else: # pragma: no cover - from importlib_metadata import EntryPoint, entry_points - -if typing.TYPE_CHECKING: - from ..types import Plugin, Schema - - if sys.version_info < (3, 8): - from typing_extensions import Protocol - else: - from typing import Protocol -else: - Protocol = object +from ..types import Plugin, Schema ENTRYPOINT_GROUP = "validate_pyproject.tool_schema" @@ -40,7 +25,7 @@ def id(self) -> str: ... def tool(self) -> str: ... @property - def schema(self) -> "Schema": ... + def schema(self) -> Schema: ... @property def help_text(self) -> str: ... @@ -50,7 +35,7 @@ def fragment(self) -> str: ... class PluginWrapper: - def __init__(self, tool: str, load_fn: "Plugin"): + def __init__(self, tool: str, load_fn: Plugin): self._tool = tool self._load_fn = load_fn @@ -63,7 +48,7 @@ def tool(self) -> str: return self._tool @property - def schema(self) -> "Schema": + def schema(self) -> Schema: return self._load_fn(self.tool) @property diff --git a/src/validate_pyproject/pre_compile/__init__.py b/src/validate_pyproject/pre_compile/__init__.py index 9cde18e..efa6d00 100644 --- a/src/validate_pyproject/pre_compile/__init__.py +++ b/src/validate_pyproject/pre_compile/__init__.py @@ -1,6 +1,6 @@ import logging import os -import sys +from importlib import metadata as _M from pathlib import Path from types import MappingProxyType from typing import TYPE_CHECKING, Dict, Mapping, Optional, Sequence, Union @@ -9,11 +9,6 @@ from .. import api, dist_name, types -if sys.version_info[:2] >= (3, 8): # pragma: no cover - from importlib import metadata as _M -else: # pragma: no cover - import importlib_metadata as _M - if TYPE_CHECKING: # pragma: no cover from ..plugins import PluginProtocol diff --git a/src/validate_pyproject/pre_compile/cli.py b/src/validate_pyproject/pre_compile/cli.py index 6694b7b..985ba74 100644 --- a/src/validate_pyproject/pre_compile/cli.py +++ b/src/validate_pyproject/pre_compile/cli.py @@ -17,13 +17,8 @@ if sys.platform == "win32": # pragma: no cover from subprocess import list2cmdline as arg_join -elif sys.version_info[:2] >= (3, 8): # pragma: no cover - from shlex import join as arg_join else: # pragma: no cover - from shlex import quote - - def arg_join(args: Sequence[str]) -> str: - return " ".join(quote(x) for x in args) + from shlex import join as arg_join _logger = logging.getLogger(__package__) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index a5e8d01..1f07dec 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,8 +1,7 @@ # The code in this module is mostly borrowed/adapted from PyScaffold and was originally # published under the MIT license # The original PyScaffold license can be found in 'NOTICE.txt' - -import sys +from importlib.metadata import EntryPoint # pragma: no cover import pytest @@ -15,13 +14,6 @@ ) -if sys.version_info[:2] >= (3, 8): - # TODO: Import directly (no need for conditional) when `python_requires = >= 3.8` - from importlib.metadata import EntryPoint # pragma: no cover -else: - from importlib_metadata import EntryPoint # pragma: no cover - - def test_load_from_entry_point__error(): # This module does not exist, so Python will have some trouble loading it # EntryPoint(name, value, group)