From 50bae5880717cffb991fea90b41c69db955c7bc3 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Fri, 1 Dec 2023 10:03:02 +0000 Subject: [PATCH] build(lint): switch over to ruff; add taplo Ruff is faster, better integrated, easier to configure... Cool! Taplo also helps with toml maintenance. --- .editorconfig | 2 +- .github/workflows/ci.yml | 2 +- .vscode/extensions.json | 2 +- .vscode/settings.json | 18 ++++++-------- copier/cli.py | 6 ++--- copier/main.py | 2 +- copier/tools.py | 13 +++++++--- copier/vcs.py | 3 ++- flake.lock | 52 ++++++++++++++++++++-------------------- flake.nix | 11 ++++----- pyproject.toml | 46 +++++++++++++++++------------------ tests/test_config.py | 4 ++-- 12 files changed, 81 insertions(+), 80 deletions(-) diff --git a/.editorconfig b/.editorconfig index dab6c0c4a..648343c14 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,5 +12,5 @@ insert_final_newline = true # For isort profile = black -[*.{code-snippets,code-workspace,json,lock,nix,tf,yaml,yml}{,.jinja}] +[*.{code-snippets,code-workspace,json,lock,nix,toml,tf,yaml,yml}{,.jinja}] indent_size = 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ad6ff60d..e298c83ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -125,7 +125,7 @@ jobs: - run: copier --version # Run nix checks - - run: nix flake check -L --accept-flake-config + - run: nix flake check -L --accept-flake-config --impure publish: if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 70419f812..a7c6476b3 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,7 @@ { "recommendations": [ + "charliermarsh.ruff", "esbenp.prettier-vscode", - "ms-python.black-formatter", "ms-python.python", "editorconfig.editorconfig", "bpruitt-goddard.mermaid-markdown-syntax-highlighting" diff --git a/.vscode/settings.json b/.vscode/settings.json index 3b841d943..dc3523f24 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,21 +2,17 @@ "editor.formatOnSave": true, "python.testing.pytestEnabled": true, "markdown.extension.toc.updateOnSave": false, - "python.formatting.provider": "none", - "python.linting.pylintEnabled": false, - "python.linting.flake8Enabled": true, - "python.linting.mypyEnabled": true, "[python]": { - "editor.formatOnSave": true, - "editor.formatOnSaveMode": "file", - "editor.defaultFormatter": "ms-python.black-formatter" + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + "source.organizeImports": "explicit" + }, + "editor.defaultFormatter": "charliermarsh.ruff", + "editor.formatOnSave": true }, "[markdown]": { "editor.formatOnSave": true, "editor.formatOnSaveMode": "file", "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "python.autoComplete.extraPaths": ["__pypackages__/3.9/lib"], - "python.analysis.extraPaths": ["__pypackages__/3.9/lib"], - "python.pythonPath": ".venv/bin/python" + } } diff --git a/copier/cli.py b/copier/cli.py index 01d3e2bd9..51d2616bb 100644 --- a/copier/cli.py +++ b/copier/cli.py @@ -1,5 +1,4 @@ -""" -Command line entrypoint. This module declares the Copier CLI applications. +"""Command line entrypoint. This module declares the Copier CLI applications. Basically, there are 3 different commands you can run: @@ -197,8 +196,7 @@ def data_file_switch(self, path: cli.ExistingFile) -> None: self.data.update(updates_without_cli_overrides) def _worker(self, src_path: OptStr = None, dst_path: str = ".", **kwargs) -> Worker: - """ - Run Copier's internal API using CLI switches. + """Run Copier's internal API using CLI switches. Arguments: src_path: The source path of the template to generate the project from. diff --git a/copier/main.py b/copier/main.py index 625919eae..3d90e853f 100644 --- a/copier/main.py +++ b/copier/main.py @@ -624,7 +624,7 @@ def _render_folder(self, src_abspath: Path) -> None: """Recursively render a folder. Args: - src_path: + src_abspath: Folder to be rendered. It must be an absolute path within the template. """ diff --git a/copier/tools.py b/copier/tools.py index 1a2f41117..384a23783 100644 --- a/copier/tools.py +++ b/copier/tools.py @@ -193,10 +193,17 @@ def _re_octal_replace(match: re.Match) -> str: def normalize_git_path(path: str) -> str: - # A filename like âñ will be reported by Git - # as "\\303\\242\\303\\261" (octal notation). - # This can be disabled with `git config core.quotepath off`. + r"""Convert weird characters returned by Git to normal UTF-8 path strings. + A filename like âñ will be reported by Git as "\\303\\242\\303\\261" (octal notation). + This can be disabled with `git config core.quotepath off`. + + Args: + path: The Git path to normalize. + + Returns: + str: The normalized Git path. + """ # Remove surrounding quotes if path[0] == path[-1] == '"': path = path[1:-1] diff --git a/copier/vcs.py b/copier/vcs.py index d342951d5..a26552238 100644 --- a/copier/vcs.py +++ b/copier/vcs.py @@ -17,7 +17,7 @@ def get_git(context_dir: OptStrOrPath = None) -> LocalCommand: - """Gets `git` command, or fails if it's not available""" + """Gets `git` command, or fails if it's not available.""" command = local["git"] if context_dir: command = command["-C", context_dir] @@ -25,6 +25,7 @@ def get_git(context_dir: OptStrOrPath = None) -> LocalCommand: def get_git_version() -> Version: + """Get the installed git version.""" git = get_git() return Version(re.findall(r"\d+\.\d+\.\d+", git("version"))[0]) diff --git a/flake.lock b/flake.lock index fe600f3b6..591e43dc1 100644 --- a/flake.lock +++ b/flake.lock @@ -8,16 +8,16 @@ "pre-commit-hooks": "pre-commit-hooks" }, "locked": { - "lastModified": 1671716968, - "narHash": "sha256-LThNtwAXH/0KVMgyTFBwl93ktuWpWTZhCh6NBlydBbQ=", + "lastModified": 1688058187, + "narHash": "sha256-ipDcc7qrucpJ0+0eYNlwnE+ISTcq4m03qW+CWUshRXI=", "owner": "cachix", "repo": "devenv", - "rev": "ba6818f4c39fd95aebdb6dc441401f2b60484652", + "rev": "c8778e3dc30eb9043e218aaa3861d42d4992de77", "type": "github" }, "original": { "owner": "cachix", - "ref": "v0.5", + "ref": "latest", "repo": "devenv", "type": "github" } @@ -25,11 +25,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1668681692, - "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=", + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", "owner": "edolstra", "repo": "flake-compat", - "rev": "009399224d5e398d03b22badca40a37ac85412a1", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "type": "github" }, "original": { @@ -146,11 +146,11 @@ "nixpkgs-regression": "nixpkgs-regression" }, "locked": { - "lastModified": 1671638174, - "narHash": "sha256-FeEmVix8l/HglWtRgeHOfjqEm2etvp+MLYd1C/raq3Y=", + "lastModified": 1676545802, + "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", "owner": "domenkozar", "repo": "nix", - "rev": "51b770e985f9e1b84fb5e03a983ef1e19f18c3e9", + "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", "type": "github" }, "original": { @@ -180,11 +180,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1671458120, - "narHash": "sha256-2+k/OONN4OF21TeoNjKB5sXVZv6Zvm/uEyQIW9OYCg8=", + "lastModified": 1678875422, + "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e37ef84b478fa8da0ced96522adfd956fde9047a", + "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", "type": "github" }, "original": { @@ -212,27 +212,27 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1671271954, - "narHash": "sha256-cSvu+bnvN08sOlTBWbBrKaBHQZq8mvk8bgpt0ZJ2Snc=", + "lastModified": 1678872516, + "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d513b448cc2a6da2c8803e3c197c9fc7e67b19e3", + "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-22.05", + "ref": "nixos-22.11", "repo": "nixpkgs", "type": "github" } }, "nixpkgs_2": { "locked": { - "lastModified": 1701069268, - "narHash": "sha256-DUotrFaAqFMze0+K1fttMzKyq8RTQapzcbjVkYnsNeM=", + "lastModified": 1701417047, + "narHash": "sha256-c7/mCMxHgrx+shWmdUtX/vThGeymGtZH4okg/gdtRco=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "45be9e40f50c6cff87b24342cf54559640a833cb", + "rev": "742049b53ce0e0d1b5aacc5836d3edf32b9cd3b3", "type": "github" }, "original": { @@ -251,11 +251,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1701038883, - "narHash": "sha256-gF/OTqn7LYsSNHKmk8Ijq0d3uSJWRNtxMoNz3MOzagA=", + "lastModified": 1701399357, + "narHash": "sha256-QSGP2J73HQ4gF5yh+MnClv2KUKzcpTmikdmV8ULfq2E=", "owner": "nix-community", "repo": "poetry2nix", - "rev": "add5dfd40aba10fb6dc82b6abf9495fdf9f33427", + "rev": "7acb78166a659d6afe9b043bb6fe5cb5e86bb75e", "type": "github" }, "original": { @@ -273,11 +273,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1671452357, - "narHash": "sha256-HqzXiQEegpRQ4VEl9pEPgHSIxhJrNJ27HfN1wOc7w2E=", + "lastModified": 1686050334, + "narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "200790e9c77064c53eaf95805b013d96615ecc27", + "rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 8bcea7160..b222c6348 100644 --- a/flake.nix +++ b/flake.nix @@ -14,7 +14,7 @@ ]; }; inputs = { - devenv.url = "github:cachix/devenv/v0.5"; + devenv.url = "github:cachix/devenv/latest"; flake-compat = { url = github:edolstra/flake-compat; flake = false; @@ -91,16 +91,15 @@ # IDE integration tools alejandra - black commitizen - isort mypy nodePackages.prettier + ruff + taplo ]; difftastic.enable = true; pre-commit.hooks = { alejandra.enable = true; - black.enable = true; commitizen.enable = true; editorconfig-checker.enable = true; editorconfig-checker.excludes = [ @@ -108,8 +107,6 @@ "\.noeof\." "\.bundle$" ]; - flake8.enable = true; - isort.enable = true; prettier.enable = true; prettier.excludes = [ # Those files have wrong syntax and would fail @@ -118,6 +115,8 @@ # HACK https://github.com/prettier/prettier/issues/9430 "^tests/demo" ]; + ruff.enable = true; + taplo.enable = true; }; } ]; diff --git a/pyproject.toml b/pyproject.toml index 69fe1562c..682489ac2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,15 +5,15 @@ version = "0.0.0" description = "A library for rendering project templates." license = "MIT" classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] authors = ["Ben Felder "] homepage = "https://github.com/copier-org/copier" @@ -27,7 +27,7 @@ copier = "copier.__main__:copier_app_run" "Bug Tracker" = "https://github.com/copier-org/copier/issues" [tool.poetry.dependencies] -python = ">=3.8,<4.0" # HACK https://github.com/PyCQA/isort/issues/1945 +python = ">=3.8" colorama = ">=0.4.6" decorator = ">=5.1.1" dunamai = ">=1.7.0" @@ -109,28 +109,28 @@ enable = true style = "pep440" vcs = "git" -[tool.black] -target-version = ["py38"] +[tool.ruff.lint] +extend-select = ["B", "D", "E", "F", "I", "UP"] +extend-ignore = ['B028', "B904", "D105", "D107", "E501"] -[tool.isort] -profile = "black" -combine_as_imports = true -known_first_party = ["copier"] +[tool.ruff.lint.per-file-ignores] +"tests/**" = ["D"] + +[tool.ruff.lint.isort] +combine-as-imports = true +known-first-party = ["copier"] + +[tool.ruff.lint.pydocstyle] +convention = "google" [tool.mypy] ignore_missing_imports = true plugins = ["pydantic.mypy"] warn_no_return = false -[tool.pydocstyle] -match_dir = "^copier" -add_ignore = ["D105", "D107"] - [tool.pytest.ini_options] addopts = "-n auto -ra" -markers = [ - "impure: needs network or is not 100% reproducible" -] +markers = ["impure: needs network or is not 100% reproducible"] [tool.commitizen] annotated_tag = true diff --git a/tests/test_config.py b/tests/test_config.py index cce5170ce..64848020c 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -124,7 +124,7 @@ def test_invalid_config_data( ) -> None: template = Template(conf_path) with pytest.raises(InvalidConfigFileError): - template.config_data + template.config_data # noqa: B018 if check_err: _, err = capsys.readouterr() assert check_err(err) @@ -198,7 +198,7 @@ def test_config_data_empty() -> None: def test_multiple_config_file_error() -> None: template = Template("tests/demo_multi_config") with pytest.raises(MultipleConfigFilesError): - template.config_data + template.config_data # noqa: B018 # ConfigData