Skip to content

Run pre-commit once in CI and replace the flake8 hook with ruff - #1599

Open
jmduarte wants to merge 6 commits into
fastmachinelearning:mainfrom
jmduarte:cleanup-duplicate-precommit-ci
Open

jmduarte wants to merge 6 commits into
fastmachinelearning:mainfrom
jmduarte:cleanup-duplicate-precommit-ci

Conversation

@jmduarte

@jmduarte jmduarte commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Description

Every pull request ran the full pre-commit suite twice, and the two runs can disagree:

check source what it ran
Format (3.8) / "Run pre-commit" .github/workflows/pre-commit.yml pre-commit run --hook-stage manual --all-files (18 hooks)
pre-commit.ci - pr the ci: block in .pre-commit-config.yaml default stage, --all-files (17 hooks)

They diverged for two independent reasons.

The hook sets differ by design. check-manifest is marked stages: [manual], so only the workflow ran
it. pre-commit.ci runs default-stage hooks only, so it never did.

The flake8 plugins were unpinned. additional_dependencies: [flake8-bugbear, flake8-print] carried no
versions, and each service caches its own hook environment, built at a different time. flake8-bugbear
26.10.27 added B045; the Actions job installed it on its next cache miss and began failing pull requests
on pre-existing code, while pre-commit.ci kept passing from an environment cached before that release. #1537
is an example: Format (3.8) failed with five B045 hits in files the PR never touched, and
pre-commit.ci - pr passed on the same commit.

This PR keeps pre-commit.ci as the formatting gate, reduces the workflow to the single hook pre-commit.ci
cannot run, and removes the flake8 hook whose unpinned plugins caused the drift:

  • .github/workflows/pre-commit.yml becomes .github/workflows/check-manifest.yml and runs
    --hook-stage manual --all-files check-manifest. Its python-version: [3.8] matrix is dropped — it has
    had no effect since Fix precommits #741 removed the setup-python step it fed, so the check name advertised a Python
    version the job never used.

  • The flake8 hook is removed, along with both plugins. Its checks move into ruff, as described below:

    • pycodestyle and pyflakes, which ruff runs as E, W and F, partly only in preview
    • flake8-bugbear
    • flake8-print's T203

    Pinning the two plugins would also have stopped the drift, but pre-commit.ci's autoupdate bumps rev:
    only, so the pins would have had to be moved by hand from then on.

  • Five nested loops reuse an enclosing loop's control variable; this is what B045 reported on Retire Quartus backend #1537. The
    inner variables are renamed (line → func_line in four writers, i → input_name in model_to_dot).
    The enumerate index in model_to_dot was only ever read by the inner loop that shadowed it, so it is
    dropped. Ruff has no B045, but PLW2901, selected below, reports all five.

  • .agents/contributing-changes.md is updated to describe the new split and no longer mentions flake8.

Moving flake8's checks into ruff

I measured this rather than reading it off the rule tables. The tools were ruff 0.16.10 and flake8 7.4.1
with flake8-bugbear 26.10.27 and flake8-print 5.0.0, run over every tracked .py file.

  • The flake8 hook reports nothing on the tree once the loops above are renamed, and neither does ruff as
    configured on main. No finding flake8 currently makes is lost.
  • Ruff with B added reports 97 findings: B905 ×64, B028 ×29 and B904 ×4. The flake8 hook reports
    none of them, for two reasons:
    • B904 and B905 are among bugbear's opinionated B9 checks, which bugbear leaves off unless they are
      selected explicitly.
    • B028 is on by default in bugbear, but bugbear only matches warnings.warn(...). Every hit here is a
      bare warn(...) imported with from warnings import warn, which ruff matches and bugbear does not.

Bugbear, check by check. bugbear 26.10.27 has 47 checks enabled by default, not counting B9. 35 of
them have a stable ruff B code. For each of the other 12, I wrote a snippet, confirmed that the flake8 hook
flags it, and ran ruff on it:

bugbear check after this PR
B001 bare except: caught by E722, already selected
B041 repeated key-value pair in a dict literal caught by F601, already selected
B037 return or yield in __init__ caught by PLE0101 / PLE0100, added here
B045 inner loop reuses an enclosing loop's variable caught by PLW2901, added here
B046 mutable value passed to dict.fromkeys caught by RUF024, added here
B044 assert on an always-true value partly: PLW0129 (added) covers strings and f-strings, F631 covers tuples; generators, lambdas, lists and dicts are not checked
B036 except BaseException without re-raising not checked
B040 exception with add_note() that is never raised not checked
B042 exception __init__ not passing all args to super() not checked
B043 delattr with a constant name not checked (ruff has it only in preview)
B047 except clause unreachable after a broader one not checked
B049 @abstractmethod not the innermost decorator not checked

