Skip to main content
Version: 2.2 (deprecated)

Adopting Pants in existing repos

Tips for how to incrementally add Pants to your repository.


We recommend using an incremental migration to adopt Pants, as it will help to ensure that your builds keep behaving how you'd expect.

Joining Slack

We would love to help you with adopting Pants. Please reach out through Slack.

1. A basic pants.toml

Follow the Getting Started guide to install Pants and set up an initial pants.toml. Validate that running ./pants count-loc '**' works properly.

Add backend_packages = ["pants.backend.python"] to the [GLOBAL] section.

2. Set up formatters/linters with basic BUILD files

Formatters and linters are often the simplest to get working because—for all tools other than Pylint— you do not need to worry about things like dependencies and third-party requirements.

First, create a BUILD file in each directory with Python code. As explained in Targets and BUILD files, you can use fewer BUILD files, such as one BUILD file per subproject: but if using coarser grained BUILD files, make sure that all Python source code is included in some target's sources parameter (either by explicitly selecting files or with sources=["**/*.py"]). We find that using one BUILD file per directory is a good default.

If your directory only contains production code, use python_library:

python_library()

If your directory only contains tests, use python_tests:

python_tests()

If your directory contains both production code and tests, use both:

python_library()

python_tests(name="tests")

Unless you want to change the default values, such as setting timeouts for your tests, you can simply use these 1-3 lines in each BUILD file.

Then, activate the Python Linters and formatters you'd like to use. Hook up the fmt and lint goals to your CI.

3. Set up tests

To get tests working, you will first need to set up third-party dependencies. We strongly recommend setting up a lockfile for reproducibility and better performance.

Pants's dependency inference will infer most dependencies for you by looking at your Python import statements. Generally, you will not need to update your BUILD files any more than the previous step.

However, if your tests depend on any resource files, you will need to explicitly declare these dependencies because Pants cannot infer them. See Resources.

Try running ./pants test :: in CI to see if any tests fail. Sometimes, your tests will fail with Pants even if they pass with your normal setup because tests are more isolated than when running Pytest/unittest directly:

  • Tests run in a chroot, meaning they can only access dependencies that Pants knows about. If you have a missing file or missing import, run ./pants dependencies path/to/my_test.py and ./pants dependencies --transitive path/to/my_test.py to confirm what you are expecting is known by Pants. If not, add to the dependencies field.
  • Test files are isolated from each other. If your tests depended on running in a certain order, they may now fail. This requires rewriting your tests to remove the shared global state.

In your CI, you may want to speed up your build by having Pants only run tests for changed files. Refer to Using Pants in CI.

4. Set up ./pants package

You can use ./pants package to package your code into various formats, such as a PEX binary, a wheel, an AWS Lambda, or a zip/tar archive.

We recommend manually verifying that this step is working how you'd like by inspecting the built packages. Alternatively, you can write automated tests that will call the equivalent of ./pants package for you, and insert the built package into your test environment.

5. Check out writing a plugin

Pants is highly extensible. In fact, all of Pants's core functionality is implemented using the exact same API used by plugins.

Check out Plugins Overview. We'd also love to help in the #plugins channel on Slack.

Some example plugins that users have written:

  • Cython support
  • Building a Docker image with packages built via ./pants package
  • Custom setup.py logic to compute the version dynamically
  • Jupyter support

Migrating from other BUILD tools? Set custom BUILD file names

If you're migrating from another build tool that already uses the name BUILD, such as Bazel or Please, you can tell Pants to use a different file name than BUILD to avoid conflicts:

pants.toml
[GLOBAL]
build_patterns = ["BUILD.pants"]

Alternatively, you can tell Pants to not look for BUILD files in certain locations. This can be helpful, for example, if you use a tool like Bazel for Java, but use Pants for Python:

pants.toml
[GLOBAL]
build_ignore = ["src/java"]