Skip to content

Commit c611fbc

Browse files
authored
Clarify ruff functionality. (#403)
* Clarify ruff functionality. * Code review comments.
1 parent 369b30b commit c611fbc

File tree

9 files changed

+79
-35
lines changed

9 files changed

+79
-35
lines changed

copier.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,11 @@ python_versions:
7878
enforce_style:
7979
help: What tooling set would you like to use to enforce code style? Use SPACE to highlight all that apply.
8080
type: str
81-
default: [ruff]
81+
default: [ruff_lint, ruff_format]
8282
multiselect: true
8383
choices:
84-
ruff: ruff
84+
ruff linting: ruff_lint
85+
ruff auto-formatter: ruff_format
8586
pylint: pylint
8687
black: black
8788
isort: isort

docs/practices/ci_precommit.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ For each pull request, our ``pre-commit.ci`` workflow will:
2222
* Analyze the src code style and report code that doesn't adhere, using
2323
the options you selected for your tooling set:
2424

25-
* "ruff": checks for linting rules, sorts imports, auto-formats code
25+
* "ruff linting": checks for linting rules, and import order
26+
* "ruff auto-formatter": auto-formats code
2627
* "pylint": checks for compliance with pylint rules
2728
* "black": auto-formats code (including notebooks)
2829
* "isort": Sort imports using ``isort``

docs/practices/linting.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ The template currently offers three tools for auto-formatting:
4444

4545
- **black** - general code formatting
4646
- **isort** - import statement sorting and organizing
47-
- **ruff** - does it all
47+
- **ruff format** - general code formatting
4848

4949
Different formatters share a lot of the same opinions, but we recommend picking
5050
a single standard for your project and sticking to it.

docs/practices/precommit.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ of these that are not useful for your project.
5959
- Runs black to enforce a particular code style on .py, .pyi and .ipynb files.
6060
One can add more file extensions by editing this hook on ``.pre-commit-config.yaml``
6161
directly. *(Optionally installed when project is created.)*
62-
* - Format and lint code using ruff
62+
* - Lint code using ruff
63+
- Runs ruff to enforce a particular code style on .py, .pyi and .ipynb files.
64+
One can add more file extensions by editing this hook on ``.pre-commit-config.yaml``
65+
directly. *(Optionally installed when project is created.)*
66+
* - Format code using ruff
6367
- Runs ruff to enforce a particular code style on .py, .pyi and .ipynb files.
6468
One can add more file extensions by editing this hook on ``.pre-commit-config.yaml``
6569
directly. *(Optionally installed when project is created.)*

docs/source/new_project.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ questions:
6262
We provide several compatible options for linters and autoformatters.
6363
Choosing a formatter or linter will include it as a project dependency and include it in the
6464
:doc:`pre-commit <../practices/precommit>` hooks.
65-
Defaults to ``ruff`` during simple installation.
65+
Defaults to ``ruff`` (linting and autoformatting) during simple installation.
6666
* - *How would you like to receive workflow failure notifications?*
6767
- See :doc:`/practices/ci_testing`.
6868
Some github workflows are not loud about their failures, so we have some configuration

python-project-template/.github/workflows/code_style.yml.jinja

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,13 @@ jobs:
5555
pylint -rn -sn --recursive=y ./benchmarks --rcfile=./tests/.pylintrc
5656
{%- endif -%}
5757
{%- endif -%}
58-
{%- if 'ruff' in enforce_style %}
59-
- name: Analyze code with ruff
58+
{%- if 'ruff_lint' in enforce_style %}
59+
- name: Analyze code with ruff formatter
6060
run: |
6161
ruff format --check
62+
{%- endif -%}
63+
{%- if 'ruff_format' in enforce_style %}
64+
- name: Analyze code with ruff linter
65+
run: |
6266
ruff check
6367
{%- endif -%}

python-project-template/.pre-commit-config.yaml.jinja

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,23 @@ repos:
9494
# https://pre-commit.com/#top_level-default_language_version
9595
language_version: python3.10
9696
{%- endif %}
97-
{%- if 'ruff' in enforce_style %}
97+
{%- if 'ruff_lint' in enforce_style %}
9898
- repo: https://github.com/astral-sh/ruff-pre-commit
9999
# Ruff version.
100-
rev: v0.1.3
100+
rev: v0.2.1
101101
hooks:
102102
- id: ruff
103-
name: Format and lint code using ruff
103+
name: Lint code using ruff; sort and organize imports
104+
types_or: [ python, pyi, jupyter ]
105+
args: ["--fix"]
106+
{%- endif %}
107+
{%- if 'ruff_format' in enforce_style %}
108+
- repo: https://github.com/astral-sh/ruff-pre-commit
109+
# Ruff version.
110+
rev: v0.2.1
111+
hooks:
112+
- id: ruff-format
113+
name: Format code using ruff
104114
types_or: [ python, pyi, jupyter ]
105115
{%- endif %}
106116
{%- if mypy_type_checking != 'none' %}

python-project-template/pyproject.toml.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ dev = [
4545
{%- if 'black' in enforce_style %}
4646
"black", # Used for static linting of files
4747
{%- endif %}
48-
{%- if 'ruff' in enforce_style %}
48+
{%- if 'ruff_lint' in enforce_style or 'ruff_format' in enforce_style %}
4949
"ruff", # Used for static linting of files
5050
{%- endif %}
5151
{%- if mypy_type_checking != 'none' %}

tests/test_package_creation.py

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,24 @@
22
import pytest_copie
33
import subprocess
44

5+
56
def successfully_created_project(result):
67
"""Basic assertions that indicate the copier was able to create a project"""
78
return result.exit_code == 0 and result.exception is None and result.project_dir.is_dir()
89

910

10-
def directory_structure_is_correct(result, package_name = "example_package"):
11+
def directory_structure_is_correct(result, package_name="example_package"):
1112
"""Test to ensure that the default directory structure ws created correctly"""
12-
return (result.project_dir / f"src/{package_name}").is_dir() and (result.project_dir / f"tests/{package_name}").is_dir()
13+
return (result.project_dir / f"src/{package_name}").is_dir() and (
14+
result.project_dir / f"tests/{package_name}"
15+
).is_dir()
1316

1417

1518
def black_runs_successfully(result):
1619
"""Test to ensure that the black linter runs successfully on the project"""
1720
# run black with `--check` to look for lint errors, but don't fix them.
1821
black_results = subprocess.run(
19-
["python", "-m", "black", "--check", (result.project_dir / "src")],
20-
cwd=result.project_dir
22+
["python", "-m", "black", "--check", (result.project_dir / "src")], cwd=result.project_dir
2123
)
2224

2325
return black_results.returncode == 0
@@ -27,27 +29,21 @@ def pylint_runs_successfully(result):
2729
"""Test to ensure that the pylint linter runs successfully on the project"""
2830
# run pylint to ensure that the hydrated files are linted correctly
2931
pylint_results = subprocess.run(
30-
["python", "-m", "pylint",
31-
"--recursive=y",
32-
"--rcfile=./src/.pylintrc",
33-
(result.project_dir / "src")],
34-
cwd=result.project_dir
32+
["python", "-m", "pylint", "--recursive=y", "--rcfile=./src/.pylintrc", (result.project_dir / "src")],
33+
cwd=result.project_dir,
3534
)
3635

3736
return pylint_results.returncode == 0
3837

3938

40-
def unit_tests_in_project_run_successfully(result, package_name = "example_package"):
39+
def unit_tests_in_project_run_successfully(result, package_name="example_package"):
4140
"""Test to ensure that the unit tests run successfully on the project
4241
4342
!!! NOTE - This doesn't currently work because we need to `pip install` the hydrated
4443
project before running the tests. And we don't have a way to create a temporary
4544
virtual environment for the project.
4645
"""
47-
pytest_results = subprocess.run(
48-
["python", "-m", "pytest"],
49-
cwd=result.project_dir
50-
)
46+
pytest_results = subprocess.run(["python", "-m", "pytest"], cwd=result.project_dir)
5147

5248
return pytest_results.returncode == 0
5349

@@ -73,10 +69,10 @@ def test_all_defaults(copie):
7369
# check to see if the README file was hydrated with copier answers.
7470
found_line = False
7571
with open(result.project_dir / "README.md") as f:
76-
for line in f:
77-
if "example_project" in line:
78-
found_line = True
79-
break
72+
for line in f:
73+
if "example_project" in line:
74+
found_line = True
75+
break
8076
assert found_line
8177

8278

@@ -107,15 +103,43 @@ def test_use_black_and_no_example_modules(copie):
107103
# check to see if the pyproject.toml file has the expected dependencies
108104
found_line = False
109105
with open(result.project_dir / "pyproject.toml") as f:
110-
for line in f:
111-
if "\"black\", # Used for static linting of files" in line:
112-
found_line = True
113-
break
106+
for line in f:
107+
if '"black", # Used for static linting of files' in line:
108+
found_line = True
109+
break
114110
assert found_line
115111

116112
assert black_runs_successfully(result)
117113

118114

115+
@pytest.mark.parametrize(
116+
"enforce_style",
117+
[
118+
[],
119+
["ruff_lint"],
120+
["ruff_format"],
121+
["ruff_lint", "pylint"],
122+
["ruff_format", "black"],
123+
["black", "pylint", "isort"],
124+
["ruff_lint", "ruff_format"],
125+
["black", "pylint", "isort", "ruff_lint", "ruff_format"],
126+
],
127+
)
128+
def test_code_style_combinations(copie, enforce_style):
129+
"""Test that various combinations of code style enforcement will
130+
still result in a valid project being created."""
131+
132+
# provide a dictionary of the non-default answers to use
133+
extra_answers = {
134+
"enforce_style": enforce_style,
135+
}
136+
result = copie.copy(extra_answers=extra_answers)
137+
assert successfully_created_project(result)
138+
assert directory_structure_is_correct(result)
139+
# black would still run successfully.
140+
assert black_runs_successfully(result)
141+
142+
119143
def test_smoke_test_notification(copie):
120144
"""Confirm we can generate a "smoke_test.yaml" file, with all
121145
notification mechanisms selected."""
@@ -130,4 +154,4 @@ def test_smoke_test_notification(copie):
130154

131155
assert successfully_created_project(result)
132156
assert directory_structure_is_correct(result)
133-
assert black_runs_successfully(result)
157+
assert black_runs_successfully(result)

0 commit comments

Comments
 (0)