//python:packaging.bzl

Public API for for building wheels.

py_package

py_package(name, deps=[], packages=[])

A rule to select all files in transitive dependencies of deps which belong to given set of Python packages.

This rule is intended to be used as data dependency to py_wheel rule.

Provides: no providers advertised.

ATTRIBUTES

name:

(required Name) A unique name for this target.

deps:

(optional list of labels, default [])

packages:

(optional list of string, default []) List of Python packages to include in the distribution. Sub-packages are automatically included.

py_wheel

py_wheel(name, twine=None, publish_args=[], kwargs)

Builds a Python Wheel.

Wheels are Python distribution format defined in https://www.python.org/dev/peps/pep-0427/.

This macro packages a set of targets into a single wheel. It wraps the py_wheel rule.

Currently only pure-python wheels are supported.

Examples:

# Package some specific py_library targets, without their dependencies
py_wheel(
    name = "minimal_with_py_library",
    # Package data. We're building "example_minimal_library-0.0.1-py3-none-any.whl"
    distribution = "example_minimal_library",
    python_tag = "py3",
    version = "0.0.1",
    deps = [
        "//examples/wheel/lib:module_with_data",
        "//examples/wheel/lib:simple_module",
    ],
)

# Use py_package to collect all transitive dependencies of a target,
# selecting just the files within a specific python package.
py_package(
    name = "example_pkg",
    # Only include these Python packages.
    packages = ["examples.wheel"],
    deps = [":main"],
)

py_wheel(
    name = "minimal_with_py_package",
    # Package data. We're building "example_minimal_package-0.0.1-py3-none-any.whl"
    distribution = "example_minimal_package",
    python_tag = "py3",
    version = "0.0.1",
    deps = [":example_pkg"],
)

