From c748c82c898adcd75d3288a7daf1b809a4ded6bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 29 Nov 2023 08:12:48 +0100 Subject: [PATCH 1/8] drop obsolete setup.cfg --- setup.cfg | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 setup.cfg diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 1294fa55..00000000 --- a/setup.cfg +++ /dev/null @@ -1,23 +0,0 @@ -[wheel] -universal = 1 - -[pycodestyle] -max-line-length = 88 -ignore = E501,E741,W503 - -[flake8] -max-line-length = 88 -ignore = E501,E741,W503 -exclude = .git,__pycache__,docs/source/conf.py,old,build,dist - -[mypy] -warn_redundant_casts = true -disallow_untyped_calls = true -disallow_untyped_defs = true -no_implicit_optional = true - -[mypy-pytest.*] -ignore_missing_imports = True - -[isort] -profile = black From b029dbf2dfa5cf56d48cf2cd4390472920b48e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 29 Nov 2023 08:13:31 +0100 Subject: [PATCH 2/8] expand ruff checks to test all --- pyproject.toml | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b4706845..971841f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,27 @@ [tool.ruff] +target-version = "py311" line-length = 88 - -select = ["E", "F", "I"] -ignore = [ "E501" ] +select = ["ALL"] +ignore = [ + # pydocstyle + "D", + # Missing type annotation for `self` in method + "ANN101", + # Trailing comma missing + "COM812", + # Unnecessary `dict` call (rewrite as a literal) + "C408", + # Boolean-typed positional argument in function definition + "FBT001", + # Logging statement uses f-string + "G004", + # disabled on ruff's recommendation as causes problems with the formatter + "ISC001", + # Use of `assert` detected + "S101", + # `subprocess` call: check for execution of untrusted input + "S603", +] [tool.mypy] python_version = "3.10" From ae4a4e8e7cd626d59faa32e00a80914dfaeaecb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 29 Nov 2023 08:14:14 +0100 Subject: [PATCH 3/8] make tests directory a proper python module --- tests/__init__.py | 0 tests/conftest.py | 4 ++-- tests/direnv_project.py | 3 ++- tests/test_gc.py | 4 ++-- tests/test_use_nix.py | 5 +++-- 5 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 tests/__init__.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/conftest.py b/tests/conftest.py index 8a849bf1..1f74975b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,4 @@ pytest_plugins = [ - "direnv_project", - "root", + "tests.direnv_project", + "tests.root", ] diff --git a/tests/direnv_project.py b/tests/direnv_project.py index ebca0172..d5681838 100644 --- a/tests/direnv_project.py +++ b/tests/direnv_project.py @@ -6,7 +6,8 @@ from typing import Iterator import pytest -from procs import run + +from .procs import run @dataclass diff --git a/tests/test_gc.py b/tests/test_gc.py index e46fcfd8..48a62adf 100644 --- a/tests/test_gc.py +++ b/tests/test_gc.py @@ -3,9 +3,9 @@ import unittest import pytest -from direnv_project import DirenvProject -from procs import run +from .direnv_project import DirenvProject +from .procs import run def common_test(direnv_project: DirenvProject) -> None: run(["nix-collect-garbage"]) diff --git a/tests/test_use_nix.py b/tests/test_use_nix.py index 0c79fa53..ce85a35c 100644 --- a/tests/test_use_nix.py +++ b/tests/test_use_nix.py @@ -5,8 +5,9 @@ from typing import Optional import pytest -from direnv_project import DirenvProject -from procs import run + +from .direnv_project import DirenvProject +from .procs import run def direnv_exec( From 26b7fce564c7bd0e375552b154c2e5521a9fc4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 29 Nov 2023 08:15:19 +0100 Subject: [PATCH 4/8] tests: avoid shadowing dir builtin --- tests/direnv_project.py | 18 +++++++++--------- tests/test_gc.py | 16 ++++++++-------- tests/test_use_nix.py | 6 +++--- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/direnv_project.py b/tests/direnv_project.py index d5681838..b5108ff0 100644 --- a/tests/direnv_project.py +++ b/tests/direnv_project.py @@ -12,12 +12,12 @@ @dataclass class DirenvProject: - dir: Path + directory: Path nix_direnv: Path @property def envrc(self) -> Path: - return self.dir / ".envrc" + return self.directory / ".envrc" def setup_envrc(self, content: str, strict_env: bool) -> None: text = textwrap.dedent( @@ -28,7 +28,7 @@ def setup_envrc(self, content: str, strict_env: bool) -> None: """ ) self.envrc.write_text(text) - run(["direnv", "allow"], cwd=self.dir) + run(["direnv", "allow"], cwd=self.directory) @pytest.fixture @@ -37,14 +37,14 @@ def direnv_project(test_root: Path, project_root: Path) -> Iterator[DirenvProjec Setups a direnv test project """ with TemporaryDirectory() as _dir: - dir = Path(_dir) / "proj" - shutil.copytree(test_root / "testenv", dir) - shutil.copyfile(project_root / "flake.nix", dir / "flake.nix") - shutil.copyfile(project_root / "flake.lock", dir / "flake.lock") - shutil.copyfile(project_root / "treefmt.nix", dir / "treefmt.nix") + directory = Path(_dir) / "proj" + shutil.copytree(test_root / "testenv", directory) + shutil.copyfile(project_root / "flake.nix", directory / "flake.nix") + shutil.copyfile(project_root / "flake.lock", directory / "flake.lock") + shutil.copyfile(project_root / "treefmt.nix", directory / "treefmt.nix") nix_direnv = project_root / "direnvrc" - c = DirenvProject(Path(dir), nix_direnv) + c = DirenvProject(Path(directory), nix_direnv) try: yield c finally: diff --git a/tests/test_gc.py b/tests/test_gc.py index 48a62adf..5d80c100 100644 --- a/tests/test_gc.py +++ b/tests/test_gc.py @@ -10,13 +10,13 @@ def common_test(direnv_project: DirenvProject) -> None: run(["nix-collect-garbage"]) - testenv = str(direnv_project.dir) + testenv = str(direnv_project.directory) out1 = run( ["direnv", "exec", testenv, "hello"], stderr=subprocess.PIPE, check=False, - cwd=direnv_project.dir, + cwd=direnv_project.directory, ) sys.stderr.write(out1.stderr) assert out1.returncode == 0 @@ -29,7 +29,7 @@ def common_test(direnv_project: DirenvProject) -> None: ["direnv", "exec", testenv, "hello"], stderr=subprocess.PIPE, check=False, - cwd=direnv_project.dir, + cwd=direnv_project.directory, ) sys.stderr.write(out2.stderr) assert out2.returncode == 0 @@ -38,18 +38,18 @@ def common_test(direnv_project: DirenvProject) -> None: def common_test_clean(direnv_project: DirenvProject) -> None: - testenv = str(direnv_project.dir) + testenv = str(direnv_project.directory) out3 = run( ["direnv", "exec", testenv, "hello"], stderr=subprocess.PIPE, check=False, - cwd=direnv_project.dir, + cwd=direnv_project.directory, ) sys.stderr.write(out3.stderr) files = [ - path for path in (direnv_project.dir / ".direnv").iterdir() if path.is_file() + path for path in (direnv_project.directory / ".direnv").iterdir() if path.is_file() ] rcs = [f for f in files if f.match("*.rc")] profiles = [f for f in files if not f.match("*.rc")] @@ -75,10 +75,10 @@ def test_use_nix(direnv_project: DirenvProject, strict_env: bool) -> None: def test_use_flake(direnv_project: DirenvProject, strict_env: bool) -> None: direnv_project.setup_envrc("use flake", strict_env=strict_env) common_test(direnv_project) - inputs = list((direnv_project.dir / ".direnv/flake-inputs").iterdir()) + inputs = list((direnv_project.directory / ".direnv/flake-inputs").iterdir()) # should only contain our flake-utils flake if len(inputs) != 4: - run(["nix", "flake", "archive", "--json"], cwd=direnv_project.dir) + run(["nix", "flake", "archive", "--json"], cwd=direnv_project.directory) print(inputs) assert len(inputs) == 4 for symlink in inputs: diff --git a/tests/test_use_nix.py b/tests/test_use_nix.py index ce85a35c..62424902 100644 --- a/tests/test_use_nix.py +++ b/tests/test_use_nix.py @@ -13,14 +13,14 @@ def direnv_exec( direnv_project: DirenvProject, cmd: str, env: Optional[dict[str, str]] = None ) -> None: - args = ["direnv", "exec", str(direnv_project.dir), "sh", "-c", cmd] + args = ["direnv", "exec", str(direnv_project.directory), "sh", "-c", cmd] print("$ " + " ".join(args)) out = run( args, stderr=subprocess.PIPE, stdout=subprocess.PIPE, check=False, - cwd=direnv_project.dir, + cwd=direnv_project.directory, env=env, ) sys.stdout.write(out.stdout) @@ -58,7 +58,7 @@ def test_no_files(direnv_project: DirenvProject, strict_env: bool) -> None: stderr=subprocess.PIPE, stdout=subprocess.PIPE, check=False, - cwd=direnv_project.dir, + cwd=direnv_project.directory, ) assert out.returncode == 0 assert 'Loaded watch: "."' not in out.stdout From 9ac34be48f75899a0bea5e55f218aab274a65f8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 29 Nov 2023 08:16:00 +0100 Subject: [PATCH 5/8] test: use builtins for type annotations instead of List / Optional --- tests/procs.py | 10 +++++----- tests/test_use_nix.py | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/procs.py b/tests/procs.py index ea837d4e..668b64f2 100644 --- a/tests/procs.py +++ b/tests/procs.py @@ -1,19 +1,19 @@ import subprocess from pathlib import Path -from typing import IO, Any, List, Optional, Union +from typing import IO, Any -_FILE = Union[None, int, IO[Any]] -_DIR = Union[None, Path, str] +_FILE = None | int | IO[Any] +_DIR = None | Path | str def run( - cmd: List[str], + cmd: list[str], text: bool = True, check: bool = True, cwd: _DIR = None, stderr: _FILE = None, stdout: _FILE = None, - env: Optional[dict[str, str]] = None, + env: dict[str, str] | None = None, ) -> subprocess.CompletedProcess: if cwd is not None: print(f"cd {cwd}") diff --git a/tests/test_use_nix.py b/tests/test_use_nix.py index 62424902..af7da4ea 100644 --- a/tests/test_use_nix.py +++ b/tests/test_use_nix.py @@ -2,7 +2,6 @@ import subprocess import sys import unittest -from typing import Optional import pytest @@ -11,7 +10,7 @@ def direnv_exec( - direnv_project: DirenvProject, cmd: str, env: Optional[dict[str, str]] = None + direnv_project: DirenvProject, cmd: str, env: dict[str, str] | None = None ) -> None: args = ["direnv", "exec", str(direnv_project.directory), "sh", "-c", cmd] print("$ " + " ".join(args)) From 8c46f6e97dc07c4244786a81127b3e74177a7703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 29 Nov 2023 08:17:29 +0100 Subject: [PATCH 6/8] tests: don't use print in favour of logger --- tests/procs.py | 7 +++++-- tests/test_gc.py | 7 +++++-- tests/test_use_nix.py | 5 ++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/procs.py b/tests/procs.py index 668b64f2..971c0e4c 100644 --- a/tests/procs.py +++ b/tests/procs.py @@ -1,3 +1,4 @@ +import logging import subprocess from pathlib import Path from typing import IO, Any @@ -5,6 +6,8 @@ _FILE = None | int | IO[Any] _DIR = None | Path | str +log = logging.getLogger(__name__) + def run( cmd: list[str], @@ -16,8 +19,8 @@ def run( env: dict[str, str] | None = None, ) -> subprocess.CompletedProcess: if cwd is not None: - print(f"cd {cwd}") - print("$ " + " ".join(cmd)) + log.debug(f"cd {cwd}") + log.debug("$ " + " ".join(cmd)) return subprocess.run( cmd, text=text, check=check, cwd=cwd, stderr=stderr, stdout=stdout, env=env ) diff --git a/tests/test_gc.py b/tests/test_gc.py index 5d80c100..8d49683b 100644 --- a/tests/test_gc.py +++ b/tests/test_gc.py @@ -1,3 +1,4 @@ +import logging import subprocess import sys import unittest @@ -7,6 +8,8 @@ from .direnv_project import DirenvProject from .procs import run +log = logging.getLogger(__name__) + def common_test(direnv_project: DirenvProject) -> None: run(["nix-collect-garbage"]) @@ -54,7 +57,7 @@ def common_test_clean(direnv_project: DirenvProject) -> None: rcs = [f for f in files if f.match("*.rc")] profiles = [f for f in files if not f.match("*.rc")] if len(rcs) != 1 or len(profiles) != 1: - print(files) + log.debug(files) assert len(rcs) == 1 assert len(profiles) == 1 @@ -79,7 +82,7 @@ def test_use_flake(direnv_project: DirenvProject, strict_env: bool) -> None: # should only contain our flake-utils flake if len(inputs) != 4: run(["nix", "flake", "archive", "--json"], cwd=direnv_project.directory) - print(inputs) + log.debug(inputs) assert len(inputs) == 4 for symlink in inputs: assert symlink.is_dir() diff --git a/tests/test_use_nix.py b/tests/test_use_nix.py index af7da4ea..f12cb6b3 100644 --- a/tests/test_use_nix.py +++ b/tests/test_use_nix.py @@ -1,3 +1,4 @@ +import logging import os import subprocess import sys @@ -8,12 +9,14 @@ from .direnv_project import DirenvProject from .procs import run +log = logging.getLogger(__name__) + def direnv_exec( direnv_project: DirenvProject, cmd: str, env: dict[str, str] | None = None ) -> None: args = ["direnv", "exec", str(direnv_project.directory), "sh", "-c", cmd] - print("$ " + " ".join(args)) + log.debug("$ " + " ".join(args)) out = run( args, stderr=subprocess.PIPE, From d5a10dc6d5c3274b7e6b3457194ab37ead80a847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 29 Nov 2023 08:21:15 +0100 Subject: [PATCH 7/8] test: other random ruff lints --- tests/direnv_project.py | 4 ++-- tests/procs.py | 3 ++- tests/root.py | 4 ++-- tests/test_gc.py | 5 ++++- tests/test_use_nix.py | 5 +++-- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/direnv_project.py b/tests/direnv_project.py index b5108ff0..f2166fef 100644 --- a/tests/direnv_project.py +++ b/tests/direnv_project.py @@ -1,9 +1,9 @@ import shutil import textwrap +from collections.abc import Iterator from dataclasses import dataclass from pathlib import Path from tempfile import TemporaryDirectory -from typing import Iterator import pytest @@ -31,7 +31,7 @@ def setup_envrc(self, content: str, strict_env: bool) -> None: run(["direnv", "allow"], cwd=self.directory) -@pytest.fixture +@pytest.fixture() def direnv_project(test_root: Path, project_root: Path) -> Iterator[DirenvProject]: """ Setups a direnv test project diff --git a/tests/procs.py b/tests/procs.py index 971c0e4c..f9d80bab 100644 --- a/tests/procs.py +++ b/tests/procs.py @@ -1,4 +1,5 @@ import logging +import shlex import subprocess from pathlib import Path from typing import IO, Any @@ -20,7 +21,7 @@ def run( ) -> subprocess.CompletedProcess: if cwd is not None: log.debug(f"cd {cwd}") - log.debug("$ " + " ".join(cmd)) + log.debug(f"$ {shlex.join(cmd)}") return subprocess.run( cmd, text=text, check=check, cwd=cwd, stderr=stderr, stdout=stdout, env=env ) diff --git a/tests/root.py b/tests/root.py index b3f0914d..a5bf3994 100644 --- a/tests/root.py +++ b/tests/root.py @@ -6,7 +6,7 @@ PROJECT_ROOT = TEST_ROOT.parent -@pytest.fixture +@pytest.fixture() def test_root() -> Path: """ Root directory of the tests @@ -14,7 +14,7 @@ def test_root() -> Path: return TEST_ROOT -@pytest.fixture +@pytest.fixture() def project_root() -> Path: """ Root directory of the tests diff --git a/tests/test_gc.py b/tests/test_gc.py index 8d49683b..26f25663 100644 --- a/tests/test_gc.py +++ b/tests/test_gc.py @@ -10,6 +10,7 @@ log = logging.getLogger(__name__) + def common_test(direnv_project: DirenvProject) -> None: run(["nix-collect-garbage"]) @@ -52,7 +53,9 @@ def common_test_clean(direnv_project: DirenvProject) -> None: sys.stderr.write(out3.stderr) files = [ - path for path in (direnv_project.directory / ".direnv").iterdir() if path.is_file() + path + for path in (direnv_project.directory / ".direnv").iterdir() + if path.is_file() ] rcs = [f for f in files if f.match("*.rc")] profiles = [f for f in files if not f.match("*.rc")] diff --git a/tests/test_use_nix.py b/tests/test_use_nix.py index f12cb6b3..804079de 100644 --- a/tests/test_use_nix.py +++ b/tests/test_use_nix.py @@ -1,5 +1,6 @@ import logging import os +import shlex import subprocess import sys import unittest @@ -16,7 +17,7 @@ def direnv_exec( direnv_project: DirenvProject, cmd: str, env: dict[str, str] | None = None ) -> None: args = ["direnv", "exec", str(direnv_project.directory), "sh", "-c", cmd] - log.debug("$ " + " ".join(args)) + log.debug(f"$ {shlex.join(args)}") out = run( args, stderr=subprocess.PIPE, @@ -28,7 +29,7 @@ def direnv_exec( sys.stdout.write(out.stdout) sys.stderr.write(out.stderr) assert out.returncode == 0 - assert "OK\n" == out.stdout + assert out.stdout == "OK\n" assert "renewed cache" in out.stderr From 4dbf3db6002b72ab701b8dc5e49baf999a24ce98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 29 Nov 2023 08:29:47 +0100 Subject: [PATCH 8/8] disable remaining failing ruff lints --- pyproject.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 971841f0..483f9dd1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,11 @@ ignore = [ "S101", # `subprocess` call: check for execution of untrusted input "S603", + + # FIXME? Maybe we should enable these? + "PLR0913", # Too many arguments in function definition (7 > 5) + "PLR2004", # Magic value used in comparison, consider replacing 4 with a constant variable + "FBT002", # Boolean default positional argument in function definition ] [tool.mypy]