diff --git a/pyproject.toml b/pyproject.toml index 4184eb7..f442f98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,6 +67,8 @@ strict = true allow-init-docstring = true arg-type-hints-in-docstring = false check-return-types = false +show-filenames-in-every-violation-message = true +skip-checking-short-docstrings = false style = 'google' [tool.pylint] diff --git a/src/ansible_dev_environment/arg_parser.py b/src/ansible_dev_environment/arg_parser.py index a004f22..67bfe6e 100644 --- a/src/ansible_dev_environment/arg_parser.py +++ b/src/ansible_dev_environment/arg_parser.py @@ -6,8 +6,12 @@ from argparse import HelpFormatter from pathlib import Path +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from typing import Any + try: from ._version import version as __version__ # type: ignore[unused-ignore,import-not-found] except ImportError: # pragma: no cover @@ -214,12 +218,17 @@ def parse() -> argparse.Namespace: class ArgumentParser(argparse.ArgumentParser): """A custom argument parser.""" - def add_argument( # type: ignore[no-untyped-def, override] + def add_argument( # type: ignore[override] self: ArgumentParser, - *args, # noqa: ANN002 - **kwargs, # noqa: ANN003 + *args: Any, # noqa: ANN401 + **kwargs: Any, # noqa: ANN401 ) -> None: - """Add an argument.""" + """Add an argument. + + Args: + *args: The arguments + **kwargs: The keyword arguments + """ if "choices" in kwargs: kwargs["help"] += f" (choices: {', '.join(kwargs['choices'])})" if "default" in kwargs and kwargs["default"] != "==SUPPRESS==": @@ -234,7 +243,8 @@ class CustomHelpFormatter(HelpFormatter): def __init__(self: CustomHelpFormatter, prog: str) -> None: """Initialize the help formatter. - :param prog: The program name + Args: + prog: The program name """ long_string = "--abc --really_really_really_log" # 3 here accounts for the spaces in the ljust(6) below diff --git a/src/ansible_dev_environment/collection.py b/src/ansible_dev_environment/collection.py index 25ba502..9a23233 100644 --- a/src/ansible_dev_environment/collection.py +++ b/src/ansible_dev_environment/collection.py @@ -54,7 +54,13 @@ def build_dir(self: Collection) -> Path: @property def site_pkg_path(self: Collection) -> Path: - """Return the site packages collection path.""" + """Return the site packages collection path. + + Returns: + The site packages collection path + Raises: + RuntimeError: If the collection namespace or name is not set + """ if not self.cnamespace or not self.cname: msg = "Collection namespace or name not set." raise RuntimeError(msg) diff --git a/src/ansible_dev_environment/config.py b/src/ansible_dev_environment/config.py index 2a9ba74..397b469 100644 --- a/src/ansible_dev_environment/config.py +++ b/src/ansible_dev_environment/config.py @@ -31,7 +31,13 @@ def __init__( output: Output, term_features: TermFeatures, ) -> None: - """Initialize the configuration.""" + """Initialize the configuration. + + Args: + args: The command line arguments + output: The output object + term_features: The terminal features + """ self._create_venv: bool = False self.args: Namespace = args self.bindir: Path diff --git a/src/ansible_dev_environment/output.py b/src/ansible_dev_environment/output.py index 5481261..577f14f 100644 --- a/src/ansible_dev_environment/output.py +++ b/src/ansible_dev_environment/output.py @@ -30,8 +30,10 @@ def round_half_up(number: float) -> int: This will always round based on distance from zero. (e.g round(2.5) = 3, round(3.5) = 4). - :param number: The number to round - :returns: The rounded number as an it + Args: + number: The number to round + Returns: + The rounded number as an it """ rounded = decimal.Decimal(number).quantize( decimal.Decimal("1"), @@ -43,7 +45,8 @@ def round_half_up(number: float) -> int: def console_width() -> int: """Get a console width based on common screen widths. - :returns: The console width + Returns: + The console width """ medium = 80 wide = 132 @@ -109,7 +112,8 @@ def log_level(self: Level) -> int: def _longest_name(cls: type[T]) -> int: """Return the longest exit message prefix. - :returns: The longest exit message prefix + Returns: + The longest exit message prefix """ return max(len(member.value) for member in cls) @@ -117,14 +121,16 @@ def _longest_name(cls: type[T]) -> int: def longest_formatted(cls: type[T]) -> int: """Return the longest exit message prefix. - :returns: The longest exit message prefix + Returns: + The longest exit message prefix """ return max(len(str(member)) for member in cls) def __str__(self: Level) -> str: """Return the exit message prefix as a string. - :returns: The exit message prefix as a string + Returns: + The exit message prefix as a string """ return ( f"{' ' * (self._longest_name() - len(self.name))}{self.name.capitalize()}: " @@ -165,10 +171,12 @@ def to_lines( ) -> list[str]: """Output exit message to the console. - :param color: Whether to color the message - :param width: Constrain message to width - :param with_prefix: Whether to prefix the message - :returns: The exit message as a string + Args: + color: Whether to color the message + width: Constrain message to width + with_prefix: Whether to prefix the message + Returns: + The exit message as a string """ prefix_length = Level.longest_formatted() indent = " " * prefix_length @@ -256,7 +264,8 @@ def __init__( # noqa: PLR0913 def critical(self: Output, msg: str) -> None: """Print a critical message to the console. - :param msg: The message to print + Args: + msg: The message to print """ self.call_count["critical"] += 1 self.log(msg, level=Level.CRITICAL) @@ -265,7 +274,8 @@ def critical(self: Output, msg: str) -> None: def debug(self: Output, msg: str) -> None: """Print a debug message to the console. - :param msg: The message to print + Args: + msg: The message to print """ self.call_count["debug"] += 1 self.log(msg, level=Level.DEBUG) @@ -273,7 +283,8 @@ def debug(self: Output, msg: str) -> None: def error(self: Output, msg: str) -> None: """Print an error message to the console. - :param msg: The message to print + Args: + msg: The message to print """ self.call_count["error"] += 1 self.log(msg, level=Level.ERROR) @@ -281,7 +292,8 @@ def error(self: Output, msg: str) -> None: def hint(self: Output, msg: str) -> None: """Print a hint message to the console. - :param msg: The message to print + Args: + msg: The message to print """ self.call_count["hint"] += 1 self.log(msg, level=Level.HINT) @@ -289,7 +301,8 @@ def hint(self: Output, msg: str) -> None: def info(self: Output, msg: str) -> None: """Print a hint message to the console. - :param msg: The message to print + Args: + msg: The message to print """ self.call_count["info"] += 1 self.log(msg, level=Level.INFO) @@ -297,7 +310,8 @@ def info(self: Output, msg: str) -> None: def note(self: Output, msg: str) -> None: """Print a note message to the console. - :param msg: The message to print + Args: + msg: The message to print """ self.call_count["note"] += 1 self.log(msg, level=Level.NOTE) @@ -305,7 +319,8 @@ def note(self: Output, msg: str) -> None: def warning(self: Output, msg: str) -> None: """Print a warning message to the console. - :param msg: The message to print + Args: + msg: The message to print """ self.call_count["warning"] += 1 self.log(msg, level=Level.WARNING) @@ -313,8 +328,9 @@ def warning(self: Output, msg: str) -> None: def log(self: Output, msg: str, level: Level = Level.ERROR) -> None: """Print a message to the console. - :param msg: The message to print - :param prefix: The prefix for the message + Args: + msg: The message to print + level: The message level """ if self.log_to_file: self.logger.log(level.log_level, msg, stacklevel=3) diff --git a/src/ansible_dev_environment/subcommands/installer.py b/src/ansible_dev_environment/subcommands/installer.py index 08c6efd..b7c36ff 100644 --- a/src/ansible_dev_environment/subcommands/installer.py +++ b/src/ansible_dev_environment/subcommands/installer.py @@ -146,7 +146,11 @@ def _install_galaxy_collections( self: Installer, collections: list[Collection], ) -> None: - """Install the collection from galaxy.""" + """Install the collection from galaxy. + + Args: + collections: The collection objects. + """ collections_str = " ".join( [f"'{collection.original}'" for collection in collections], ) diff --git a/src/ansible_dev_environment/subcommands/lister.py b/src/ansible_dev_environment/subcommands/lister.py index a259601..55e7ef3 100644 --- a/src/ansible_dev_environment/subcommands/lister.py +++ b/src/ansible_dev_environment/subcommands/lister.py @@ -26,7 +26,11 @@ def __init__(self: Lister, config: Config, output: Output) -> None: self._output = output def run(self: Lister) -> None: - """Run the Lister.""" + """Run the Lister. + + Raises: + TypeError: If the link is not a string. + """ # pylint: disable=too-many-locals collections = collect_manifests( target=self._config.site_pkg_collections_path, diff --git a/src/ansible_dev_environment/subcommands/treemaker.py b/src/ansible_dev_environment/subcommands/treemaker.py index 3f2e40a..70b8841 100644 --- a/src/ansible_dev_environment/subcommands/treemaker.py +++ b/src/ansible_dev_environment/subcommands/treemaker.py @@ -30,7 +30,11 @@ def __init__(self: TreeMaker, config: Config, output: Output) -> None: self._output = output def run(self: TreeMaker) -> None: # noqa: C901, PLR0912, PLR0915 - """Run the command.""" + """Run the command. + + Raises: + TypeError: If the tree dict is not a dict. + """ # pylint: disable=too-many-locals builder_introspect(self._config, self._output) diff --git a/src/ansible_dev_environment/tree.py b/src/ansible_dev_environment/tree.py index 77d07fc..da404ef 100644 --- a/src/ansible_dev_environment/tree.py +++ b/src/ansible_dev_environment/tree.py @@ -23,7 +23,12 @@ def __init__( obj: JSONVal, term_features: TermFeatures, ) -> None: - """Initialize the renderer.""" + """Initialize the renderer. + + Args: + obj: The object to render + term_features: The terminal features + """ self.obj = obj self._lines: list[str] = [] self.blue: list[ScalarVal] = [] @@ -85,7 +90,13 @@ def in_color(self: Tree, val: ScalarVal) -> str: @staticmethod def is_scalar(obj: JSONVal) -> bool: - """Check if the object is a scalar.""" + """Check if the object is a scalar. + + Args: + obj: The object to check + Returns: + Whether the object is a scalar + """ return isinstance(obj, str | int | float | bool) or obj is None def _print_tree( # noqa: C901, PLR0913, PLR0912 @@ -167,11 +178,19 @@ def _print_tree( # noqa: C901, PLR0913, PLR0912 raise TypeError(err) def append(self: Tree, string: str) -> None: - """Append a line to the output.""" + """Append a line to the output. + + Args: + string: The string to append + """ self._lines.append(string) def render(self: Tree) -> str: - """Render the root of the tree.""" + """Render the root of the tree. + + Returns: + The rendered tree + """ # if not isinstance(self.obj, dict): self._print_tree(self.obj, is_last=False, is_root=True, was_list=False) return "\n".join(self._lines) + "\n" diff --git a/src/ansible_dev_environment/utils.py b/src/ansible_dev_environment/utils.py index a625c70..fcf7994 100644 --- a/src/ansible_dev_environment/utils.py +++ b/src/ansible_dev_environment/utils.py @@ -42,7 +42,11 @@ class TermFeatures: links: bool def any_enabled(self: TermFeatures) -> bool: - """Return True if any features are enabled.""" + """Return True if any features are enabled. + + Returns: + True if any features are enabled + """ return any((self.color, self.links)) @@ -72,19 +76,19 @@ def term_link(uri: str, term_features: TermFeatures, label: str) -> str: class Ansi: """ANSI escape codes.""" - BLUE = "\x1B[34m" - BOLD = "\x1B[1m" - CYAN = "\x1B[36m" - GREEN = "\x1B[32m" - ITALIC = "\x1B[3m" - MAGENTA = "\x1B[35m" - RED = "\x1B[31m" - RESET = "\x1B[0m" - REVERSED = "\x1B[7m" - UNDERLINE = "\x1B[4m" - WHITE = "\x1B[37m" - YELLOW = "\x1B[33m" - GREY = "\x1B[90m" + BLUE = "\x1b[34m" + BOLD = "\x1b[1m" + CYAN = "\x1b[36m" + GREEN = "\x1b[32m" + ITALIC = "\x1b[3m" + MAGENTA = "\x1b[35m" + RED = "\x1b[31m" + RESET = "\x1b[0m" + REVERSED = "\x1b[7m" + UNDERLINE = "\x1b[4m" + WHITE = "\x1b[37m" + YELLOW = "\x1b[33m" + GREY = "\x1b[90m" def subprocess_run( # noqa: PLR0913 @@ -95,7 +99,18 @@ def subprocess_run( # noqa: PLR0913 cwd: Path | None = None, env: dict[str, str] | None = None, ) -> subprocess.CompletedProcess[str]: - """Run a subprocess command.""" + """Run a subprocess command. + + Args: + command: The command to run + verbose: The verbosity level + msg: The message to display + output: The output object + cwd: The current working directory + env: The environment variables + Returns: + The completed process + """ cmd = f"Running command: {command}" output.debug(cmd) log_level = logging.ERROR - (verbose * 10) @@ -123,8 +138,10 @@ def subprocess_run( # noqa: PLR0913 def oxford_join(words: list[str]) -> str: """Join a list of words with commas and an oxford comma. - :param words: A list of words to join - :return: A string of words joined with commas and an oxford comma + Args: + words: A list of words to join + Returns: + A string of words joined with commas and an oxford comma """ words.sort() if not words: @@ -139,8 +156,11 @@ def oxford_join(words: list[str]) -> str: def opt_deps_to_files(collection_path: Path, dep_str: str) -> list[Path]: """Convert a string of optional dependencies to a list of files. - :param dep_str: A string of optional dependencies - :return: A list of files + Args: + collection_path: The path to the collection + dep_str: A string of optional dependencies + Returns: + A list of files """ deps = dep_str.split(",") files = [] @@ -290,7 +310,13 @@ def builder_introspect(config: Config, output: Output) -> None: def collections_from_requirements(file: Path) -> list[dict[str, str]]: - """Build a list of collections from a requirements file.""" + """Build a list of collections from a requirements file. + + Args: + file: The requirements file + Returns: + A list of collections + """ collections = [] try: with file.open() as requirements_file: diff --git a/tests/integration/test_basic.py b/tests/integration/test_basic.py index 5b20da2..280d3ad 100644 --- a/tests/integration/test_basic.py +++ b/tests/integration/test_basic.py @@ -16,7 +16,13 @@ def test_venv( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: - """Basic smoke test.""" + """Basic smoke test. + + Args: + capsys: Capture stdout and stderr + tmp_path: Temporary directory + monkeypatch: Pytest monkeypatch + """ # disable color for json output term_features = TermFeatures(color=False, links=False) output = Output( @@ -108,7 +114,13 @@ def test_non_local( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: - """Install non-local collection.""" + """Install non-local collection. + + Args: + capsys: Capture stdout and stderr + tmp_path: Temporary directory + monkeypatch: Pytest monkeypatch + """ monkeypatch.setattr( "sys.argv", [ @@ -142,7 +154,14 @@ def test_requirements( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: - """Install non-local collection.""" + """Install non-local collection. + + Args: + capsys: Capture stdout and stderr + tmp_path: Temporary directory + monkeypatch: Pytest monkeypatch + + """ requirements = Path(__file__).parent.parent / "fixtures" / "requirements.yml" monkeypatch.setattr( "sys.argv", diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 7084f44..a799f06 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -18,7 +18,10 @@ def output(tmp_path: Path) -> Output: """Create an Output class object as fixture. - :param tmp_path: App configuration object. + Args: + tmp_path: Temporary directory. + Returns: + Output: Output class object. """ return Output( log_file=str(tmp_path) + "ansible-creator.log", diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 95a93e8..be8225f 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -103,7 +103,11 @@ @pytest.mark.parametrize("scenario", scenarios) def test_parse_collection_request(scenario: tuple[str, Collection | None]) -> None: - """Test that the parse_collection_request function works as expected.""" + """Test that the parse_collection_request function works as expected. + + Args: + scenario: A tuple containing the string to parse and the expected result. + """ string, spec = scenario if spec is None: with pytest.raises(SystemExit):