Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style: tighten ruff lints #1557

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions copier/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Copier CLI entrypoint."""

from .cli import CopierApp

# HACK https://github.com/nix-community/poetry2nix/issues/504
Expand Down
19 changes: 8 additions & 11 deletions copier/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ def _handle_exceptions(method: Callable[[], None]) -> int:
try:
try:
method()
except KeyboardInterrupt:
raise UserMessageError("Execution stopped by user")
except KeyboardInterrupt as e:
raise UserMessageError("Execution stopped by user") from e
except UserMessageError as error:
print(colors.red | "\n".join(error.args), file=sys.stderr)
return 1
Expand All @@ -84,21 +84,18 @@ class CopierApp(cli.Application):
"""The Copier CLI application."""

DESCRIPTION = "Create a new project from a template."
DESCRIPTION_MORE = (
dedent(
"""\
DESCRIPTION_MORE = dedent(
"""\
Docs in https://copier.readthedocs.io/

"""
)
+ (
colors.yellow
| dedent(
"""\
) + (
colors.yellow
| dedent(
"""\
WARNING! Use only trusted project templates, as they might
execute code with the same level of access as your user.\n
"""
)
)
)
VERSION = copier_version()
Expand Down
3 changes: 2 additions & 1 deletion copier/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ def __init__(self, features: Sequence[str]):
s = "s" if len(features) > 1 else ""
super().__init__(
f"Template uses potentially unsafe feature{s}: {', '.join(features)}.\n"
"If you trust this template, consider adding the `--trust` option when running `copier copy/update`."
"If you trust this template, consider adding the `--trust` option when"
"running `copier copy/update`."
)


Expand Down
19 changes: 12 additions & 7 deletions copier/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Main functions and classes, used to generate or update projects."""

from __future__ import annotations

import os
Expand Down Expand Up @@ -119,12 +120,14 @@ class Worker:
See [cleanup_on_error][].

defaults:
When `True`, use default answers to questions, which might be null if not specified.
When `True`, use default answers to questions, which might be null if not
specified.

See [defaults][].

user_defaults:
Specify user defaults that may override a template's defaults during question prompts.
Specify user defaults that may override a template's defaults during
question prompts.

overwrite:
When `True`, Overwrite files that already exist, without asking.
Expand Down Expand Up @@ -497,7 +500,7 @@ def jinja_env(self) -> SandboxedEnvironment:
f"Copier could not load some Jinja extensions:\n{error}\n"
"Make sure to install these extensions alongside Copier itself.\n"
"See the docs at https://copier.readthedocs.io/en/latest/configuring/#jinja_extensions"
)
) from error
# patch the `to_json` filter to support Pydantic dataclasses
env.filters["to_json"] = partial(
env.filters["to_json"], default=to_jsonable_python
Expand Down Expand Up @@ -801,8 +804,8 @@ def run_update(self) -> None:
raise UserMessageError("Cannot update: version from template not detected.")
if self.subproject.template.version > self.template.version:
raise UserMessageError(
f"You are downgrading from {self.subproject.template.version} to {self.template.version}. "
"Downgrades are not supported."
f"You are downgrading from {self.subproject.template.version} to "
f"{self.template.version}. Downgrades are not supported."
)
if not self.overwrite:
# Only git-tracked subprojects can be updated, so the user can
Expand Down Expand Up @@ -865,7 +868,8 @@ def _apply_update(self): # noqa: C901
self._execute_tasks(
self.template.migration_tasks("before", self.subproject.template)
)
# Clear last answers cache to load possible answers migration, if skip_answered flag is not set
# Clear last answers cache to load possible answers migration, if
# skip_answered flag is not set
if self.skip_answered is False:
self.answers = AnswersMap()
with suppress(AttributeError):
Expand Down Expand Up @@ -947,7 +951,8 @@ def _apply_update(self): # noqa: C901
# see SO post: https://stackoverflow.com/questions/77391627/
# and Git docs: https://git-scm.com/docs/git-update-index#_using_index_info.
# For each file with conflict markers, we update the index to add
# higher order versions of their paths, without entries for resolved contents.
# higher order versions of their paths, without entries for resolved
# contents.
if conflicted:
input_lines = []
for line in (
Expand Down
1 change: 1 addition & 0 deletions copier/subproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

A *subproject* is a project that gets rendered and/or updated with Copier.
"""

from __future__ import annotations

from dataclasses import field
Expand Down
1 change: 1 addition & 0 deletions copier/template.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Tools related to template management."""

from __future__ import annotations

import re
Expand Down
11 changes: 7 additions & 4 deletions copier/tools.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Some utility functions."""

from __future__ import annotations

import errno
Expand Down Expand Up @@ -152,7 +153,8 @@ def force_str_end(original_str: str, end: str = "\n") -> str:
def handle_remove_readonly(
func: Callable,
path: str,
# TODO: Change this union to simply `BaseException` when Python 3.11 support is dropped
# TODO: Change this union to simply `BaseException` when Python 3.11 support is
# dropped
exc: BaseException | tuple[type[BaseException], BaseException, TracebackType],
) -> None:
"""Handle errors when trying to remove read-only files through `shutil.rmtree`.
Expand All @@ -178,7 +180,8 @@ def handle_remove_readonly(
def readlink(link: Path) -> Path:
"""A custom version of os.readlink/pathlib.Path.readlink.

pathlib.Path.readlink is what we ideally would want to use, but it is only available on python>=3.9.
pathlib.Path.readlink is what we ideally would want to use, but it is only available
on python>=3.9.
"""
if sys.version_info >= (3, 9):
return link.readlink()
Expand All @@ -196,8 +199,8 @@ def _re_octal_replace(match: re.Match) -> str:
def normalize_git_path(path: str) -> str:
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`.
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.
Expand Down
5 changes: 3 additions & 2 deletions copier/user_data.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Functions used to load user data."""

from __future__ import annotations

import json
Expand Down Expand Up @@ -41,7 +42,7 @@
def _make_secret() -> str:
warnings.warn(
"'make_secret' will be removed in a future release of Copier.\n"
"Please use this instead: {{ 999999999999999999999999999999999|ans_random|hash('sha512') }}\n"
"Please use this instead: {{ 999999999999999999999999999999999|ans_random|hash('sha512') }}\n" # noqa: E501
"random and hash filters documentation: https://docs.ansible.com/ansible/2.3/playbooks_filters.html",
FutureWarning,
)
Expand Down Expand Up @@ -476,7 +477,7 @@
try:
return yaml.safe_load(string)
except yaml.error.YAMLError as error:
raise ValueError(str(error))
raise ValueError(str(error)) from error

Check warning on line 480 in copier/user_data.py

View check run for this annotation

Codecov / codecov/patch

copier/user_data.py#L480

Added line #L480 was not covered by tests


def load_answersfile_data(
Expand Down
5 changes: 3 additions & 2 deletions copier/vcs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Utilities related to VCS."""

import os
import re
import sys
Expand Down Expand Up @@ -172,8 +173,8 @@ def clone(url: str, ref: OptStr = None) -> str:
file_url = url
if is_git_shallow_repo(file_url):
warn(
f"The repository '{url}' is a shallow clone, this might lead to unexpected "
"failure or unusually high resource consumption.",
f"The repository '{url}' is a shallow clone, this might lead to "
"unexpected failure or unusually high resource consumption.",
ShallowCloneWarning,
)
else:
Expand Down
8 changes: 5 additions & 3 deletions devtasks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Development helper tasks."""

import logging
import shutil
from pathlib import Path
Expand Down Expand Up @@ -78,9 +79,10 @@
)
except ProcessExecutionError:
_logger.info(
"Couldn't create copier-lint-v1 container, probably because a previous one exists. "
"Remove it if you want to recycle it. Otherwise, this is OK."
"Couldn't create copier-lint-v1 container, probably because a previous "
"one exists. Remove it if you want to recycle it. Otherwise, this is"
"OK."
danieleades marked this conversation as resolved.
Show resolved Hide resolved
)
runner["container", "start", "--attach", "copier-lint-v1"] & TEE
except ProcessExecutionError as error:
raise SystemExit(error.errno)
raise SystemExit(error.errno) from error

Check warning on line 88 in devtasks.py

View check run for this annotation

Codecov / codecov/patch

devtasks.py#L88

Added line #L88 was not covered by tests
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,11 @@ extend-select = [
"PGH",
"UP",
]
extend-ignore = ['B028', "B904", "D105", "D107", "E501"]
ignore = ["B028"]

[tool.ruff.lint.per-file-ignores]
"tests/**" = ["D"]
"tests/**" = ["D100", "D101", "D102", "D103", "D104", "D107"]
"copier/errors.py" = ["D107"]

[tool.ruff.lint.isort]
combine-as-imports = true
Expand Down
8 changes: 3 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ def _spawn(cmd: tuple[str, ...], *, timeout: int | None = None) -> PopenSpawn:

@pytest.fixture(scope="session", autouse=True)
def default_gitconfig(default_gitconfig: GitConfig) -> GitConfig:
"""
Use a clean and isolated default gitconfig avoiding user settings to break some tests.
"""Use a clean and isolated default gitconfig avoiding user settings to break some tests.

Add plumbum support to the original session-scoped fixture.
"""
""" # noqa: E501
# local.env is a snapshot frozen at Python startup requiring its own monkeypatching
for var in list(local.env.keys()):
if var.startswith("GIT_"):
Expand All @@ -56,8 +55,7 @@ def default_gitconfig(default_gitconfig: GitConfig) -> GitConfig:

@pytest.fixture
def gitconfig(gitconfig: GitConfig) -> Iterator[GitConfig]:
"""
Use a clean and isolated gitconfig to test some specific user settings.
"""Use a clean and isolated gitconfig to test some specific user settings.

Add plumbum support to the original function-scoped fixture.
"""
Expand Down
5 changes: 2 additions & 3 deletions tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@


class Spawn(Protocol):
def __call__(self, cmd: tuple[str, ...], *, timeout: int | None) -> PopenSpawn:
...
def __call__(self, cmd: tuple[str, ...], *, timeout: int | None) -> PopenSpawn: ...


class Keyboard(str, Enum):
Expand Down Expand Up @@ -124,7 +123,7 @@ def build_file_tree(spec: Mapping[StrOrPath, str | bytes | Path], dedent: bool =
def expect_prompt(
tui: PopenSpawn, name: str, expected_type: str, help: OptStr = None
) -> None:
"""Check that we get a prompt in the standard form"""
"""Check that we get a prompt in the standard form."""
if help:
tui.expect_exact(help)
else:
Expand Down
24 changes: 11 additions & 13 deletions tests/test_answersfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,15 @@
@pytest.fixture(scope="module")
def template_path(tmp_path_factory: pytest.TempPathFactory) -> str:
root = tmp_path_factory.mktemp("template")
build_file_tree(
{
(root / "[[ _copier_conf.answers_file ]].tmpl"): (
"""\
build_file_tree({
(root / "[[ _copier_conf.answers_file ]].tmpl"): (
"""\
# Changes here will be overwritten by Copier
[[ _copier_answers|to_nice_yaml ]]
"""
),
(root / "copier.yml"): (
f"""\
),
(root / "copier.yml"): (
f"""\
_answers_file: .answers-file-changed-in-template.yml
_templates_suffix: {SUFFIX_TMPL}
_envops: {BRACKET_ENVOPS_JSON}
Expand All @@ -38,16 +37,15 @@ def template_path(tmp_path_factory: pytest.TempPathFactory) -> str:
secret: yes
default: password two
"""
),
(root / "round.txt.tmpl"): (
"""\
),
(root / "round.txt.tmpl"): (
"""\
It's the [[round]] round.
password_1=[[password_1]]
password_2=[[password_2]]
"""
),
}
)
),
})
return str(root)


Expand Down
3 changes: 1 addition & 2 deletions tests/test_answersfile_templating.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ def template_path(tmp_path_factory: pytest.TempPathFactory) -> str:
def test_answersfile_templating(
template_path: str, tmp_path: Path, answers_file: str | None
) -> None:
"""
Test copier behaves properly when _answers_file contains a template
"""Test copier behaves properly when _answers_file contains a template.

Checks that template is resolved successfully and that a subsequent
copy that resolves to a different answers file doesn't clobber the
Expand Down
Loading
Loading