Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add Ruff linter pre-commit hook #690

Merged
merged 1 commit into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 9 additions & 28 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,24 @@ repos:
args: [--fix=lf]
- id: debug-statements
- id: check-added-large-files
- repo: https://github.com/asottile/pyupgrade
rev: v3.17.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.0
hooks:
- id: pyupgrade
args: [--py39-plus]
- repo: https://github.com/psf/black
rev: 24.8.0
hooks:
- id: black
- id: ruff-format
- id: ruff
args:
- --exclude=/(tests)/
- --line-length=120
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
args: ["--profile", "black", "--filter-files"]
- --fix
exclude: |
(?x)^(
|tests/.*
)$
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
hooks:
- id: codespell
args:
- --ignore-words-list=nin,astroid
- --skip=poetry.lock
- repo: https://github.com/PyCQA/flake8
rev: 7.1.1
hooks:
- id: flake8
exclude: |
(?x)^(
.*/testdata/.*
|.*/testpath/.*
|tests/tools/pylint/test_no_init_found/.*
|tests/test_message\.py
)$
args:
- --max-line-length=120
- repo: https://github.com/regebro/pyroma
rev: "4.2"
hooks:
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
html_title = "prospector documentation"

# A shorter title for the navigation bar. Default is the same as html_title.
html_short_title = "prospector-%s" % version
html_short_title = f"prospector-{version}"

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
Expand Down
2 changes: 1 addition & 1 deletion prospector/autodetect.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def find_from_path(path: Path) -> set[str]:
names |= find_from_imports(contents)
except encoding.CouldNotHandleEncoding as err:
# TODO: this output will break output formats such as JSON
warnings.warn(f"{err.path}: {err.__cause__}", ImportWarning)
warnings.warn(f"{err.path}: {err.__cause__}", ImportWarning, stacklevel=0)

if len(names) == len(POSSIBLE_LIBRARIES):
# don't continue on recursing, there's no point!
Expand Down
20 changes: 13 additions & 7 deletions prospector/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
except ImportError:
import sre_constants # pylint: disable=deprecated-module

import contextlib

