Proposition - pre-commit for linting
Description
Zendesk Ticket IDs
has to be done after
Activity
Jesse Sopel November 8, 2023 at 3:39 PM
Also note, for pyupgrade
, for as long as we are stuck on Python 3.9, you may need to add --keep-runtime-typing
to the args
list if you use pydantic or Fast API and types are required at runtime to avoid Union
being converted to a pipe operator and causing runtime issues.
Jesse Sopel November 8, 2023 at 1:52 PMEdited
Just to note, I updated the examples following our implementation in with the pyproject.toml
and updated their versions. Still when adding it is good to run pre-commit autoupdate
to ensure you have the latest. More documentation on mypy and static typing can be found on our site:
Jesse Sopel December 23, 2022 at 1:27 PM
Awesome! Thanks for trying it out and giving your feedback. Much appreciated.
Sébastien Duthil December 22, 2022 at 7:25 PMEdited
Thanks for the instructions! After trying it, I find it really nice And running only on the committed files speeds it up enough for me
Jesse Sopel December 22, 2022 at 6:29 PMEdited
Definitely a good point. Usually it takes 1-5 seconds depending on both the number of hooks you run and how many files you are committing. But it only runs on stages files (unless ran manually with pre-commit run --all-files
so it is usually very quick. You can tell it to run at different stages, like post-commit, but I don’t think it’s possible to run it whilst writing the message. Anyways that would prevent you seeing the output. The very first time a hook is run it can take up to 30 seconds or so to create the environments, but they re-used on all subsequent runs so they are fast.
If you want to try it out I have a branch of agid where I was testing things out for the workshop. You can checkout the branch, install pre-commit, run pre-commit install
in the repo, make some changes and commit them locally to test it out. Just keep in mind it will probably give you a bunch or errors since mypy is configured, but there is intentionally a lot of typing issues to fix still. (if you do that though, just remember to do pre-commit uninstall
after, otherwise it will cause problems when you change branches)
Details
Priority
MediumAssignee
UnassignedUnassignedReporter
Jesse SopelJesse SopelPair
Charles LangloisFrançois Blackburn
Details
Details
Priority
Assignee
Reporter
Pair
Zendesk Support
Linked Tickets
Zendesk Support
Linked Tickets
Zendesk Support

I know this is not a priority and even if people are interested it doesn’t have to be done all at once, but it’s just an idea.
As we are starting to get quite a few things that run in Tox and I thought it might be nice to automate a few things to ensure we actually follow our style guide. One tool that I really like to use is pre-commit. It’s lightweight and runs fast and has hooks for tons of different languages and things. I think this could be a good addition to our toolbox and provide an easier way to run linting tasks. Obviously this does not replace tox for running tests, while in theory it could it would slow down each commit. It is really designed for linting and other checks. There are a ton of existing hooks for all sorts of checks for python, JS, yaml, Dockerfile, spelling mistakes, etc. You can also easily create your own hooks either locally or by creating a
.pre-commit-hooks.yaml
in a git repo. It can then be used in any repository by simply including it in the project’s config. For example adding the file to the repo could allow it to easily be included in repositories and run automatically via this file.In order to use the plugin, each repo needs to have a config file called
.pre-commit-config.yaml
that contains the list of hooks to run. They will be run in the order they are listed. You can run it manually withpre-commit run --all-files
but you can also run it automatically on every commit (it only runs on files added in the commit) if you install it as a pre-commit hook withpre-commit install
. In order to allow for the configs to be shared with IDEs and other tools and provide consistent results, the configuration for said tools will be configured in the project’spyproject.toml
instead of the pre-commit config where possible.Here is an example config that contains a few useful hooks.
.pre-commit-config.yaml
pyproject.toml
This example automatically:
Removes trailing whitespaces (
trailing-whitespace
)Ensures a file is empty or ends with a newline (
end-of-file-fixer
)Validates any committed yaml (
check-yaml
) and toml (check-toml
) filesUpgrades old school python syntax to new syntax automatically using pyupgrade (eg. format/% to f-string, remove object inheritance, upgrade typing, etc). This profile limits it to python 3.7 as that’s what we currently have, but could be bumped to 3.9 for bullseye.
Runs flake8 as it currently is run in tox
Automatically sorts and groups imports with isort as our style guide suggests (in a way compatible with black).
Automatically fixes styling issues with black
Runs mypy to check static types to avoid issues (mypy can be left out of an initial phase for a project if adding types is out of scope)
Note: If you use pyupgrade on a repository that uses pydantic, FastAPI or other libraries where it will do runtime introspection of type hints, you might need to use the argument
--keep-runtime-typing
to ensure it does not automatically upgrade the types to newer syntax as it will cause errors when Python 3.9 tries to evaluate themObviously not all of these are required and some others might be useful, but it shows what it can do.
As we don’t want to duplicate this logic in tox probably we could remove the linting jobs from tox and run pre-commit in the CI as well do ensure we always have the expected behaviour.
If we want to install this for all repos, we can use the git init templatedir to automatically install it in all newly cloned repos, or we could add it to existing ones with find and
pre-commit install
.