Skip to content

Commit

Permalink
Configure ruff and apply prescribed fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
nat-n committed Sep 24, 2023
1 parent 29f4a54 commit 2c6e6bd
Show file tree
Hide file tree
Showing 51 changed files with 369 additions and 358 deletions.
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
4 changes: 3 additions & 1 deletion poethepoet/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from .__version__ import __version__

__all__ = ["__version__", "main"]


def main():
import sys
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion poethepoet/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 6 additions & 8 deletions poethepoet/completion/zsh.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down Expand Up @@ -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]
Expand Down
8 changes: 4 additions & 4 deletions poethepoet/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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}"
)
Expand Down Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion poethepoet/env/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
12 changes: 7 additions & 5 deletions poethepoet/env/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
):
Expand All @@ -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)
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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()
Expand Down
18 changes: 12 additions & 6 deletions poethepoet/env/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -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<esc_naked>[\w\d_]+)|" # $VAR preceded by an odd num of \
r"(?:[^\\]|^)(?:\\(?:\\{2})*)\$\{(?P<esc_paren>[\w\d_]+)\}|" # ${VAR} preceded by an odd num of \
r"\$(?P<naked>[\w\d_]+)|" # $VAR
r"\${(?P<paren>[\w\d_]+)}" # ${VAR}
# $VAR preceded by an odd num of \
r"(?:[^\\]|^)(?:\\(?:\\{2})*)\$(?P<esc_naked>[\w\d_]+)"
# ${VAR} preceded by an odd num of \
r"|(?:[^\\]|^)(?:\\(?:\\{2})*)\$\{(?P<esc_paren>[\w\d_]+)\}"
# $VAR
r"|\$(?P<naked>[\w\d_]+)"
# ${VAR}
r"|\${(?P<paren>[\w\d_]+)}"
")"
)

_SHELL_VAR_PATTERN_BRACES = re.compile(
# Matches shell variable patterns, distinguishing escaped examples (to be ignored)
r"(?:"
r"(?:[^\\]|^)(?:\\(?:\\{2})*)\$\{(?P<esc_paren>[\w\d_]+)\}|" # ${VAR} preceded by an odd num of \
r"\${(?P<paren>[\w\d_]+)}" # ${VAR}
# ${VAR} preceded by an odd num of \
r"(?:[^\\]|^)(?:\\(?:\\{2})*)\$\{(?P<esc_paren>[\w\d_]+)\}"
# ${VAR}
r"|\${(?P<paren>[\w\d_]+)}"
")"
)

Expand Down
2 changes: 2 additions & 0 deletions poethepoet/executor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
from .poetry import PoetryExecutor
from .simple import SimpleExecutor
from .virtualenv import VirtualenvExecutor

__all__ = ["PoeExecutor", "PoetryExecutor", "SimpleExecutor", "VirtualenvExecutor"]
5 changes: 3 additions & 2 deletions poethepoet/executor/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
1 change: 0 additions & 1 deletion poethepoet/executor/poetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion poethepoet/executor/virtualenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down
18 changes: 2 additions & 16 deletions poethepoet/helpers/command/__init__.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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})
Expand Down
34 changes: 18 additions & 16 deletions poethepoet/helpers/command/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -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] = []
Expand Down Expand Up @@ -95,7 +94,10 @@ class Glob(ContentNode):
"""

# This pattern is equivalent to what this node might parse
PATTERN = r"(?P<simple>[\?\*])|(?P<complex>\[(?:\!?\](?:[^\s\]\\]|\\.)*|(?:[^\s\]\\]|\\.)+)\])"
PATTERN = (
r"(?P<simple>[\?\*])"
r"|(?P<complex>\[(?:\!?\](?:[^\s\]\\]|\\.)*|(?:[^\s\]\\]|\\.)+)\])"
)

def _parse(self, chars: ParseCursor):
char = chars.peek()
Expand Down
13 changes: 7 additions & 6 deletions poethepoet/helpers/command/ast_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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]
Expand Down
11 changes: 6 additions & 5 deletions poethepoet/helpers/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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 = (
Expand All @@ -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:
Expand Down

0 comments on commit 2c6e6bd

Please sign in to comment.