From 2c6e6bd75e5cea8c3c0315032c4b1920c3bf486a Mon Sep 17 00:00:00 2001 From: Nat Noordanus Date: Sat, 23 Sep 2023 22:53:45 +0200 Subject: [PATCH] Configure ruff and apply prescribed fixes --- docs/conf.py | 1 + poethepoet/__init__.py | 4 +- poethepoet/app.py | 2 +- poethepoet/completion/zsh.py | 14 ++-- poethepoet/config.py | 8 +- poethepoet/env/cache.py | 3 +- poethepoet/env/parse.py | 12 +-- poethepoet/env/template.py | 18 +++-- poethepoet/executor/__init__.py | 2 + poethepoet/executor/base.py | 5 +- poethepoet/executor/poetry.py | 1 - poethepoet/executor/virtualenv.py | 5 +- poethepoet/helpers/command/__init__.py | 18 +---- poethepoet/helpers/command/ast.py | 34 ++++---- poethepoet/helpers/command/ast_core.py | 13 +-- poethepoet/helpers/python.py | 11 +-- poethepoet/plugin.py | 8 +- poethepoet/task/__init__.py | 11 +++ poethepoet/task/args.py | 1 - poethepoet/task/base.py | 11 ++- poethepoet/task/expr.py | 2 +- poethepoet/task/graph.py | 2 +- poethepoet/task/script.py | 6 +- poethepoet/task/sequence.py | 7 +- poethepoet/task/switch.py | 3 +- poethepoet/ui.py | 6 +- poetry.lock | 29 ++++++- pyproject.toml | 43 +++++++--- tests/conftest.py | 40 ++++++---- tests/env/test_parse_env_file.py | 1 + .../fixtures/scripts_project/pkg/__init__.py | 6 +- .../simple_project/scripts_pkg/__init__.py | 2 +- tests/fixtures/venv_project/scripts.py | 2 +- tests/helpers/command/test_ast.py | 80 ++++++------------- tests/test_api.py | 2 - tests/test_cli.py | 7 +- tests/test_cmd_tasks.py | 53 +++++------- tests/test_envfile.py | 5 -- tests/test_executors.py | 21 ++--- tests/test_expr_task.py | 42 +++++----- tests/test_graph_execution.py | 3 +- tests/test_ignore_fail.py | 2 +- tests/test_includes.py | 3 - tests/test_poe_config.py | 17 +--- tests/test_poetry_plugin.py | 66 +++++++-------- tests/test_script_tasks.py | 13 +-- tests/test_sequence_tasks.py | 32 ++++---- tests/test_shell_completion.py | 12 +-- tests/test_shell_task.py | 29 +++---- tests/test_switch_task.py | 3 - tests/test_task_running.py | 6 +- 51 files changed, 369 insertions(+), 358 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index a18a363d..b8a7911e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,3 +1,4 @@ +# ruff: noqa: E501 # Configuration file for the Sphinx documentation builder. # # For the full list of built-in configuration values, see the documentation: diff --git a/poethepoet/__init__.py b/poethepoet/__init__.py index d5a0f16a..48e0efb0 100644 --- a/poethepoet/__init__.py +++ b/poethepoet/__init__.py @@ -1,5 +1,7 @@ from .__version__ import __version__ +__all__ = ["__version__", "main"] + def main(): import sys @@ -29,7 +31,7 @@ def main(): from .app import PoeThePoet - app = PoeThePoet(cwd=Path(".").resolve(), output=sys.stdout) + app = PoeThePoet(cwd=Path().resolve(), output=sys.stdout) result = app(cli_args=sys.argv[1:]) if result: raise SystemExit(result) diff --git a/poethepoet/app.py b/poethepoet/app.py index c150c069..47035836 100644 --- a/poethepoet/app.py +++ b/poethepoet/app.py @@ -68,7 +68,7 @@ def __init__( from .config import PoeConfig from .ui import PoeUi - self.cwd = cwd or Path(".").resolve() + self.cwd = cwd or Path().resolve() self.config = ( config if isinstance(config, PoeConfig) diff --git a/poethepoet/completion/zsh.py b/poethepoet/completion/zsh.py index bb72072f..29f934f4 100644 --- a/poethepoet/completion/zsh.py +++ b/poethepoet/completion/zsh.py @@ -11,7 +11,7 @@ def get_zsh_completion_script() -> str: from ..app import PoeThePoet # build and interogate the argument parser as the normal cli would - app = PoeThePoet(cwd=Path(".").resolve()) + app = PoeThePoet(cwd=Path().resolve()) parser = app.ui.build_parser() global_options = parser._action_groups[1]._group_actions excl_groups = [ @@ -45,13 +45,11 @@ def format_exclusions(excl_option_strings): tuple(), ) # collect all option strings that are exclusive with this one - excl_option_strings: Set[str] = set( - [ - option_string - for excl_option in excl_options - for option_string in excl_option.option_strings - ] - ) | set(option.option_strings) + excl_option_strings: Set[str] = { + option_string + for excl_option in excl_options + for option_string in excl_option.option_strings + } | set(option.option_strings) if len(excl_option_strings) == 1: options_part = option.option_strings[0] diff --git a/poethepoet/config.py b/poethepoet/config.py index f64dd1fa..7962d015 100644 --- a/poethepoet/config.py +++ b/poethepoet/config.py @@ -51,7 +51,7 @@ def __init__( table: Optional[Mapping[str, Any]] = None, config_name: str = "pyproject.toml", ): - self.cwd = Path(".").resolve() if cwd is None else Path(cwd) + self.cwd = Path().resolve() if cwd is None else Path(cwd) self._poe = {} if table is None else dict(table) self._config_name = config_name self._project_dir: Optional[Path] = None @@ -111,7 +111,7 @@ def load(self, target_dir: Optional[str] = None): try: self._project = self._read_config_file(config_path) self._poe = self._project["tool"]["poe"] - except KeyError as error: + except KeyError: raise PoeException( f"No poe configuration found in file at {self._config_name}" ) @@ -216,8 +216,8 @@ def find_config_file(self, target_dir: Optional[str] = None) -> Path: target_path = target_path.joinpath(self._config_name) if not target_path.exists(): raise PoeException( - f"Poe could not find a {self._config_name} file at the given location: " - f"{target_dir}" + f"Poe could not find a {self._config_name} file at the given " + f"location: {target_dir}" ) return target_path diff --git a/poethepoet/env/cache.py b/poethepoet/env/cache.py index 3e914cc3..0d3c1bee 100644 --- a/poethepoet/env/cache.py +++ b/poethepoet/env/cache.py @@ -32,7 +32,8 @@ def get(self, envfile_path_str: str) -> Dict[str, str]: except ValueError as error: message = error.args[0] raise ExecutionError( - f"Syntax error in referenced envfile: {envfile_path_str!r}; {message}" + f"Syntax error in referenced envfile: {envfile_path_str!r};" + f" {message}" ) from error elif self._ui is not None: diff --git a/poethepoet/env/parse.py b/poethepoet/env/parse.py index 531d8fbd..fdfbfa55 100644 --- a/poethepoet/env/parse.py +++ b/poethepoet/env/parse.py @@ -78,6 +78,7 @@ def parse_env_file(content_lines: Sequence[str]): continue if ( + # ruff: noqa: E501 re.match(WHITESPACE_PATTERN, content[cursor:], re.MULTILINE).end() # type: ignore == len(content) - cursor ): @@ -93,11 +94,11 @@ def parse_env_file(content_lines: Sequence[str]): if var_name_match: cursor += var_name_match.span()[1] raise ParserException( - f"Expected assignment operator", cursor, content_lines + "Expected assignment operator", cursor, content_lines ) raise ParserException( - f"Expected variable assignment", cursor, content_lines + "Expected variable assignment", cursor, content_lines ) var_name = match.group(1) @@ -145,7 +146,8 @@ def parse_env_file(content_lines: Sequence[str]): # Omit escaped new line continue - # Non-escaped backslashes that don't precede a terminator are dropped + # Non-escaped backslashes that don't precede a terminator are + # dropped var_content.append(next_char) continue @@ -155,7 +157,7 @@ def parse_env_file(content_lines: Sequence[str]): SINGLE_QUOTE_VALUE_PATTERN, content[cursor:], re.MULTILINE ) if match is None: - raise ParserException(f"Unmatched single quote", cursor, content_lines) + raise ParserException("Unmatched single quote", cursor, content_lines) var_content.append(match.group(1)) cursor += match.end() state = ParserState.SCAN_VALUE @@ -167,7 +169,7 @@ def parse_env_file(content_lines: Sequence[str]): DOUBLE_QUOTE_VALUE_PATTERN, content[cursor:], re.MULTILINE ) if match is None: - raise ParserException(f"Unmatched double quote", cursor, content_lines) + raise ParserException("Unmatched double quote", cursor, content_lines) new_var_content, backslashes_or_dquote = match.groups() var_content.append(new_var_content) cursor += match.end() diff --git a/poethepoet/env/template.py b/poethepoet/env/template.py index e9cc4b34..cda3c3e8 100644 --- a/poethepoet/env/template.py +++ b/poethepoet/env/template.py @@ -5,18 +5,24 @@ # Matches shell variable patterns, distinguishing escaped examples (to be ignored) # There may be a more direct way to doing this r"(?:" - r"(?:[^\\]|^)(?:\\(?:\\{2})*)\$(?P[\w\d_]+)|" # $VAR preceded by an odd num of \ - r"(?:[^\\]|^)(?:\\(?:\\{2})*)\$\{(?P[\w\d_]+)\}|" # ${VAR} preceded by an odd num of \ - r"\$(?P[\w\d_]+)|" # $VAR - r"\${(?P[\w\d_]+)}" # ${VAR} + # $VAR preceded by an odd num of \ + r"(?:[^\\]|^)(?:\\(?:\\{2})*)\$(?P[\w\d_]+)" + # ${VAR} preceded by an odd num of \ + r"|(?:[^\\]|^)(?:\\(?:\\{2})*)\$\{(?P[\w\d_]+)\}" + # $VAR + r"|\$(?P[\w\d_]+)" + # ${VAR} + r"|\${(?P[\w\d_]+)}" ")" ) _SHELL_VAR_PATTERN_BRACES = re.compile( # Matches shell variable patterns, distinguishing escaped examples (to be ignored) r"(?:" - r"(?:[^\\]|^)(?:\\(?:\\{2})*)\$\{(?P[\w\d_]+)\}|" # ${VAR} preceded by an odd num of \ - r"\${(?P[\w\d_]+)}" # ${VAR} + # ${VAR} preceded by an odd num of \ + r"(?:[^\\]|^)(?:\\(?:\\{2})*)\$\{(?P[\w\d_]+)\}" + # ${VAR} + r"|\${(?P[\w\d_]+)}" ")" ) diff --git a/poethepoet/executor/__init__.py b/poethepoet/executor/__init__.py index 5c959b62..34c8a9a2 100644 --- a/poethepoet/executor/__init__.py +++ b/poethepoet/executor/__init__.py @@ -2,3 +2,5 @@ from .poetry import PoetryExecutor from .simple import SimpleExecutor from .virtualenv import VirtualenvExecutor + +__all__ = ["PoeExecutor", "PoetryExecutor", "SimpleExecutor", "VirtualenvExecutor"] diff --git a/poethepoet/executor/base.py b/poethepoet/executor/base.py index 4bf8d2c1..e9d4b911 100644 --- a/poethepoet/executor/base.py +++ b/poethepoet/executor/base.py @@ -118,7 +118,7 @@ def _resolve_implementation( else: if config_executor_type not in cls.__executor_types: raise PoeException( - f"Cannot instantiate unknown executor" + repr(config_executor_type) + "Cannot instantiate unknown executor" + repr(config_executor_type) ) return cls.__executor_types[config_executor_type] @@ -206,6 +206,7 @@ def _exec_via_subproc( popen_kwargs["stdin"] = PIPE if self.capture_stdout: if isinstance(self.capture_stdout, str): + # ruff: noqa: SIM115 popen_kwargs["stdout"] = open(self.capture_stdout, "wb") else: popen_kwargs["stdout"] = PIPE @@ -232,7 +233,7 @@ def handle_sigint(signum, _frame): # send data to the subprocess and wait for it to finish (captured_stdout, _) = proc.communicate(input) - if self.capture_stdout == True: + if self.capture_stdout is True: self.context.save_task_output(self.invocation, captured_stdout) # restore signal handler diff --git a/poethepoet/executor/poetry.py b/poethepoet/executor/poetry.py index cfdb5f9e..3c552f59 100644 --- a/poethepoet/executor/poetry.py +++ b/poethepoet/executor/poetry.py @@ -22,7 +22,6 @@ def execute( """ poetry_env = self._get_poetry_virtualenv() - project_dir = self.context.config.project_dir if poetry_env: from ..virtualenv import Virtualenv diff --git a/poethepoet/executor/virtualenv.py b/poethepoet/executor/virtualenv.py index 996fe012..bd03d109 100644 --- a/poethepoet/executor/virtualenv.py +++ b/poethepoet/executor/virtualenv.py @@ -62,7 +62,10 @@ def validate_executor_config(cls, config: Dict[str, Any]) -> Optional[str]: Validate that location is a string if given and no other options are given. """ if "location" in config and not isinstance(config["location"], str): - return f"The location option virtualenv executor must be a string not: {config['location']!r}" + return ( + "The location option virtualenv executor must be a string not: " + f"{config['location']!r}" + ) extra_options = set(config.keys()) - {"type", "location"} if extra_options: return f"Unexpected keys for executor config: {extra_options!r}" diff --git a/poethepoet/helpers/command/__init__.py b/poethepoet/helpers/command/__init__.py index ba2c687d..82ebf135 100644 --- a/poethepoet/helpers/command/__init__.py +++ b/poethepoet/helpers/command/__init__.py @@ -1,20 +1,6 @@ import re from glob import escape -from typing import ( - TYPE_CHECKING, - Dict, - Generic, - Iterable, - Iterator, - List, - Literal, - Mapping, - Optional, - Tuple, - Type, - TypeVar, - cast, -) +from typing import TYPE_CHECKING, Iterator, List, Mapping, Optional, Tuple, cast if TYPE_CHECKING: from .ast import Line, ParseConfig @@ -42,7 +28,7 @@ def resolve_command_tokens( patterns that are not escaped or quoted. In case there are glob patterns in the token, any escaped glob characters will have been escaped with []. """ - from .ast import Glob, ParamExpansion, ParseConfig, ParseCursor, PythonGlob, Script + from .ast import Glob, ParamExpansion, ParseConfig, PythonGlob if not config: config = ParseConfig(substitute_nodes={Glob: PythonGlob}) diff --git a/poethepoet/helpers/command/ast.py b/poethepoet/helpers/command/ast.py index 5153df3b..1c544fc4 100644 --- a/poethepoet/helpers/command/ast.py +++ b/poethepoet/helpers/command/ast.py @@ -2,34 +2,33 @@ This module implements a heirarchical parser and AST along the lines of the following grammar which is a subset of bash syntax. -script : line* -line : word* comment? -word : segment* -segment : UNQUOTED_CONTENT | single_quoted_sement | double_quoted_sement +script : line* +line : word* comment? +word : segment* +segment : UNQUOTED_CONTENT | single_quoted_sement | double_quoted_sement -unquoted_sement : UNQUOTED_CONTENT | param_expansion | glob -single_quoted_sement : "'" SINGLE_QUOTED_CONTENT "'" -double_quoted_sement : "\"" (DOUBLE_QUOTED_CONTENT | param_expansion) "\"" +unquoted_sement : UNQUOTED_CONTENT | param_expansion | glob +single_quoted_sement : "'" SINGLE_QUOTED_CONTENT "'" +double_quoted_sement : "\"" (DOUBLE_QUOTED_CONTENT | param_expansion) "\"" -comment : /#[^\n\r\f\v]*/ -glob : "?" | "*" | "[" /(\!?\]([^\s\]\\]|\\.)*|([^\s\]\\]|\\.)+)*/ "]" +comment : /#[^\n\r\f\v]*/ +glob : "?" | "*" | "[" /(\!?\]([^\s\]\\]|\\.)*|([^\s\]\\]|\\.)+)*/ "]" -UNQUOTED_CONTENT : /[^\s;#*?[$]+/ -SINGLE_QUOTED_CONTENT : /[^']+/ -DOUBLE_QUOTED_CONTENT : /([^\$"]|\[\$"])+/ +UNQUOTED_CONTENT : /[^\s;#*?[$]+/ +SINGLE_QUOTED_CONTENT : /[^']+/ +DOUBLE_QUOTED_CONTENT : /([^\$"]|\[\$"])+/ """ from typing import Iterable, List, Literal, Optional, Tuple, Union, cast +from .ast_core import ContentNode, ParseConfig, ParseCursor, ParseError, SyntaxNode + PARAM_INIT_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" PARAM_CHARS = PARAM_INIT_CHARS + "0123456789" LINE_BREAK_CHARS = "\r\n\f\v" LINE_SEP_CHARS = LINE_BREAK_CHARS + ";" -from .ast_core import ContentNode, ParseConfig, ParseCursor, ParseError, SyntaxNode - - class SingleQuotedText(ContentNode): def _parse(self, chars: ParseCursor): content: List[str] = [] @@ -95,7 +94,10 @@ class Glob(ContentNode): """ # This pattern is equivalent to what this node might parse - PATTERN = r"(?P[\?\*])|(?P\[(?:\!?\](?:[^\s\]\\]|\\.)*|(?:[^\s\]\\]|\\.)+)\])" + PATTERN = ( + r"(?P[\?\*])" + r"|(?P\[(?:\!?\](?:[^\s\]\\]|\\.)*|(?:[^\s\]\\]|\\.)+)\])" + ) def _parse(self, chars: ParseCursor): char = chars.peek() diff --git a/poethepoet/helpers/command/ast_core.py b/poethepoet/helpers/command/ast_core.py index 0e547025..3516a145 100644 --- a/poethepoet/helpers/command/ast_core.py +++ b/poethepoet/helpers/command/ast_core.py @@ -48,7 +48,7 @@ def iter_chars(): @classmethod def from_string(cls, string: str): - return cls((char for char in string)) + return cls(char for char in string) def peek(self): if not self._pushback_stack: @@ -145,11 +145,12 @@ def children(self) -> Tuple["SyntaxNode", ...]: def pretty(self, indent: int = 0, increment: int = 4): indent += increment - lines = [f"{self.__class__.__name__}:"] - for child in self: - lines.append(" " * indent + child.pretty(indent)) - - return "\n".join(lines) + return "\n".join( + [ + f"{self.__class__.__name__}:", + *(" " * indent + child.pretty(indent) for child in self), + ] + ) def __getitem__(self, index: int): return self._children[index] diff --git a/poethepoet/helpers/python.py b/poethepoet/helpers/python.py index 7dc9be96..f13cdab6 100644 --- a/poethepoet/helpers/python.py +++ b/poethepoet/helpers/python.py @@ -173,7 +173,7 @@ def _validate_nodes_and_get_names( ast.YieldFrom, ) - if isinstance(node, ast.Name) and not node.id in ignore_names: + if isinstance(node, ast.Name) and node.id not in ignore_names: yield node elif isinstance(node, ast.Call): @@ -207,12 +207,12 @@ def _validate_nodes_and_get_names( elif isinstance(node, (ast.ListComp, ast.SetComp, ast.GeneratorExp, ast.DictComp)): # ignore comprehension/generator scoped variables - comp_vars = set( + comp_vars = { gen_node.id for comp_node in node.generators for gen_node in ast.walk(comp_node.target) if isinstance(gen_node, ast.Name) - ) | set(ignore_names) + } | set(ignore_names) if isinstance(node, ast.DictComp): yield from _validate_nodes_and_get_names( @@ -300,7 +300,7 @@ def _get_name_source_segment(source: str, node: ast.Name): and must be valid identifiers. It is expected to be correct in all cases, and performant in common cases. """ - if sys.version_info.minor >= 8: + if sys.version_info >= (3, 8): return ast.get_source_segment(source, node) partial_result = ( @@ -311,7 +311,8 @@ def _get_name_source_segment(source: str, node: ast.Name): # The name probably extends to the first ascii char outside of [a-zA-Z\d_] # regex will always match with valid arguments to this function - partial_result = re.match(IDENTIFIER_PATTERN, partial_result).group() # type: ignore + # type: ignore + partial_result = re.match(IDENTIFIER_PATTERN, partial_result).group() # This bit is a nasty hack, but probably always gets skipped while not partial_result.isidentifier() and partial_result: diff --git a/poethepoet/plugin.py b/poethepoet/plugin.py index f8d1cdb2..3c478c9c 100644 --- a/poethepoet/plugin.py +++ b/poethepoet/plugin.py @@ -53,10 +53,10 @@ def get_poe(cls, application: Application, io: IO): poetry_env_path = EnvManager(application.poetry).get().path # pylint: disable=bare-except - except: + except: # noqa: E722 poetry_env_path = None - cwd = Path(".").resolve() + cwd = Path().resolve() config = PoeConfig(cwd=cwd) if io.output.is_quiet(): @@ -81,7 +81,7 @@ def activate(self, application: Application) -> None: return self._activate(application) # pylint: disable=bare-except - except: + except: # noqa: E722 import os import sys @@ -150,7 +150,7 @@ def _get_config(cls, application: Application) -> Dict[str, Any]: pyproject = application.poetry.pyproject.data # pylint: disable=bare-except - except: + except: # noqa: E722 # Fallback to loading the config again in case of future failure of the # above undocumented API import tomlkit diff --git a/poethepoet/task/__init__.py b/poethepoet/task/__init__.py index 1fa902d0..1a851d1c 100644 --- a/poethepoet/task/__init__.py +++ b/poethepoet/task/__init__.py @@ -6,3 +6,14 @@ from .sequence import SequenceTask from .shell import ShellTask from .switch import SwitchTask + +__all__ = [ + "PoeTask", + "CmdTask", + "ExprTask", + "RefTask", + "ScriptTask", + "SequenceTask", + "ShellTask", + "SwitchTask", +] diff --git a/poethepoet/task/args.py b/poethepoet/task/args.py index 9d287ddf..aeaba47c 100644 --- a/poethepoet/task/args.py +++ b/poethepoet/task/args.py @@ -14,7 +14,6 @@ if TYPE_CHECKING: from argparse import ArgumentParser - from ..config import PoeConfig from ..env.manager import EnvVarsManager ArgParams = Dict[str, Any] diff --git a/poethepoet/task/base.py b/poethepoet/task/base.py index a6bcfaaa..f101b410 100644 --- a/poethepoet/task/base.py +++ b/poethepoet/task/base.py @@ -236,7 +236,10 @@ def run( if context.dry and upstream_invocations.get("uses", {}): self._print_action( - f"unresolved dependency task results via uses option for task {self.name!r}", + ( + "unresolved dependency task results via uses option for task " + f"{self.name!r}" + ), dry=True, unresolved=True, ) @@ -418,7 +421,8 @@ def validate_def( ): return ( f"Invalid task: {task_name!r}. deps options contains " - f"reference to task with use_exec set to true: {dep_task_name!r}" + "reference to task with use_exec set to true: " + f"{dep_task_name!r}" ) if "uses" in task_def: @@ -444,7 +448,8 @@ def validate_def( ): return ( f"Invalid task: {task_name!r}. uses options contains " - f"reference to task with use_exec set to true: {dep_task_name!r}" + "reference to task with use_exec set to true: " + f"{dep_task_name!r}" ) elif isinstance(task_def, list): diff --git a/poethepoet/task/expr.py b/poethepoet/task/expr.py index 5303a188..3b9a327f 100644 --- a/poethepoet/task/expr.py +++ b/poethepoet/task/expr.py @@ -60,7 +60,7 @@ def _handle_run( f"{format_class(named_arg_values)}", f"{format_class(env_values, classname='__env')}", f"result = ({expr});", - f"print(result);", + "print(result);", ] falsy_return_code = int(self.options.get("assert", False)) diff --git a/poethepoet/task/graph.py b/poethepoet/task/graph.py index 4f26c658..18d8d6e5 100644 --- a/poethepoet/task/graph.py +++ b/poethepoet/task/graph.py @@ -74,7 +74,7 @@ def get_execution_plan(self) -> List[List["PoeTask"]]: # scheduling stages: List[List[TaskExecutionNode]] = [self.sources] - visited = set(source.identifier for source in self.sources) + visited = {source.identifier for source in self.sources} while True: next_stage = [] diff --git a/poethepoet/task/script.py b/poethepoet/task/script.py index bd5b38fd..4b1663ca 100644 --- a/poethepoet/task/script.py +++ b/poethepoet/task/script.py @@ -58,7 +58,7 @@ def _handle_run( ] if self.options.get("print_result"): - script.append(f"_r is not None and print(_r);") + script.append("_r is not None and print(_r);") # Exactly which python executable to use is usually resolved by the executor # It's important that the script contains no line breaks to avoid issues on @@ -93,8 +93,8 @@ def parse_content(self, args: Optional[Dict[str, Any]]) -> Tuple[str, str]: """ Returns the module to load, and the function call to execute. - Will raise an exception if the function call contains invalid syntax or references - variables that are not in scope. + Will raise an exception if the function call contains invalid syntax or + references variables that are not in scope. """ from ..helpers.python import resolve_expression diff --git a/poethepoet/task/sequence.py b/poethepoet/task/sequence.py index a0c6a36f..49c6df49 100644 --- a/poethepoet/task/sequence.py +++ b/poethepoet/task/sequence.py @@ -17,7 +17,6 @@ from ..config import PoeConfig from ..context import RunContext from ..env.manager import EnvVarsManager - from ..executor import PoeExecutor from ..ui import PoeUi @@ -45,7 +44,7 @@ def __init__( invocation: Tuple[str, ...], capture_stdout: bool = False, ): - assert capture_stdout == False + assert capture_stdout is False super().__init__(name, content, options, ui, config, invocation) self.subtasks = [ @@ -131,8 +130,8 @@ def _validate_task_def( if isinstance(task_item, dict): if len(task_item.get("args", tuple())): return ( - "Unsupported option `args` for task declared inside sequence task " - f"{task_name!r}." + "Unsupported option `args` for task declared inside sequence " + f"task {task_name!r}." ) subtask_issue = cls.validate_def( diff --git a/poethepoet/task/switch.py b/poethepoet/task/switch.py index 1d8e1c38..e6dd145f 100644 --- a/poethepoet/task/switch.py +++ b/poethepoet/task/switch.py @@ -19,7 +19,6 @@ from ..config import PoeConfig from ..context import RunContext from ..env.manager import EnvVarsManager - from ..executor import PoeExecutor from ..ui import PoeUi @@ -113,7 +112,7 @@ def _handle_run( if context.dry: self._print_action( - f"unresolved case for switch task", dry=True, unresolved=True + "unresolved case for switch task", dry=True, unresolved=True ) return 0 diff --git a/poethepoet/ui.py b/poethepoet/ui.py index e5d24aab..3685f15d 100644 --- a/poethepoet/ui.py +++ b/poethepoet/ui.py @@ -181,7 +181,9 @@ def print_help( result.append( ( "

