diff --git a/.github/workflows/pyupgrade.yml b/.github/workflows/pyupgrade.yml index d7bbd3884..a9f1d762f 100644 --- a/.github/workflows/pyupgrade.yml +++ b/.github/workflows/pyupgrade.yml @@ -19,5 +19,5 @@ jobs: from pyupgrade._main import main from glob import glob files = glob('**/*.py', recursive=True) - sys.exit(main(files + ['--py37-plus'])) + sys.exit(main(files + ['--py38-plus'])) " || ( git diff ; false ) diff --git a/action/tests/test_main.py b/action/tests/test_main.py index 20db3e6e5..e0d726154 100644 --- a/action/tests/test_main.py +++ b/action/tests/test_main.py @@ -220,9 +220,8 @@ def test_runs_darker(tmp_path, env, expect): run_module("main") darker = str(tmp_path / ".darker-env" / BIN / "darker") - # We can change `c[0][0][0]` to `c.args[0][0]` after dropping Python 3.7 support. # This gets the first list item of the first positional argument to the `run` call. - assert darker in [c[0][0][0] for c in main_patch.subprocess.run.call_args_list] + assert darker in [c.args[0][0] for c in main_patch.subprocess.run.call_args_list] def test_error_if_pip_fails(tmp_path, capsys): diff --git a/release_tools/bump_version.py b/release_tools/bump_version.py index 895c852ef..9867a4ac4 100644 --- a/release_tools/bump_version.py +++ b/release_tools/bump_version.py @@ -22,19 +22,13 @@ import sys from datetime import date from pathlib import Path -from typing import Dict, List, Match, Optional, Tuple +from typing import Dict, List, Match, Optional, Tuple, TypedDict from warnings import warn import click import requests from packaging.version import Version -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - - VERSION_PY_PATH = "src/darker/version.py" diff --git a/release_tools/update_contributors.py b/release_tools/update_contributors.py index 74d144230..7acbad12a 100644 --- a/release_tools/update_contributors.py +++ b/release_tools/update_contributors.py @@ -14,14 +14,13 @@ # pylint: disable=too-few-public-methods,abstract-method import re -import sys import xml.etree.ElementTree as ET # nosec from dataclasses import dataclass from functools import total_ordering from itertools import groupby from pathlib import Path from textwrap import dedent, indent -from typing import Any, Dict, Iterable, List, MutableMapping, Optional, cast +from typing import Any, Dict, Iterable, List, MutableMapping, Optional, TypedDict, cast import click import defusedxml.ElementTree @@ -30,11 +29,6 @@ from requests_cache.session import CachedSession from ruamel import yaml -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - @click.group() def cli() -> None: diff --git a/setup.cfg b/setup.cfg index 1c3c919ed..e17d91bc4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,6 @@ description = Apply Black formatting only in regions changed since last commit long_description_content_type = text/x-rst classifiers = Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 @@ -30,10 +29,9 @@ install_requires = # NOTE: remember to keep `constraints-oldest.txt` in sync with these black>=21.5b1,<24.2 # upper limit until incompatibility fixed toml>=0.10.0 - typing-extensions ; python_version < "3.8" # NOTE: remember to keep `.github/workflows/python-package.yml` in sync # with the minimum required Python version -python_requires = >=3.7 +python_requires = >=3.8 [options.packages.find] where = src diff --git a/src/darker/black_diff.py b/src/darker/black_diff.py index 77c962b19..4fc42963c 100644 --- a/src/darker/black_diff.py +++ b/src/darker/black_diff.py @@ -34,9 +34,8 @@ """ import inspect import logging -import sys from pathlib import Path -from typing import Collection, Optional, Pattern, Set, Tuple, Union +from typing import Collection, Optional, Pattern, Set, Tuple, TypedDict, Union # `FileMode as Mode` required to satisfy mypy==0.782. Strange. from black import FileMode as Mode @@ -57,11 +56,6 @@ from darker.config import ConfigurationError from darker.utils import TextDocument -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - __all__ = ["BlackConfig", "Mode", "run_black"] logger = logging.getLogger(__name__) diff --git a/src/darker/config.py b/src/darker/config.py index 702c1f0a3..02f47584c 100644 --- a/src/darker/config.py +++ b/src/darker/config.py @@ -2,21 +2,15 @@ import logging import os -import sys from argparse import ArgumentParser, Namespace from dataclasses import dataclass, field from pathlib import Path -from typing import Dict, Iterable, List, Optional, Set, Union, cast +from typing import Dict, Iterable, List, Optional, Set, TypedDict, Union, cast import toml from darker.black_compat import find_project_root -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - class TomlArrayLinesEncoder(toml.TomlEncoder): # type: ignore """Format TOML so list items are each on their own line""" diff --git a/src/darker/git.py b/src/darker/git.py index 160b745b8..370a92777 100644 --- a/src/darker/git.py +++ b/src/darker/git.py @@ -29,19 +29,6 @@ from darker.multiline_strings import get_multiline_string_ranges from darker.utils import GIT_DATEFORMAT, TextDocument -if sys.version_info < (3, 8): - - def shlex_join(split_command: Iterable[str]) -> str: - """Backport `shlex.join` for Python 3.7 - - :param split_command: The elements on the command line - :return: The command line as one string, with appropriate quoting - - """ - return " ".join(shlex.quote(arg) for arg in split_command) - -else: - shlex_join = shlex.join logger = logging.getLogger(__name__) @@ -338,7 +325,7 @@ def _git_check_output( encoding: Optional[str] = None, ) -> Union[str, bytes]: """Log command line, run Git, return stdout, exit with 123 on error""" - logger.debug("[%s]$ git %s", cwd, shlex_join(cmd)) + logger.debug("[%s]$ git %s", cwd, shlex.join(cmd)) try: return check_output( # nosec ["git"] + cmd, diff --git a/src/darker/import_sorting.py b/src/darker/import_sorting.py index 38bb84090..95d3f7867 100644 --- a/src/darker/import_sorting.py +++ b/src/darker/import_sorting.py @@ -1,9 +1,8 @@ """Helpers for invoking ``isort`` and acting on its output""" import logging -import sys from pathlib import Path -from typing import Any, Collection, List, Optional +from typing import Any, Collection, List, Optional, TypedDict from darker.black_compat import find_project_root from darker.diff import diff_chunks @@ -11,12 +10,6 @@ from darker.git import EditedLinenumsDiffer from darker.utils import DiffChunk, TextDocument, glob_any -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - - try: import isort diff --git a/src/darker/linting.py b/src/darker/linting.py index 1e285d68f..fcd514266 100644 --- a/src/darker/linting.py +++ b/src/darker/linting.py @@ -51,10 +51,9 @@ git_get_content_at_revision, git_get_root, git_rev_parse, - shlex_join, ) from darker.highlighting import colorize -from darker.utils import WINDOWS, fix_py37_win_tempdir_permissions +from darker.utils import WINDOWS logger = logging.getLogger(__name__) @@ -300,7 +299,7 @@ def _check_linter_output( else: cmdline_parts = cmdline cmdline_and_paths = cmdline_parts + [str(path) for path in sorted(paths)] - logger.debug("[%s]$ %s", root, shlex_join(cmdline_and_paths)) + logger.debug("[%s]$ %s", root, shlex.join(cmdline_and_paths)) with Popen( # nosec cmdline_and_paths, stdout=PIPE, @@ -336,7 +335,7 @@ def run_linter( # pylint: disable=too-many-locals cmdline_str = cmdline else: linter = cmdline[0] - cmdline_str = shlex_join(cmdline) + cmdline_str = shlex.join(cmdline) # 10. run a linter subprocess for files mentioned on the command line which may be # modified or unmodified, to get current linting status in the working tree # (steps 10.-12. are optional) @@ -534,7 +533,6 @@ def _get_messages_from_linters_for_baseline( make_linter_env(root, rev1_commit), normalize_whitespace, ) - fix_py37_win_tempdir_permissions(tmpdir) return result diff --git a/src/darker/tests/conftest.py b/src/darker/tests/conftest.py index 2760ec90d..88cf210fb 100644 --- a/src/darker/tests/conftest.py +++ b/src/darker/tests/conftest.py @@ -10,7 +10,6 @@ from black import find_project_root as black_find_project_root from darker.git import _git_check_output_lines, git_get_version -from darker.utils import fix_py37_win_tempdir_permissions class GitRepoFixture: @@ -122,8 +121,6 @@ def git_repo(tmp_path, monkeypatch): yield repository - fix_py37_win_tempdir_permissions(repository.root) - @pytest.fixture def find_project_root_cache_clear(): diff --git a/src/darker/utils.py b/src/darker/utils.py index 812b3a302..a992240fc 100644 --- a/src/darker/utils.py +++ b/src/darker/utils.py @@ -2,13 +2,12 @@ import io import logging -import os import sys import tokenize from datetime import datetime from itertools import chain from pathlib import Path -from typing import Collection, Iterable, List, Tuple, Union +from typing import Collection, Iterable, List, Tuple logger = logging.getLogger(__name__) @@ -240,27 +239,3 @@ def glob_any(path: Path, patterns: Collection[str]) -> bool: """ return any(path.glob(pattern) for pattern in patterns) - - -def fix_py37_win_tempdir_permissions(dirpath: Union[str, Path]) -> None: - """Work around a `tempfile` clean-up issue on Windows with Python 3.7 - - Call this before exiting a ``with TemporaryDirectory():`` block or in teardown for - a Pytest fixture which creates a temporary directory. - - See discussion in https://github.com/akaihola/darker/pull/393 - Solution borrowed from https://github.com/python/cpython/pull/10320 - - :param dirpath: The root path of the temporary directory - - """ - if not WINDOWS or sys.version_info >= (3, 8): - return - for root, dirs, files in os.walk(dirpath): - for name in dirs + files: - path = os.path.join(root, name) - try: - os.chflags(path, 0) # type: ignore[attr-defined] - except AttributeError: - pass - os.chmod(path, 0o700)