-
-
Notifications
You must be signed in to change notification settings - Fork 782
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add linting to CI via pre-commit #987
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate (here and/or on comments on the files) on what these two new yaml files accomplishes?
lint.yml
seems pretty straightforward, but I also noticed thatpre-commit/action
is apparently deprecated in favor ofpre-commit.ci
: https://github.com/pre-commit/actionpre-commit-config.yaml
is used bypre-commit.ci
, and possibly bypre-commit/action
too. However it's not obvious why it lists seemingly unrelated repos.
Are we using pre-commit.ci
or just the action? Is there something else that contributors need to do to enable the pre-commit hooks? Should this be documented somewhere?
Sure!
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's some notes on the hooks I added here.
They're some I commonly use for my projects. We can add or remove as we see fit.
- repo: https://github.com/asottile/pyupgrade | ||
rev: v3.2.2 | ||
hooks: | ||
- id: pyupgrade |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pyupgrade is a formatter that upgrades to newer Python syntax: https://github.com/asottile/pyupgrade
- repo: https://github.com/psf/black | ||
rev: 22.10.0 | ||
hooks: | ||
- id: black |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Black code formatter: https://github.com/psf/black
- repo: https://github.com/PyCQA/isort | ||
rev: 5.10.1 | ||
hooks: | ||
- id: isort |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isort to sort imports: https://github.com/PyCQA/isort
- id: flake8 | ||
additional_dependencies: [flake8-2020] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flake8 to find style errors using pycodestyle and pyflakes (both builtin plugins: https://flake8.pycqa.org/en/latest/) and flake8-2020 (version comparison problems: https://github.com/asottile/flake8-2020)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe worth replacing flake8-2020
with something much more useful, flake8-bugbear. It's more or less the official set of first-party optional checks by the PyCQA that don't meet the strict standards of pyflakes
but are still very likely to be mistakes of some sort; I'm not sure I've ever seen a false positive with it. It seems a lot more worth adding than flake8-2020
, which is a single check for a single specific issue that is not used here and very unlikely to ever be, at the point.
- repo: https://github.com/pre-commit/pygrep-hooks | ||
rev: v1.9.0 | ||
hooks: | ||
- id: python-check-blanket-noqa |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This repo has a bunch of simple grep checks. This hook makes sure any # noqa
annotations include a code like # noqa: F401
:
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v4.3.0 | ||
hooks: | ||
- id: check-json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This repo has lots of different checkers. This checks syntax of JSON files (will be added for the release chart PR).
rev: v4.3.0 | ||
hooks: | ||
- id: check-json | ||
- id: check-merge-conflict |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checks for accidentally committed merge conflict stuff:
<<<<<<< HEAD
=======
>>>>>>> new_branch_to_merge_later
hooks: | ||
- id: check-json | ||
- id: check-merge-conflict | ||
- id: check-yaml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checks syntax of YAML files. Can help find mistakes before the CI fails to run.
- id: end-of-file-fixer | ||
- id: trailing-whitespace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some whitespace fixers.
ci: | ||
autoupdate_schedule: quarterly |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defines a schedule for https://pre-commit.ci/ to send autoupdate PRs. I find the weekly default to be too noisy. monthly
is also a choice, and these can be updated manually at any time (via the tool or as needed).
Thanks for the detailed and very informative reply! The only issue I have is that I'm not a big fan of |
Personally, I don't like black's .py changes. They are also a violation of at least the spirit of PEP8. |
To avoid holding up this PR over Black, you could consider dropping it from here and deferring it to a future one. Or, to at least hugely reduce the diff noise to almost nothing (unless I'm missing something), you could disable the quote normalization, which only leaves one single change (using a single-line hanging indent instead of an ugly two-line split in one spot). |
For comparison I've updated Black to skip string normalisation. How does that look? And here's how blue looks:
But happy to drop it if you prefer. |
As far as I'm aware, I don't always 100% agree with every choice Black makes, but the way I see it, as much as I sometimes love to haggle over such minutia (and don't we all?), there are way more important things to worry and debate about than code style, since everyone has different preferences when it comes to that. The advantage of Black is you can just write your code however you want, and it will automatically take care of conforming it to a standard style while avoiding bikeshedding over what color to paint it. I've learned the long-term value of this the hard way (and continue to)... |
Of the three I like the third the most. Dropping both ( Click for bikeshedding aside
|
Ah yes! Pretty much, plus some other minor things we're not worried about so it's better to track upstream Black. Shall we go for what's currently in this PR (Black+88+skip quote normalisation) or drop it altogether? Or if people aren't keen on a formatter, I'm fine on leaving it out. Click for bikeshedding aside
res = some_func(
that, has, many, arguments, on, three, or, even,
four, lines
) Nitpick: Black won't format like that. Here's an example based on real code. If there's room, it keeps them in one line: def _carry(value1: float, value2: float, ratio: float) -> tuple[float, float]:
... If too long, it does this: def _carry(
value1: float, value2: float, ratio: float, unit: Unit, min_unit: Unit
) -> tuple[float, float]:
... And if still too long, it does this: def _carry(
value1: float,
value2: float,
ratio: float,
unit: Unit,
min_unit: Unit,
suppress: typing.Iterable[Unit],
) -> tuple[float, float]:
... A benefit is that diffs become clearer, it shows exactly the one new addition. Readability is important and a lot time is spent reading code in diffs, often side-by-side in narrower columns. There's also some stuff in Black I'm not so keen on, but like CAM said, find there's massive benefit in just letting it take care of all that stuff. Before Black there was yapf, which had so many options it could be hard to settle on which to use :) |
FWIW I prefer the former if others don't have strong objections, for the reasons mentions (which gives the same results as Blue for this repo, in particular the "third option" above that Ezio and I both mention we prefer the most of them).
That and yapf used a complex dynamic weighting algorithm that give quite non-deterministic, variable results depending on code's context, which resulted in a lot of fluctuations and diff noise. I also seem to recall some other ancillary issues with it. And before yapf, there was autopep8, which wasn't as much of a comprehensive autoformatter (such that two blocks of CST would be formatted the same) and just strictly enforced PEP 8's guidelines and no more. Surely there were other formatters before that too (Yapf stood for "Yet another Python formatter", after all) but it seems their names have been mostly lost to time. |
I recently contributed to another repo that uses pre-commit and ran into two problems while trying to fix some CI failures:
Footnotes
|
Did you run the tools directly? e.g. With pre-commit, the magic command is
Yes. Pinning means we don't run into sudden failures, for example, when a linter adds a new check, and means we can deal with those separately instead of in "normal" PRs. Yes, we need to update those from time to time. Either manually ( A second benefit of https://pre-commit.ci: if I submit a PR and don't apply Black formatting, the CI will do it and update the PR automatically. It saves a lot of manual work for reviewer and contributor: you don't need to tell me what to do (manual formatting or how to install and run extra tools), and I don't need to do it.
Yeah, pylint is pretty noisy, I very occasionally run it locally and don't use it any CI. |
Yes. The repo had a bunch of other checks, and I thought it would be easier to just install those two.
In my specific case, |
If you use
Its also very straightforward to just have a monthly, quarterly, etc. GitHub action that just runs I typically use such automation on repos with a handful of relatively straightforward checks. With more tools in play, I find that given tool updates often require manual fixes, introduce new checks/settings or have other non-trivial changes, on most of my repos I run
That can also be done via a GitHub Action without the need for a third party service and the significant limitations of pre-commit CI; see this example. There's also the brand new pre-commit.ci lite, which allows us to get the same auto-fix features as pre-commit.ci by just adding one extra step in the GitHub Actions workflow added here. Contrary to the name, it is this "lite" version that actually offers the full power of pre-commit, as pre-commit.ci can only execute a limited set of pre-installed checks. It does require enabling the Pre-Commit.ci lite GitHub application for some reason, which we may want to avoid by just implementing it ourselves like in the example above.
I do run Pylint in CI via pre-commit and find it useful, but it does take some customization to turn down or disable some of the checks, especially the refactoring ones. Others often find a more shotgun approach useful, disabling all but the warnings and errors, as well as some categories of the same with a higher false positive ratio.
Personally, I always just |
Given that this repository does not have a large corpus of code, we've configured black to avoid rewriting quotes to reduce churn, and ~all of the code already formats as black would, does anyone of us think that adopting black here is a blocking concern for this PR? If no one thinks it's a blocking concern, then let's move forward on this. Otherwise, let's remove black from the list of linters, merge this PR, and argue about black separately. Either way, we should do an update of the pins before landing this. :) |
FWIW, my take is given that, with quote normalization disabled, there's only a single existing line changed by Black, we should just rebase with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, FWIW
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One other thing here: If we're going to add pre-commit, we should move the Sphinx-Lint check under pre-commit as opposed to being hardcoded into the build workflow.
Moved! |
I was going to add this to the forthcoming release cycle (draft) PR, but better to split it out to its own PR.
This adds formatters and linters to the CI via pre-commit, we can adjust these as needed.