Skip to content

Commit

Permalink
Update to ruff (instead of pylint (and isort)) (#192)
Browse files Browse the repository at this point in the history
Remove pylint as a dependency.
Remove all "# pylint: disable=..." statements.
Remove pylint and isort as pre-commit hooks.
Add ruff as a pre-commit hook.
Avoid running pylint in the CI.

Add (back) disable E501 statements.
E501: Line too long.
Add it for either lines with string-formatted type (which has to be on
one line) or an f-string with a single variable (i.e., a single-line
f-string part with an implemented logic for a variable that results in
the line being too long).

Add explicit rule set to ruff
Extend arguments to ruff CLI, ensuring no unsafe fixes are made and any
fixes are shown explicitly in the output.

Add pyupgrade pre-commit hook

Enforce importing __future__.annotations in all Python files.

Base it on scientific-python and then update it to fit this package.
  • Loading branch information
CasperWA authored Dec 14, 2023
1 parent ddda034 commit e4b2cc9
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 176 deletions.
2 changes: 1 addition & 1 deletion .github/utils/run_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ def main(hook: str, options: list[str]) -> None:
hook=sys.argv[1],
options=sys.argv[2:] if len(sys.argv) > 2 else [],
)
except Exception as exc: # pylint: disable=broad-except
except Exception as exc:
sys.exit(str(exc))
10 changes: 3 additions & 7 deletions .github/workflows/_local_ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,9 @@ jobs:
# general
install_extras: "[dev,docs,testing]"

# pre-commit
skip_pre-commit_hooks: pylint,pylint-tests

# pylint
pylint_runs: |
--rcfile=pyproject.toml ci_cd
--rcfile=pyproject.toml --disable=import-outside-toplevel,redefined-outer-name tests
# pylint & safety
run_pylint: false
run_safety: true

# build dist
build_libs: flit
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/_local_ci_update_dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,5 @@ jobs:
extra_to_dos: "- [ ] Make sure the PR is **squash** merged, with a sensible commit message."
update_pre-commit: true
install_extras: "[dev]"
skip_pre-commit_hooks: "pylint,pylint-tests"
secrets:
PAT: ${{ secrets.RELEASE_PAT }}
64 changes: 19 additions & 45 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,16 @@ repos:
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]

# isort is a tool to sort and group import statements in Python files
# It works on files in-place
- repo: https://github.com/timothycrosley/isort
rev: 5.12.0
hooks:
- id: isort
args:
- "--profile=black"
- "--filter-files"
- "--skip-gitignore"
- "--add-import=from __future__ import annotations"

# pyupgrade is a tool to automatically upgrade Python syntax for newer versions
# pyupgrade is a tool for automatically upgrading Python syntax for newer versions of
# the language
# It works on files in-place
- repo: https://github.com/asottile/pyupgrade
# Latest version for Python 3.7: 3.3.2
# Latest version for Python 3.8: 3.8.0
rev: v3.15.0
hooks:
- id: pyupgrade
args: ["--py37-plus"]
args: [--py37-plus]

# Black is a code style and formatter
# It works on files in-place
Expand All @@ -48,6 +37,22 @@ repos:
hooks:
- id: black

# ruff is a Python linter, incl. import sorter and formatter
# It works partly on files in-place
# More information can be found in its documentation:
# https://docs.astral.sh/ruff/
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.7
hooks:
- id: ruff
# Fix what can be fixed in-place and exit with non-zero status if files were
# changed and/or there are rules violations.
args:
- "--fix"
- "--exit-non-zero-on-fix"
- "--show-fixes"
- "--no-unsafe-fixes"

# Bandit is a security linter
# More information can be found in its documentation:
# https://bandit.readthedocs.io/en/latest/
Expand All @@ -74,34 +79,3 @@ repos:
- id: docs-api-reference
args:
- "--package-dir=ci_cd"

