diff --git a/copier.yml b/copier.yml
index 57f5c5e..1445ac1 100644
--- a/copier.yml
+++ b/copier.yml
@@ -59,6 +59,7 @@ preferred_linter:
choices:
black: black
pylint: pylint
+ ruff: ruff
none: none
when: "{{ custom_install }}"
diff --git a/docs/practices/linting.rst b/docs/practices/linting.rst
index 629c446..89e9a0c 100644
--- a/docs/practices/linting.rst
+++ b/docs/practices/linting.rst
@@ -17,7 +17,7 @@ the code they're looking at adheres to that agreed-upon coding standard.
A code reviewer won't be distracted by improper spacing, and can focus their
reviewing effort on the meat of the code.
-There are two main linters suggested by this template: pylint and black. While
+There are three main linters suggested by this template: pylint, black, and ruff. While
they have a lot of the same opinions, we recommend picking a single standard for
your project and sticking to it.
If some folks use one linter, this may cause undue churn in your source files as
@@ -72,6 +72,20 @@ the ``./src`` and ``./tests`` directories. This allows separate configurations
for source versus test code. Take a look at the configuration documentation
for pylint here: https://pylint.readthedocs.io/en/latest/user_guide/configuration/index.html
+
+Modifying ruff
+.................
+
+`Ruff `_ is a very performant and highly customizable linting
+tool. The configuration for ruff is maintained in the ``pyproject.toml`` file.
+Ruff has many rules split into groups that can be selected to use when checking code.
+By default, we mostly follow the set of rules suggested by the
+`ruff documentation `_, with a few extra
+rules as suggested by
+`Rubin Data Management `_.
+For more information on configuration, see ruff's documentation here:
+https://docs.astral.sh/ruff/configuration/
+
How to switch or remove linters
-------------------------------
diff --git a/docs/source/new_project.rst b/docs/source/new_project.rst
index acff037..7def731 100644
--- a/docs/source/new_project.rst
+++ b/docs/source/new_project.rst
@@ -56,8 +56,9 @@ questions:
* - *What tooling would you like to use to enforce code style?*
- A linter is a tool to automatically format for consistency (see :doc:`Linting <../practices/linting>`).
We provide options for `black `_,
- `pylint `_, or no linter. Choosing a linter will include it as a
- project dependency and include it in the :doc:`pre-commit <../practices/precommit>` hooks.
+ `pylint `_, `ruff `_ or no linter.
+ Choosing a linter will include it as a project dependency and include it in the
+ :doc:`pre-commit <../practices/precommit>` hooks.
Defaults to ``pylint`` during simple installation.
* - *Do you want to use isort to maintain a specific ordering for module imports?*
- `isort `_ is a tool for ordering imports in a standard order.
diff --git a/python-project-template/.github/workflows/{% if preferred_linter != 'none' %}linting.yml{% endif %}.jinja b/python-project-template/.github/workflows/{% if preferred_linter != 'none' %}linting.yml{% endif %}.jinja
index e0c8989..b2cbb96 100644
--- a/python-project-template/.github/workflows/{% if preferred_linter != 'none' %}linting.yml{% endif %}.jinja
+++ b/python-project-template/.github/workflows/{% if preferred_linter != 'none' %}linting.yml{% endif %}.jinja
@@ -41,4 +41,7 @@ jobs:
uses: psf/black@stable
with:
src: ./src
+{%- elif preferred_linter == 'ruff' %}
+ run: |
+ ruff check --output-format=github .
{%- endif %}
diff --git a/python-project-template/.pre-commit-config.yaml.jinja b/python-project-template/.pre-commit-config.yaml.jinja
index 4bd504c..b5e145a 100644
--- a/python-project-template/.pre-commit-config.yaml.jinja
+++ b/python-project-template/.pre-commit-config.yaml.jinja
@@ -99,6 +99,13 @@ repos:
# pre-commit's default_language_version, see
# https://pre-commit.com/#top_level-default_language_version
language_version: python3.10
+{% elif preferred_linter == 'ruff' %}
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ # Ruff version.
+ rev: v0.1.3
+ hooks:
+ - id: ruff
+ types_or: [ python, pyi, jupyter ]
{% endif %}
{% if mypy_type_checking != 'none' %}
diff --git a/python-project-template/pyproject.toml.jinja b/python-project-template/pyproject.toml.jinja
index 4ca2d82..2e490c7 100644
--- a/python-project-template/pyproject.toml.jinja
+++ b/python-project-template/pyproject.toml.jinja
@@ -42,6 +42,8 @@ dev = [
"pylint", # Used for static linting of files
{%- elif preferred_linter == 'black' %}
"black", # Used for static linting of files
+{%- elif preferred_linter == 'ruff' %}
+ "ruff", # Used for static linting of files
{%- endif %}
{%- if mypy_type_checking != 'none' %}
"mypy", # Used for static type checking of files
@@ -82,6 +84,29 @@ target-version = ["py38"]
profile = "black"
line_length = 110
+{%- if preferred_linter == 'ruff' %}
+
+[tool.ruff]
+line-length = 110
+target-version = "py38"
+select = [
+ # pycodestyle
+ "E",
+ "W",
+ # Pyflakes
+ "F",
+ # pep8-naming
+ "N",
+ # pyupgrade
+ "UP",
+ # flake8-bugbear
+ "B",
+ # flake8-simplify
+ "SIM",
+ # isort
+ "I",
+]
+{%- endif %}
{%- if mypy_type_checking != 'none' %}
[tool.setuptools.package-data]
{{package_name}} = ["py.typed"]