from prospector import tools
from prospector.autodetect import autodetect_libraries
from prospector.compat import is_relative_to
Expand Down Expand Up @@ -174,7 +176,7 @@ def _get_profile(

# Use the strictness profile only if no profile has been given
if config.strictness is not None and config.strictness:
cmdline_implicit.append("strictness_%s" % config.strictness)
cmdline_implicit.append(f"strictness_{config.strictness}")
strictness = config.strictness

# the profile path is
Expand All @@ -196,8 +198,14 @@ def _get_profile(
profile = ProspectorProfile.load(profile_name, profile_path, forced_inherits=forced_inherits)
except CannotParseProfile as cpe:
sys.stderr.write(
"Failed to run:\nCould not parse profile %s as it is not valid YAML\n%s\n"
% (cpe.filepath, cpe.get_parse_message())
"\n".join(
[
"Failed to run:",
f"Could not parse profile {cpe.filepath} as it is not valid YAML",
f"{cpe.get_parse_message()}",
"",
]
)
)
sys.exit(1)
except ProfileNotFound as nfe:
Expand Down Expand Up @@ -273,10 +281,8 @@ def _determine_ignores(
# ignore-patterns:
# uses: django
continue
try:
with contextlib.suppress(sre_constants.error):
ignores.append(re.compile(pattern))
except sre_constants.error:
pass

# Convert ignore paths into patterns
boundary = r"(^|/|\\)%s(/|\\|$)"
Expand Down Expand Up @@ -318,7 +324,7 @@ def tool_options(self, tool_name: str) -> dict[str, str]:
return tool.get("options", {})

def external_config_location(self, tool_name: str) -> Optional[Path]:
return getattr(self.config, "%s_config_file" % tool_name, None)
return getattr(self.config, f"{tool_name}_config_file", None)

@property
def die_on_tool_error(self) -> bool:
Expand Down
16 changes: 8 additions & 8 deletions prospector/config/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,10 @@ def build_command_line_source(
},
"output_format": {
"flags": ["-o", "--output-format"],
"help": "The output format. Valid values are: %s. This will output to stdout by default, "
"however a target file can be used instead by adding :path-to-output-file, eg, -o json:output.json"
% (", ".join(sorted(FORMATTERS.keys())),),
"help": "The output format. Valid values are: {}. This will output to stdout by default, "
"however a target file can be used instead by adding :path-to-output-file, eg, -o json:output.json".format(
", ".join(sorted(FORMATTERS.keys()))
),
},
"absolute_paths": {
"help": "Whether to output absolute paths when referencing files "
Expand All @@ -199,9 +200,8 @@ def build_command_line_source(
"flags": ["-t", "--tool"],
"help": "A list of tools to run. This lets you set exactly which "
"tools to run. To add extra tools to the defaults, see "
"--with-tool. Possible values are: %s. By "
"default, the following tools will be run: %s"
% (
"--with-tool. Possible values are: {}. By "
"default, the following tools will be run: {}".format(
", ".join(sorted(TOOLS.keys())),
", ".join(sorted(DEFAULT_TOOLS)),
),
Expand All @@ -210,14 +210,14 @@ def build_command_line_source(
"flags": ["-w", "--with-tool"],
"help": "A list of tools to run in addition to the default tools. "
"To specify all tools explicitly, use the --tool argument. "
"Possible values are %s." % (", ".join(sorted(TOOLS.keys()))),
"Possible values are {}.".format(", ".join(sorted(TOOLS.keys()))),
},
"without_tools": {
"flags": ["-W", "--without-tool"],
"help": "A list of tools that should not be run. Useful to turn off "
"only a single tool from the defaults. "
"To specify all tools explicitly, use the --tool argument. "
"Possible values are %s." % (", ".join(sorted(TOOLS.keys()))),
"Possible values are {}.".format(", ".join(sorted(TOOLS.keys()))),
},
"profiles": {
"flags": ["-P", "--profile"],
Expand Down
6 changes: 1 addition & 5 deletions prospector/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ class FatalProspectorException(Exception):
Problems in prospector itself should raise this to notify
the user directly. Errors in dependent tools should be
caught and the user notified elegantly.

"""

# (see also the --die-on-tool-error flag)
Expand All @@ -27,10 +26,7 @@ def __init__(self, path: Path):
class PermissionMissing(Exception):
def __init__(self, path: Path):
docs_url = "https://prospector.landscape.io/en/master/profiles.html#ignoring-paths-and-patterns"
if os.path.isdir(path):
what = f"directory {path}"
else:
what = f"the file {path}"
what = f"directory {path}" if os.path.isdir(path) else f"the file {path}"
error_msg = (
f"The current user {os.getlogin()} does not have permission to open "
f"{what}. Either fix permissions or tell prospector to skip it "
Expand Down
2 changes: 1 addition & 1 deletion prospector/formatters/base_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class SummaryFormatter(Formatter):
summary_labels = (
("started", "Started", None),
("completed", "Finished", None),
("time_taken", "Time Taken", lambda x: "%s seconds" % x),
("time_taken", "Time Taken", lambda x: f"{x} seconds"),
("formatter", "Formatter", None),
("profiles", "Profiles", None),
("strictness", "Strictness", None),
Expand Down
5 changes: 2 additions & 3 deletions prospector/formatters/emacs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ def render_message(self, message: Message) -> str:
message.location.line,
(message.location.character or 0) + 1,
),
" L%s:%s %s: %s - %s"
% (
" L{}:{} {}: {} - {}".format(
message.location.line or "-",
message.location.character if message.location.line else "-",
message.location.function,
message.source,
message.code,
),
" %s" % message.message,
f" {message.message}",
]

return "\n".join(output)
7 changes: 3 additions & 4 deletions prospector/formatters/grouped.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,15 @@ def render_messages(self) -> str:
output.append(str(filename))

for line in sorted(groups[filename].keys(), key=lambda x: 0 if x is None else int(x)):
output.append(" Line: %s" % line)
output.append(f" Line: {line}")

for message in groups[filename][line]:
output.append(
" %s: %s / %s%s"
% (
" {}: {} / {}{}".format(
message.source,
message.code,
message.message,
(" (col %s)" % message.location.character) if message.location.character else "",
(f" (col {message.location.character})") if message.location.character else "",
)
)

Expand Down
2 changes: 1 addition & 1 deletion prospector/formatters/pylint.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def render(self, summary: bool = True, messages: bool = True, profile: bool = Fa
module_name = self._make_path(message.location.path).replace(os.path.sep, ".")
module_name = re.sub(r"(\.__init__)?\.py$", "", module_name)

header = "************* Module %s" % module_name
header = f"************* Module {module_name}"
output.append(header)

# ={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
Expand Down
8 changes: 3 additions & 5 deletions prospector/formatters/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,16 @@


class TextFormatter(SummaryFormatter):

def render_message(self, message: Message) -> str:
output = []

if message.location.module:
output.append(f"{message.location.module} ({self._make_path(message.location.path)}):")
else:
output.append("%s:" % self._make_path(message.location.path))
output.append(f"{self._make_path(message.location.path)}:")

output.append(
" L%s:%s %s: %s - %s"
% (
" L{}:{} {}: {} - {}".format(
message.location.line or "-",
message.location.character if message.location.character else "-",
message.location.function,
Expand All @@ -28,7 +26,7 @@ def render_message(self, message: Message) -> str:
)
)

output.append(" %s" % message.message)
output.append(f" {message.message}")

return "\n".join(output)

Expand Down
2 changes: 1 addition & 1 deletion prospector/formatters/vscode.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def render(self, summary: bool = True, messages: bool = True, profile: bool = Fa
module_name = self._make_path(message.location.path).replace(os.path.sep, ".")
module_name = re.sub(r"(\.__init__)?\.py$", "", module_name)

header = "************* Module %s" % module_name
header = f"************* Module {module_name}"
output.append(header)

template = "%(line)s,%(character)s,%(code)s,%(code)s:%(source)s %(message)s"
Expand Down
4 changes: 2 additions & 2 deletions prospector/formatters/xunit.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def render(self, summary: bool = True, messages: bool = True, profile: bool = Fa
testsuite_el = xml_doc.createElement("testsuite")
testsuite_el.setAttribute("errors", str(self.summary["message_count"]))
testsuite_el.setAttribute("failures", "0")
testsuite_el.setAttribute("name", "prospector-%s" % "-".join(self.summary["tools"]))
testsuite_el.setAttribute("name", "prospector-{}".format("-".join(self.summary["tools"])))
testsuite_el.setAttribute("tests", str(self.summary["message_count"]))
testsuite_el.setAttribute("time", str(self.summary["time_taken"]))
xml_doc.appendChild(testsuite_el)
Expand All @@ -38,7 +38,7 @@ def render(self, summary: bool = True, messages: bool = True, profile: bool = Fa

failure_el = xml_doc.createElement("error")
failure_el.setAttribute("message", message.message.strip())
failure_el.setAttribute("type", "%s Error" % message.source)
failure_el.setAttribute("type", f"{message.source} Error")
template = "%(path)s:%(line)s: [%(code)s(%(source)s), %(function)s] %(message)s"
cdata = template % {
"path": self._make_path(message.location.path),
Expand Down
13 changes: 3 additions & 10 deletions prospector/pathutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ def is_python_module(path: Path) -> bool:


def is_virtualenv(path: Path) -> bool:
if os.name == "nt":
# Windows!
clues = ("Scripts", "lib", "include")
else:
clues = ("bin", "lib", "include")
clues = ("Scripts", "lib", "include") if os.name == "nt" else ("bin", "lib", "include")

try:
# just get the name, iterdir returns absolute paths by default
Expand All @@ -37,8 +33,5 @@ def is_virtualenv(path: Path) -> bool:
# if we do have all three directories, make sure that it's not
# just a coincidence by doing some heuristics on the rest of
# the directory
if len(dircontents) > 7:
# if there are more than 7 things it's probably not a virtualenvironment
return False

return True
# if there are more than 7 things it's probably not a virtualenvironment
return len(dircontents) <= 7
sbrunner marked this conversation as resolved.
Show resolved Hide resolved
15 changes: 8 additions & 7 deletions prospector/postfilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,16 @@ def filter_messages(filepaths: List[Path], messages: List[Message]) -> List[Mess
continue

# some lines are skipped entirely by messages
if relative_message_path in lines_to_ignore:
if message.location.line in lines_to_ignore[relative_message_path]:
continue
if relative_message_path in lines_to_ignore and message.location.line in lines_to_ignore[relative_message_path]:
continue

# and some lines have only certain messages explicitly ignored
if relative_message_path in messages_to_ignore:
if message.location.line in messages_to_ignore[relative_message_path]:
if message.code in messages_to_ignore[relative_message_path][message.location.line]:
continue
if (
relative_message_path in messages_to_ignore
and message.location.line in messages_to_ignore[relative_message_path]
and message.code in messages_to_ignore[relative_message_path][message.location.line]
):
continue

# otherwise this message was not filtered
filtered.append(message)
Expand Down
10 changes: 5 additions & 5 deletions prospector/profiles/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ def __init__(self, filepath: str, parse_error: Exception) -> None:
self.parse_error = parse_error

def get_parse_message(self) -> str:
return "{}\n on line {} : char {}".format(
self.parse_error.problem, # type: ignore[attr-defined]
self.parse_error.problem_mark.line, # type: ignore[attr-defined]
self.parse_error.problem_mark.column, # type: ignore[attr-defined]
return (
f"{self.parse_error.problem}\n" # type: ignore[attr-defined]
f" on line {self.parse_error.problem_mark.line}: " # type: ignore[attr-defined]
f"char {self.parse_error.problem_mark.column}" # type: ignore[attr-defined]
)

def __repr__(self) -> str:
return "Could not parse profile found at %s - it is not valid YAML" % self.filepath
return f"Could not parse profile found at {self.filepath} - it is not valid YAML"
2 changes: 1 addition & 1 deletion prospector/profiles/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def _determine_strictness(profile_dict: dict[str, Any], inherits: list[str]) ->
strictness = profile_dict.get("strictness")
if strictness is None:
return None, False
return ("strictness_%s" % strictness), True
return (f"strictness_{strictness}"), True


def _determine_pep8(profile_dict: dict[str, Any]) -> tuple[Optional[str], bool]:
Expand Down
Loading
Loading