- repo: local
hooks:
# pylint is a Python linter
# It is run through the local environment to ensure external packages can be
# imported without issue.
# For more information about pylint see its documentation at:
# https://pylint.pycqa.org/en/latest/
- id: pylint
name: pylint
entry: pylint
args: ["--rcfile=pyproject.toml"]
language: python
types: [python]
require_serial: true
exclude: ^tests/.*$
# pylint is a Python linter
# It is run through the local environment to ensure external packages can be
# imported without issue.
# For more information about pylint see its documentation at:
# https://pylint.pycqa.org/en/latest/
- id: pylint-tests
name: pylint - tests
entry: pylint
args:
- "--rcfile=pyproject.toml"
- "--disable=import-outside-toplevel,redefined-outer-name"
language: python
types: [python]
require_serial: true
files: ^tests/.*$
9 changes: 6 additions & 3 deletions ci_cd/tasks/api_reference_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"""
from __future__ import annotations

# pylint: disable=duplicate-code
import logging
import os
import re
Expand Down Expand Up @@ -97,7 +96,7 @@
"special_option",
],
)
def create_api_reference_docs( # pylint: disable=too-many-locals,too-many-branches,too-many-statements,line-too-long
def create_api_reference_docs(
context,
package_dir,
pre_clean=False,
Expand Down Expand Up @@ -312,7 +311,11 @@ def write_file(full_path: Path, content: str) -> None:
f"{py_path_root}/{filename.stem}"
if str(relpath) == "."
or (str(relpath) == package.name and not single_package)
else f"{py_path_root}/{relpath if single_package else relpath.relative_to(package.name)}/{filename.stem}"
else (
f"{py_path_root}/"
f"{relpath if single_package else relpath.relative_to(package.name)}/" # noqa: E501
f"{filename.stem}"
)
)

# Replace OS specific path separators with forward slashes before
Expand Down
2 changes: 1 addition & 1 deletion ci_cd/tasks/docs_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
},
iterable=["replacement"],
)
def create_docs_index( # pylint: disable=too-many-locals
def create_docs_index(
context,
pre_commit=False,
root_repo_path=".",
Expand Down
18 changes: 7 additions & 11 deletions ci_cd/tasks/setver.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
},
iterable=["code_base_update"],
)
def setver( # pylint: disable=too-many-locals
def setver(
_,
package_dir,
version,
Expand All @@ -66,7 +66,7 @@ def setver( # pylint: disable=too-many-locals
version: str = version # type: ignore[no-redef]
root_repo_path: str = root_repo_path # type: ignore[no-redef]
code_base_update: list[str] = code_base_update # type: ignore[no-redef]
code_base_update_separator: str = code_base_update_separator # type: ignore[no-redef] # pylint: disable=line-too-long
code_base_update_separator: str = code_base_update_separator # type: ignore[no-redef]
test: bool = test # type: ignore[no-redef]
fail_fast: bool = fail_fast # type: ignore[no-redef]

Expand Down Expand Up @@ -120,9 +120,7 @@ def setver( # pylint: disable=too-many-locals
)

filepath = Path(
filepath.format(
**{"package_dir": package_dir, "version": semantic_version}
)
filepath.format(package_dir=package_dir, version=semantic_version)
).resolve()
if not filepath.exists():
error_msg = (
Expand All @@ -143,9 +141,7 @@ def setver( # pylint: disable=too-many-locals
filepath,
pattern,
replacement,
replacement.format(
**{"package_dir": package_dir, "version": semantic_version}
),
replacement.format(package_dir=package_dir, version=semantic_version),
)
if test:
print(
Expand All @@ -154,7 +150,7 @@ def setver( # pylint: disable=too-many-locals
)
print(
"replacement (handled): "
f"{replacement.format(**{'package_dir': package_dir, 'version': semantic_version})}" # pylint: disable=line-too-long
f"{replacement.format(package_dir=package_dir, version=semantic_version)}" # noqa: E501
)

try:
Expand All @@ -163,7 +159,7 @@ def setver( # pylint: disable=too-many-locals
(
pattern,
replacement.format(
**{"package_dir": package_dir, "version": semantic_version}
package_dir=package_dir, version=semantic_version
),
),
)
Expand All @@ -176,7 +172,7 @@ def setver( # pylint: disable=too-many-locals
f"{Emoji.CROSS_MARK.value} Error: Could not update file {filepath}"
f" according to the given input:\n\n pattern: {pattern}\n "
"replacement: "
f"{replacement.format(**{'package_dir': package_dir, 'version': semantic_version})}" # pylint: disable=line-too-long
f"{replacement.format(package_dir=package_dir, version=semantic_version)}" # noqa: E501
)

print(
Expand Down
5 changes: 1 addition & 4 deletions ci_cd/tasks/update_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
Update dependencies in a `pyproject.toml` file.
"""
# pylint: disable=duplicate-code
from __future__ import annotations

import logging
Expand Down Expand Up @@ -36,8 +35,6 @@
)

if TYPE_CHECKING: # pragma: no cover
from typing import Union

from invoke import Context, Result

from ci_cd.utils.versions import IgnoreUpdateTypes, IgnoreVersions
Expand Down Expand Up @@ -114,7 +111,7 @@ def _format_and_update_dependency(
},
iterable=["ignore"],
)
def update_deps( # pylint: disable=too-many-branches,too-many-locals,too-many-statements
def update_deps(
context,
root_repo_path=".",
fail_fast=False,
Expand Down
10 changes: 7 additions & 3 deletions ci_cd/utils/console_printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@

import platform
from enum import Enum
from typing import TYPE_CHECKING

if TYPE_CHECKING: # pragma: no cover
from typing_extensions import Self


class Emoji(str, Enum):
"""Unicode strings for certain emojis."""

def __new__(cls, value: str) -> Emoji:
def __new__(cls, value: str) -> Self:
obj = str.__new__(cls, value)
if platform.system() == "Windows":
# Windows does not support unicode emojis, so we replace them with
Expand All @@ -27,7 +31,7 @@ def __new__(cls, value: str) -> Emoji:
class Color(str, Enum):
"""ANSI escape sequences for colors."""

def __new__(cls, value: str) -> Color:
def __new__(cls, value: str) -> Self:
obj = str.__new__(cls, value)
obj._value_ = value
return obj
Expand All @@ -49,7 +53,7 @@ def write(self, text: str) -> str:
class Formatting(str, Enum):
"""ANSI escape sequences for formatting."""

def __new__(cls, value: str) -> Formatting:
def __new__(cls, value: str) -> Self:
obj = str.__new__(cls, value)
obj._value_ = value
return obj
Expand Down
Loading

0 comments on commit e4b2cc9

Please sign in to comment.