PLE0100, PLE0101, PLW0129 and RUF024 report nothing on the tree.

PLW2901 is broader than B045. It also flags a loop variable reassigned inside its own loop, and it
reported 93 of those. 66 of them reassign line in the writers' template loops, as in
line = line.replace(...). They are renamed (see the
changes below).

BLE001 comes close to B036, but it also flags except Exception (33 hits), so it is not added.

pycodestyle. ruff has several of pycodestyle's checks only in preview, so E and W alone do not
select them:

  • indentation (E11x)
  • whitespace (E2xx)
  • blank lines (E3xx)
  • E502 and W391

They are restored with lint.preview = true, lint.explicit-preview-rules = true, and the 38 codes flake8
ran listed in lint.extend-select. flake8's default and --extend-ignore lists left E203, E226, E241
and E242 off, so those stay off. The 38 report nothing on the tree.

Side effects of turning on preview:

  • explicit-preview-rules keeps prefixes like E and B from selecting other preview rules.
  • lint.preview still turns on preview behaviour for the stable rules. That adds no findings today. If a
    ruff release changes it, the change surfaces on pre-commit.ci's quarterly autoupdate PR.
  • Preview makes ruff print rule names instead of codes. output-prefer-rule-codes = true reverts that.

pycodestyle's E12x continuation-line checks have no ruff implementation, stable or preview, and are no
longer checked. ruff-format enforces the layout they checked everywhere except inside # fmt: off.

flake8-print. The hook ignored only T201, so flake8-print's T202, T203 and T204 were on. T203
(pprint) is now selected in ruff. Ruff has no equivalent for T202 (print referenced without being
called) or T204 (a function or argument named pprint), and neither occurs in the tree.

The changes:

  • pyproject.toml, lint.select: adds the following:

    • B
    • the four stand-in codes in the table
    • PLW2901
    • T203
  • pyproject.toml, preview pycodestyle checks: lint.extend-select, lint.preview,
    lint.explicit-preview-rules and output-prefer-rule-codes, as described above.

  • pyproject.toml, lint.ignore: adds B028 and B905, with a comment. Neither is a mechanical fix.

    • For B028, the right stacklevel depends on how far each warn() sits from user code.
    • For B905, strict=False on all 64 zip() calls would only be noise, while strict=True changes
      behaviour wherever the lengths can differ.

    Enabling either is a separate decision.

  • E741: the hook's per-file E741 ignore for bit_exact.py needs no carrying over, because the global
    lint.ignore = ["E741"] already covers it.

    • The 22 # noqa: E741 comments flake8 needed elsewhere are removed.
    • Two of them, in utils/fixed_point_utils.py, lacked the colon, so both tools read them as blanket
      noqa.
  • B904 fixes: the four raise statements inside except blocks now chain with from e:

    • the ahls lookup in AlteraBackend.build
    • the kerassurgeon import in reduce_model
    • two ortools imports in knapsack.py

    The original exception still appears in the traceback, which now says "direct cause" where it said
    "during handling".

  • PLW2901 renames: the 93 reassigned loop variables in 21 files are renamed.

    • In most loops the loop target gets a new name (template_line, weight, item, ...) and the body
      keeps its name, so each loop changes in one or two lines.
    • Where the reassignment was conditional, the result gets its own name, with the loop value as its
      default.
  • Ruff's file scope: include listed tests/**/*.py, but the tests live in test/; it now says
    test/**/*.py. Under pre-commit this made no difference. Pre-commit passes file names, and ruff applies
    only exclude to names it is given, so the 109 test files were already linted. A plain ruff check .,
    however, skipped them.

  • Two scope differences from flake8 remain, both deliberate:

    • Ruff skips hls4ml/templates/**, so the three vivado_accelerator/*/python_drivers/axi_stream_driver.py
      files that flake8 linted are no longer linted. They are clean under the new rules. Widening the scope
      would also reformat all three, because the same exclude applies to ruff-format.
    • Ruff lints docs/conf.py, which the flake8 hook excluded. It is clean.

