Skip to content

Commit f7bd0ab

Browse files
committed
Added ruff
1 parent 78e7505 commit f7bd0ab

3 files changed

Lines changed: 166 additions & 0 deletions

File tree

.github/workflows/ruff.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Ruff
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches: [main]
7+
pull_request:
8+
branches: [main]
9+
types: [opened, synchronize, reopened]
10+
11+
# Cancel in-flight runs of the same PR/branch when a new commit is pushed.
12+
concurrency:
13+
group: ruff-${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
lint:
18+
name: ruff check
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- name: Checkout ARC
23+
uses: actions/checkout@v6
24+
25+
- name: Set up Python
26+
uses: actions/setup-python@v6
27+
with:
28+
python-version: '3.12'
29+
cache: pip
30+
31+
# Use the official astral-sh/ruff-action — it pins ruff and runs both
32+
# `ruff check` and `ruff format --check` against the configuration in
33+
# pyproject.toml. Pinning the action ref keeps the runner reproducible.
34+
#
35+
# NOTE on `continue-on-error: true`:
36+
# The ARC codebase predates ruff and currently has ~300 lint findings
37+
# against the configured rule set. We land ruff in non-blocking mode
38+
# first so the team can see the report on every PR without the gate
39+
# being red. To make ruff a hard gate (recommended once the residual
40+
# findings are cleaned up), remove `continue-on-error: true` from
41+
# both steps below.
42+
- name: Run ruff check
43+
uses: astral-sh/ruff-action@v3
44+
continue-on-error: true
45+
with:
46+
args: 'check arc/'
47+
48+
- name: Run ruff format --check
49+
uses: astral-sh/ruff-action@v3
50+
continue-on-error: true
51+
with:
52+
args: 'format --check arc/'

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Automated Rate Calculator | ARC
22

33
![Build Status](https://github.com/ReactionMechanismGenerator/ARC/actions/workflows/cont_int.yml/badge.svg)
4+
[![Ruff](https://github.com/ReactionMechanismGenerator/ARC/actions/workflows/ruff.yml/badge.svg)](https://github.com/ReactionMechanismGenerator/ARC/actions/workflows/ruff.yml)
45
[![codecov](https://codecov.io/gh/ReactionMechanismGenerator/ARC/branch/main/graph/badge.svg)](https://codecov.io/gh/ReactionMechanismGenerator/ARC)
56
[![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
67
![Release](https://img.shields.io/badge/version-1.1.0-blue.svg)

pyproject.toml

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,116 @@ requires = [
66
"numpy",
77
]
88
build-backend = "setuptools.build_meta"
9+
10+
# ---------------------------------------------------------------------------
11+
# Ruff configuration
12+
# ---------------------------------------------------------------------------
13+
# Ruff is the canonical linter for ARC. The selected rule set is intentionally
14+
# conservative for a working scientific codebase: bug-finding + import-sorting +
15+
# pyupgrade only. Stylistic rules (line length, naming, docstrings) are left
16+
# off until the team explicitly opts in. To run locally:
17+
#
18+
# ruff check arc/
19+
# ruff check --fix arc/ # auto-fix the safe ones
20+
# ruff format --check arc/ # check formatting only (does not modify)
21+
#
22+
# CI runs both `ruff check` and `ruff format --check` on every PR via
23+
# .github/workflows/ruff.yml. Both steps are currently non-blocking; see the
24+
# workflow file for the plan to make them gating.
25+
# ---------------------------------------------------------------------------
26+
[tool.ruff]
27+
# Match the Python pinned in environment.yml. Bumping this is the right
28+
# knob to enable newer pyupgrade rewrites once the conda env moves forward.
29+
target-version = "py312"
30+
line-length = 120
31+
extend-exclude = [
32+
"build",
33+
"dist",
34+
"*.egg-info",
35+
".eggs",
36+
"ipython", # notebook tutorials
37+
"arc/molecule", # Cython-compiled sources + tightly coupled modules
38+
]
39+
40+
[tool.ruff.lint]
41+
# Rule families enabled (kept tight; can grow over time):
42+
# E pycodestyle errors (real syntactic / structural issues)
43+
# F pyflakes (unused imports, undefined names, …)
44+
# W pycodestyle warnings (trailing whitespace, blank-line issues)
45+
# I isort (import ordering — auto-fixable)
46+
# B flake8-bugbear (likely-bug patterns: mutable defaults, …)
47+
# UP pyupgrade (modernize old syntax for the target Python)
48+
# RUF ruff-specific (small high-signal correctness checks)
49+
# C4 flake8-comprehensions (clearer list/set/dict comprehensions)
50+
select = ["E", "F", "W", "I", "B", "UP", "RUF", "C4"]
51+
# Per-rule overrides — these are the rules that produce false positives on
52+
# scientific Python code more often than they catch real bugs, plus the
53+
# stylistic-modernization rules that would otherwise flood the inbox on a
54+
# mature codebase. Each ignore is justified inline so future maintainers can
55+
# see why it was added and revisit if the situation changes.
56+
ignore = [
57+
# --- whitespace / formatting (let `ruff format` handle these) ----------
58+
"E501", # line too long — allow long XYZ blocks, SMILES, docstrings
59+
"E731", # do not assign a lambda — common in numerical code
60+
"E741", # ambiguous variable name (l/I/O) — allowed for math/physics
61+
"W291", # trailing whitespace — formatter's job
62+
"W293", # blank-line whitespace — formatter's job
63+
# --- typing modernization (we keep the legacy form for now) -----------
64+
"UP006", # `list` instead of `List` — pre-PEP604 form is in heavy use
65+
"UP007", # `X | Y` instead of `Union[X, Y]` — same reason
66+
"UP035", # `typing.X` deprecated — same reason
67+
"UP045", # `X | None` instead of `Optional[X]` — same reason (1290+ hits)
68+
# --- pyupgrade modernizations that aren't worth a churn-PR ------------
69+
"UP009", # UTF-8 encoding declaration — harmless leftover
70+
"UP015", # redundant open mode `'r'` — harmless
71+
"UP025", # unicode kind prefix `u""` — harmless
72+
"UP030", # `format()` literal positional indexes — minor
73+
"UP032", # use f-string instead of `.format()` — minor
74+
# --- bugbear false positives on numerical code ------------------------
75+
"B007", # unused loop control variable — common with `for _, x in …`
76+
"B008", # function calls in arg defaults
77+
"B905", # zip() without strict — would require a churn PR
78+
# --- comprehension preferences (taste, not bugs) ----------------------
79+
"C408", # unnecessary `dict()` call
80+
"C416", # unnecessary comprehension
81+
"C419", # unnecessary comprehension in `any()`/`all()`/etc.
82+
# --- ruff-specific noise on chemistry text ----------------------------
83+
"RUF001", # ambiguous unicode in strings — Greek letters in chemistry text
84+
"RUF002", # ambiguous unicode in docstrings — same
85+
"RUF003", # ambiguous unicode in comments — same
86+
"RUF005", # collection literal concatenation — taste
87+
"RUF012", # mutable class attributes annotated with ClassVar — too noisy
88+
"RUF013", # implicit `Optional` — would need typing-wide cleanup
89+
"RUF059", # unused unpacked variable — taste
90+
]
91+
92+
[tool.ruff.lint.per-file-ignores]
93+
# Tests routinely use long literal blocks (XYZ strings, expected dicts, …)
94+
# and `assert` patterns that some lint rules flag as "useless".
95+
"**/*test*.py" = ["E501", "F841", "B017", "RUF015"]
96+
"arc/testing/**" = ["E501", "F841"]
97+
# __init__.py files re-export symbols and need wildcard / unused-import patterns.
98+
"**/__init__.py" = ["F401", "F403"]
99+
# Standalone scripts run inside isolated envs and may import packages not
100+
# installed in the main env — don't flag those imports.
101+
"arc/job/adapters/scripts/*.py" = ["F401", "E402"]
102+
103+
[tool.ruff.lint.isort]
104+
known-first-party = ["arc"]
105+
combine-as-imports = true
106+
force-sort-within-sections = false
107+
section-order = [
108+
"future",
109+
"standard-library",
110+
"third-party",
111+
"first-party",
112+
"local-folder",
113+
]
114+
115+
[tool.ruff.format]
116+
# Format settings for `ruff format`. Not enforced by CI yet — the team can
117+
# opt in to a one-time mass reformat by running `ruff format arc/`.
118+
quote-style = "single"
119+
indent-style = "space"
120+
line-ending = "lf"
121+
docstring-code-format = false

0 commit comments

Comments
 (0)