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

chore: add more Ruff checks and fixes #893

Open
wants to merge 3 commits into
base: main
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
18 changes: 12 additions & 6 deletions .github/action_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ def filter_version(version: str) -> str:

version_parts = version_.split(".")
if len(version_parts) < 2:
raise ValueError(f"invalid version: {version}")
msg = f"invalid version: {version}"
raise ValueError(msg)
if not version_parts[0].isdigit():
raise ValueError(f"invalid major python version: {version}")
msg = f"invalid major python version: {version}"
raise ValueError(msg)
if not version_parts[1].isdigit():
raise ValueError(f"invalid minor python version: {version}")
msg = f"invalid minor python version: {version}"
raise ValueError(msg)
return ".".join(version_parts[:2])


Expand All @@ -36,20 +39,22 @@ def setup_action(input_: str) -> None:
pypy_versions = [version for version in versions if version.startswith("pypy")]
pypy_versions_filtered = [filter_version(version) for version in pypy_versions]
if len(pypy_versions) != len(set(pypy_versions_filtered)):
raise ValueError(
msg = (
"multiple versions specified for the same 'major.minor' PyPy interpreter:"
f" {pypy_versions}"
)
raise ValueError(msg)

cpython_versions = [version for version in versions if version not in pypy_versions]
cpython_versions_filtered = [
filter_version(version) for version in cpython_versions
]
if len(cpython_versions) != len(set(cpython_versions_filtered)):
raise ValueError(
msg = (
"multiple versions specified for the same 'major.minor' CPython"
f" interpreter: {cpython_versions}"
)
raise ValueError(msg)

# cpython shall be installed last because
# other interpreters also define pythonX.Y symlinks.
Expand All @@ -70,5 +75,6 @@ def setup_action(input_: str) -> None:

if __name__ == "__main__":
if len(sys.argv) != 2:
raise AssertionError(f"invalid arguments: {sys.argv}")
msg = f"invalid arguments: {sys.argv}"
raise AssertionError(msg)
setup_action(sys.argv[1])
4 changes: 2 additions & 2 deletions nox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from nox import project
from nox._cli import main
from nox._options import noxfile_options as options
from nox._parametrize import Param as param
from nox._parametrize import Param as param # noqa: N813
from nox._parametrize import parametrize_decorator as parametrize
from nox.registry import session_decorator as session
from nox.sessions import Session
Expand All @@ -26,11 +26,11 @@

__all__ = [
"Session",
"main",
"needs_version",
"options",
"param",
"parametrize",
"project",
"session",
"main",
]
14 changes: 7 additions & 7 deletions nox/_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
import functools
import inspect
import types
from collections.abc import Iterable, Mapping, Sequence
from typing import TYPE_CHECKING, Any, Callable, TypeVar, cast

from . import _typing

if TYPE_CHECKING:
from collections.abc import Iterable, Mapping, Sequence

from . import _typing
from ._parametrize import Param

T = TypeVar("T", bound=Callable[..., Any])
Expand All @@ -32,12 +32,12 @@
class FunctionDecorator:
"""This is a function decorator."""

def __new__(
def __new__( # noqa: PYI034
cls: Any, func: Callable[..., Any], *args: Any, **kwargs: Any
) -> FunctionDecorator:
obj = super().__new__(cls)
functools.update_wrapper(obj, func)
return cast(FunctionDecorator, obj)
self = super().__new__(cls)
functools.update_wrapper(self, func)
return cast(FunctionDecorator, self)


def _copy_func(src: T, name: str | None = None) -> T:
Expand Down
15 changes: 9 additions & 6 deletions nox/_option_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@
import functools
from argparse import ArgumentError as ArgumentError # noqa: PLC0414
from argparse import ArgumentParser, Namespace
from collections.abc import Callable, Iterable
from typing import Any, Literal
from typing import TYPE_CHECKING, Any, Literal

import argcomplete
import attrs
import attrs.validators as av

if TYPE_CHECKING:
from collections.abc import Callable, Iterable

av_opt_str = av.optional(av.instance_of(str))
av_opt_list_str = av.optional(
av.deep_iterable(
Expand Down Expand Up @@ -198,6 +200,7 @@ def make_flag_pair(
name: str,
enable_flags: tuple[str, str] | tuple[str],
disable_flags: tuple[str, str] | tuple[str],
*,
default: bool | Callable[[], bool] = False,
**kwargs: Any,
) -> tuple[Option, Option]:
Expand Down Expand Up @@ -277,9 +280,8 @@ def parser(self) -> ArgumentParser:

# Every option must have a group (except for hidden options)
if option.group is None:
raise ValueError(
f"Option {option.name} must either have a group or be hidden."
)
msg = f"Option {option.name} must either have a group or be hidden."
raise ValueError(msg)

argument = groups[option.group.name].add_argument(
*option.flags, help=option.help, default=option.default, **option.kwargs
Expand Down Expand Up @@ -331,7 +333,8 @@ def namespace(self, **kwargs: Any) -> argparse.Namespace:
# used in tests.
for key, value in kwargs.items():
if key not in args:
raise KeyError(f"{key} is not an option.")
msg = f"{key} is not an option."
raise KeyError(msg)
args[key] = value

return argparse.Namespace(**args)
Expand Down
35 changes: 22 additions & 13 deletions nox/_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@
import itertools
import os
import sys
from collections.abc import Iterable
from typing import Any, Callable, Literal, Sequence
from typing import TYPE_CHECKING, Any, Callable, Literal, Sequence

import argcomplete

from nox import _option_set
from nox._option_set import NoxOptions
from nox.tasks import discover_manifest, filter_manifest, load_nox_module
from nox.virtualenv import ALL_VENVS

if TYPE_CHECKING:
from collections.abc import Iterable

from nox._option_set import NoxOptions

ReuseVenvType = Literal["no", "yes", "never", "always"]

"""All of Nox's configuration options."""
Expand Down Expand Up @@ -129,9 +132,8 @@ def _force_venv_backend_merge_func(
command_args.force_venv_backend is not None
and command_args.force_venv_backend != "none"
):
raise ValueError(
"You can not use `--no-venv` with a non-none `--force-venv-backend`"
)
msg = "You can not use `--no-venv` with a non-none `--force-venv-backend`"
raise ValueError(msg)
return "none"
return command_args.force_venv_backend or noxfile_args.force_venv_backend # type: ignore[return-value]

Expand Down Expand Up @@ -191,7 +193,7 @@ def _default_list() -> list[str] | None:
return _default_list


def _color_finalizer(value: bool, args: argparse.Namespace) -> bool:
def _color_finalizer(_value: bool, args: argparse.Namespace) -> bool: # noqa: FBT001
"""Figures out the correct value for "color" based on the two color flags.

Args:
Expand Down Expand Up @@ -224,7 +226,7 @@ def _force_pythons_finalizer(
return value


def _R_finalizer(value: bool, args: argparse.Namespace) -> bool:
def _R_finalizer(value: bool, args: argparse.Namespace) -> bool: # noqa: FBT001
"""Propagate -R to --reuse-existing-virtualenvs and --no-install and --reuse-venv=yes."""
if value:
args.reuse_venv = "yes"
Expand All @@ -233,7 +235,8 @@ def _R_finalizer(value: bool, args: argparse.Namespace) -> bool:


def _reuse_existing_virtualenvs_finalizer(
value: bool, args: argparse.Namespace
value: bool, # noqa: FBT001
args: argparse.Namespace,
) -> bool:
"""Propagate --reuse-existing-virtualenvs to --reuse-venv=yes."""
if value:
Expand All @@ -242,7 +245,7 @@ def _reuse_existing_virtualenvs_finalizer(


def _posargs_finalizer(
value: Sequence[Any], args: argparse.Namespace
value: Sequence[Any], _args: argparse.Namespace
) -> Sequence[Any] | list[Any]:
"""Removes the leading "--"s in the posargs array (if any) and asserts that
remaining arguments came after a "--".
Expand All @@ -268,7 +271,9 @@ def _posargs_finalizer(


def _python_completer(
prefix: str, parsed_args: argparse.Namespace, **kwargs: Any
prefix: str, # noqa: ARG001
parsed_args: argparse.Namespace,
**kwargs: Any,
) -> Iterable[str]:
module = load_nox_module(parsed_args)
manifest = discover_manifest(module, parsed_args)
Expand All @@ -282,7 +287,9 @@ def _python_completer(


def _session_completer(
prefix: str, parsed_args: argparse.Namespace, **kwargs: Any
prefix: str, # noqa: ARG001
parsed_args: argparse.Namespace,
**kwargs: Any,
) -> Iterable[str]:
parsed_args.list_sessions = True
module = load_nox_module(parsed_args)
Expand All @@ -296,7 +303,9 @@ def _session_completer(


def _tag_completer(
prefix: str, parsed_args: argparse.Namespace, **kwargs: Any
prefix: str, # noqa: ARG001
parsed_args: argparse.Namespace,
**kwargs: Any,
) -> Iterable[str]:
module = load_nox_module(parsed_args)
manifest = discover_manifest(module, parsed_args)
Expand Down
12 changes: 7 additions & 5 deletions nox/_parametrize.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@

import functools
import itertools
from collections.abc import Callable, Sequence
from typing import Any, Iterable, Union
from typing import TYPE_CHECKING, Any, Iterable, Union

if TYPE_CHECKING:
from collections.abc import Callable, Sequence


class Param:
Expand Down Expand Up @@ -73,9 +75,9 @@ def copy(self) -> Param:

def update(self, other: Param) -> None:
self.id = ", ".join([str(self), str(other)])
self.args = self.args + other.args
self.arg_names = self.arg_names + other.arg_names
self.tags = self.tags + other.tags
self.args += other.args
self.arg_names += other.arg_names
self.tags += other.tags

def __eq__(self, other: object) -> bool:
if isinstance(other, self.__class__):
Expand Down
6 changes: 4 additions & 2 deletions nox/_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class CycleError(ValueError):
def lazy_stable_topo_sort(
dependencies: Mapping[Node, Iterable[Node]],
root: Node,
*,
drop_root: bool = True,
) -> Iterator[Node]:
"""Returns the "lazy, stable" topological sort of a dependency graph.
Expand Down Expand Up @@ -118,7 +119,7 @@ def lazy_stable_topo_sort(
~nox._resolver.CycleError: If a dependency cycle is encountered.
"""

visited = {node: False for node in dependencies}
visited = dict.fromkeys(dependencies, False)

def prepended_by_dependencies(
node: Node,
Expand Down Expand Up @@ -191,7 +192,8 @@ def extend_walk(
# Dependency cycle found.
walk_list = list(walk)
cycle = walk_list[walk_list.index(node) :] + [node]
raise CycleError("Nodes are in a dependency cycle", tuple(cycle))
msg = "Nodes are in a dependency cycle"
raise CycleError(msg, tuple(cycle))
walk[node] = None
return walk

Expand Down
7 changes: 3 additions & 4 deletions nox/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def _parse_needs_version(source: str, filename: str = "<unknown>") -> str | None

def _read_needs_version(filename: str) -> str | None:
"""Read ``nox.needs_version`` from the user's Noxfile."""
with open(filename) as io:
with open(filename, encoding="utf-8") as io:
source = io.read()

return _parse_needs_version(source, filename=filename)
Expand All @@ -81,9 +81,8 @@ def _check_nox_version_satisfies(needs_version: str) -> None:
raise InvalidVersionSpecifier(message) from error

if not specifiers.contains(version, prereleases=True):
raise VersionCheckFailed(
f"The Noxfile requires Nox {specifiers}, you have {version}"
)
msg = f"The Noxfile requires Nox {specifiers}, you have {version}"
raise VersionCheckFailed(msg)


def check_nox_version(filename: str) -> None:
Expand Down
19 changes: 10 additions & 9 deletions nox/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@
import shutil
import subprocess
import sys
from collections.abc import Iterable, Mapping, Sequence
from typing import Literal
from typing import TYPE_CHECKING, Literal

from nox.logger import logger
from nox.popen import DEFAULT_INTERRUPT_TIMEOUT, DEFAULT_TERMINATE_TIMEOUT, popen

TYPE_CHECKING = False

if TYPE_CHECKING:
from collections.abc import Iterable, Mapping, Sequence
from typing import IO

ExternalType = Literal["error", True, False]
Expand All @@ -53,7 +51,8 @@ def which(program: str | os.PathLike[str], paths: Sequence[str] | None) -> str:
return os.fspath(full_path)

logger.error(f"Program {program} not found.")
raise CommandFailed(f"Program {program} not found")
msg = f"Program {program} not found"
raise CommandFailed(msg)


def _clean_env(env: Mapping[str, str | None] | None = None) -> dict[str, str] | None:
Expand Down Expand Up @@ -111,7 +110,8 @@ def run(
f" at {cmd_path}. Pass external=True into run() to explicitly allow"
" this."
)
raise CommandFailed("External program disallowed.")
msg = "External program disallowed."
raise CommandFailed(msg)
if external is False:
logger.warning(
f"Warning: {cmd} is not installed into the virtualenv, it is"
Expand Down Expand Up @@ -141,13 +141,14 @@ def run(
if silent:
sys.stderr.write(output)

raise CommandFailed(f"Returned code {return_code}")
msg = f"Returned code {return_code}"
raise CommandFailed(msg)

if output:
logger.output(output)

return output if silent else True

except KeyboardInterrupt:
logger.error("Interrupted...")
raise

return output if silent else True
Loading
Loading