All Projects β†’ thundergolfer β†’ Bazel Mypy Integration

thundergolfer / Bazel Mypy Integration

Licence: mit
πŸπŸŒΏπŸ’š Integrate MyPy type-checking into your Python Bazel builds

Programming Languages

python
139335 projects - #7 most used programming language

Projects that are alternatives of or similar to Bazel Mypy Integration

Rules foreign cc
Build rules for interfacing with "foreign" (non-Bazel) build systems (CMake, configure-make, GNU Make, boost, ninja)
Stars: ✭ 418 (+945%)
Mutual labels:  bazel
Zhihudailypurify
Purified version of Zhihu Daily - ζ›΄ηΊ―ε‡€ηš„ηŸ₯乎ζ—₯ζŠ₯
Stars: ✭ 4,998 (+12395%)
Mutual labels:  bazel
Gazel
DEPRECATED: use gazelle
Stars: ✭ 22 (-45%)
Mutual labels:  bazel
Subpar
Subpar is a utility for creating self-contained python executables. It is designed to work well with Bazel.
Stars: ✭ 471 (+1077.5%)
Mutual labels:  bazel
Buildtools
A bazel BUILD file formatter and editor
Stars: ✭ 538 (+1245%)
Mutual labels:  bazel
Awesome Bazel
A curated list of Bazel rules, tooling and resources.
Stars: ✭ 640 (+1500%)
Mutual labels:  bazel
Examples
Examples for Bazel
Stars: ✭ 412 (+930%)
Mutual labels:  bazel
Rules codeowners
Bazel rules for generating CODEOWNERS from a workspace.
Stars: ✭ 31 (-22.5%)
Mutual labels:  bazel
Daml
The Daml smart contract language
Stars: ✭ 548 (+1270%)
Mutual labels:  bazel
Colossus
Colossus β€”Β An example microservice architecture for Kubernetes using Bazel, Go, Java, Docker, Kubernetes, Minikube, Gazelle, gRPC, Prometheus, Grafana, and more
Stars: ✭ 917 (+2192.5%)
Mutual labels:  bazel
Android Studio Poet
Generate large Android Studio projects
Stars: ✭ 489 (+1122.5%)
Mutual labels:  bazel
Intellij
IntelliJ plugin for Bazel projects
Stars: ✭ 500 (+1150%)
Mutual labels:  bazel
Tl
The compiler for Teal, a typed dialect of Lua
Stars: ✭ 716 (+1690%)
Mutual labels:  type-checking
Caer
High-performance Vision library in Python. Scale your research, not boilerplate.
Stars: ✭ 452 (+1030%)
Mutual labels:  type-checking
Rules terraform
Bazel rules for using Hashicorp's Terraform in your Bazel builds.
Stars: ✭ 26 (-35%)
Mutual labels:  bazel
Objectmodel
Strong Dynamically Typed Object Modeling for JavaScript
Stars: ✭ 415 (+937.5%)
Mutual labels:  type-checking
Startup Os
Working examples of Google's Open Source stack and deployment to the cloud.
Stars: ✭ 564 (+1310%)
Mutual labels:  bazel
Platforms
Constraint values for specifying platforms and toolchains
Stars: ✭ 34 (-15%)
Mutual labels:  bazel
Rules go
Go rules for Bazel
Stars: ✭ 852 (+2030%)
Mutual labels:  bazel
Rules docker
Rules for building and handling Docker images with Bazel
Stars: ✭ 744 (+1760%)
Mutual labels:  bazel

bazel-mypy-integration

Integrate MyPy type-checking into your Python Bazel builds.


⚠️ This software is now in 'production' use, but still in the PRE-RELEASE PHASE and under active development. Please give it a try, and ⭐️ or watch the repo to follow progress ⚠️


mypy is an incremental type system for Python. Incremental type systems arguably become essential when Python codebases grow to be very large [1, 2, 3, 4]. As Bazel is a build system designed for very large codebases, it makes sense that they should work together to help a Python codebase scale.

With bazel-mypy-integration, type errors are flagged as bazel build errors, so that teams can be sure their type-checking is being respected.

Usage

Aspect-based

It's recommended that you register this integration's Aspect to run everytime you build Python code. To do that you can add the following to your .bazelrc:

build --aspects @mypy_integration//:mypy.bzl%mypy_aspect
build --output_groups=+mypy

But if you want to invoke the integration directly, you can do so with:

bazel build --aspects @mypy_integration//:mypy.bzl%mypy_aspect --output_groups=mypy  //my/python/code/...

If there's a typing error in your Python code, then your build will fail. You'll see something like:

ERROR: /Users/jonathonbelotti/Code/thundergolfer/bazel-mypy-integration/examples/hangman/BUILD:1:1: 
MyPy hangman/hangman_dummy_out failed (Exit 1) hangman_mypy_exe failed: error executing command bazel-out/darwin-fastbuild/bin/hangman/hangman_mypy_exe

Use --sandbox_debug to see verbose messages from the sandbox
hangman/hangman.py:52: error: Syntax error in type annotation
hangman/hangman.py:52: note: Suggestion: Use Tuple[T1, ..., Tn] instead of (T1, ..., Tn)
Found 1 error in 1 file (checked 1 source file)
INFO: Elapsed time: 2.026s, Critical Path: 1.85s
INFO: 1 process: 1 darwin-sandbox.
FAILED: Build did NOT complete successfully

mypy_test rule-based

An alternative to registering the Aspect is to use the mypy_test rule which will run MyPy when the target run with bazel test.

load("@mypy_integration//:mypy.bzl", "mypy_test")

mypy_test(
    name = "foo_mypy_test",
    deps = [
        ":foo", # py_[library, binary, test] target
    ],
)

If there's a typing error in your Python code, then the test will fail. Using --test_output=all will ensure the MyPy error is visible in the console.

Installation

1. Create a file that will specify the version of mypy to use. You will pass the Bazel label for this file to the deps() function in @mypy_integration//repositories:deps.bzl, which below is named mypy_integration_deps(...):

mypy==0.750

(In the examples/ Bazel workspace this file is specified in tools/typing/)

2. Next, add the following to your WORKSPACE:

mypy_integration_version = "0.1.0" # latest @ November 15th 2020

http_archive(
    name = "mypy_integration",
    sha256 = "511ca642294129b7abebf6afd48aa63e7d91de3ec5fa0689d60d1dc6a94a7d1a",
    strip_prefix = "bazel-mypy-integration-{version}".format(version = mypy_integration_version),
    url = "https://github.com/thundergolfer/bazel-mypy-integration/archive/{version}.tar.gz".format(
        version = mypy_integration_version,
    ),
)

load(
    "@mypy_integration//repositories:repositories.bzl",
    mypy_integration_repositories = "repositories",
)
mypy_integration_repositories()

load("@mypy_integration//:config.bzl", "mypy_configuration")
# Optionally pass a MyPy config file, otherwise pass no argument.
mypy_configuration("//tools/typing:mypy.ini")

load("@mypy_integration//repositories:deps.bzl", mypy_integration_deps = "deps")

mypy_integration_deps(
    mypy_requirements_file="//tools/typing:mypy_version.txt",
)

Note that by default mypy_integration_deps will default to passing "python3" as the interpreter used at install, but this can be overridden by setting python_interpreter or python_interpreter_target (but not both).

3. Finally, if using the Bazel Aspect, add the following to your .bazelrc so that MyPy checking is run whenever Python code is built:

build --aspects @mypy_integration//:mypy.bzl%mypy_aspect
build --output_groups=+mypy

3b. If using the Bazel rule, you'll add to a BUILD file something like:

load("@mypy_integration//:mypy.bzl", "mypy_test")

py_binary(
    name = "foo",
    srcs = glob(["foopy"]),
    main = "foo.py",
    python_version = "PY3",
    deps = [],
)

mypy_test(
    name = "foo_mypy",
    deps = [
        ":foo",
    ],
)

Configuration

To support the MyPy configuration file you can add the following to your WORKSPACE:

load("@mypy_integration//:config.bzl", "mypy_configuration")

mypy_configuration("//tools/typing:mypy.ini")

where //tools/typing:mypy.ini is a valid MyPy config file.

πŸ›  Development

Testing

./test.sh runs some basic integration tests. Right now, running the integration in the Bazel workspace in examples/ tests a lot more functionality but can't automatically test failure cases.

Adopters

Here's a (non-exhaustive) list of companies that use bazel-mypy-integration in production. Don't see yours? You can add it in a PR!

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].