Type of change

  • Bug fix (non-breaking)
  • New feature (non-breaking)
  • Breaking change (existing configs, APIs or generated code behave differently)
  • New frontend / backend
  • New layer / operator support
  • New configuration option — a new io_type, Strategy, or config attribute
  • Research paper implementation
  • Documentation
  • Build, CI or tooling
  • Refactor / cleanup (no functional change)

Affected areas

Backends: local variable renames only, in the writers for every backend. Altera also gets exception
chaining in AlteraBackend.build.

  • Vivado, Vitis, VivadoAccelerator, VitisUnified, Quartus, Altera, Catapult, Coyote, Libero,
    SymbolicExpression, XLS (writers)
  • Backend-independent (core IR, optimizer, hls4ml.model): renames in Layer.__init__,
    Layer._validate_attributes, bit_exact.get_input_layers, profiling and serialization

Frontends:

  • PyTorch: a rename in the RNN input parsing of parse_pytorch_model
  • Not related to a frontend

Components:

  • IR (layers + model graph) / optimizer passes
  • C++ templates / HLS sources under hls4ml/templates/
  • Profiling, reporting or the CLI
  • Packaging, build or CI

Configurations affected and exercised

No configuration axis is involved. The Python changes rename local variables and chain exceptions where a
missing tool or optional dependency is reported. Each row below is a project written with write() on the
commit before the renames and again after them, then diffed.

Backend io_type Strategy Verified
Vivado, Vitis, Quartus, Altera, Catapult, Coyote, VivadoAccelerator io_parallel Latency write() output identical before and after
VitisUnified io_stream Latency write() output identical before and after
Vivado io_stream Latency write() output and bit_exact.get_input_layers results identical
Vivado (GRU, stacked LSTM→GRU, PyTorch) io_parallel Latency write() output identical before and after
Vitis, multigraph io_parallel Latency write() output identical before and after
XLS n/a n/a write() output identical before and after
SymbolicExpression (vivado_hls, vitis_hls) n/a n/a write() output identical before and after
Libero io_parallel Latency not exercised: write() fails on main too, because templates/libero/build_lib.sh does not exist
n/a n/a n/a pre-commit (both stages)

New configuration axis introduced by this PR (if any): none

Impact on generated HLS

  • This PR does not change the generated HLS for existing models.
  • This PR changes the generated HLS. Numbers below.

Numerical behaviour: bit-exact vs main. The generated projects in the table above are identical before
and after the renames.

Tests

No test is added. The change is CI and lint configuration, plus edits that no test can distinguish from
main:

  • loop and local variable renames
  • __cause__ set on exceptions raised when an optional dependency or tool is missing
  • removed # noqa comments

Test configuration: pre-commit 4.6.0 on macOS 15 (Darwin 25.6.0); ruff 0.16.10, and flake8 7.4.1 under
Python 3.12 for the comparison above. The before/after check ran under Python 3.12.13 in a scratch
environment:

  • torch 2.15.0

  • keras 3.15.1 with the torch backend

  • quantizers 1.2.2. The current 2.0.0 removes get_fixed_quantizer_np, so import hls4ml fails with it, on
    main too. bump quantizers to 2 #1604 adapts hls4ml to it.

  • pre-commit run --all-files: every default-stage hook passes.

  • pre-commit run --hook-stage manual --all-files: check-manifest could not be checked locally. It fails
    for reasons unrelated to this change:

    • four submodules are uninitialised in this working copy
    • a stray untracked .bak~ file sits under hls4ml/templates/
    • p-clang-format runs sed -i.bak without removing the backups, so any all-files run leaves .bak
      files under hls4ml/templates/ that check-manifest then trips on

    That last cause is not addressed here.

  • test/pytest/test_agent_docs.py: passes (38 passed, 1 skipped).

  • Before/after comparison of the renames. I ran a script on the commit before the renames and again on
    the change. It writes the projects in the table above and also exercises:

    • serialization and deserialization
    • WeightsTorch, weights_keras and activations_keras
    • parse_einsum on invalid strings
    • _make_vivado_tables
    • compare_dicts from synthesis_helpers.py

    All recorded results are identical. Of the 1816 files written, the only ones that differ are files that
    also differ between two runs of the unchanged commit:

    • pickled tensors in hls4ml_config.yml
    • the Catapult tarball's timestamp
    • the flow order in the serialized graph_state.json

    Coverage shows every renamed statement ran, with these exceptions:

    • the getitem-inside-a-tuple branch in parse_pytorch_model
    • the Libero build-script loop
    • test_graph.py and test/board/vitis_unified_hw_test.py, which need Keras with TensorFlow and a board
  • The rest of the pytest suite was not run locally. The GitLab pipeline on this PR is the first run of it.