To publish the wheel to PyPI, the twine package is required. rules_python doesn’t provide twine itself, see [https://github.com/bazelbuild/rules_python/issues/1016]. However you can install it with pip_parse, just like we do in the WORKSPACE file in rules_python.

Once you’ve installed twine, you can pass its label to the twine attribute of this macro, to get a “[name].publish” target.

Example:

py_wheel(
    name = "my_wheel",
    twine = "@publish_deps_twine//:pkg",
    ...
)

Now you can run a command like the following, which publishes to https://test.pypi.org/

% TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-*** \
    bazel run --stamp --embed_label=1.2.4 -- \
    //path/to:my_wheel.publish --repository testpypi

PARAMETERS

name:

A unique name for this target.

twine:

(default None) A label of the external location of the py_library target for twine

publish_args:

(default []) arguments passed to twine, e.g. [”–repository-url”, “https://pypi.my.org/simple/”]. These are subject to make var expansion, as with the args attribute. Note that you can also pass additional args to the bazel run command as in the example above.

kwargs:

other named parameters passed to the underlying py_wheel rule

py_wheel_dist

py_wheel_dist(name, out, wheel=None)

Prepare a dist/ folder, following Python’s packaging standard practice.

See https://packaging.python.org/en/latest/tutorials/packaging-projects/#generating-distribution-archives which recommends a dist/ folder containing the wheel file(s), source distributions, etc.

This also has the advantage that stamping information is included in the wheel’s filename.

Provides: no providers advertised.

ATTRIBUTES

name:

(required Name) A unique name for this target.

out:

(required string) name of the resulting directory

wheel:

(optional label, default None) a py_wheel target

Required providers: PyWheelInfo

py_wheel_rule

py_wheel_rule(name, deps=[], abi=”none”, distribution, platform=”any”, python_tag=”py3”, stamp=-1, version, extra_requires={}, extra_requires_files={}, requires=[], requires_file=None, console_scripts={}, entry_points={}, author=””, author_email=””, classifiers=[], description_content_type=””, description_file=None, extra_distinfo_files={}, homepage=””, license=””, project_urls={}, python_requires=””, strip_path_prefixes=[], summary=””)

Internal rule used by the py_wheel macro.

These intentionally have the same name to avoid sharp edges with Bazel macros. For example, a bazel query for a user’s py_wheel macro expands to py_wheel targets, in the way they expect.

Provides: no providers advertised.

ATTRIBUTES

name:

(required Name) A unique name for this target.

deps:

(optional list of labels, default []) Targets to be included in the distribution.

The targets to package are usually py_library rules or filesets (for packaging data files).

Note it’s usually better to package py_library targets and use entry_points attribute to specify console_scripts than to package py_binary rules. py_binary targets would wrap a executable script that tries to locate .runfiles directory which is not packaged in the wheel.

abi:

(optional string, default "none") Python ABI tag. ‘none’ for pure-Python wheels.

distribution:

(required string) Name of the distribution.

This should match the project name onm PyPI. It’s also the name that is used to refer to the package in other packages’ dependencies.

Workspace status keys are expanded using {NAME} format, for example:

  • distribution = "package.{CLASSIFIER}"

  • distribution = "{DISTRIBUTION}"

For the available keys, see https://bazel.build/docs/user-manual#workspace-status

platform:

(optional string, default "any") Supported platform. Use ‘any’ for pure-Python wheel.

If you have included platform-specific data, such as a .pyd or .so extension module, you will need to specify the platform in standard pip format. If you support multiple platforms, you can define platform constraints, then use a select() to specify the appropriate specifier, eg:

platform = select({     "//platforms:windows_x86_64": "win_amd64",     "//platforms:macos_x86_64": "macosx_10_7_x86_64",     "//platforms:linux_x86_64": "manylinux2014_x86_64", })

python_tag:

(optional string, default "py3") Supported Python version(s), eg py3, cp35.cp36, etc

stamp:

(optional [int][int], default -1) Whether to encode build information into the wheel. Possible values:

  • stamp = 1: Always stamp the build information into the wheel, even in –nostamp builds. This setting should be avoided, since it potentially kills remote caching for the target and any downstream actions that depend on it.

  • stamp = 0: Always replace build information by constant values. This gives good build result caching.

  • stamp = -1: Embedding of build information is controlled by the –[no]stamp flag.

Stamped targets are not rebuilt unless their dependencies change.

version:

(required string) Version number of the package.

Note that this attribute supports stamp format strings as well as ‘make variables’. For example:

  • version = "1.2.3-{BUILD_TIMESTAMP}"

  • version = "{BUILD_EMBED_LABEL}"

  • version = "$(VERSION)"

Note that Bazel’s output filename cannot include the stamp information, as outputs must be known during the analysis phase and the stamp data is available only during the action execution.

The py_wheel macro produces a .dist-suffix target which creates a dist/ folder containing the wheel with the stamped name, suitable for publishing.

See py_wheel_dist for more info.

extra_requires:

(optional dict of string to list of string, default {}) A mapping of extras options to lists of requirements (similar to requires). This attribute is mutually exclusive with extra_requires_file.

extra_requires_files:

(optional dict of label to string, default {}) A mapping of requirements files (similar to requires_file) to the name of an extras option This attribute is mutually exclusive with extra_requires.

requires:

(optional list of string, default []) List of requirements for this package. See the section on Declaring required dependency for details and examples of the format of this argument. This attribute is mutually exclusive with requires_file.

requires_file:

(optional label, default None) A file containing a list of requirements for this package. See the section on Declaring required dependency for details and examples of the format of this argument. This attribute is mutually exclusive with requires.

console_scripts:

(optional dict of string to string, default {}) Deprecated console_script entry points, e.g. {'main': 'examples.wheel.main:main'}.

Deprecated: prefer the entry_points attribute, which supports console_scripts as well as other entry points.

entry_points:

(optional dict of string to list of string, default {}) entry_points, e.g. {'console_scripts': ['main = examples.wheel.main:main']}.

author:

(optional string, default "") A string specifying the author of the package.

author_email:

(optional string, default "") A string specifying the email address of the package author.

classifiers:

(optional list of string, default []) A list of strings describing the categories for the package. For valid classifiers see https://pypi.org/classifiers

description_content_type:

(optional string, default "") The type of contents in description_file. If not provided, the type will be inferred from the extension of description_file. Also see https://packaging.python.org/en/latest/specifications/core-metadata/#description-content-type

description_file:

(optional label, default None) A file containing text describing the package.

extra_distinfo_files:

(optional dict of label to string, default {}) Extra files to add to distinfo directory in the archive.

homepage:

(optional string, default "") A string specifying the URL for the package homepage.

license:

(optional string, default "") A string specifying the license of the package.

project_urls:

(optional dict of string to string, default {}) A string dict specifying additional browsable URLs for the project and corresponding labels, where label is the key and url is the value. e.g {{"Bug Tracker": "http://bitbucket.org/tarek/distribute/issues/"}}

python_requires:

(optional string, default "") Python versions required by this distribution, e.g. ‘>=3.5,<3.7’

strip_path_prefixes:

(optional list of string, default []) path prefixes to strip from files added to the generated package

summary:

(optional string, default "") A one-line summary of what the distribution does

PyWheelInfo

PyWheelInfo(name_file, wheel)

Information about a wheel produced by py_wheel

FIELDS

name_file:

File: A file containing the canonical name of the wheel (after stamping, if enabled).

wheel:

File: The wheel file itself.