Skip to content
Open
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
25 changes: 25 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: CI (Lint)

on:
# Triggers the workflow on push or pull request events
push:
branches: [main]
pull_request:
branches:
- "*"

permissions:
contents: read

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
with:
python-version: "3.9"

- uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
42 changes: 42 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "v4.6.0"
hooks:
- id: check-added-large-files
args: ["--maxkb=1024"]
- id: check-case-conflict
- id: check-merge-conflict
- id: check-symlinks
- id: check-yaml
- id: debug-statements
exclude: "Base/QTGUI/Testing/Data/Input/qSlicerScriptedLoadableModuleSyntaxErrorTestWidget.py|Base/QTGUI/Testing/Data/Input/qSlicerScriptedLoadableModuleSyntaxErrorTest.py"
- id: end-of-file-fixer
exclude: "\\.(md5|svg|vtk|vtp)$|^Resources\\/[^\\/]+\\.h$|\\/ColorFiles\\/.+\\.txt$|Data\\/Input\\/.+$"
- id: mixed-line-ending
exclude: "\\.(svg|vtk|vtp)$"
- id: trailing-whitespace
exclude: "\\.(svg|vtk|vtp)$"

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.5
hooks:
- id: ruff
args: ["--fix", "--show-fixes"]

- repo: https://github.com/asottile/pyupgrade
rev: v3.17.0
hooks:
- id: pyupgrade
args: [--py39-plus]

- repo: https://github.com/pre-commit/mirrors-prettier
rev: "v4.0.0-alpha.8"
hooks:
- id: prettier
types_or: [yaml]

- repo: https://github.com/python-jsonschema/check-jsonschema
rev: "0.29.1"
hooks:
- id: check-dependabot
- id: check-github-workflows
136 changes: 136 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
target-version = "py39"
line-length = 550

extend-exclude = [
"Base/QTGUI/Testing/Data/Input/qSlicerScriptedLoadableModuleSyntaxErrorTest.py",
"Base/QTGUI/Testing/Data/Input/qSlicerScriptedLoadableModuleSyntaxErrorTestWidget.py",
]

[lint]
select = [
# "ARG", # flake8-unused-arguments
# "ANN", # flake8-annotations
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"COM", # flake8-commas
"E", "F", "W", # flake8
"D", # pydocstyle
# "EXE", # flake8-executable
# "G", # flake8-logging-format
"ICN", # flake8-import-conventions
"ISC", # flake8-implicit-str-concat
"NPY", # NumPy specific rules
# "PERF", # Perflint
"PGH", # pygrep-hooks
# "PIE", # flake8-pie
"PL", # pylint
"Q", # flake8-quote
"RET", # flake8-return
"RUF", # Ruff-specific
# "S", # flake8-bandit
# "SIM", # flake8-simplify
"UP", # pyupgrade
"YTT", # flake8-2020
]
extend-ignore = [
"E402", # Module level import not at top of file
"G004", # logging-f-string
"PIE790", # unnecessary-pass

"B006", # Do not use mutable data structures for argument defaults.
"B007", # Loop control variable not used within the loop body.
"B008", # Do not perform function calls in argument defaults.
"B009", # Do not call getattr(x, 'attr'), instead use normal property access: x.attr.
"B010", # Do not call setattr with a constant attribute value, it is not any safer than normal property access.\\
"B018", # Found useless expression. Either assign it to a variable or remove it.
"B028", # No explicit `stacklevel` keyword argument found
"B904", # Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None`
# to distinguish them from errors in exception handling
"C413", # Unnecessary `reversed` call around `sorted()`
"C408", # Unnecessary `dict` call (rewrite as a literal)
"C418", # Unnecessary `dict` literal passed to `dict()` (remove the outer call to `dict()`)
"C419", # Unnecessary list comprehension.

"D10", # undocumented-public-*
"D202", # No blank lines allowed after function docstring"
"D205", # 1 blank line required between summary line and description
"D4",

"E401", # Multiple imports on one line
"E714", # Test for object identity should be `is not`
"E713", # Test for membership should be `not in`
"E721", # Do not compare types, use `isinstance()`
"E722", # Do not use bare `except`
"E731", # Do not assign a `lambda` expression, use a `def`

"F403", # 'from module import *' used; unable to detect undefined names
"F405", # name may be undefined, or defined from star import
"F541", # f-string without any placeholders
"F811", # Redefinition of unused `module` from line N
"F821", # Undefined name
"F841", # Local variable is assigned to but never used

"G002", # Logging statement uses `%`
"G010", # `warn` is deprecated in favor of `warning`

"ICN001", # `numpy` should be imported as `np`
"ISC002", # Implicitly concatenated string literals over multiple lines
"ISC003", # Explicitly concatenated string should be implicitly concatenated

"PLR0912", # Too many branche
"PLR0913", # Too many arguments in function definition
"PLR0911", # Too many return statements
"PLR0915", # Too many statements
"PLR1701", # Merge `isinstance` calls
"PLR1711", # Useless `return` statement at end of function
"PLR1714", # Consider merging multiple comparisons
"PLR1722", # Use `sys.exit()` instead of `exit`
"PLR2004", # Magic value used in comparison
"PLR5501", # Use `elif` instead of `else` then `if`, to reduce indentation

"PLW0120", # `else` clause on loop without a `break` statement; remove the `else` and de-indent all the code inside it
"PLW0127", # self-assigning-variable Self-assignment of variable {name}
"PLW0602", # Using global for `{name}` but no assignment is done
"PLW0603", # Using the global statement to update {name} is discouraged
"PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target

"Q003", # Change outer quotes to avoid escaping inner quotes

"RET501", # Do not explicitly return None in function if it is the only possible return value
"RET502", # Do not implicitly return None in function able to return non-None value
"RET503", # Missing explicit return at the end of function able to return non-None value
"RET504", # Unnecessary assignment to {name} before return statement
"RET505", # Unnecessary {branch} after return statement
"RET506", # Unnecessary {branch} after raise statement
"RET508", # Unnecessary {branch} after break statement

"RUF005", # Consider {expression} instead of concatenation
"RUF010", # Use explicit conversion flag
"RUF012", # Mutable class attributes should be annotated with typing.ClassVar
"RUF013", # PEP 484 prohibits implicit `Optional`
"RUF100", # Unused `noqa` directive (non-enabled: `F401`)

"SIM108", # Use ternary operator
"SIM115", # Use context handler for opening files

"UP018", # Unnecessary `int` call (rewrite as a literal)
"UP030", # Use implicit references for positional format fields
"UP031", # Use format specifiers instead of percent format
"UP032", # Use f-string instead of `format` call
]

[lint.pydocstyle]
convention = "pep257"

[lint.per-file-ignores]
# Module imported but unused
"Base/Python/mrml.py" = ["F401"]
"Base/Python/slicer/logic.py" = ["F401"]
"Base/Python/slicer/parameterNodeWrapper/__init__.py" = ["F401"]
"Base/Python/vtkAddon.py" = ["F401"]
"Base/Python/vtkITK.py" = ["F401"]
"Base/Python/vtkSegmentationCore.py" = ["F401"]
"Base/Python/vtkTeem.py" = ["F401"]
"Modules/*/__init__.py" = ["F401"]
"Extensions/*/__init__.py" = ["F401"]
"Utilities/*/__init__.py" = ["F401"]
Loading