AI assistance disclosure

  • None — no AI tool was used.
  • Assisted — completion, refactoring, docstrings, tests; design and code are mine.
  • Substantial — significant AI-generated portions, reviewed and edited by me.
  • Agentic — produced largely end-to-end by an AI agent from my prompts.

Tool(s) and model(s): Claude Code (Claude Opus 5 and Claude Opus 5.5). The T203 commit (e9fabcb) was
applied from a Copilot review suggestion.

Where it was used: the whole change. That covers:

  • diagnosing the divergence between the two pre-commit runs
  • the workflow, .pre-commit-config.yaml and pyproject.toml edits
  • the flake8 and ruff comparison and the per-rule probes
  • the loop variable renames, the four B904 fixes and the noqa removals
  • the before/after comparison of the generated projects
  • the agent-doc update and this description

If anything other than None is ticked, confirm all of the following:

  • I am the author of this contribution and take full responsibility for
    it.
    I have read and understood every line and can explain and defend it
    in review.
  • I verified the generated code against real hls4ml and HLS semantics —
    no invented APIs, config keys, pragmas or citations.
  • All numbers, logs and test results quoted in this PR come from runs I
    actually performed, not from agent output.
  • I have the right to submit this work under the project's licence, and to
    my knowledge it does not reproduce third-party code that would conflict
    with it.
  • No AI tool is credited as an author in any commit in this branch.

Checklist

Required:

  • I have read the contributing guidelines.
  • I installed and ran pre-commit on the files I edited.
  • I added tests under test/pytest covering this change (a bug fix should
    add a test that fails on main and passes here).
  • I self-reviewed the full diff and it contains no leftover debug code,
    commented-out blocks or unrelated changes.
  • The AI assistance disclosure above is complete and accurate.

If applicable:

  • Documentation under docs/ updated.
  • No new build or synthesis warnings.
  • Public API / config schema changes are documented.

Release note

none

Every pull request ran the full pre-commit suite twice: on pre-commit.ci,
configured by the ci: block in .pre-commit-config.yaml, and in the Format job
of the Run pre-commit workflow. The two disagree, because they resolve the
hooks differently.

The flake8 hook declared flake8-bugbear and flake8-print with no versions, and
each service caches its own hook environment, built at a different time. When
flake8-bugbear 26.10.27 added B045, the Actions job installed it on its next
cache miss and started failing unrelated pull requests, while pre-commit.ci
kept passing from an older cached environment.

Keep pre-commit.ci as the formatting gate and reduce the workflow to the one
hook pre-commit.ci does not run: check-manifest, which is manual-stage. Pin the
two flake8 plugins so local runs, pre-commit.ci and the workflow resolve to the
same tools.

Pinning flake8-bugbear at 26.10.27 turns on B045, which flags five nested loops
that reuse an enclosing loop's control variable. Rename the inner variables.
The enumerate index in model_to_dot was only ever read by the inner loop that
shadowed it, so drop it. No behaviour changes.

Also drop the python-version matrix from the workflow, which has had no effect
since fastmachinelearning#741 removed the setup-python step it fed.
@jmduarte jmduarte added the please test Trigger testing by creating local PR branch label Oct 30, 2026
The flake8 hook duplicated ruff's E, W and F checks; what it added was
flake8-bugbear. Select B in ruff, plus PLE0100, PLE0101, PLW0129 and
RUF024 for the bugbear checks ruff has no B code for, and drop the flake8
hook together with its pinned plugins.

Ignore B028 and B905, which flake8-bugbear did not report on this tree and
which need a decision at each call site, and chain the four re-raised
exceptions B904 reports. Point ruff's include at test/, where the tests
are, instead of the nonexistent tests/.
@jmduarte jmduarte changed the title Run the pre-commit suite once in CI Run pre-commit once in CI and replace the flake8 hook with ruff Oct 30, 2026
@jmitrevs
jmitrevs requested a balanced review from Copilot November 1, 2026 21:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Ruff’s selection omits the previously enabled T203 check for pprint debug output, so T203 must be added to preserve lint coverage.

1 open issue
What changed in this PR

