diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a819b7623c..e8a033ba22 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: rev: "0.12.1" hooks: - id: pyproject-fmt - additional_dependencies: ["tox>=4.6.1"] + additional_dependencies: ["tox>=4.6.3"] - repo: https://github.com/pre-commit/mirrors-prettier rev: "v3.0.0-alpha.9-for-vscode" hooks: diff --git a/docs/tox_conf.py b/docs/tox_conf.py index 6fe593f717..341c002b82 100644 --- a/docs/tox_conf.py +++ b/docs/tox_conf.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, cast +from typing import TYPE_CHECKING, Any, ClassVar, cast from docutils.nodes import Element, Node, Text, container, fully_normalize_name, literal, paragraph, reference, strong from docutils.parsers.rst.directives import flag, unchanged, unchanged_required @@ -11,6 +11,8 @@ from sphinx.util.logging import getLogger if TYPE_CHECKING: + from typing import Final + from docutils.parsers.rst.states import RSTState, RSTStateMachine LOGGER = getLogger(__name__) @@ -19,7 +21,7 @@ class ToxConfig(SphinxDirective): name = "conf" has_content = True - option_spec = { + option_spec: Final[ClassVar[dict[str, Any]]] = { "keys": unchanged_required, "version_added": unchanged, "version_changed": unchanged, diff --git a/pyproject.toml b/pyproject.toml index 427a0137d5..14f7befb2e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,10 +52,10 @@ dependencies = [ "chardet>=5.1", "colorama>=0.4.6", "filelock>=3.12.2", - 'importlib-metadata>=6.6; python_version < "3.8"', + 'importlib-metadata>=6.7; python_version < "3.8"', "packaging>=23.1", - "platformdirs>=3.5.3", - "pluggy>=1", + "platformdirs>=3.8", + "pluggy>=1.2", "pyproject-api>=1.5.2", 'tomli>=2.0.1; python_version < "3.11"', 'typing-extensions>=4.6.3; python_version < "3.8"', @@ -82,7 +82,7 @@ optional-dependencies.testing = [ "hatch-vcs>=0.3", "hatchling>=1.17.1", "psutil>=5.9.5", - "pytest>=7.3.2", + "pytest>=7.4", "pytest-cov>=4.1", "pytest-mock>=3.11.1", "pytest-xdist>=3.3.1", diff --git a/src/tox/config/cli/ini.py b/src/tox/config/cli/ini.py index e0cd717916..84de3a8c37 100644 --- a/src/tox/config/cli/ini.py +++ b/src/tox/config/cli/ini.py @@ -5,7 +5,7 @@ import os from configparser import ConfigParser from pathlib import Path -from typing import Any +from typing import TYPE_CHECKING, Any, ClassVar from platformdirs import user_config_dir @@ -13,12 +13,15 @@ from tox.config.loader.ini import IniLoader from tox.config.source.ini_section import CORE +if TYPE_CHECKING: + from typing import Final + DEFAULT_CONFIG_FILE = Path(user_config_dir("tox")) / "config.ini" class IniConfig: TOX_CONFIG_FILE_ENV_VAR = "TOX_USER_CONFIG_FILE" - STATE = {None: "failed to parse", True: "active", False: "missing"} + STATE: Final[ClassVar[dict[bool | None], str]] = {None: "failed to parse", True: "active", False: "missing"} def __init__(self) -> None: config_file = os.environ.get(self.TOX_CONFIG_FILE_ENV_VAR, None) diff --git a/src/tox/config/loader/str_convert.py b/src/tox/config/loader/str_convert.py index 919f064a2e..ddcdb5a54d 100644 --- a/src/tox/config/loader/str_convert.py +++ b/src/tox/config/loader/str_convert.py @@ -5,11 +5,14 @@ import sys from itertools import chain from pathlib import Path -from typing import Any, Iterator +from typing import TYPE_CHECKING, Any, Iterator from tox.config.loader.convert import Convert from tox.config.types import Command, EnvList +if TYPE_CHECKING: + from typing import Final + class StrConvert(Convert[str]): """A class converting string values to tox types.""" @@ -111,8 +114,8 @@ def to_env_list(value: str) -> EnvList: elements = list(chain.from_iterable(extend_factors(expr) for expr in value.split("\n"))) return EnvList(elements) - TRUTHFUL_VALUES = {"true", "1", "yes", "on"} - FALSE_VALUES = {"false", "0", "no", "off", ""} + TRUTHFUL_VALUES: Final[set[str]] = {"true", "1", "yes", "on"} + FALSE_VALUES: Final[set[str]] = {"false", "0", "no", "off", ""} VALID_BOOL = sorted(TRUTHFUL_VALUES | FALSE_VALUES) @staticmethod diff --git a/src/tox/report.py b/src/tox/report.py index 029e1e4e4d..ac71f8c1a1 100644 --- a/src/tox/report.py +++ b/src/tox/report.py @@ -8,10 +8,13 @@ from io import BytesIO, TextIOWrapper from pathlib import Path from threading import Thread, current_thread, enumerate, local -from typing import IO, Iterator, Tuple +from typing import IO, TYPE_CHECKING, ClassVar, Iterator, Tuple from colorama import Fore, Style, init +if TYPE_CHECKING: + from typing import Final + LEVELS = { 0: logging.CRITICAL, 1: logging.ERROR, @@ -29,7 +32,7 @@ class _LogThreadLocal(local): """A thread local variable that inherits values from its parent.""" - _ident_to_data: dict[int | None, str] = {} + _ident_to_data: Final[ClassVar[dict[int | None, str]]] = {} def __init__(self, out_err: OutErr) -> None: self.name = self._ident_to_data.get(getattr(current_thread(), "parent_ident", None), "ROOT") diff --git a/src/tox/tox_env/python/pip/req_file.py b/src/tox/tox_env/python/pip/req_file.py index ed4fc7c8ad..55d9d36e4c 100644 --- a/src/tox/tox_env/python/pip/req_file.py +++ b/src/tox/tox_env/python/pip/req_file.py @@ -8,12 +8,13 @@ if TYPE_CHECKING: from argparse import ArgumentParser, Namespace from pathlib import Path + from typing import Final class PythonDeps(RequirementsFile): # these options are valid in requirements.txt, but not via pip cli and # thus cannot be used in the testenv `deps` list - _illegal_options = ["hash"] + _illegal_options: Final[list[str]] = ["hash"] def __init__(self, raw: str, root: Path) -> None: super().__init__(root / "tox.ini", constraint=False) diff --git a/src/tox/util/spinner.py b/src/tox/util/spinner.py index c1b9cc94a0..e39d92a652 100644 --- a/src/tox/util/spinner.py +++ b/src/tox/util/spinner.py @@ -13,12 +13,13 @@ if TYPE_CHECKING: from types import TracebackType + from typing import Any, ClassVar, Final if sys.platform == "win32": # pragma: win32 cover import ctypes class _CursorInfo(ctypes.Structure): - _fields_ = [("size", ctypes.c_int), ("visible", ctypes.c_byte)] + _fields_: Final[ClassVar[list[tuple[str, Any]]]] = [("size", ctypes.c_int), ("visible", ctypes.c_byte)] def _file_support_encoding(chars: Sequence[str], file: IO[str]) -> bool: @@ -47,8 +48,8 @@ class Outcome(NamedTuple): class Spinner: CLEAR_LINE = "\033[K" max_width = 120 - UNICODE_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"] - ASCII_FRAMES = ["|", "-", "+", "x", "*"] + UNICODE_FRAMES: Final[ClassVar[list[str]]] = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"] + ASCII_FRAMES: Final[ClassVar[list[str]]] = ["|", "-", "+", "x", "*"] UNICODE_OUTCOME = Outcome(ok="✔", fail="✖", skip="⚠") ASCII_OUTCOME = Outcome(ok="+", fail="!", skip="?") diff --git a/tox.ini b/tox.ini index c18af66651..0e28277f24 100644 --- a/tox.ini +++ b/tox.ini @@ -52,7 +52,7 @@ commands = [testenv:type] description = run type check on code base deps = - mypy==1.3 + mypy==1.4.1 types-cachetools>=5.3.0.5 types-chardet>=5.0.4.6 commands =