diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 07c5185..8e4d6d6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: 'v4.4.0' + rev: 'v4.6.0' hooks: - id: end-of-file-fixer - id: trailing-whitespace @@ -27,27 +27,27 @@ repos: - id: mixed-line-ending args: [--fix=lf] - repo: https://github.com/asottile/pyupgrade - rev: 'v3.3.1' + rev: 'v3.17.0' hooks: - id: pyupgrade args: - - --py38-plus + - --py310-plus - repo: https://github.com/PyCQA/isort - rev: '5.12.0' + rev: '5.13.2' hooks: - id: isort - repo: https://github.com/psf/black - rev: '23.1.0' + rev: '24.8.0' hooks: - id: black - repo: https://github.com/PyCQA/flake8 - rev: '6.0.0' + rev: '7.1.1' hooks: - id: flake8 args: - --show-source - repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v1.10.0' + rev: 'v1.11.2' hooks: - id: mypy args: diff --git a/src/rapids_pre_commit_hooks/alpha_spec.py b/src/rapids_pre_commit_hooks/alpha_spec.py index dd3d982..df71aa7 100644 --- a/src/rapids_pre_commit_hooks/alpha_spec.py +++ b/src/rapids_pre_commit_hooks/alpha_spec.py @@ -16,7 +16,6 @@ import os import re from functools import cache, total_ordering -from typing import Optional import yaml from packaging.requirements import InvalidRequirement, Requirement @@ -63,7 +62,7 @@ def strip_cuda_suffix(args: argparse.Namespace, name: str) -> str: def check_and_mark_anchor( anchors: dict[str, "yaml.Node"], used_anchors: set[str], node: "yaml.Node" -) -> tuple[bool, Optional[str]]: +) -> tuple[bool, str | None]: for key, value in anchors.items(): if value == node: anchor = key diff --git a/src/rapids_pre_commit_hooks/copyright.py b/src/rapids_pre_commit_hooks/copyright.py index 53de97e..fd5abc8 100644 --- a/src/rapids_pre_commit_hooks/copyright.py +++ b/src/rapids_pre_commit_hooks/copyright.py @@ -19,7 +19,7 @@ import re import warnings from collections.abc import Callable -from typing import Optional, Union +from typing import Optional import git @@ -63,7 +63,7 @@ def add_copy_rename_note( linter: Linter, warning: LintWarning, change_type: str, - old_filename: Optional[Union[str, os.PathLike[str]]], + old_filename: str | os.PathLike[str] | None, ): CHANGE_VERBS = { "C": "copied", @@ -89,7 +89,7 @@ def add_copy_rename_note( def apply_copyright_revert( linter: Linter, change_type: str, - old_filename: Optional[Union[str, os.PathLike[str]]], + old_filename: str | os.PathLike[str] | None, old_match: re.Match, new_match: re.Match, ) -> None: @@ -123,8 +123,8 @@ def apply_copyright_update( def apply_copyright_check( linter: Linter, change_type: str, - old_filename: Optional[Union[str, os.PathLike[str]]], - old_content: Optional[str], + old_filename: str | os.PathLike[str] | None, + old_content: str | None, ) -> None: if linter.content != old_content: current_year = datetime.datetime.now().year @@ -154,7 +154,7 @@ def apply_copyright_check( linter.add_warning((0, 0), "no copyright notice found") -def get_target_branch(repo: "git.Repo", args: argparse.Namespace) -> Optional[str]: +def get_target_branch(repo: "git.Repo", args: argparse.Namespace) -> str | None: """Determine which branch is the "target" branch. The target branch is determined in the following order: @@ -222,7 +222,7 @@ def get_target_branch(repo: "git.Repo", args: argparse.Namespace) -> Optional[st def get_target_branch_upstream_commit( repo: "git.Repo", args: argparse.Namespace -) -> Optional[git.Commit]: +) -> git.Commit | None: # If no target branch can be determined, use HEAD if it exists target_branch_name = get_target_branch(repo, args) if target_branch_name is None: @@ -278,7 +278,7 @@ def try_get_ref(remote: "git.Remote") -> Optional["git.Reference"]: def get_changed_files( args: argparse.Namespace, -) -> dict[Union[str, os.PathLike[str]], tuple[str, Optional["git.Blob"]]]: +) -> dict[str | os.PathLike[str], tuple[str, Optional["git.Blob"]]]: try: repo = git.Repo() except git.InvalidGitRepositoryError: @@ -288,9 +288,9 @@ def get_changed_files( for filename in filenames } - changed_files: dict[ - Union[str, os.PathLike[str]], tuple[str, Optional["git.Blob"]] - ] = {f: ("A", None) for f in repo.untracked_files} + changed_files: dict[str | os.PathLike[str], tuple[str, Optional["git.Blob"]]] = { + f: ("A", None) for f in repo.untracked_files + } target_branch_upstream_commit = get_target_branch_upstream_commit(repo, args) if target_branch_upstream_commit is None: changed_files.update( @@ -316,7 +316,7 @@ def get_changed_files( return changed_files -def normalize_git_filename(filename: Union[str, os.PathLike[str]]) -> Optional[str]: +def normalize_git_filename(filename: str | os.PathLike[str]) -> str | None: relpath = os.path.relpath(filename) if re.search(r"^\.\.(/|$)", relpath): return None @@ -324,7 +324,7 @@ def normalize_git_filename(filename: Union[str, os.PathLike[str]]) -> Optional[s def find_blob( - tree: "git.Tree", filename: Union[str, os.PathLike[str]] + tree: "git.Tree", filename: str | os.PathLike[str] ) -> Optional["git.Blob"]: d1, d2 = os.path.split(filename) split = [d2] diff --git a/src/rapids_pre_commit_hooks/lint.py b/src/rapids_pre_commit_hooks/lint.py index fcc06b9..f811381 100644 --- a/src/rapids_pre_commit_hooks/lint.py +++ b/src/rapids_pre_commit_hooks/lint.py @@ -21,7 +21,6 @@ import warnings from collections.abc import Callable from itertools import pairwise -from typing import Optional from rich.console import Console from rich.markup import escape @@ -105,7 +104,7 @@ def fix(self) -> str: return replaced_content def _print_note( - self, note_type: str, pos: _PosType, msg: str, newtext: Optional[str] = None + self, note_type: str, pos: _PosType, msg: str, newtext: str | None = None ) -> None: line_index = self._line_for_pos(pos[0]) line_pos = self.lines[line_index] @@ -156,7 +155,7 @@ def print_warnings(self, fix_applied: bool = False) -> None: self._print_note("note", replacement.pos, replacement_msg, newtext) def _print_highlighted_code( - self, pos: _PosType, replacement: Optional[str] = None + self, pos: _PosType, replacement: str | None = None ) -> None: line_index = self._line_for_pos(pos[0]) line_pos = self.lines[line_index] diff --git a/test/rapids_pre_commit_hooks/test_alpha_spec.py b/test/rapids_pre_commit_hooks/test_alpha_spec.py index ce61ff8..a94810a 100644 --- a/test/rapids_pre_commit_hooks/test_alpha_spec.py +++ b/test/rapids_pre_commit_hooks/test_alpha_spec.py @@ -68,9 +68,12 @@ def test_get_rapids_version( ), }, ) - with set_cwd(tmp_path), patch( - "rapids_pre_commit_hooks.alpha_spec.all_metadata", - Mock(return_value=MOCK_METADATA), + with ( + set_cwd(tmp_path), + patch( + "rapids_pre_commit_hooks.alpha_spec.all_metadata", + Mock(return_value=MOCK_METADATA), + ), ): if version_file: with open("VERSION", "w") as f: @@ -526,11 +529,14 @@ def test_check_dependencies( common_indices, specific_indices, ): - with patch( - "rapids_pre_commit_hooks.alpha_spec.check_common", Mock() - ) as mock_check_common, patch( - "rapids_pre_commit_hooks.alpha_spec.check_specific", Mock() - ) as mock_check_specific: + with ( + patch( + "rapids_pre_commit_hooks.alpha_spec.check_common", Mock() + ) as mock_check_common, + patch( + "rapids_pre_commit_hooks.alpha_spec.check_specific", Mock() + ) as mock_check_specific, + ): args = Mock() linter = lint.Linter("dependencies.yaml", content) anchors = Mock() @@ -579,11 +585,14 @@ def test_check_root(content, indices): def test_check_alpha_spec(): CONTENT = "dependencies: []" - with patch( - "rapids_pre_commit_hooks.alpha_spec.check_root", Mock() - ) as mock_check_root, patch( - "rapids_pre_commit_hooks.alpha_spec.AnchorPreservingLoader", MagicMock() - ) as mock_anchor_preserving_loader: + with ( + patch( + "rapids_pre_commit_hooks.alpha_spec.check_root", Mock() + ) as mock_check_root, + patch( + "rapids_pre_commit_hooks.alpha_spec.AnchorPreservingLoader", MagicMock() + ) as mock_anchor_preserving_loader, + ): args = Mock() linter = lint.Linter("dependencies.yaml", CONTENT) alpha_spec.check_alpha_spec(linter, args) diff --git a/test/rapids_pre_commit_hooks/test_copyright.py b/test/rapids_pre_commit_hooks/test_copyright.py index 3fdec5e..5fc9387 100644 --- a/test/rapids_pre_commit_hooks/test_copyright.py +++ b/test/rapids_pre_commit_hooks/test_copyright.py @@ -888,9 +888,11 @@ def mock_os_walk(top): Mock( return_value=( ( - "." - if (rel := os.path.relpath(dirpath, top)) == "." - else os.path.join(".", rel), + ( + "." + if (rel := os.path.relpath(dirpath, top)) == "." + else os.path.join(".", rel) + ), dirnames, filenames, ) @@ -899,9 +901,11 @@ def mock_os_walk(top): ), ) - with tempfile.TemporaryDirectory() as non_git_dir, patch( - "os.getcwd", Mock(return_value=non_git_dir) - ), mock_os_walk(non_git_dir): + with ( + tempfile.TemporaryDirectory() as non_git_dir, + patch("os.getcwd", Mock(return_value=non_git_dir)), + mock_os_walk(non_git_dir), + ): with open(os.path.join(non_git_dir, "top.txt"), "w") as f: f.write("Top file\n") os.mkdir(os.path.join(non_git_dir, "subdir1")) @@ -947,11 +951,13 @@ def file_contents(verbed): ] ) - with patch("os.getcwd", Mock(return_value=git_repo.working_tree_dir)), mock_os_walk( - git_repo.working_tree_dir - ), patch( - "rapids_pre_commit_hooks.copyright.get_target_branch_upstream_commit", - Mock(return_value=None), + with ( + patch("os.getcwd", Mock(return_value=git_repo.working_tree_dir)), + mock_os_walk(git_repo.working_tree_dir), + patch( + "rapids_pre_commit_hooks.copyright.get_target_branch_upstream_commit", + Mock(return_value=None), + ), ): assert copyright.get_changed_files(Mock()) == { "untouched.txt": ("A", None), @@ -1043,9 +1049,12 @@ def file_contents(verbed): "renamed_2.txt": ("R", "renamed.txt"), } - with patch("os.getcwd", Mock(return_value=git_repo.working_tree_dir)), patch( - "rapids_pre_commit_hooks.copyright.get_target_branch_upstream_commit", - Mock(return_value=target_branch.commit), + with ( + patch("os.getcwd", Mock(return_value=git_repo.working_tree_dir)), + patch( + "rapids_pre_commit_hooks.copyright.get_target_branch_upstream_commit", + Mock(return_value=target_branch.commit), + ), ): changed_files = copyright.get_changed_files(Mock()) assert { @@ -1134,9 +1143,12 @@ def write_file(filename, contents): commit_date=datetime.datetime(2024, 5, 1, tzinfo=datetime.timezone.utc), ) - with patch("os.getcwd", Mock(return_value=git_repo.working_tree_dir)), patch( - "rapids_pre_commit_hooks.copyright.get_target_branch", - Mock(return_value="branch-1-2"), + with ( + patch("os.getcwd", Mock(return_value=git_repo.working_tree_dir)), + patch( + "rapids_pre_commit_hooks.copyright.get_target_branch", + Mock(return_value="branch-1-2"), + ), ): changed_files = copyright.get_changed_files(Mock()) assert { diff --git a/test/rapids_pre_commit_hooks/test_lint.py b/test/rapids_pre_commit_hooks/test_lint.py index aef3da2..51f23d9 100644 --- a/test/rapids_pre_commit_hooks/test_lint.py +++ b/test/rapids_pre_commit_hooks/test_lint.py @@ -183,8 +183,9 @@ def bracket_file(self, tmp_path): @contextlib.contextmanager def mock_console(self): m = Mock() - with patch("rich.console.Console", m), patch( - "rapids_pre_commit_hooks.lint.Console", m + with ( + patch("rich.console.Console", m), + patch("rapids_pre_commit_hooks.lint.Console", m), ): yield m @@ -216,9 +217,10 @@ def bracket_check(self, linter, args): ) def test_no_warnings_no_fix(self, hello_world_file): - with patch( - "sys.argv", ["check-test", "--check-test", hello_world_file.name] - ), self.mock_console() as console: + with ( + patch("sys.argv", ["check-test", "--check-test", hello_world_file.name]), + self.mock_console() as console, + ): m = LintMain() m.argparser.add_argument("--check-test", action="store_true") m.argparser.add_argument("--check-test-note", action="store_true") @@ -230,9 +232,13 @@ def test_no_warnings_no_fix(self, hello_world_file): ] def test_no_warnings_fix(self, hello_world_file): - with patch( - "sys.argv", ["check-test", "--check-test", "--fix", hello_world_file.name] - ), self.mock_console() as console: + with ( + patch( + "sys.argv", + ["check-test", "--check-test", "--fix", hello_world_file.name], + ), + self.mock_console() as console, + ): m = LintMain() m.argparser.add_argument("--check-test", action="store_true") m.argparser.add_argument("--check-test-note", action="store_true") @@ -244,9 +250,11 @@ def test_no_warnings_fix(self, hello_world_file): ] def test_warnings_no_fix(self, hello_world_file): - with patch( - "sys.argv", ["check-test", "--check-test", hello_world_file.name] - ), self.mock_console() as console, pytest.raises(SystemExit, match=r"^1$"): + with ( + patch("sys.argv", ["check-test", "--check-test", hello_world_file.name]), + self.mock_console() as console, + pytest.raises(SystemExit, match=r"^1$"), + ): m = LintMain() m.argparser.add_argument("--check-test", action="store_true") m.argparser.add_argument("--check-test-note", action="store_true") @@ -276,9 +284,14 @@ def test_warnings_no_fix(self, hello_world_file): ] def test_warnings_fix(self, hello_world_file): - with patch( - "sys.argv", ["check-test", "--check-test", "--fix", hello_world_file.name] - ), self.mock_console() as console, pytest.raises(SystemExit, match=r"^1$"): + with ( + patch( + "sys.argv", + ["check-test", "--check-test", "--fix", hello_world_file.name], + ), + self.mock_console() as console, + pytest.raises(SystemExit, match=r"^1$"), + ): m = LintMain() m.argparser.add_argument("--check-test", action="store_true") m.argparser.add_argument("--check-test-note", action="store_true") @@ -308,10 +321,19 @@ def test_warnings_fix(self, hello_world_file): ] def test_warnings_note(self, hello_world_file): - with patch( - "sys.argv", - ["check-test", "--check-test", "--check-test-note", hello_world_file.name], - ), self.mock_console() as console, pytest.raises(SystemExit, match=r"^1$"): + with ( + patch( + "sys.argv", + [ + "check-test", + "--check-test", + "--check-test-note", + hello_world_file.name, + ], + ), + self.mock_console() as console, + pytest.raises(SystemExit, match=r"^1$"), + ): m = LintMain() m.argparser.add_argument("--check-test", action="store_true") m.argparser.add_argument("--check-test-note", action="store_true") @@ -345,16 +367,20 @@ def test_warnings_note(self, hello_world_file): ] def test_multiple_files(self, hello_world_file, hello_file): - with patch( - "sys.argv", - [ - "check-test", - "--check-test", - "--fix", - hello_world_file.name, - hello_file.name, - ], - ), self.mock_console() as console, pytest.raises(SystemExit, match=r"^1$"): + with ( + patch( + "sys.argv", + [ + "check-test", + "--check-test", + "--fix", + hello_world_file.name, + hello_file.name, + ], + ), + self.mock_console() as console, + pytest.raises(SystemExit, match=r"^1$"), + ): m = LintMain() m.argparser.add_argument("--check-test", action="store_true") m.argparser.add_argument("--check-test-note", action="store_true") @@ -396,17 +422,21 @@ def test_multiple_files(self, hello_world_file, hello_file): def test_binary_file(self, binary_file): mock_linter = Mock(wraps=Linter) - with patch( - "sys.argv", - [ - "check-test", - "--check-test", - "--fix", - binary_file.name, - ], - ), patch("rapids_pre_commit_hooks.lint.Linter", mock_linter), pytest.warns( - BinaryFileWarning, - match=r"^Refusing to run text linter on binary file .*\.$", + with ( + patch( + "sys.argv", + [ + "check-test", + "--check-test", + "--fix", + binary_file.name, + ], + ), + patch("rapids_pre_commit_hooks.lint.Linter", mock_linter), + pytest.warns( + BinaryFileWarning, + match=r"^Refusing to run text linter on binary file .*\.$", + ), ): m = LintMain() m.argparser.add_argument("--check-test", action="store_true") @@ -416,13 +446,17 @@ def test_binary_file(self, binary_file): mock_linter.assert_not_called() def test_long_file(self, long_file): - with patch( - "sys.argv", - [ - "check-test", - long_file.name, - ], - ), self.mock_console() as console, pytest.raises(SystemExit, match=r"^1$"): + with ( + patch( + "sys.argv", + [ + "check-test", + long_file.name, + ], + ), + self.mock_console() as console, + pytest.raises(SystemExit, match=r"^1$"), + ): m = LintMain() with m.execute() as ctx: ctx.add_check(self.long_file_check) @@ -454,13 +488,17 @@ def test_long_file(self, long_file): ] def test_long_file_delete(self, long_file): - with patch( - "sys.argv", - [ - "check-test", - long_file.name, - ], - ), self.mock_console() as console, pytest.raises(SystemExit, match=r"^1$"): + with ( + patch( + "sys.argv", + [ + "check-test", + long_file.name, + ], + ), + self.mock_console() as console, + pytest.raises(SystemExit, match=r"^1$"), + ): m = LintMain() with m.execute() as ctx: ctx.add_check(self.long_delete_fix_check) @@ -487,14 +525,18 @@ def test_long_file_delete(self, long_file): ] def test_long_file_fix(self, long_file): - with patch( - "sys.argv", - [ - "check-test", - "--fix", - long_file.name, - ], - ), self.mock_console() as console, pytest.raises(SystemExit, match=r"^1$"): + with ( + patch( + "sys.argv", + [ + "check-test", + "--fix", + long_file.name, + ], + ), + self.mock_console() as console, + pytest.raises(SystemExit, match=r"^1$"), + ): m = LintMain() with m.execute() as ctx: ctx.add_check(self.long_file_check) @@ -526,14 +568,18 @@ def test_long_file_fix(self, long_file): ] def test_long_file_delete_fix(self, long_file): - with patch( - "sys.argv", - [ - "check-test", - "--fix", - long_file.name, - ], - ), self.mock_console() as console, pytest.raises(SystemExit, match=r"^1$"): + with ( + patch( + "sys.argv", + [ + "check-test", + "--fix", + long_file.name, + ], + ), + self.mock_console() as console, + pytest.raises(SystemExit, match=r"^1$"), + ): m = LintMain() with m.execute() as ctx: ctx.add_check(self.long_delete_fix_check) @@ -554,14 +600,18 @@ def test_long_file_delete_fix(self, long_file): ] def test_bracket_file(self, bracket_file): - with patch( - "sys.argv", - [ - "check-test", - "--fix", - bracket_file.name, - ], - ), self.mock_console() as console, pytest.raises(SystemExit, match=r"^1$"): + with ( + patch( + "sys.argv", + [ + "check-test", + "--fix", + bracket_file.name, + ], + ), + self.mock_console() as console, + pytest.raises(SystemExit, match=r"^1$"), + ): m = LintMain() with m.execute() as ctx: ctx.add_check(self.bracket_check) diff --git a/test/test_pre_commit.py b/test/test_pre_commit.py index 4579aa0..f23660c 100644 --- a/test/test_pre_commit.py +++ b/test/test_pre_commit.py @@ -60,8 +60,10 @@ def run_pre_commit(git_repo, hook_name, expected_status, exc): def list_files(top): for dirpath, _, filenames in os.walk(top): for filename in filenames: - yield filename if top == dirpath else os.path.join( - os.path.relpath(top, dirpath), filename + yield ( + filename + if top == dirpath + else os.path.join(os.path.relpath(top, dirpath), filename) ) example_dir = os.path.join(EXAMPLES_DIR, hook_name, expected_status) @@ -89,9 +91,10 @@ def list_files(top): commit_date=datetime.datetime(2024, 2, 1, tzinfo=datetime.timezone.utc), ) - with set_cwd(git_repo.working_tree_dir), pytest.raises( - exc - ) if exc else contextlib.nullcontext(): + with ( + set_cwd(git_repo.working_tree_dir), + pytest.raises(exc) if exc else contextlib.nullcontext(), + ): subprocess.check_call( [sys.executable, "-m", "pre_commit", "try-repo", REPO_DIR, hook_name, "-a"], env={**os.environ, "TARGET_BRANCH": "master"},