This PR removes duplicate pre-commit execution from CI, keeps formatting checks in pre-commit.ci, and moves supported flake8-bugbear coverage into Ruff.

Changes:

  • Narrows the GitHub Actions workflow to the manual-only check-manifest hook and updates contributor guidance.
  • Removes flake8, expands Ruff’s rules, and corrects test-directory discovery.
  • Renames shadowed loop variables and adds explicit exception chaining.

Tests and hooks were not run during this review.

File Description
pyproject.toml Adds Ruff rules and corrects the test discovery path.
hls4ml/​writer/​vivado_writer.py Renames a shadowed inner-loop variable.
hls4ml/​writer/​libero_writer.py Renames a shadowed inner-loop variable.
hls4ml/​writer/​coyote_writer.py Renames a shadowed inner-loop variable.
hls4ml/​writer/​catapult_writer.py Renames a shadowed inner-loop variable.
hls4ml/​utils/​plot.py Removes an unused index and clarifies input iteration.
hls4ml/​optimization/​dsp_aware_pruning/​knapsack.py Chains optional-dependency import errors explicitly.
hls4ml/​optimization/​dsp_aware_pruning/​keras/​reduction.py Chains the Keras Surgeon import error explicitly.
hls4ml/​backends/​altera/​altera_backend.py Chains the missing-tool error explicitly.
.pre-commit-config.yaml Removes the flake8 hook and its plugins.
.github/​workflows/​check-manifest.yml Runs only manifest validation and removes the unused matrix.
.agents/​contributing-changes.md Documents Ruff and the split CI responsibilities.

Review effort: Balanced

Comment thread pyproject.toml Resolved
Added T203 to lint selection for improved code checks.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@JanFSchulte JanFSchulte added please test Trigger testing by creating local PR branch and removed please test Trigger testing by creating local PR branch labels Nov 2, 2026

@JanFSchulte JanFSchulte left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments inline. Two more that don't attach to lines in the diff:

  • Leftover # noqa: E741 comments. With flake8 gone they do nothing, since ruff already ignores E741 globally through lint.ignore. There are about 20 of them, in distributed_arithmetic.py, keras/hgq_proxy_model.py, keras_v3/hgq2/{_base,softmax,unary_lut}.py, keras_v3/pquant/_base.py, pytorch/pquant.py and test/pytest/test_softmax.py. They could be removed here, or left until someone enables RUF100.
  • PR template. "I added tests under test/pytest covering this change" is ticked, but the Tests section says no test is added. Since this is an agent-assisted PR, please also confirm that the author ticked the attestation boxes themselves.

Comment thread pyproject.toml Outdated
lint.select = [ "E", "F", "F401", "I", "W" ]
lint.ignore = [ "E741" ]
# PLE0100, PLE0101, PLW0129 and RUF024 stand in for flake8-bugbear B037, B044 and B046, which ruff has no B code for
lint.select = [ "B", "E", "F", "F401", "I", "PLE0100", "PLE0101", "PLW0129", "RUF024", "T203", "W" ]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description says nothing checks for the B045 loop-variable shadowing after this change. As far as I know, ruff's PLW2901 (redefined-loop-name) flags an inner for target that overwrites an outer loop variable, which is the bug class the writer renames in this PR fix. Could it be selected? It will also flag reassignments such as line = line.replace(...) in coyote_writer.py (around line 226), so those would need renaming too.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Selected in 5e77481. On main's versions of the files, PLW2901 reports all five nested loops this PR
renames, so it covers what B045 caught.

It also reports 93 reassignments of a loop variable inside its own loop. 66 of them reassign line in the
writers' template loops, as in line = line.replace(...). All 93 are renamed:

  • Usually the loop target gets a new name (template_line, weight, item, ...) and the body keeps its
    name, so each loop changes in one or two lines.
  • Where the reassignment was conditional, the result gets its own name, with the loop value as the default.

To check that nothing moved, I generated output before and after the renames and diffed it. That covered:

  • write() for Vivado, Vitis, Quartus, Altera, Catapult, Coyote, VivadoAccelerator, VitisUnified (io_stream),
    XLS and Symbolic (Vivado HLS, Vitis HLS, libs path present and missing)
  • a Vitis multigraph and two PyTorch RNN models
  • serialization
  • the PyTorch and Keras weight and activation profiling
  • the einsum and Vivado report helpers

The outputs are identical. The only differences are files that also differ between two runs of the unchanged
tree: pickled tensors in hls4ml_config.yml, the Catapult tarball's timestamp, and the flow order in the
serialized graph state.

Coverage shows every renamed statement ran except two:

  • the getitem-inside-a-tuple branch of the PyTorch RNN input parsing
  • the Libero build-script loop. Its template, templates/libero/build_lib.sh, doesn't exist on main, so
    that write fails before and after this change.

Comment thread .pre-commit-config.yaml
- id: pyupgrade
args: ["--py310-plus"]

- repo: https://github.com/pycqa/flake8

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing flake8 also removes pycodestyle E1xx/E2xx/E3xx and W391. In ruff those rules are preview-only, and E/W in lint.select enable only the stable ones. ruff-format fixes most of these, but not inside # fmt: off blocks or in comment spacing. The check that today's tree passes shows nothing breaks now, not that future code would still be caught. Is losing these acceptable, or should preview = true (or an explicit preview selection) be considered?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're back. lint.preview = true and lint.explicit-preview-rules = true are now set, and
lint.extend-select lists the 38 preview pycodestyle codes flake8 ran. flake8 skipped E203, E226, E241 and
E242 through its default and --extend-ignore lists, so those stay off. On the tree they report nothing.

Some details:

  • Prefixes still select stable rules only. With explicit-preview-rules, selections like E and B
    don't pick up preview rules.
  • Preview changes stable rules too. lint.preview also turns on preview behaviour for the stable rules.
    That adds no findings today, but it can change with a ruff release. If it does, it will show up on
    pre-commit.ci's quarterly autoupdate PR, not on unrelated PRs.
  • Rule codes in output. Preview makes ruff print rule names instead of codes. output-prefer-rule-codes = true undoes that. # noqa: <code> works either way.
  • Still not checked: E12x. pycodestyle's E12x continuation-line checks have no ruff implementation, stable
    or preview. ruff-format covers them everywhere except inside # fmt: off.

Comment thread .agents/contributing-changes.md Outdated
`.pre-commit-config.yaml` runs ruff (with `--fix`) and ruff-format, pyupgrade targeting Python 3.10,
pyproject-fmt, the standard whitespace and YAML hooks, and `p-clang-format` for C and C++ — so edited
`nnet_utils` headers are reformatted too. Ruff's rules live in `[tool.ruff]` in `pyproject.toml`: a
125-character line limit plus the pycodestyle, pyflakes, isort and bugbear checks.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This overstates the coverage. Only the stable pycodestyle subset runs (see the comment on .pre-commit-config.yaml), and bugbear B028/B905 are ignored, with B045 having no ruff equivalent. Maybe something like "pyflakes, isort, the stable pycodestyle rules and most bugbear checks".

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworded to "pyflakes, isort, and most pycodestyle and bugbear checks". I also added a pointer to PLW2901,
since it now rejects the line = line.replace(...) idiom.

Comment thread .agents/contributing-changes.md Outdated

The first run of a hook installs its own environment and needs network access. Commit the reformatting the
hooks apply; pull requests that fail these checks are not reviewed.
The first run of a hook installs its own environment and needs network access. Hook revisions are pinned, so

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Hook revisions are pinned, so a local run resolves to the same tools CI uses" is stronger than what pinning rev guarantees. Unpinned additional_dependencies and transitive dependencies resolve when the environment is built, and check-manifest builds the sdist under build isolation with whatever setuptools/setuptools_scm is current. I'd soften this or drop the sentence.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped. The paragraph is back to what main says.

Select PLW2901 and rename the 93 loop variables it reports, enable the
preview-only pycodestyle checks flake8 ran, remove the E741 noqa comments
only flake8 needed, and correct the contributing doc's description of ruff.
@jmduarte

jmduarte commented Nov 3, 2026 •

Copy link
Copy Markdown
Member Author
  • PR template. "I added tests under test/pytest covering this change" is ticked, but the Tests section says no test is added. Since this is an agent-assisted PR, please also confirm that the author ticked the attestation boxes themselves.

I did tick them myself, but erroneously ticked this one :)

Also, I unchecked the AI credit tickbox because Copilot signed its autofix :|

@jmduarte jmduarte added please test Trigger testing by creating local PR branch and removed please test Trigger testing by creating local PR branch labels Nov 3, 2026
PLW2901, selected on this branch, flags n_out being reassigned when the
call gives no output_size. The parser came in from main with fastmachinelearning#1597.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

please test Trigger testing by creating local PR branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants