Add a pre-commit-hook for decay file validation#598
Conversation
|
as a follow up to our discussion yesterday at the Decfiles repo, here a codex-based draft version of the pre-commit-hook. Before marking this as ready, I will test this for sure a bit more in depth. But at least it already goes along the lines, I would like it to be eventually. Details we can probably discuss once we align on a conceptual vision of the tool. |
|
Hello. I am overwhelmed these days. It is a good problem to have ... ;-) I will try and get back to you this week. I am also adding @henryiii to the review for all his expertise. Thank you very much! |
|
Here's a quick AI review from Opus 4.8, you can feed this back into codex (rubber duck style) if you wish. Thanks for letting me know what model you are using, so I know which model to review with. :) From my fairly quick look at the moment, this looks a lot like flake8, which is a good thing. Idea seems good too. (Needs a rebase, too, of course) 🤖 AI text below 🤖 I've completed a thorough review of PR #598. Here's my assessment. Review: PR #598 — Add
|
|
Yes, that is fine. I am on holidays for one and a half week, so not sure when I have the time to act on it. But once I am back, I will do it as one of the first things. |
|
And thanks for the review by the way. It all sounds reasonable. |
|
Super! My all means do enjoy your hols! No rush. Thank you. |
06fbce5 to
a123220
Compare
|
Thanks @henryiii for the detailed review, and @eduardo-rodrigues for waiting for me to address it. The review was very helpful. I have now rebased the branch and worked through all of the points. For context, I am using GPT-5.6 Codex for the implementation and review iterations and this overview here: The changes since the review are:
There were a few further fixes after a deeper review:
I verified the result with the focused validator tests, the complete test suite, all configured pre-commit hooks, mypy, Ruff, codespell, The PR should now be ready for another review. Thanks again! |
|
Small correction to my previous update: my first attempt at fixing the repository-local hook for pre-commit.ci was not sufficient.
The setup now separates the two use cases explicitly:
I verified the local hook from a fresh pre-commit cache, and the new PR head ( |
|
One final follow-up: I added a downstream-style I also corrected the documentation: the feature is now listed under Unreleased rather than v1.0.0, The focused validator suite now has 23 passing tests, and all relevant pre-commit checks pass. |
Local speed comparisonBenchmark on macOS arm64 using 9,415 tracked
prek was about 33% faster from a cold cache (preparing hook repo, building the pre-commit env, etc.) and 19% faster with warm caches. Warm prek runs were 3.20–3.26 s, versus 3.96–4.05 s for pre-commit. Both runners found the same substantive diagnostics; only batching and output order differed. The validator's parsing work dominates warm runs, so prek provides a useful but not dramatic steady-state improvement. No hook changes are required to use it. |
|
Hi. Many thanks for the grand update. I will get to it very soon ... Starting with the bottom comment - the timing seems reasonable to me, I mean with the warm cache. On my laptop, with ProcessPoolExecutor, I typically parse all 9800-ish LHCb dec files in about 35 seconds. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #598 +/- ##
==========================================
+ Coverage 96.68% 97.60% +0.91%
==========================================
Files 5 6 +1
Lines 996 1210 +214
==========================================
+ Hits 963 1181 +218
+ Misses 33 29 -4 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| - ``parser-warning`` | ||
| - An otherwise unclassified warning was emitted by ``DecFileParser``. | ||
|
|
||
| When run through pre-commit, failures include the validator output. Parser |
There was a problem hiding this comment.
At this point, when the pre-commit hook hasn't yet been presented, giving the example output seems a wee out of place. It would be better to exemplify the sort of outputs given by the decaylanguage-validate script. If the same - have not yet checked - then it's just a matter of changing the wording.
| By default, at most 100 diagnostics are printed before the remaining diagnostics | ||
| are summarized. Pass ``--max-diagnostics=0`` to print every diagnostic. | ||
|
|
||
| Downstream projects can use the packaged pre-commit hook: |
There was a problem hiding this comment.
This part would deserve a subsection on its own, similarly to what you have presently in CONTRIBUTING.rst. This way people looking at the package can immediately realise the "good-old functionality" and the fact that validation can now be done trivially in repositories via the hook.
| diagnostic codes. Downstream pre-commit hooks can disable experiment-specific | ||
| codes with options such as ``--ignore=DLW004``. | ||
|
|
||
| On failure, pre-commit shows output such as: |
There was a problem hiding this comment.
Similar comment to above - is it really specific to the pre-commit output or rather the output of the script introduced above?
| decaylanguage-validate path/to/decfiles-directory | ||
|
|
||
| Use ``decaylanguage-validate --list-diagnostics`` to list selectable | ||
| diagnostic codes. Downstream pre-commit hooks can disable experiment-specific |
There was a problem hiding this comment.
Ditto - mixing the validation script itself with its usage via the hooks. This is the quickstart, the one page ead before anything, hence introduce the script and maybe link to the section with more details, including the availability of the pre-commit hook.
|
|
||
| def _validate_ignore_codes(codes: Iterable[str]) -> list[str]: | ||
| prefixes = {rule.code[:3] for rule in DIAGNOSTIC_RULES} | ||
| valid_codes = set(_RULES_BY_CODE) |
There was a problem hiding this comment.
The set(...) constructor does not seem necessary here since _RULES_BY_CODE is defined as a set via ´{...}´. You could then get rid of the temporary variable valid_codes and simplify a tiny bit the code.
| def _validate_ignore_codes(codes: Iterable[str]) -> list[str]: | ||
| prefixes = {rule.code[:3] for rule in DIAGNOSTIC_RULES} | ||
| valid_codes = set(_RULES_BY_CODE) | ||
| invalid = [ |
There was a problem hiding this comment.
If I understand correctly, the "massaging" here is to be able to ignore say all DLW with a simple ignore=DLW? Otherwise, why would you define the prefixes and have valid_codes | prefixes below? Maybe I'm just confused. In any case, if I'm correct, then this regex-ish possibility needs to be documented (apologies if it is already, I did not check yet in the remainder of the PR) and it would make sense to add a comment in this function to be clear of intentions to the code reader.
(There may be other places where a little comment line would help the code reader.)
|
|
||
|
|
||
| class Style: | ||
| def __init__(self, enabled: bool) -> None: |
There was a problem hiding this comment.
Suggest renaming enabled to use_color.
|
|
||
|
|
||
| def test_main_returns_failure_for_diagnostics() -> None: | ||
| assert main(["--color=never", str(DIR / "../data/duplicate-decays.dec")]) == 1 |
There was a problem hiding this comment.
Why isn't "black"/std colour text returned?
| ) | ||
|
|
||
|
|
||
| def test_main_rejects_unknown_ignore_code() -> None: |
There was a problem hiding this comment.
This test should cover the line above to which you added "pragma: no cover"?
| To run a subset of tests:: | ||
|
|
||
| nox -s tests-3.9 -- -k test_myfeature | ||
|
|
There was a problem hiding this comment.
As hinted at above, I think this is more for the documentation above. A CONTRIBUTING file is for contributors, and the hook is for customers. This would be on the edge if people were developing dec files to add, but then they would run the script to validate, I would imagine.
WDYT?
eduardo-rodrigues
left a comment
There was a problem hiding this comment.
Hello again, @jpwgnr. I did a full pass, now. This is truly super 👍. Thank you so much!
I left a few little suggestions, many trivial to resolve. Others are up for discussion and we could also move them to a follow-up contribution if you welcome a quick release with this to then start making tests in LHCb with the pre-commit hook. Just let me know and we adapt.
Again, thank you!
Co-authored-by: Eduardo Rodrigues <eduardo.rodrigues@cern.ch>
Co-authored-by: Eduardo Rodrigues <eduardo.rodrigues@cern.ch>
|
Thanks a lot for your super detailed feedback, I saw it and I hope I find the time to come back to you tomorrow :). |
Top. My privelege - I had to try and be thorough as this is really great. I see you've been busy on the LHCb Mattermost, no worries ;-). |
Summary
Add a first-party
decaylanguage-validatecommand and pre-commit hook for validating EvtGen.decfiles withDecFileParser.The validator reports stable diagnostic codes so downstream experiments can choose their own policy, for example ignoring LHCb-style unmatched
CDecaysource warnings with--ignore=DLW004.Changes
decaylanguage.dec.validatewith a CLI entry point exposed asdecaylanguage-validate..pre-commit-hooks.yamlso external repositories can useid: decaylanguage-validate..decfiles, excluding intentional negative fixtures.DLP001parse errorsDLW001duplicateDecayblocksDLW002missingCopyDecaysourceDLW003duplicateDecay/CDecayDLW004missingCDecaysourceDLW005self-conjugateCDecayDLW999unclassified parser warnings--max-diagnostics.Testing
Also tested on the local LHCb DecFiles checkout:
This leaves
DLP001,DLW001, andDLW003diagnostics after ignoring the expected LHCb-styleDLW004findings.