USAGE

", - f" {self.program_name} [-h] [-v | -q] [--root PATH] [--ansi | --no-ansi] task [task arguments]", + f" {self.program_name}" + " [-h] [-v | -q] [--root PATH] [--ansi | --no-ansi]" + " task [task arguments]", ) ) @@ -234,7 +236,7 @@ def print_help( section if isinstance(section, str) else "\n".join(section).strip("\n") for section in result ) - + f"\n" + + "\n" + ("\n" if verbosity >= 0 else "") ) diff --git a/poetry.lock b/poetry.lock index 5bb26d27..3bfe748c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2398,6 +2398,33 @@ testing = ["coverage-conditional-plugin (>=0.5)", "coverage[toml] (>=6.0)", "pyt toml = ["tomli (>=2.0)"] type-check = ["mypy (>=1.0)", "types-docutils (>=0.18)"] +[[package]] +name = "ruff" +version = "0.0.291" +description = "An extremely fast Python linter, written in Rust." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.291-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:b97d0d7c136a85badbc7fd8397fdbb336e9409b01c07027622f28dcd7db366f2"}, + {file = "ruff-0.0.291-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:6ab44ea607967171e18aa5c80335237be12f3a1523375fa0cede83c5cf77feb4"}, + {file = "ruff-0.0.291-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a04b384f2d36f00d5fb55313d52a7d66236531195ef08157a09c4728090f2ef0"}, + {file = "ruff-0.0.291-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b727c219b43f903875b7503a76c86237a00d1a39579bb3e21ce027eec9534051"}, + {file = "ruff-0.0.291-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87671e33175ae949702774071b35ed4937da06f11851af75cd087e1b5a488ac4"}, + {file = "ruff-0.0.291-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b75f5801547f79b7541d72a211949754c21dc0705c70eddf7f21c88a64de8b97"}, + {file = "ruff-0.0.291-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b09b94efdcd162fe32b472b2dd5bf1c969fcc15b8ff52f478b048f41d4590e09"}, + {file = "ruff-0.0.291-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d5b56bc3a2f83a7a1d7f4447c54d8d3db52021f726fdd55d549ca87bca5d747"}, + {file = "ruff-0.0.291-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13f0d88e5f367b2dc8c7d90a8afdcfff9dd7d174e324fd3ed8e0b5cb5dc9b7f6"}, + {file = "ruff-0.0.291-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b3eeee1b1a45a247758ecdc3ab26c307336d157aafc61edb98b825cadb153df3"}, + {file = "ruff-0.0.291-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6c06006350c3bb689765d71f810128c9cdf4a1121fd01afc655c87bab4fb4f83"}, + {file = "ruff-0.0.291-py3-none-musllinux_1_2_i686.whl", hash = "sha256:fd17220611047de247b635596e3174f3d7f2becf63bd56301fc758778df9b629"}, + {file = "ruff-0.0.291-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5383ba67ad360caf6060d09012f1fb2ab8bd605ab766d10ca4427a28ab106e0b"}, + {file = "ruff-0.0.291-py3-none-win32.whl", hash = "sha256:1d5f0616ae4cdc7a938b493b6a1a71c8a47d0300c0d65f6e41c281c2f7490ad3"}, + {file = "ruff-0.0.291-py3-none-win_amd64.whl", hash = "sha256:8a69bfbde72db8ca1c43ee3570f59daad155196c3fbe357047cd9b77de65f15b"}, + {file = "ruff-0.0.291-py3-none-win_arm64.whl", hash = "sha256:d867384a4615b7f30b223a849b52104214442b5ba79b473d7edd18da3cde22d6"}, + {file = "ruff-0.0.291.tar.gz", hash = "sha256:c61109661dde9db73469d14a82b42a88c7164f731e6a3b0042e71394c1c7ceed"}, +] + [[package]] name = "secretstorage" version = "3.3.3" @@ -2938,4 +2965,4 @@ poetry-plugin = ["poetry"] [metadata] lock-version = "2.0" python-versions = ">=3.8" -content-hash = "a8a8883286a543c298a507c3fd1e783def8fa5d432d9e857e7142d7b13dc8d16" +content-hash = "d84a9e34df074bb3e3d197eca20c9812e2f5fe4bc40b5b5adae59fd8dc2afd4a" diff --git a/pyproject.toml b/pyproject.toml index 85c6a129..f48b9396 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,7 @@ pylint = "^2.13.0" pytest = "^7.1.2" pytest-cov = "^3.0.0" rstcheck = { version = "^6.1.2", python = "<4" } +ruff = "^0.0.291" virtualenv = "^20.14.1" @@ -54,6 +55,14 @@ poethepoet = "poethepoet.plugin:PoetryPlugin" _clean_docs.script = "shutil:rmtree('docs/_build', ignore_errors=1)" + [tool.poe.tasks.format] + help = "Run all formating tools on the code base" + sequence = ["format-ruff", "format-isort", "format-black"] + + [tool.poe.tasks.format-ruff] + help = "Run ruff fixer on code base" + cmd = "ruff check . --fix-only" + [tool.poe.tasks.format-isort] help = "Run isort on the code base" cmd = "isort ." @@ -62,10 +71,6 @@ _clean_docs.script = "shutil:rmtree('docs/_build', ignore_errors=1)" help = "Run black on the code base" cmd = "black ." - [tool.poe.tasks.format] - help = "Run formating tools on the code base" - sequence = ["format-isort", "format-black"] - [tool.poe.tasks.docs] help = "Build the docs using Sphinx" cmd = "sphinx-build docs docs/_build" @@ -114,9 +119,21 @@ _clean_docs.script = "shutil:rmtree('docs/_build', ignore_errors=1)" cmd = "mypy poethepoet --ignore-missing-imports" [tool.poe.tasks.lint] - help = "Run the linter" + help = "Run linting tools on the code base" + sequence = ["lint-ruff", "lint-pylint"] + + [tool.poe.tasks.lint-ruff] + help = "Evaluate ruff rules" + cmd = "ruff check ." + + [tool.poe.tasks.lint-pylint] + help = "Evaluate pylint rules" cmd = "pylint poethepoet" + [tool.poe.tasks.style] + help = "Validate code style" + sequence = ["style-isort", "style-black"] + [tool.poe.tasks.style-black] help = "Validate black code style" cmd = "black . --check --diff" @@ -125,10 +142,6 @@ _clean_docs.script = "shutil:rmtree('docs/_build', ignore_errors=1)" help = "Validate isort code style" cmd = "isort . --check --diff" - [tool.poe.tasks.style] - help = "Validate code style" - sequence = ["style-isort", "style-black"] - [tool.poe.tasks.check] help = "Run all checks on the code base" sequence = ["docs-check", "style", "types", "lint", "test"] @@ -160,17 +173,29 @@ ignore_directives = [ "include" ] + [tool.coverage.report] omit = ["**/site-packages/**", "poethepoet/completion/*", "poethepoet/plugin.py"] + [tool.pytest.ini_options] markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"')" ] + [tool.isort] profile = "black" + +[tool.ruff] +select = [ + "E", "F", "I", "W", "UP", "YTT","ASYNC","C4", + "T10", "G", "PIE", "PYI", "PT", "Q", "SIM", "TCH", "PTH", "PERF","RUF"] +ignore = ["C408", "PT015", "SIM118", "PTH109", "PTH123", "RUF012"] +fixable = ["E", "F", "I"] + + [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" diff --git a/tests/conftest.py b/tests/conftest.py index 43f3bf67..55189de5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,13 +4,11 @@ import sys import time import venv -from collections import namedtuple from contextlib import contextmanager from io import StringIO from pathlib import Path from subprocess import PIPE, Popen -from tempfile import TemporaryDirectory -from typing import Any, Dict, List, Mapping, Optional +from typing import Any, Dict, List, Mapping, NamedTuple, Optional import pytest import tomli @@ -73,17 +71,21 @@ def high_verbosity_project_path(): return PROJECT_ROOT.joinpath("tests", "fixtures", "high_verbosity") -@pytest.fixture(scope="function") +@pytest.fixture() def temp_file(tmp_path): # not using NamedTemporaryFile here because it doesn't work on windows tmpfilepath = tmp_path / "tmp_test_file" tmpfilepath.touch() - yield tmpfilepath + return tmpfilepath -class PoeRunResult( - namedtuple("PoeRunResult", ("code", "path", "capture", "stdout", "stderr")) -): +class PoeRunResult(NamedTuple): + code: int + path: str + capture: str + stdout: str + stderr: str + def __str__(self): return ( "PoeRunResult(\n" @@ -96,7 +98,7 @@ def __str__(self): ) -@pytest.fixture(scope="function") +@pytest.fixture() def run_poe_subproc(projects, temp_file, tmp_path, is_windows): coverage_setup = ( "from coverage import Coverage;" @@ -118,17 +120,19 @@ def run_poe_subproc( cwd: Optional[str] = None, config: Optional[Mapping[str, Any]] = None, coverage: bool = not is_windows, - env: Dict[str, str] = None, + env: Optional[Dict[str, str]] = None, project: Optional[str] = None, ) -> PoeRunResult: if cwd is None: cwd = projects.get(project, projects["example"]) + if config is not None: config_path = tmp_path.joinpath("tmp_test_config_file") with config_path.open("w+") as config_file: - toml.dump(config, config_file) + tomli.dump(config, config_file) config_file.seek(0) config_arg = rf"tomli.load(open(r\"{config_path}\", \"rb\"))" + else: config_arg = "None" @@ -172,7 +176,7 @@ def run_poe_subproc( return run_poe_subproc -@pytest.fixture(scope="function") +@pytest.fixture() def run_poe(capsys, projects): def run_poe( *run_args: str, @@ -198,7 +202,7 @@ def run_poe( return run_poe -@pytest.fixture(scope="function") +@pytest.fixture() def run_poe_main(capsys, projects): def run_poe_main( *cli_args: str, @@ -305,7 +309,8 @@ def use_venv( install_into_virtualenv(location, contents) yield - # Only cleanup if we actually created it to avoid this fixture being a bit dangerous + # Only cleanup if we actually created it to avoid this fixture being a bit + # dangerous if not did_exist: try_rm_dir(location) @@ -333,7 +338,8 @@ def use_virtualenv( install_into_virtualenv(location, contents) yield - # Only cleanup if we actually created it to avoid this fixture being a bit dangerous + # Only cleanup if we actually created it to avoid this fixture being a bit + # dangerous if not did_exist: try_rm_dir(location) @@ -343,14 +349,14 @@ def use_virtualenv( def try_rm_dir(location: Path): try: shutil.rmtree(location) - except: + except: # noqa: E722 # The above sometimes files with a Permissions error in CI for Windows # No idea why, but maybe this will help print("Retrying venv cleanup") time.sleep(1) try: shutil.rmtree(location) - except: + except: # noqa: E722 print( "Cleanup failed. You might need to run `poe clean` before tests can be " "run again." diff --git a/tests/env/test_parse_env_file.py b/tests/env/test_parse_env_file.py index e61bbc74..542765cc 100644 --- a/tests/env/test_parse_env_file.py +++ b/tests/env/test_parse_env_file.py @@ -218,5 +218,6 @@ def test_parse_valid_env_files(example): @pytest.mark.parametrize("example", invalid_examples) def test_parse_invalid_env_files(example): + # ruff: noqa: PT011 with pytest.raises(ValueError): parse_env_file(example) diff --git a/tests/fixtures/scripts_project/pkg/__init__.py b/tests/fixtures/scripts_project/pkg/__init__.py index db43080d..519c907e 100644 --- a/tests/fixtures/scripts_project/pkg/__init__.py +++ b/tests/fixtures/scripts_project/pkg/__init__.py @@ -1,5 +1,4 @@ import sys -from typing import Any, Optional def uprint(*objects, sep=" ", end="\n", file=sys.stdout): @@ -7,7 +6,10 @@ def uprint(*objects, sep=" ", end="\n", file=sys.stdout): if enc == "UTF-8": print(*objects, sep=sep, end=end, file=file) else: - f = lambda obj: str(obj).encode(enc, errors="backslashreplace").decode(enc) + + def f(obj): + return str(obj).encode(enc, errors="backslashreplace").decode(enc) + print(*map(f, objects), sep=sep, end=end, file=file) diff --git a/tests/fixtures/simple_project/scripts_pkg/__init__.py b/tests/fixtures/simple_project/scripts_pkg/__init__.py index 3bac913c..a155bd03 100644 --- a/tests/fixtures/simple_project/scripts_pkg/__init__.py +++ b/tests/fixtures/simple_project/scripts_pkg/__init__.py @@ -3,5 +3,5 @@ def detect_poe_test_package(): import poe_test_package print("poe_test_package found at", poe_test_package.__file__) - except: + except: # noqa: E722 print("No poe_test_package found") diff --git a/tests/fixtures/venv_project/scripts.py b/tests/fixtures/venv_project/scripts.py index c7fa155b..16701734 100644 --- a/tests/fixtures/venv_project/scripts.py +++ b/tests/fixtures/venv_project/scripts.py @@ -5,6 +5,6 @@ def test_package_version(): def test_package_exec_version(): - from subprocess import PIPE, Popen + from subprocess import Popen Popen(["test_print_version"]) diff --git a/tests/helpers/command/test_ast.py b/tests/helpers/command/test_ast.py index 4fa7f24e..fb12d00b 100644 --- a/tests/helpers/command/test_ast.py +++ b/tests/helpers/command/test_ast.py @@ -3,15 +3,7 @@ import pytest from poethepoet.helpers.command import parse_poe_cmd -from poethepoet.helpers.command.ast import ( - Glob, - Line, - ParamExpansion, - PythonGlob, - Script, - Segment, - Word, -) +from poethepoet.helpers.command.ast import Glob, PythonGlob, Script from poethepoet.helpers.command.ast_core import ParseConfig, ParseCursor, ParseError @@ -117,39 +109,39 @@ def test_parse_params(): def test_invalid_param_expansion(): with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd("""${}""", config=ParseConfig()) + parse_poe_cmd("""${}""", config=ParseConfig()) assert excinfo.value.args[0] == "Bad substitution: ${}" with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd("""${ x }""", config=ParseConfig()) + parse_poe_cmd("""${ x }""", config=ParseConfig()) assert ( excinfo.value.args[0] == "Bad substitution: Illegal first character in parameter name ' '" ) with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd("""${!x }""", config=ParseConfig()) + parse_poe_cmd("""${!x }""", config=ParseConfig()) assert ( excinfo.value.args[0] == "Bad substitution: Illegal first character in parameter name '!'" ) with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd("""${x }""", config=ParseConfig()) + parse_poe_cmd("""${x }""", config=ParseConfig()) assert ( excinfo.value.args[0] == "Bad substitution: Illegal character in parameter name ' '" ) with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd("""${x-}""", config=ParseConfig()) + parse_poe_cmd("""${x-}""", config=ParseConfig()) assert ( excinfo.value.args[0] == "Bad substitution: Illegal character in parameter name '-'" ) with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd("""${""", config=ParseConfig()) + parse_poe_cmd("""${""", config=ParseConfig()) assert ( excinfo.value.args[0] == "Unexpected end of input, expected closing '}' after '${'" @@ -194,32 +186,32 @@ def test_parse_quotes(): ) first_word = tree.lines[0].words[0] - assert first_word.segments[0].is_quoted == False - assert first_word.segments[0].is_single_quoted == False - assert first_word.segments[0].is_double_quoted == False - assert first_word.segments[1].is_quoted == True - assert first_word.segments[1].is_single_quoted == True - assert first_word.segments[1].is_double_quoted == False - assert first_word.segments[2].is_quoted == True - assert first_word.segments[2].is_single_quoted == False - assert first_word.segments[2].is_double_quoted == True + assert first_word.segments[0].is_quoted is False + assert first_word.segments[0].is_single_quoted is False + assert first_word.segments[0].is_double_quoted is False + assert first_word.segments[1].is_quoted is True + assert first_word.segments[1].is_single_quoted is True + assert first_word.segments[1].is_double_quoted is False + assert first_word.segments[2].is_quoted is True + assert first_word.segments[2].is_single_quoted is False + assert first_word.segments[2].is_double_quoted is True def test_parse_unmatched_quotes(): with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd(""" ok"not ok """) + parse_poe_cmd(""" ok"not ok """) assert ( excinfo.value.args[0] == "Unexpected end of input with unmatched double quote" ) with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd(r""" ok"not ok\" """) + parse_poe_cmd(r""" ok"not ok\" """) assert ( excinfo.value.args[0] == "Unexpected end of input with unmatched double quote" ) with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd(""" ok'not ok """) + parse_poe_cmd(""" ok'not ok """) assert ( excinfo.value.args[0] == "Unexpected end of input with unmatched single quote" ) @@ -227,11 +219,11 @@ def test_parse_unmatched_quotes(): def test_invalid_features(): with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd("""end\\""") + parse_poe_cmd("""end\\""") assert excinfo.value.args[0] == "Unexpected end of input after backslash" with pytest.raises(ParseError) as excinfo: - tree = parse_poe_cmd("""end[\\""", config=ParseConfig()) + parse_poe_cmd("""end[\\""", config=ParseConfig()) assert ( excinfo.value.args[0] == "Invalid pattern: unexpected end of input after backslash" @@ -349,30 +341,6 @@ def test_parse_python_style_non_globs(): ) -def test_parse_non_globs(): - tree = Script( - ParseCursor.from_file( - StringIO( - """ - ab[cd ]ef - """ - ) - ), - config=ParseConfig(), - ) - print(tree.pretty()) - assert len(tree.lines) == 1 - assert tree.lines[0] == ( - ( - ( - "ab", - "[cd", - ), - ), - (("]ef",),), - ) - - def test_parse_line_breaks(): tree = Script( ParseCursor.from_string( @@ -430,9 +398,9 @@ def test_ast_node_formatting(): ParamExpansion: 'world' UnquotedText: '!'""" ) - assert ( - repr(tree) - == "Script(Line(Word(Segment(UnquotedText('hello'))), Word(Segment(ParamExpansion('world'), UnquotedText('!')))))" + assert repr(tree) == ( + "Script(Line(Word(Segment(UnquotedText('hello')))," + " Word(Segment(ParamExpansion('world'), UnquotedText('!')))))" ) diff --git a/tests/test_api.py b/tests/test_api.py index e3e653b4..8180a0ad 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,5 +1,3 @@ -import re - import pytest diff --git a/tests/test_cli.py b/tests/test_cli.py index faa50308..34a11ffb 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,7 +1,5 @@ import re -import pytest - from poethepoet import __version__ @@ -67,7 +65,7 @@ def test_version_option(run_poe): def test_dry_run(run_poe_subproc): result = run_poe_subproc("-d", "show_env") - assert result.capture == f"Poe => poe_test_env\n" + assert result.capture == "Poe => poe_test_env\n" assert result.stdout == "" assert result.stderr == "" @@ -105,7 +103,8 @@ def test_documentation_of_task_named_args(run_poe): r" --age, -a \s+\n" r" --height, -h \s+The user's height in meters\n" r" greet-strict \s+All arguments are required\n" - r" --greeting \s+this one is required \[default: \$\{DOES\}n't \$\{STUFF\}\]\n" + r" --greeting" + r" \s+this one is required \[default: \$\{DOES\}n't \$\{STUFF\}\]\n" r" --name \s+and this one is required\n", result.capture, ) diff --git a/tests/test_cmd_tasks.py b/tests/test_cmd_tasks.py index 6c143577..12eb88e4 100644 --- a/tests/test_cmd_tasks.py +++ b/tests/test_cmd_tasks.py @@ -1,11 +1,8 @@ -import os - - def test_call_echo_task(run_poe_subproc, projects, esc_prefix): result = run_poe_subproc("echo", "foo", "!", project="cmds") - assert ( - result.capture - == f"Poe => poe_test_echo POE_ROOT:{projects['cmds']} Password1, task_args: foo !\n" + assert result.capture == ( + "Poe => poe_test_echo " + f"POE_ROOT:{projects['cmds']} Password1, task_args: foo !\n" ) assert result.stdout == f"POE_ROOT:{projects['cmds']} Password1, task_args: foo !\n" assert result.stderr == "" @@ -13,7 +10,7 @@ def test_call_echo_task(run_poe_subproc, projects, esc_prefix): def test_setting_envvar_in_task(run_poe_subproc, projects): result = run_poe_subproc("show_env", project="cmds") - assert result.capture == f"Poe => poe_test_env\n" + assert result.capture == "Poe => poe_test_env\n" assert f"POE_ROOT={projects['cmds']}" in result.stdout assert result.stderr == "" @@ -22,7 +19,7 @@ def test_cmd_task_with_dash_case_arg(run_poe_subproc): result = run_poe_subproc( "greet", "--formal-greeting=hey", "--subject=you", project="cmds" ) - assert result.capture == f"Poe => poe_test_echo hey you\n" + assert result.capture == "Poe => poe_test_echo hey you\n" assert result.stdout == "hey you\n" assert result.stderr == "" @@ -37,7 +34,7 @@ def test_cmd_task_with_args_and_extra_args(run_poe_subproc): "!", project="cmds", ) - assert result.capture == f"Poe => poe_test_echo hey you guy !\n" + assert result.capture == "Poe => poe_test_echo hey you guy !\n" assert result.stdout == "hey you guy !\n" assert result.stderr == "" @@ -46,7 +43,7 @@ def test_cmd_alias_env_var(run_poe_subproc): result = run_poe_subproc( "surfin-bird", project="cmds", env={"SOME_INPUT_VAR": "BIRD"} ) - assert result.capture == f"Poe => poe_test_echo BIRD is the word\n" + assert result.capture == "Poe => poe_test_echo BIRD is the word\n" assert result.stdout == "BIRD is the word\n" assert result.stderr == "" @@ -61,20 +58,16 @@ def test_cmd_task_with_multiple_value_arg(run_poe_subproc): def test_cmd_task_with_cwd_option(run_poe_subproc, poe_project_path): result = run_poe_subproc("cwd", project="cwd") assert result.capture == "Poe => poe_test_pwd\n" - assert ( - result.stdout - == f'{poe_project_path.joinpath("tests", "fixtures", "cwd_project", "subdir", "foo")}\n' - ) + path_parts = ("tests", "fixtures", "cwd_project", "subdir", "foo") + assert result.stdout == f"{poe_project_path.joinpath(*path_parts)}\n" assert result.stderr == "" def test_cmd_task_with_cwd_option_env(run_poe_subproc, poe_project_path): result = run_poe_subproc("cwd_env", project="cwd", env={"BAR_ENV": "bar"}) assert result.capture == "Poe => poe_test_pwd\n" - assert ( - result.stdout - == f'{poe_project_path.joinpath("tests", "fixtures", "cwd_project", "subdir", "bar")}\n' - ) + path_parts = ["tests", "fixtures", "cwd_project", "subdir", "bar"] + assert result.stdout == f"{poe_project_path.joinpath(*path_parts)}\n" assert result.stderr == "" @@ -87,10 +80,8 @@ def test_cmd_task_with_cwd_option_pwd(run_poe_subproc, poe_project_path): ), ) assert result.capture == "Poe => poe_test_pwd\n" - assert ( - result.stdout - == f'{poe_project_path.joinpath("tests", "fixtures", "cwd_project", "subdir", "foo")}\n' - ) + path_parts = ["tests", "fixtures", "cwd_project", "subdir", "foo"] + assert result.stdout == f"{poe_project_path.joinpath(*path_parts)}\n" assert result.stderr == "" @@ -110,32 +101,28 @@ def test_cmd_task_with_cwd_option_pwd_override(run_poe_subproc, poe_project_path ), ) assert result.capture == "Poe => poe_test_pwd\n" - assert ( - result.stdout - == f'{poe_project_path.joinpath("tests", "fixtures", "cwd_project", "subdir", "bar")}\n' - ) + path_parts = ["tests", "fixtures", "cwd_project", "subdir", "bar"] + assert result.stdout == f"{poe_project_path.joinpath(*path_parts)}\n" assert result.stderr == "" def test_cmd_task_with_cwd_option_arg(run_poe_subproc, poe_project_path): result = run_poe_subproc("cwd_arg", "--foo_var", "foo", project="cwd") assert result.capture == "Poe => poe_test_pwd\n" - assert ( - result.stdout - == f'{poe_project_path.joinpath("tests", "fixtures", "cwd_project", "subdir", "foo")}\n' - ) + path_parts = ["tests", "fixtures", "cwd_project", "subdir", "foo"] + assert result.stdout == f"{poe_project_path.joinpath(*path_parts)}\n" assert result.stderr == "" def test_cmd_task_with_with_glob_arg_and_cwd(run_poe_subproc, poe_project_path): result = run_poe_subproc("ls", "--path-arg", "./subdir", project="cwd") assert result.capture == "Poe => ls ./subdir\n" - assert result.stdout == f"bar\nfoo\n" + assert result.stdout == "bar\nfoo\n" assert result.stderr == "" result = run_poe_subproc("ls", "--cwd-arg", "subdir", project="cwd") assert result.capture == "Poe => ls\n" - assert result.stdout == f"bar\nfoo\n" + assert result.stdout == "bar\nfoo\n" assert result.stderr == "" result = run_poe_subproc( @@ -143,5 +130,5 @@ def test_cmd_task_with_with_glob_arg_and_cwd(run_poe_subproc, poe_project_path): ) assert result.capture.startswith("Poe => ls ") assert result.capture.endswith("foo\n") - assert result.stdout == f"bar.txt\n" + assert result.stdout == "bar.txt\n" assert result.stderr == "" diff --git a/tests/test_envfile.py b/tests/test_envfile.py index e3f72fac..2f660ee9 100644 --- a/tests/test_envfile.py +++ b/tests/test_envfile.py @@ -1,8 +1,3 @@ -import os -import sys -from pathlib import Path - - def test_global_envfile_and_default(run_poe_subproc): result = run_poe_subproc("deploy-dev", project="envfile") assert ( diff --git a/tests/test_executors.py b/tests/test_executors.py index 208e344c..74b84583 100644 --- a/tests/test_executors.py +++ b/tests/test_executors.py @@ -1,5 +1,4 @@ import sys -from pathlib import Path import pytest @@ -20,8 +19,8 @@ def test_virtualenv_executor_fails_without_venv_dir(run_poe_subproc, projects): assert result.stderr == "" -@pytest.mark.slow -def test_virtualenv_executor_activates_venv( # TODO: fix dependency to get poe_test_env!! +@pytest.mark.slow() +def test_virtualenv_executor_activates_venv( run_poe_subproc, with_virtualenv_and_venv, projects ): venv_path = projects["venv"].joinpath("myvenv") @@ -34,7 +33,7 @@ def test_virtualenv_executor_activates_venv( # TODO: fix dependency to get poe_ assert result.stderr == "" -@pytest.mark.slow +@pytest.mark.slow() def test_virtualenv_executor_provides_access_to_venv_content( run_poe_subproc, with_virtualenv_and_venv, projects ): @@ -63,7 +62,7 @@ def test_virtualenv_executor_provides_access_to_venv_content( assert result.stderr == "" -@pytest.mark.slow +@pytest.mark.slow() def test_detect_venv( projects, run_poe_subproc, @@ -82,7 +81,8 @@ def test_detect_venv( assert result.stdout == "No poe_test_package found\n" assert result.stderr == "" - # if we install poe_test_package into this virtualenv then we should get a different result + # if we install poe_test_package into this virtualenv then we should get a + # different result install_into_virtualenv( venv_path, ("./tests/fixtures/packages/poe_test_package",) ) @@ -92,14 +92,17 @@ def test_detect_venv( if is_windows: assert result.stdout.endswith( ( - f"\\tests\\fixtures\\simple_project\\venv\\lib\\site-packages\\poe_test_package\\__init__.py\n", + "\\tests\\fixtures\\simple_project\\venv\\lib\\site-packages" + "\\poe_test_package\\__init__.py\n", # Lib has a captital with python >=11 - f"\\tests\\fixtures\\simple_project\\venv\\Lib\\site-packages\\poe_test_package\\__init__.py\n", + "\\tests\\fixtures\\simple_project\\venv\\Lib\\site-packages" + "\\poe_test_package\\__init__.py\n", ) ) else: assert result.stdout.endswith( - f"/tests/fixtures/simple_project/venv/lib/python{PY_V}/site-packages/poe_test_package/__init__.py\n" + f"/tests/fixtures/simple_project/venv/lib/python{PY_V}" + "/site-packages/poe_test_package/__init__.py\n" ) assert result.stderr == "" diff --git a/tests/test_expr_task.py b/tests/test_expr_task.py index d0d891e7..b01e8de5 100644 --- a/tests/test_expr_task.py +++ b/tests/test_expr_task.py @@ -1,24 +1,24 @@ def test_expr_with_args(run_poe_subproc): result = run_poe_subproc("expr_with_args", project="expr") - assert ( - result.capture - == """Poe => "power level is " + (f"only {power_level}" if int(${power_level}) <= 9000 else 'over nine thousand!\')\n""" + assert result.capture == ( + """Poe => "power level is " + (f"only {power_level}" """ + """if int(${power_level}) <= 9000 else 'over nine thousand!\')\n""" ) assert result.stdout == "power level is only 42\n" assert result.stderr == "" result = run_poe_subproc("expr_with_args", "999", project="expr") - assert ( - result.capture - == """Poe => "power level is " + (f"only {power_level}" if int(${power_level}) <= 9000 else 'over nine thousand!\')\n""" + assert result.capture == ( + """Poe => "power level is " + (f"only {power_level}" """ + """if int(${power_level}) <= 9000 else 'over nine thousand!\')\n""" ) assert result.stdout == "power level is only 999\n" assert result.stderr == "" result = run_poe_subproc("expr_with_args", "9001", project="expr") - assert ( - result.capture - == """Poe => "power level is " + (f"only {power_level}" if int(${power_level}) <= 9000 else 'over nine thousand!\')\n""" + assert result.capture == ( + """Poe => "power level is " + (f"only {power_level}" """ + """if int(${power_level}) <= 9000 else 'over nine thousand!\')\n""" ) assert result.stdout == "power level is over nine thousand!\n" assert result.stderr == "" @@ -26,17 +26,17 @@ def test_expr_with_args(run_poe_subproc): def test_expr_with_argv(run_poe_subproc): result = run_poe_subproc("expr_with_argv", "999", project="expr") - assert ( - result.capture - == """Poe => "power level is " + (f"only {sys.argv[1]}" if int(sys.argv[1]) <= 9000 else 'over nine thousand!\')\n""" + assert result.capture == ( + """Poe => "power level is " + (f"only {sys.argv[1]}" """ + """if int(sys.argv[1]) <= 9000 else 'over nine thousand!\')\n""" ) assert result.stdout == "power level is only 999\n" assert result.stderr == "" result = run_poe_subproc("expr_with_argv", "9001", project="expr") - assert ( - result.capture - == """Poe => "power level is " + (f"only {sys.argv[1]}" if int(sys.argv[1]) <= 9000 else 'over nine thousand!\')\n""" + assert result.capture == ( + """Poe => "power level is " + (f"only {sys.argv[1]}" """ + """if int(sys.argv[1]) <= 9000 else 'over nine thousand!\')\n""" ) assert result.stdout == "power level is over nine thousand!\n" assert result.stderr == "" @@ -49,9 +49,9 @@ def test_expr_with_env_vars(run_poe_subproc): project="expr", env={"VAR_FOO": "foo", "VAR_BAR": "2", "VAR_BAZ": "boo"}, ) - assert ( - result.capture - == "Poe => [${VAR_FOO} * int(${VAR_BAR})][0] + (f'{${VAR_BAZ}}') + '${NOTHING}'\n" + assert result.capture == ( + "Poe => [${VAR_FOO} * int(${VAR_BAR})][0] + (f'{${VAR_BAZ}}')" + " + '${NOTHING}'\n" ) assert result.stdout == "foofooboo\n" assert result.stderr == "" @@ -85,9 +85,9 @@ def test_expr_with_assert(run_poe_subproc): def test_expr_with_uses(run_poe_subproc): result = run_poe_subproc("expr_with_uses", project="expr") - assert ( - result.capture - == "Poe <= 0\nPoe => f'There have been {${GOOD_DAYS}} since the last failed test.'\n" + assert result.capture == ( + "Poe <= 0\n" + "Poe => f'There have been {${GOOD_DAYS}} since the last failed test.'\n" ) assert result.stdout == "There have been 0 since the last failed test.\n" assert result.stderr == "" diff --git a/tests/test_graph_execution.py b/tests/test_graph_execution.py index 6991fb38..0e7d37c8 100644 --- a/tests/test_graph_execution.py +++ b/tests/test_graph_execution.py @@ -22,7 +22,8 @@ def test_uses_dry_run(run_poe_subproc): "Poe <= poe_test_echo about\n" "Poe <= poe_test_echo hello\n" "Poe ?? unresolved dependency task results via uses option for task 'think'\n" - "Poe ?? unresolved dependency task results via uses option for task 'deep-graph-with-args'\n" + "Poe ?? unresolved dependency task results via uses option for task" + " 'deep-graph-with-args'\n" ) assert result.stdout == "" assert result.stderr == "" diff --git a/tests/test_ignore_fail.py b/tests/test_ignore_fail.py index 0580c839..335cf44a 100644 --- a/tests/test_ignore_fail.py +++ b/tests/test_ignore_fail.py @@ -1,7 +1,7 @@ import pytest -@pytest.fixture +@pytest.fixture() def generate_pyproject(tmp_path): """Return function which generates pyproject.toml with a given ignore_fail value.""" diff --git a/tests/test_includes.py b/tests/test_includes.py index 98597ee7..c1bb1008 100644 --- a/tests/test_includes.py +++ b/tests/test_includes.py @@ -1,6 +1,3 @@ -import os - - def test_docs_for_include_toml_file(run_poe_subproc): result = run_poe_subproc(project="includes") assert ( diff --git a/tests/test_poe_config.py b/tests/test_poe_config.py index 96b54fb8..d7224ea7 100644 --- a/tests/test_poe_config.py +++ b/tests/test_poe_config.py @@ -1,10 +1,3 @@ -import os -import shutil -import tempfile -from pathlib import Path - -import pytest - # Setting POETRY_VIRTUALENVS_CREATE stops poetry from creating the virtualenv and # spamming about it in stdout no_venv = {"POETRY_VIRTUALENVS_CREATE": "false"} @@ -26,17 +19,15 @@ def test_setting_default_task_type(run_poe_subproc, projects, esc_prefix): def test_setting_default_array_item_task_type(run_poe_subproc): result = run_poe_subproc("composite_task", project="scripts", env=no_venv) - assert ( - result.capture == f"Poe => poe_test_echo Hello\nPoe => poe_test_echo World!\n" - ) - assert result.stdout == f"Hello\nWorld!\n" + assert result.capture == "Poe => poe_test_echo Hello\nPoe => poe_test_echo World!\n" + assert result.stdout == "Hello\nWorld!\n" assert result.stderr == "" def test_setting_global_env_vars(run_poe_subproc): result = run_poe_subproc("travel", env=no_venv) - assert result.capture == f"Poe => poe_test_echo from EARTH to\nPoe => travel[1]\n" - assert result.stdout == f"from EARTH to\nMARS\n" + assert result.capture == "Poe => poe_test_echo from EARTH to\nPoe => travel[1]\n" + assert result.stdout == "from EARTH to\nMARS\n" assert result.stderr == "" diff --git a/tests/test_poetry_plugin.py b/tests/test_poetry_plugin.py index eb20b61a..8008b01d 100644 --- a/tests/test_poetry_plugin.py +++ b/tests/test_poetry_plugin.py @@ -1,25 +1,24 @@ import re -from sys import version_info import pytest @pytest.fixture(scope="session") -def setup_poetry_project(run_poetry, projects): +def _setup_poetry_project(run_poetry, projects): run_poetry(["install"], cwd=projects["poetry_plugin"]) @pytest.fixture(scope="session") -def setup_poetry_project_empty_prefix(run_poetry, projects): +def _setup_poetry_project_empty_prefix(run_poetry, projects): run_poetry(["install"], cwd=projects["poetry_plugin/empty_prefix"].parent) @pytest.fixture(scope="session") -def setup_poetry_project_with_prefix(run_poetry, projects): +def _setup_poetry_project_with_prefix(run_poetry, projects): run_poetry(["install"], cwd=projects["poetry_plugin/with_prefix"].parent) -@pytest.mark.slow +@pytest.mark.slow() def test_poetry_help(run_poetry, projects): result = run_poetry([], cwd=projects["poetry_plugin"]) assert result.stdout.startswith("Poetry (version ") @@ -28,10 +27,9 @@ def test_poetry_help(run_poetry, projects): # assert result.stderr == "" -@pytest.mark.slow -def test_task_with_cli_dependency( - run_poetry, projects, setup_poetry_project, is_windows -): +@pytest.mark.slow() +@pytest.mark.usefixtures("_setup_poetry_project") +def test_task_with_cli_dependency(run_poetry, projects, is_windows): result = run_poetry( ["poe", "cow-greet", "yo yo yo"], cwd=projects["poetry_plugin"], @@ -49,8 +47,9 @@ def test_task_with_cli_dependency( # assert result.stderr == "" -@pytest.mark.slow -def test_task_with_lib_dependency(run_poetry, projects, setup_poetry_project): +@pytest.mark.slow() +@pytest.mark.usefixtures("_setup_poetry_project") +def test_task_with_lib_dependency(run_poetry, projects): result = run_poetry(["poe", "cow-cheese"], cwd=projects["poetry_plugin"]) assert result.stdout == ( "Poe => from cowpy import cow; print(list(cow.COWACTERS)[5])\ncheese\n" @@ -58,8 +57,9 @@ def test_task_with_lib_dependency(run_poetry, projects, setup_poetry_project): # assert result.stderr == "" -@pytest.mark.slow -def test_task_accepts_any_args(run_poetry, projects, setup_poetry_project): +@pytest.mark.slow() +@pytest.mark.usefixtures("_setup_poetry_project") +def test_task_accepts_any_args(run_poetry, projects): result = run_poetry( ["poe", "echo", "--lol=:D", "--version", "--help"], cwd=projects["poetry_plugin"], @@ -70,10 +70,9 @@ def test_task_accepts_any_args(run_poetry, projects, setup_poetry_project): # assert result.stderr == "" -@pytest.mark.slow -def test_poetry_help_without_poe_command_prefix( - run_poetry, projects, setup_poetry_project_empty_prefix -): +@pytest.mark.slow() +@pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") +def test_poetry_help_without_poe_command_prefix(run_poetry, projects): result = run_poetry([], cwd=projects["poetry_plugin/empty_prefix"].parent) assert result.stdout.startswith("Poetry (version ") assert "\n cow-greet" in result.stdout @@ -81,10 +80,9 @@ def test_poetry_help_without_poe_command_prefix( # assert result.stderr == "" -@pytest.mark.slow -def test_running_tasks_without_poe_command_prefix( - run_poetry, projects, setup_poetry_project_empty_prefix -): +@pytest.mark.slow() +@pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") +def test_running_tasks_without_poe_command_prefix(run_poetry, projects): result = run_poetry( ["echo", "--lol=:D", "--version", "--help"], cwd=projects["poetry_plugin/empty_prefix"].parent, @@ -95,10 +93,9 @@ def test_running_tasks_without_poe_command_prefix( # assert result.stderr == "" -@pytest.mark.slow -def test_poetry_help_with_poe_command_prefix( - run_poetry, projects, setup_poetry_project_empty_prefix -): +@pytest.mark.slow() +@pytest.mark.usefixtures("_setup_poetry_project_empty_prefix") +def test_poetry_help_with_poe_command_prefix(run_poetry, projects): result = run_poetry([], cwd=projects["poetry_plugin/with_prefix"].parent) assert result.stdout.startswith("Poetry (version ") assert "\n foo cow-greet" in result.stdout @@ -106,10 +103,9 @@ def test_poetry_help_with_poe_command_prefix( # assert result.stderr == "" -@pytest.mark.slow -def test_running_tasks_with_poe_command_prefix( - run_poetry, projects, setup_poetry_project_with_prefix -): +@pytest.mark.slow() +@pytest.mark.usefixtures("_setup_poetry_project_with_prefix") +def test_running_tasks_with_poe_command_prefix(run_poetry, projects): result = run_poetry( ["foo", "echo", "--lol=:D", "--version", "--help"], cwd=projects["poetry_plugin/with_prefix"].parent, @@ -120,10 +116,9 @@ def test_running_tasks_with_poe_command_prefix( # assert result.stderr == "" -@pytest.mark.slow -def test_running_tasks_with_poe_command_prefix( - run_poetry, projects, setup_poetry_project_with_prefix -): +@pytest.mark.slow() +@pytest.mark.usefixtures("_setup_poetry_project_with_prefix") +def test_running_tasks_with_poe_command_prefix_missing_args(run_poetry, projects): result = run_poetry( ["foo"], cwd=projects["poetry_plugin/with_prefix"].parent, @@ -132,8 +127,9 @@ def test_running_tasks_with_poe_command_prefix( # assert result.stderr == "" -@pytest.mark.slow -def test_running_poetry_command_with_hooks(run_poetry, projects, setup_poetry_project): +@pytest.mark.slow() +@pytest.mark.usefixtures("_setup_poetry_project") +def test_running_poetry_command_with_hooks(run_poetry, projects): result = run_poetry(["env", "info"], cwd=projects["poetry_plugin"]) assert "THIS IS YOUR ENV!" in result.stdout assert "THAT WAS YOUR ENV!" in result.stdout diff --git a/tests/test_script_tasks.py b/tests/test_script_tasks.py index 1cf64378..c511fb20 100644 --- a/tests/test_script_tasks.py +++ b/tests/test_script_tasks.py @@ -1,14 +1,11 @@ import difflib -import shutil - -import pytest no_venv = {"POETRY_VIRTUALENVS_CREATE": "false"} def test_script_task_with_hard_coded_args(run_poe_subproc, projects, esc_prefix): result = run_poe_subproc("static-args-test", project="scripts", env=no_venv) - assert result.capture == f"Poe => static-args-test\n" + assert result.capture == "Poe => static-args-test\n" assert result.stdout == ( "str: pat a cake\n" "int: 1\n" @@ -65,12 +62,10 @@ def test_script_task_with_cli_args(run_poe_subproc, is_windows): project="scripts", env=no_venv, ) - assert ( - result.capture == f"Poe => greet-passed-args --greeting=hello --user=nat\n" - ), [ + assert result.capture == "Poe => greet-passed-args --greeting=hello --user=nat\n", [ li for li in difflib.ndiff( - result.capture, f"Poe => greet-passed-args --greeting=hello --user=nat\n" + result.capture, "Poe => greet-passed-args --greeting=hello --user=nat\n" ) if li[0] != " " ] @@ -109,7 +104,7 @@ def test_script_task_with_args_optional(run_poe_subproc, projects, is_windows): def test_script_task_default_arg(run_poe_subproc): result = run_poe_subproc("greet-full-args", project="scripts", env=no_venv) - assert result.capture == f"Poe => greet-full-args\n" + assert result.capture == "Poe => greet-full-args\n" # hi is the default value for --greeting assert result.stdout == "hi None None None\n" assert result.stderr == "" diff --git a/tests/test_sequence_tasks.py b/tests/test_sequence_tasks.py index e76c6601..c7eb899f 100644 --- a/tests/test_sequence_tasks.py +++ b/tests/test_sequence_tasks.py @@ -1,32 +1,34 @@ def test_sequence_task(run_poe_subproc, esc_prefix): result = run_poe_subproc("composite_task", project="sequences") - assert ( - result.capture - == f"Poe => poe_test_echo Hello\nPoe => poe_test_echo World!\nPoe => poe_test_echo :)!\n" + assert result.capture == ( + "Poe => poe_test_echo Hello\n" + "Poe => poe_test_echo World!\n" + "Poe => poe_test_echo :)!\n" ) - assert result.stdout == f"Hello\nWorld!\n:)!\n" + assert result.stdout == "Hello\nWorld!\n:)!\n" assert result.stderr == "" def test_another_sequence_task(run_poe_subproc, esc_prefix): # This should be exactly the same as calling the composite_task task directly result = run_poe_subproc("also_composite_task", project="sequences") - assert ( - result.capture - == f"Poe => poe_test_echo Hello\nPoe => poe_test_echo World!\nPoe => poe_test_echo :)!\n" + assert result.capture == ( + "Poe => poe_test_echo Hello\n" + "Poe => poe_test_echo World!\n" + "Poe => poe_test_echo :)!\n" ) - assert result.stdout == f"Hello\nWorld!\n:)!\n" + assert result.stdout == "Hello\nWorld!\n:)!\n" assert result.stderr == "" def test_a_script_sequence_task_with_args(run_poe_subproc, esc_prefix): # This should be exactly the same as calling the composite_task task directly result = run_poe_subproc("greet-multiple", "--mouse=Jerry", project="sequences") - assert ( - result.capture - == f"Poe => my_package:main(environ.get('cat'))\nPoe => my_package:main(environ['mouse'])\n" + assert result.capture == ( + "Poe => my_package:main(environ.get('cat'))\n" + "Poe => my_package:main(environ['mouse'])\n" ) - assert result.stdout == f"hello Tom\nhello Jerry\n" + assert result.stdout == "hello Tom\nhello Jerry\n" assert result.stderr == "" @@ -34,9 +36,9 @@ def test_sequence_task_with_multiple_value_arg(run_poe_subproc): result = run_poe_subproc( "multiple-value-arg", "hey", "1", "2", "3", project="sequences" ) - assert ( - result.capture - == "Poe => poe_test_echo first: hey\nPoe => poe_test_echo second: 1 2 3\nPoe => poe_test_echo Done.\n" + assert result.capture == ( + "Poe => poe_test_echo first: hey\nPoe => poe_test_echo second: 1 2 3\n" + "Poe => poe_test_echo Done.\n" ) assert result.stdout == "first: hey\nsecond: 1 2 3\nDone.\n" assert result.stderr == "" diff --git a/tests/test_shell_completion.py b/tests/test_shell_completion.py index a527cfcb..e27126b2 100644 --- a/tests/test_shell_completion.py +++ b/tests/test_shell_completion.py @@ -1,9 +1,9 @@ def test_describe_tasks(run_poe_main): result = run_poe_main("_describe_tasks") # expect an ordered listing of non-hidden tasks defined in the dummy_project - assert ( - result.stdout - == "echo show_env greet greet-shouty count also_echo sing part1 composite_task also_composite_task greet-multiple travel\n" + assert result.stdout == ( + "echo show_env greet greet-shouty count also_echo sing part1 composite_task " + "also_composite_task greet-multiple travel\n" ) assert result.stderr == "" @@ -11,9 +11,9 @@ def test_describe_tasks(run_poe_main): def test_list_tasks(run_poe_main): result = run_poe_main("_list_tasks") # expect an ordered listing of non-hidden tasks defined in the dummy_project - assert ( - result.stdout - == "echo show_env greet greet-shouty count also_echo sing part1 composite_task also_composite_task greet-multiple travel\n" + assert result.stdout == ( + "echo show_env greet greet-shouty count also_echo sing part1 composite_task" + " also_composite_task greet-multiple travel\n" ) assert result.stderr == "" diff --git a/tests/test_shell_task.py b/tests/test_shell_task.py index 9b80e573..37fe6fa7 100644 --- a/tests/test_shell_task.py +++ b/tests/test_shell_task.py @@ -5,9 +5,9 @@ def test_shell_task(run_poe_subproc): result = run_poe_subproc("count", project="shells") - assert ( - result.capture - == f"Poe => poe_test_echo 1 && poe_test_echo 2 && poe_test_echo $(python -c 'print(1 + 2)')\n" + assert result.capture == ( + "Poe => poe_test_echo 1 && poe_test_echo 2 " + "&& poe_test_echo $(python -c 'print(1 + 2)')\n" ) assert result.stdout == "1\n2\n3\n" assert result.stderr == "" @@ -15,7 +15,7 @@ def test_shell_task(run_poe_subproc): def test_shell_task_raises_given_extra_args(run_poe): result = run_poe("count", "bla", project="shells") - assert f"\n\nError: Shell task 'count' does not accept arguments" in result.capture + assert "\n\nError: Shell task 'count' does not accept arguments" in result.capture assert result.stdout == "" assert result.stderr == "" @@ -24,13 +24,13 @@ def test_multiline_non_default_type_task(run_poe_subproc): # This should be exactly the same as calling the echo task directly result = run_poe_subproc("sing", project="shells") assert result.capture == ( - f'Poe => poe_test_echo "this is the story";\n' + 'Poe => poe_test_echo "this is the story";\n' 'poe_test_echo "all about how" && # the last line won\'t run\n' 'poe_test_echo "my life got flipped;\n' ' turned upside down" ||\npoe_test_echo "bam bam baaam bam"\n' ) assert result.stdout == ( - f"this is the story\n" + "this is the story\n" "all about how\n" "my life got flipped;\n" " turned upside down\n" @@ -42,7 +42,7 @@ def test_shell_task_with_dash_case_arg(run_poe_subproc): result = run_poe_subproc( "greet", "--formal-greeting=hey", "--subject=you", project="shells" ) - assert result.capture == (f"Poe => poe_test_echo $formal_greeting $subject\n") + assert result.capture == ("Poe => poe_test_echo $formal_greeting $subject\n") assert result.stdout == "hey you\n" assert result.stderr == "" @@ -50,7 +50,7 @@ def test_shell_task_with_dash_case_arg(run_poe_subproc): @pytest.mark.skipif(not shutil.which("sh"), reason="No sh available") def test_interpreter_sh(run_poe_subproc): result = run_poe_subproc("echo_sh", project="shells") - assert result.capture == (f"Poe => poe_test_echo $0 $test_var\n") + assert result.capture == ("Poe => poe_test_echo $0 $test_var\n") assert "roflcopter" in result.stdout assert result.stderr == "" @@ -58,7 +58,7 @@ def test_interpreter_sh(run_poe_subproc): @pytest.mark.skipif(not shutil.which("bash"), reason="No bash available") def test_interpreter_bash(run_poe_subproc): result = run_poe_subproc("echo_bash", project="shells") - assert result.capture == (f"Poe => poe_test_echo $0 $test_var\n") + assert result.capture == ("Poe => poe_test_echo $0 $test_var\n") assert "bash" in result.stdout assert "roflcopter" in result.stdout assert result.stderr == "" @@ -67,15 +67,15 @@ def test_interpreter_bash(run_poe_subproc): @pytest.mark.skipif(not shutil.which("pwsh"), reason="No pwsh available") def test_interpreter_pwsh(run_poe_subproc): result = run_poe_subproc("echo_pwsh", project="shells") - assert result.capture == (f"Poe => poe_test_echo $ENV:test_var\n") + assert result.capture == ("Poe => poe_test_echo $ENV:test_var\n") assert "roflcopter" in result.stdout assert result.stderr == "" @pytest.mark.skipif(not shutil.which("powershell"), reason="No powershell available") -def test_interpreter_pwsh(run_poe_subproc): +def test_interpreter_powershell(run_poe_subproc): result = run_poe_subproc("echo_powershell", project="shells") - assert result.capture == (f"Poe => poe_test_echo $ENV:test_var\n") + assert result.capture == ("Poe => poe_test_echo $ENV:test_var\n") assert "roflcopter" in result.stdout assert result.stderr == "" @@ -83,7 +83,8 @@ def test_interpreter_pwsh(run_poe_subproc): def test_interpreter_python(run_poe_subproc): result = run_poe_subproc("echo_python", project="shells") assert result.capture == ( - f'Poe => import sys, os\n\ndef run():\n print(sys.version_info, os.environ.get("test_var"))\n\nrun()\n' + "Poe => import sys, os\n\ndef run():\n" + ' print(sys.version_info, os.environ.get("test_var"))\n\nrun()\n' ) assert result.stdout.startswith("sys.version_info(major=3,") assert "roflcopter" in result.stdout @@ -109,7 +110,7 @@ def test_global_interpreter_config(run_poe_subproc, projects): f'--root={projects["shells/shell_interpreter_config"]}', "echo_python", ) - assert result.capture == (f"Poe => import sys\nprint(sys.version_info)\n") + assert result.capture == "Poe => import sys\nprint(sys.version_info)\n" assert result.stdout.startswith("sys.version_info(major=3,") assert result.stderr == "" diff --git a/tests/test_switch_task.py b/tests/test_switch_task.py index 9bdcce44..7061a0ed 100644 --- a/tests/test_switch_task.py +++ b/tests/test_switch_task.py @@ -1,8 +1,5 @@ -import shutil import sys -import pytest - def test_switch_on_platform(run_poe_subproc): common_prefix = "Poe <= override or sys.platform\n" diff --git a/tests/test_task_running.py b/tests/test_task_running.py index d206fc94..785a6485 100644 --- a/tests/test_task_running.py +++ b/tests/test_task_running.py @@ -3,9 +3,9 @@ def test_ref_task(run_poe_subproc, projects, esc_prefix): result = run_poe_subproc( "also_echo", "foo", "!", env={"POETRY_VIRTUALENVS_CREATE": "false"} ) - assert ( - result.capture - == f"Poe => poe_test_echo POE_ROOT:{projects['example']} Password1, task_args: foo !\n" + assert result.capture == ( + "Poe => poe_test_echo " + f"POE_ROOT:{projects['example']} Password1, task_args: foo !\n" ) assert ( result.stdout == f"POE_ROOT:{projects['example']} Password1, task_args: foo !\n"