Pants Developers Guide

This page describes the developer workflow when changing Pants itself. (If you wanted instructions for using Pants to develop other programs, please see First Tutorial.)

These instructions assume you've already downloaded the source code.

Running from sources

As pants is implemented in python it can be run directly from sources.

$ ./pants goals
<remainder of output omitted for brevity>

If you want to run pants from sources, but in another repo to test changes before a release, you can run it like so:

(other repo) $ PANTS_PLUGINS="[]" \
  PANTS_PYTHONPATH="['/path/to/pants/repo/contrib/python/src/python']" \
  PANTS_BACKEND_PACKAGES="['pants.contrib.python.checks']" \
  /path/to/pants/repo/pants compile ::

You may hit an error with version mismatch:

...
Exception message: Version mismatch: Requested version was 1.1.0, our version is 1.2.0-dev0.

If so, you can add a PANTS_VERSION environment variable like so:

(other repo) $ PANTS_PLUGINS="[]" \
  PANTS_PYTHONPATH="['/path/to/pants/repo/contrib/python/src/python']" \
  PANTS_BACKEND_PACKAGES="['pants.contrib.python.checks']" \
  PANTS_VERSION=1.2.0-dev0 \
  /path/to/pants/repo/pants compile ::

Here the environment variables are used to make sure any pants plugins your other repo uses will also be run from pants sources. Explaining each environment variable:

  • PANTS_PLUGINS: This should always be as-shown, ie: an empty list.
  • PANTS_PYTHONPATH: This is a comma-separated list of PYTHONPATH elements. The values can be taken from the pants repo pants.ini. You'll need one path per plugin your other repo uses.
  • PANTS_BACKEND_PACKAGES: This is a comma-separated list of plugin package names. These values can also be taken from the pants repo pants.ini. You'll need one package name per plugin your other repo uses.
  • PANTS_VERSION: The version of pants required by the repo.

If your other repo uses plugins but you don't use this environment variable technique, or you do use it but miss one or more plugins, pants will still run, but the result can be confusing since the plugins not covered by the environment variable settings will run from a cached binary distribution and not from your local edits to pants. It's worth adding temporary print statements to make sure you're hitting your code edits if you aren't using a debugger.

Building Pants PEX for Production

You will usually want to use an official published version of pants. But what if you want to let some of your internal users try out the latest and greatest unreleased code? What if you want to create a custom build of pants with some unpublished patches? In that case, you want to build a production ready version of pants including dependencies for all platforms, not just your development environment.

In the following examples, you'll be using 2 local repos. The path to the pantsbuild/pants clone will be /tmp/pantsbuild and the path to your repo /your/repo in all the examples below; make sure to substitute your own paths when adapting this recipe to your environment.

You'll need to setup some files one-time in your own repo:

$ cat pants-production.requirements.txt
# Replace this path with the path to your pantsbuild.pants clone.
-f /tmp/pantsbuild/dist/
pantsbuild.pants

$ cat BUILD.pants-production
python_requirements('pants-production.requirements.txt')

python_binary(
  name='pants',
  entry_point='pants.bin.pants_loader:main',
  # You may want to tweak the list of supported platforms to match your environment.
  platforms=[
    'current',
    'linux-x86_64',
    'macosx-10.4-x86_64',
  ],
  # You may want to adjust the python interpreter constraints, but note that pants requires
  # python2.7 currently.
  compatibility='CPython>=2.7,<3',
  dependencies=[
    ':pantsbuild.pants',
    # List any other pants backend local or remote deps here, ie:
    # ':pantsbuild.pants.contrib.go' or 'src/python/your/pants/plugin'
  ]
)

$ cat pants-production.ini
[python-repos]
# You should replace these repos with your own housing pre-built eggs or wheels for the
# platforms you support.
repos: [
    "https://pantsbuild.github.io/cheeseshop/third_party/python/dist/index.html",
    "https://pantsbuild.github.io/cheeseshop/third_party/python/index.html"
  ]

indexes: ["https://pypi.python.org/simple/"]

To (re-)generate a pants.pex you then run these 2 commands:

  1. In your pantsbuild/pants clone, create a local pants release from master:

    $ rm -rf dist && ./build-support/bin/release.sh -n
    
  2. In your own repo the following command will create a locally built pants.pex for all platforms:

    $ /tmp/pantsbuild/pants --pants-config-files=pants-production.ini clean-all binary //:pants
    

The resulting pants.pex will be in the dist/ directory:

$ ls -l dist/pants.pex
-rwxr-xr-x  1 pantsdev  pantsdev  5561254 Oct  8 09:52 dist/pants.pex

You can see that the pex contains bundled dependencies for both mac and linux:

$ unzip -l dist/pants.pex | grep -e 'macos\|linux'

You can distribute the resulting pants.pex file to your users via your favorite method. A user can just copy this pex to the top of their Pants workspace and use it:

$ cp /mnt/fd0/pants.pex .
$ ./pants.pex goal test examples/tests/java/org/pantsbuild/example/hello/greet:

Testing

Running Tests

Pants has many tests. There are BUILD targets to run those tests. We try to keep them passing. A Travis-CI job runs tests on each SHA pushed to origin on github.com/pantsbuild/pants.

