Skip to content
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

Offer more python linter tools (black, mypy, isort) #19827

Open
svenevs opened this issue Jul 21, 2023 · 7 comments
Open

Offer more python linter tools (black, mypy, isort) #19827

svenevs opened this issue Jul 21, 2023 · 7 comments
Assignees
Labels
component: build system Bazel, CMake, dependencies, memory checkers, linters priority: low type: feature request

Comments

@svenevs
Copy link
Contributor

svenevs commented Jul 21, 2023

Followup task from #17962. Python files developed there were originally being linted with the following:

#!/usr/bin/env python3

# This file is in tools/workspace/vtk/lint_me.py
#
# Dependencies:
#     pip install black flake8 flake8-import-order mypy
#
# Running it:
#     MYPYPATH="$PWD:$PWD/image" ./lint_me.py

import os
import subprocess
from pathlib import Path


def main():
    this_file_dir = Path(__file__).parent.absolute()
    py_files = [str(p) for p in this_file_dir.rglob("*.py")]

    subprocess.check_call(
        [
            "black",
            "--line-length",
            "80",
            *py_files,
        ]
    )

    mypy_env = os.environ.copy()
    mypy_path = f"{this_file_dir}:{this_file_dir / 'image'}"
    mypy_env["MYPYPATH"] = mypy_path
    subprocess.check_call(
        [
            "mypy",
            "--config-file",
            str(this_file_dir / "mypy.ini"),
            "--explicit-package-bases",
            str(this_file_dir),
        ],
        env=mypy_env,
    )

    subprocess.check_call(["flake8", *py_files])


if __name__ == "__main__":
    main()

and a config file

[mypy]

[mypy-lsb_release.*]
ignore_missing_imports = True

[mypy-bazel_tools.*]
ignore_missing_imports = True

Drake has mypy, we could consider adding to //tools/lint and adding a new lint check on the tools/workspace/vtk directory. mypy is still a tool that you have to coerce at times, but IME it's worth it. The example that came up is it would have helped me know I broke the linux codepath when refactoring on mac. There are certainly downsides to it, but at least for that code, it's setup and able to be type checked so I think we should continue to keep it that way if possible.

Drake already runs flake8, and I'll let the birds decide on black. I'd say there's no excuse not to use black if we also use clang-format 😉 But it's not already part of the drake dependencies.

There are other places (drake-ci) I would like to re-request these three tools for.

CC @jwnimmer-tri @BetsyMcPhail @mwoehlke-kitware as the people who will also have to interact with these.

@svenevs svenevs self-assigned this Jul 21, 2023
@xuchenhan-tri xuchenhan-tri added the component: build system Bazel, CMake, dependencies, memory checkers, linters label Jul 26, 2023
@jwnimmer-tri
Copy link
Collaborator

See also #13571 for adding isort as a linter.

Also note that https://github.com/RobotLocomotion/drake-blender has some Bazel integration of both black and isort that we could backport into Drake.

I think the call to action here is to add all three tools as linter opt-ins, like so:

--- a/tools/lint/lint.bzl
+++ b/tools/lint/lint.bzl
@@ -14,6 +14,9 @@ def add_lint_tests(
         bazel_lint_extra_srcs = None,
         bazel_lint_exclude = None,
         enable_clang_format_lint = True,
+        enable_black_lint = False,
+        enable_isort_lint = False,
+        enable_mypy_lint = False,
         enable_install_lint = True,
         enable_library_lint = True):
     """For every rule in the BUILD file so far, and for all Bazel files in this

Possibly we should split each one (isort, black, mypy) into a dedicated issue number. We can do that later once we start digging in.

@jwnimmer-tri jwnimmer-tri changed the title Drake VTK Build System Linting Offer more python linter tools (black, mypy, isort) Jul 27, 2023
@svenevs
Copy link
Contributor Author

svenevs commented Jul 27, 2023

That sounds good to me. The only snag I can see is the configuration file I needed above, and how to enable that for just one BUILD.bazel. Possibly I can provide the string and then the implementation generates it before running mypy? Or I check in the file and tell the bazel function to use it with a relative file path?

Not sure if local mypy configs are a good idea long term, or if there should just be one global drake one. Probably the latter, and likely we'll also want to install additional package-types from pip as more code tries to use mypy.

We may want to consider allowing a single BUILD.bazel to provide command line arguments to mypy. The example above I needed --explicit-package-bases for convoluted import reasons + the docker / macOS split that is slightly awkward and unlikely to come up elsewhere.

Edit: also, MYPYPATH is unlikely to be needed elsewhere. Just because of how that code has to be organized (image module and docker primarily).

@jwnimmer-tri
Copy link
Collaborator

Yes, nominally any config file(s) should be Drake-wide.

... for convoluted import reasons + the docker / macOS split that is slightly awkward and unlikely to come up elsewhere.

Those hijinks (sys.path manual hacking) are defective anyway, and I plan to rewrite that code sooner or later to avoid it.

@jwnimmer-tri
Copy link
Collaborator

jwnimmer-tri commented Jan 11, 2024

The higher priority is isort and black. (In other words, help our contributors with code formatting and auto-fixing.) The mypy would be a second step.

Another fair candidate for the second phase would be flake8.

@jwnimmer-tri
Copy link
Collaborator

The code at https://github.com/RobotLocomotion/drake-blender/blob/main/tools/defs.bzl might be a useful starting point (not sure)?

This might end up blocked on #8392. If our various platforms don't have a sufficiently sync'd version of the linter available, we might cause problems for our developers if the rules fight each other. We might need to uniformly pin the linters using requirements.txt, which would mean we need rules_python to pull in the pip stuff for us.

@svenevs
Copy link
Contributor Author

svenevs commented Mar 19, 2024

I haven't looked much, just stumbled across a possibly interesting alternative: https://docs.astral.sh/ruff/

@jwnimmer-tri
Copy link
Collaborator

I'm going to close #14234 as a duplicate of this. As mentioned upthread, another tool we can consider here is flake8.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: build system Bazel, CMake, dependencies, memory checkers, linters priority: low type: feature request
Development

No branches or pull requests

4 participants