Skip to content

Commit 04ab64c

Browse files
authored
Pre-commit: add Ruff (#261)
* Replaces flake8 and all its enabled plugins with Ruff * Use Ruff formatter as a drop-in replacement of Black * Simplifies the configuration using a single `pyproject.toml` instead of multiple files (`pytest.ini`, `flake8`).
1 parent 5a3fa10 commit 04ab64c

11 files changed

Lines changed: 142 additions & 126 deletions

.flake8

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,28 @@
11
---
22
name: Build Tutorial Container
33
on:
4-
push:
5-
branches:
6-
- main
7-
paths-ignore:
8-
- '*.md'
9-
- slides/**
10-
- images/**
11-
- .gitignore
12-
workflow_dispatch:
13-
4+
push:
5+
branches:
6+
- main
7+
paths-ignore:
8+
- '*.md'
9+
- slides/**
10+
- images/**
11+
- .gitignore
12+
workflow_dispatch:
1413
jobs:
15-
repo2docker:
16-
runs-on: ubuntu-latest
17-
permissions:
18-
packages: write
19-
steps:
20-
- name: checkout files in repo
21-
uses: actions/checkout@main
22-
23-
- name: update jupyter dependencies with repo2docker
24-
uses: jupyterhub/repo2docker-action@master
25-
with:
26-
DOCKER_USERNAME: ${{ github.actor }}
27-
DOCKER_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
28-
DOCKER_REGISTRY: ghcr.io
29-
IMAGE_NAME: ${{ github.repository }}
30-
FORCE_REPO2DOCKER_VERSION: jupyter-repo2docker==2023.06.0
14+
repo2docker:
15+
runs-on: ubuntu-latest
16+
permissions:
17+
packages: write
18+
steps:
19+
- name: checkout files in repo
20+
uses: actions/checkout@main
21+
- name: update jupyter dependencies with repo2docker
22+
uses: jupyterhub/repo2docker-action@master
23+
with:
24+
DOCKER_USERNAME: ${{ github.actor }}
25+
DOCKER_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
26+
DOCKER_REGISTRY: ghcr.io
27+
IMAGE_NAME: ${{ github.repository }}
28+
FORCE_REPO2DOCKER_VERSION: jupyter-repo2docker==2023.06.0

.pre-commit-config.yaml

Lines changed: 31 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,34 @@
11
---
22
ci:
3-
autoupdate_schedule: quarterly
4-
3+
autoupdate_schedule: quarterly
54
repos:
6-
- repo: https://github.com/pre-commit/pre-commit-hooks
7-
rev: v4.6.0
8-
hooks:
9-
- id: end-of-file-fixer
10-
- id: trailing-whitespace
11-
exclude: miscellaneous/structures/SiO2.xyz
12-
- id: check-yaml
13-
- id: check-added-large-files
14-
args: [--maxkb=6000]
15-
- repo: https://github.com/pycqa/isort
16-
rev: 5.13.2
17-
hooks:
18-
- id: isort
19-
args: [--profile, black, --filter-files]
20-
- repo: https://github.com/PyCQA/autoflake
21-
rev: v2.3.1
22-
hooks:
23-
- id: autoflake
24-
- repo: https://github.com/asottile/pyupgrade
25-
rev: v3.16.0
26-
hooks:
27-
- id: pyupgrade
28-
args: [--py38-plus]
29-
- repo: https://github.com/psf/black
30-
rev: 24.4.2
31-
hooks:
32-
- id: black
33-
language_version: python3 # Should be a command that runs python3.6+
34-
- repo: https://github.com/PyCQA/flake8
35-
rev: 7.1.0
36-
hooks:
37-
- id: flake8
38-
args: [--count, --show-source, --statistics]
39-
additional_dependencies:
40-
- flake8-bugbear
41-
- flake8-builtins
42-
- flake8-comprehensions
43-
- flake8-debugger
44-
- flake8-logging-format
45-
- pep8-naming
46-
- pyflakes
47-
- tryceratops
48-
# - repo: https://github.com/pre-commit/mirrors-mypy
49-
# rev: v1.5.1
50-
# hooks:
51-
# - id: mypy
52-
# additional_dependencies:
53-
# - types-click-spinner
54-
# - types-requests
55-
# - types-tabulate
56-
# - types-toml
57-
- repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt
58-
rev: 0.2.3
59-
hooks:
60-
- id: yamlfmt
61-
- repo: https://github.com/asottile/setup-cfg-fmt
62-
rev: v2.5.0
63-
hooks:
64-
- id: setup-cfg-fmt
65-
- repo: https://github.com/kynan/nbstripout
66-
rev: 0.7.1
67-
hooks:
68-
- id: nbstripout
5+
- repo: https://github.com/pre-commit/pre-commit-hooks
6+
rev: v5.0.0
7+
hooks:
8+
- id: end-of-file-fixer
9+
- id: trailing-whitespace
10+
- id: check-yaml
11+
- id: check-added-large-files
12+
args: [--maxkb=6000]
13+
- repo: https://github.com/astral-sh/ruff-pre-commit
14+
rev: v0.7.4
15+
hooks:
16+
# Ruff fix
17+
- id: ruff
18+
types_or: [python, pyi]
19+
args: [--fix]
20+
name: ruff (fix)
21+
# Ruff formatter
22+
- id: ruff-format
23+
types_or: [python, pyi]
24+
name: ruff (format)
25+
- repo: https://github.com/google/yamlfmt
26+
rev: v0.14.0
27+
hooks:
28+
- id: yamlfmt
29+
name: YAML (format)
30+
types: [yaml]
31+
- repo: https://github.com/kynan/nbstripout
32+
rev: 0.8.1
33+
hooks:
34+
- id: nbstripout

.yamlfmt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
formatter:
2+
type: basic
3+
include_document_start: true
4+
retain_line_breaks: true
5+
output_format: line

binder/environment.yml

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
---
22
name: python-tutorial
33
channels:
4-
- conda-forge
4+
- conda-forge
55
dependencies:
6-
- python=3.10
7-
- pip
8-
- pip:
9-
- numpy
10-
- matplotlib
11-
- pandas
12-
- ipywidgets
13-
- ipynbname
14-
- jupyterlab
15-
- pytest
16-
- pytest-timeout
17-
- markdown
18-
- pre-commit
19-
- geostatspy
20-
- gstools
21-
- scikit-learn
22-
- attrs
23-
- multiprocess
6+
- python=3.10
7+
- pip
8+
- pip:
9+
- numpy
10+
- matplotlib
11+
- pandas
12+
- ipywidgets
13+
- ipynbname
14+
- jupyterlab
15+
- pytest
16+
- pytest-timeout
17+
- markdown
18+
- pre-commit
19+
- geostatspy
20+
- gstools
21+
- scikit-learn
22+
- attrs
23+
- multiprocess

pyproject.toml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
[tool.ruff]
2+
# Line length (Black default)
3+
line-length = 88
4+
5+
# Python target version
6+
target-version = "py38"
7+
8+
# Ignored rules for the entire project
9+
[tool.ruff.lint]
10+
ignore = [
11+
"E501", # Line too long
12+
"E203", # Whitespace before ':'
13+
# "TRY301", # Raise within try block (this is actually a good practice)
14+
# "W503" # Line break before binary operator (not PEP8 enforced, so not implemented in Ruff)
15+
]
16+
17+
# flake8 plugins to enable:
18+
# - flake8-bugbear B
19+
# - flake8-builtins A
20+
# - flake8-comprehensions C4
21+
# - flake8-debugger T10
22+
# - flake8-logging-format G
23+
# - pep8-naming N
24+
# - pyflakes F
25+
# - tryceratops TRY
26+
select = [
27+
"A", # flake8-builtins
28+
"B", # flake8-bugbear
29+
"C4", # flake8-comprehensions
30+
"T10", # flake8-debugger
31+
"G", # flake8-logging-format
32+
"N", # pep8-naming
33+
"F", # pyflakes
34+
"TRY", # tryceratops
35+
"I", # isort
36+
"E", # pycodestyle errors
37+
"UP", # pyupgrade
38+
]
39+
40+
# Per-file rule ignores
41+
[tool.ruff.lint.per-file-ignores]
42+
# Trailing whitespace in comment
43+
"binder/ipython_config.py" = ["E266"]
44+
# suppress `raise ... from err`
45+
# Why we ignore B904 from the object-oriented tests?
46+
# We do want to raise an assertion error if the check on the solution function attributes fails,
47+
# but Python by default will raise a TypeError via vars(solution_result)
48+
# if the result is not a class and therefore doesn't have a __dict__ attribute.
49+
"tutorial/tests/test_object_oriented_programming.py" = ["B904"]
50+
51+
# Ruff formatting
52+
[tool.ruff.format]
53+
quote-style = "double"
54+
indent-style = "space"
55+
56+
# pytest
57+
[tool.pytest.ini_options]
58+
addopts = "-v --tb=short"

pytest.ini

Lines changed: 0 additions & 2 deletions
This file was deleted.

tutorial/tests/test_functional_programming.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ def reference_exercise6(my_list: List[Tuple[str, int]]) -> List[Tuple[str, float
143143

144144

145145
def test_exercise6(
146-
function_to_test: Callable[[List[Tuple[str, int]]], List[Tuple[str, float]]]
146+
function_to_test: Callable[[List[Tuple[str, int]]], List[Tuple[str, float]]],
147147
):
148148
input_data = reference_exercise5(get_data_exercise5())
149149
assert function_to_test(input_data) == reference_exercise6(input_data)

tutorial/tests/test_input_output.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,7 @@ def test_write_file(function_to_test, tmp_path: pl.Path):
9898
function_to_test(tmp_user)
9999
reference_write_file(tmp_test)
100100

101-
assert (
102-
tmp_user.exists()
103-
), """The file was not created. Make sure to create the file in the function. Hint: use `open(output_file, "w")`"""
101+
assert tmp_user.exists(), """The file was not created. Make sure to create the file in the function. Hint: use `open(output_file, "w")`"""
104102

105103
assert (
106104
tmp_user.read_text() == tmp_test.read_text()

tutorial/tests/test_object_oriented_programming.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ def test_oop_str_and_repr(first_name, last_name, function_to_test):
177177
validate_oop_str_method(solution_result)
178178
validate_oop_repr_method(solution_result)
179179

180-
assert str(solution_result) == str(
181-
reference_result
180+
assert (
181+
str(solution_result) == str(reference_result)
182182
), "The __str__() result does not match the template 'My name is {first_name} {last_name}'."
183183
assert (
184184
solution_result.__repr__() == reference_result.__repr__()

0 commit comments

Comments
 (0)