Most test are runnable as regular Pants test targets. To find tests that work with a particular feature, you might explore tests/python/pants_tests/.../BUILD.

Before contributing a change to Pants, make sure it passes all of our continuous integration (CI) tests: everything builds, all tests pass. To try all the CI tests in a few configurations, you can run the same script that our Travis CI does. This can take a while, but it's a good idea to run it before you contribute a change or merge it to master:

$ ./build-support/bin/ci.sh

To run just Pants' unit tests (skipping the can-be-slow integration tests), filter out the python tests tagged with 'integration':

$ ./pants test tests/python/pants_test:: --tag=-integration

For convenience, this is wrapped up in a script build-support/bin/unit-test.sh.

If you only want to run tests for changed targets, then you can use the test-changed goal:

$ ./pants test-changed

You can run your code through the Travis-CI before you submit a change. Travis-CI is integrated with the pull requests for the pantsbuild/pants repo. Travis-CI will test it soon after the pull request is created. It will queue up a new job every time you subsequently push your branch.

To kick off a new CI-build, push a branch to your fork of pantsbuild/pants. Create a pull request on the pantsbuild/pants repo, not your fork. If you are posting a review request, put the pull request number into the Bug field. Then, when you close the request, you can navigate from the bug number to easily close the pull request.

Debugging

To run Pants under pdb and set a breakpoint, you can typically add

import pdb; pdb.set_trace()

...where you first want to break. If the code is in a test, instead use

import pytest; pytest.set_trace()

To run tests and bring up pdb for failing tests, you can instead pass --pdb to test.pytest --options:

$ ./pants test.pytest --options='--pdb' tests/python/pants_test/tasks:
... plenty of test output ...
tests/python/pants_test/tasks/test_targets_help.py E
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

cls = <class 'pants_test.tasks.test_targets_help.TargetsHelpTest'>

    @classmethod
    def setUpClass(cls):
>     super(TargetsHelpTest, cls).setUpClass()
E     AttributeError: 'super' object has no attribute 'setUpClass'

tests/python/pants_test/tasks/test_targets_help.py:24: AttributeError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> /Users/lhosken/workspace/pants/tests/python/pants_test/tasks/test_targets_help.py(24)setUpClass()
-> super(TargetsHelpTest, cls).setUpClass()
(Pdb)

Debug quickly; that test target will time out in a couple of minutes, quitting you out.

To start an interactive Python shell that can import Pants modules, use the usual ./pants repl on a python_library target that builds (or depends on) the modules you want:

$ ./pants repl src/python/pants/build_graph
/Users/lhosken/workspace/pants src/python/pants/build_graph
Python 2.6.8 (unknown, Mar  9 2014, 22:16:00)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from pants.build_graph.target import Target
>>>

Developing and Debugging a JVM Tool

Some Pants tools are written in Java and Scala. If you need to debug one of these tools and change code, keep in mind that these tools don't run straight from the Pants source tree. They expect their jar dependencies to be resolved through external jar dependencies. This means that to use a development version of a tool you will need to adjust the external dependency information in BUILD.tools to point Pants at a development version of your jar file.

First, create a jar file for the tool with the binary goal.

$ ./pants binary src/java/org/pantsbuild/tools/jar:main

The above command will create dist/jar-tool.jar according to the jvm_binary target defined in src/java/org/pantsbuild/tools/jar/BUILD

You'll need to update the jar dependency that this tool uses for Pants to see the development version. See Using a SNAPSHOT JVM Dependency which describes how to specify the url and mutable attributes of a jar dependency found on the local filesystem:

jar_library(name='jar-tool',
    jars=[
      jar(org='org.pantsbuild', name='jar-tool', rev='1.2.3-SNAPSHOT',
          url='file:///Users/squarepants/Src/pants/dist/jar-tool.jar', mutable=True),
  ],
)

For debugging, append JVM args to turn on the debugger for the appropriate tool in pants.ini:

[jar-tool]
jvm_options: ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005']

Note that most tools run under nailgun by default. The easiest way to debug them is to disable nailgun by specifying the command line option --no-use-nailgun or setting use_nailgun: False in the specific tool section or in the [DEFAULT] section of pants.ini.

[DEFAULT]
use_nailgun: False

JVM Tool Development Tips

If you need to debug the tool under nailgun, make sure you run pants goal ng-killall or pants goal clean-all after you update the jar file so that any running nailgun servers are restarted on the next invocation of Pants.

Also, you may need to clean up some additional state when testing a tool. Some tools cache a shaded version under ~/.cache/pants/artifact_cache/. Clear out the cache before testing a new version of the tool as follows:

$ rm -rf ~/.cache/pants/artifact_cache

If you have trouble resolving the file with Ivy after making the above changes to BUILD.tools:

  • Make sure your url is absolute and contains three slashes (///) at the start of the path.
  • If your repo has an ivysettings.xml file (the pants repo currently does not), try adding a minimal <filesystem> resolver that doesn't enforce a pom being present as follows:

    <resolvers>
      <chain name="chain-repos" returnFirst="true">
        <filesystem name="internal"></filesystem>
        ...
      </chain>
    </resolvers>
    
Generated by publish_docs from dist/markdown/html/src/docs/howto_develop.html 2018-05-03T17:02:30.125575