When your Python code imports Thrift generated files, Pants will detect the imports and run the Apache Thrift compiler to generate those files.
Example repository
See [the codegen example repository](🔗) for an example of using Thrift to generate Python.
Benefit of Pants: generated files are always up-to-date
With Pants, there's no need to manually regenerate your code or check it into version control. Pants will ensure you are always using up-to-date files in your builds.
Thanks to fine-grained caching, Pants will regenerate the minimum amount of code required when you do make changes.
## Step 1: Activate the Thrift Python backend
Add this to your `pants.toml
`:
You will also need to make sure that `thrift
` is discoverable on your PATH, as Pants does not [install Thrift](🔗) for you. Alternatively, you can tell Pants where to discover Thrift:
This backend adds the new [`thrift_source
`](🔗) target, which you can confirm by running `./pants help thrift_source
`.
To reduce boilerplate, you can also use the [`thrift_sources
`](🔗) target, which generates one `thrift_source
` target per file in the `sources
` field.
## Step 2: Set up the `thrift
` runtime library
Generated Python files require the [`thrift
` dependency](🔗) for their imports to work properly.
Add `thrift
` to your project, e.g. your `requirements.txt
` (see [Third-party dependencies](🔗)).
Pants will then automatically add these dependencies to your `thrift_sources
` targets created in the next step.
## Step 3: Generate `thrift_sources
` target
Run [`./pants tailor ::
`](🔗) for Pants to create a `thrift_sources
` target wherever you have `.thrift
` files:
Pants will use [dependency inference](🔗) for any `import
` statements in your `.thrift
` files, which you can confirm by running `./pants dependencies path/to/file.thrift
`. You should also see the `python_requirement
` target for the `thrift
` library from the previous step.
## Step 4: Confirm Python imports are working
Now, you can import the generated Python modules in your Python code.
For each Thrift file, the compiler will generate at least three files `__init__.py
`, `ttypes.py
`, and `constants.py
`. The location of those files—and corresponding imports—depends on whether you set `namespace py
` in your `.thrift
` file:
`namespace py ` | Behavior | Example |
unset | Files generated as top-level modules, without any prefix directories. | `models/user.thrift `
Generated:
- `__init__.py `
- `user/__init__.py `
- `user/constants.py `
- `user/ttypes.py `Python import:
`import user.ttypes ` |
set | Files generated into the namespace. | `models/user.thrift `, with `namespace py custom_namespace.user `
Generated:
- `__init__.py `
- `custom_namespace/__init__.py `
- `custom_namespace/user/__init__.py `
- `custom_namespace/user/constants.py `
- `custom_namespace/user/ttypes.py `Python import:
`import custom_namespace.user.ttypes ` |
As shown in the table, your Python imports depend on whether the Thrift file uses `namespace py
`.
Imports behave the same regardless of whether you have [source roots](🔗), such as `src/thrift
`. The import will still either be the top-level file like `user.ttypes
` or the custom namespace.
Pants's dependency inference will detect Python imports of Thrift modules, which you can confirm by running `./pants dependencies path/to/file.py
`.
You can also [manually add](🔗) the dependency:
TIp: set `
namespace py
`Pants can handle Thrift regardless of whether you set `
namespace py
`.However, it's often a good idea to set the namespace because it can make your imports more predictable and declarative. It also reduces the risk of your Thrift file names conflicting with other Python modules used, such as those from third-party requirements.
For example, compare `
import user.ttypes
` to `import codegen.models.user.ttypes
`.
Run `
./pants export-codegen ::
` to inspect the files`
./pants export-codegen ::
` will run all relevant code generators and write the files to `dist/codegen
` using the same paths used normally by Pants.You do not need to run this goal for codegen to work when using Pants; `
export-codegen
` is only for external consumption outside of Pants.
## Multiple resolves
If you're using [multiple resolves](🔗) (i.e. multiple lockfiles), then you may need to set the `python_resolve
` field. `thrift_source
` targets only work with a single resolve, meaning, for example, that a `python_source
` target that uses the resolve 'a' can only depend on Thrift targets that also uses this same resolve.
By default, `thrift_source
` / `thrift_sources
` targets use the resolve set by the option `[python].default_resolve
`. To use a different resolve, set the field `python_resolve: str
` to one of the values from the option `[python].resolves
`.
You must also make sure that any resolves that use codegen include the `python_requirement
` target for the `thrift
` runtime library from Step 2. Pants will eagerly validate this for you.
If the same Thrift files should work with multiple resolves, you can use the
[`parametrize
`](🔗) mechanism.
For example: