xref: /aosp_15_r20/external/bazelbuild-rules_python/python/private/pypi/attrs.bzl (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1*60517a1eSAndroid Build Coastguard Worker# Copyright 2023 The Bazel Authors. All rights reserved.
2*60517a1eSAndroid Build Coastguard Worker#
3*60517a1eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*60517a1eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*60517a1eSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*60517a1eSAndroid Build Coastguard Worker#
7*60517a1eSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*60517a1eSAndroid Build Coastguard Worker#
9*60517a1eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*60517a1eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*60517a1eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*60517a1eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*60517a1eSAndroid Build Coastguard Worker# limitations under the License.
14*60517a1eSAndroid Build Coastguard Worker
15*60517a1eSAndroid Build Coastguard Worker"common attributes for whl_library and pip_repository"
16*60517a1eSAndroid Build Coastguard Worker
17*60517a1eSAndroid Build Coastguard WorkerATTRS = {
18*60517a1eSAndroid Build Coastguard Worker    "download_only": attr.bool(
19*60517a1eSAndroid Build Coastguard Worker        doc = """
20*60517a1eSAndroid Build Coastguard WorkerWhether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of
21*60517a1eSAndroid Build Coastguard Worker--platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different
22*60517a1eSAndroid Build Coastguard Workerplatform from the host platform.
23*60517a1eSAndroid Build Coastguard Worker        """,
24*60517a1eSAndroid Build Coastguard Worker    ),
25*60517a1eSAndroid Build Coastguard Worker    "enable_implicit_namespace_pkgs": attr.bool(
26*60517a1eSAndroid Build Coastguard Worker        default = False,
27*60517a1eSAndroid Build Coastguard Worker        doc = """
28*60517a1eSAndroid Build Coastguard WorkerIf true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary
29*60517a1eSAndroid Build Coastguard Workerand py_test targets must specify either `legacy_create_init=False` or the global Bazel option
30*60517a1eSAndroid Build Coastguard Worker`--incompatible_default_to_explicit_init_py` to prevent `__init__.py` being automatically generated in every directory.
31*60517a1eSAndroid Build Coastguard Worker
32*60517a1eSAndroid Build Coastguard WorkerThis option is required to support some packages which cannot handle the conversion to pkg-util style.
33*60517a1eSAndroid Build Coastguard Worker            """,
34*60517a1eSAndroid Build Coastguard Worker    ),
35*60517a1eSAndroid Build Coastguard Worker    "environment": attr.string_dict(
36*60517a1eSAndroid Build Coastguard Worker        doc = """
37*60517a1eSAndroid Build Coastguard WorkerEnvironment variables to set in the pip subprocess.
38*60517a1eSAndroid Build Coastguard WorkerCan be used to set common variables such as `http_proxy`, `https_proxy` and `no_proxy`
39*60517a1eSAndroid Build Coastguard WorkerNote that pip is run with "--isolated" on the CLI so `PIP_<VAR>_<NAME>`
40*60517a1eSAndroid Build Coastguard Workerstyle env vars are ignored, but env vars that control requests and urllib3
41*60517a1eSAndroid Build Coastguard Workercan be passed. If you need `PIP_<VAR>_<NAME>`, take a look at `extra_pip_args`
42*60517a1eSAndroid Build Coastguard Workerand `envsubst`.
43*60517a1eSAndroid Build Coastguard Worker        """,
44*60517a1eSAndroid Build Coastguard Worker        default = {},
45*60517a1eSAndroid Build Coastguard Worker    ),
46*60517a1eSAndroid Build Coastguard Worker    "envsubst": attr.string_list(
47*60517a1eSAndroid Build Coastguard Worker        mandatory = False,
48*60517a1eSAndroid Build Coastguard Worker        doc = """\
49*60517a1eSAndroid Build Coastguard WorkerA list of environment variables to substitute (e.g. `["PIP_INDEX_URL",
50*60517a1eSAndroid Build Coastguard Worker"PIP_RETRIES"]`). The corresponding variables are expanded in `extra_pip_args`
51*60517a1eSAndroid Build Coastguard Workerusing the syntax `$VARNAME` or `${VARNAME}` (expanding to empty string if unset)
52*60517a1eSAndroid Build Coastguard Workeror `${VARNAME:-default}` (expanding to default if the variable is unset or empty
53*60517a1eSAndroid Build Coastguard Workerin the environment). Note: On Bazel 6 and Bazel 7.0 changes to the variables named
54*60517a1eSAndroid Build Coastguard Workerhere do not cause packages to be re-fetched. Don't fetch different things based
55*60517a1eSAndroid Build Coastguard Workeron the value of these variables.
56*60517a1eSAndroid Build Coastguard Worker""",
57*60517a1eSAndroid Build Coastguard Worker    ),
58*60517a1eSAndroid Build Coastguard Worker    "experimental_requirement_cycles": attr.string_list_dict(
59*60517a1eSAndroid Build Coastguard Worker        default = {},
60*60517a1eSAndroid Build Coastguard Worker        doc = """\
61*60517a1eSAndroid Build Coastguard WorkerA mapping of dependency cycle names to a list of requirements which form that cycle.
62*60517a1eSAndroid Build Coastguard Worker
63*60517a1eSAndroid Build Coastguard WorkerRequirements which form cycles will be installed together and taken as
64*60517a1eSAndroid Build Coastguard Workerdependencies together in order to ensure that the cycle is always satisified.
65*60517a1eSAndroid Build Coastguard Worker
66*60517a1eSAndroid Build Coastguard WorkerExample:
67*60517a1eSAndroid Build Coastguard Worker  `sphinx` depends on `sphinxcontrib-serializinghtml`
68*60517a1eSAndroid Build Coastguard Worker  When listing both as requirements, ala
69*60517a1eSAndroid Build Coastguard Worker
70*60517a1eSAndroid Build Coastguard Worker  ```
71*60517a1eSAndroid Build Coastguard Worker  py_binary(
72*60517a1eSAndroid Build Coastguard Worker    name = "doctool",
73*60517a1eSAndroid Build Coastguard Worker    ...
74*60517a1eSAndroid Build Coastguard Worker    deps = [
75*60517a1eSAndroid Build Coastguard Worker      "@pypi//sphinx:pkg",
76*60517a1eSAndroid Build Coastguard Worker      "@pypi//sphinxcontrib_serializinghtml",
77*60517a1eSAndroid Build Coastguard Worker     ]
78*60517a1eSAndroid Build Coastguard Worker  )
79*60517a1eSAndroid Build Coastguard Worker  ```
80*60517a1eSAndroid Build Coastguard Worker
81*60517a1eSAndroid Build Coastguard Worker  Will produce a Bazel error such as
82*60517a1eSAndroid Build Coastguard Worker
83*60517a1eSAndroid Build Coastguard Worker  ```
84*60517a1eSAndroid Build Coastguard Worker  ERROR: .../external/pypi_sphinxcontrib_serializinghtml/BUILD.bazel:44:6: in alias rule @pypi_sphinxcontrib_serializinghtml//:pkg: cycle in dependency graph:
85*60517a1eSAndroid Build Coastguard Worker      //:doctool (...)
86*60517a1eSAndroid Build Coastguard Worker      @pypi//sphinxcontrib_serializinghtml:pkg (...)
87*60517a1eSAndroid Build Coastguard Worker  .-> @pypi_sphinxcontrib_serializinghtml//:pkg (...)
88*60517a1eSAndroid Build Coastguard Worker  |   @pypi_sphinxcontrib_serializinghtml//:_pkg (...)
89*60517a1eSAndroid Build Coastguard Worker  |   @pypi_sphinx//:pkg (...)
90*60517a1eSAndroid Build Coastguard Worker  |   @pypi_sphinx//:_pkg (...)
91*60517a1eSAndroid Build Coastguard Worker  `-- @pypi_sphinxcontrib_serializinghtml//:pkg (...)
92*60517a1eSAndroid Build Coastguard Worker  ```
93*60517a1eSAndroid Build Coastguard Worker
94*60517a1eSAndroid Build Coastguard Worker  Which we can resolve by configuring these two requirements to be installed together as a cycle
95*60517a1eSAndroid Build Coastguard Worker
96*60517a1eSAndroid Build Coastguard Worker  ```
97*60517a1eSAndroid Build Coastguard Worker  pip_parse(
98*60517a1eSAndroid Build Coastguard Worker    ...
99*60517a1eSAndroid Build Coastguard Worker    experimental_requirement_cycles = {
100*60517a1eSAndroid Build Coastguard Worker      "sphinx": [
101*60517a1eSAndroid Build Coastguard Worker        "sphinx",
102*60517a1eSAndroid Build Coastguard Worker        "sphinxcontrib-serializinghtml",
103*60517a1eSAndroid Build Coastguard Worker      ]
104*60517a1eSAndroid Build Coastguard Worker    },
105*60517a1eSAndroid Build Coastguard Worker  )
106*60517a1eSAndroid Build Coastguard Worker  ```
107*60517a1eSAndroid Build Coastguard Worker
108*60517a1eSAndroid Build Coastguard WorkerWarning:
109*60517a1eSAndroid Build Coastguard Worker  If a dependency participates in multiple cycles, all of those cycles must be
110*60517a1eSAndroid Build Coastguard Worker  collapsed down to one. For instance `a <-> b` and `a <-> c` cannot be listed
111*60517a1eSAndroid Build Coastguard Worker  as two separate cycles.
112*60517a1eSAndroid Build Coastguard Worker""",
113*60517a1eSAndroid Build Coastguard Worker    ),
114*60517a1eSAndroid Build Coastguard Worker    "experimental_target_platforms": attr.string_list(
115*60517a1eSAndroid Build Coastguard Worker        default = [],
116*60517a1eSAndroid Build Coastguard Worker        doc = """\
117*60517a1eSAndroid Build Coastguard WorkerA list of platforms that we will generate the conditional dependency graph for
118*60517a1eSAndroid Build Coastguard Workercross platform wheels by parsing the wheel metadata. This will generate the
119*60517a1eSAndroid Build Coastguard Workercorrect dependencies for packages like `sphinx` or `pylint`, which include
120*60517a1eSAndroid Build Coastguard Worker`colorama` when installed and used on Windows platforms.
121*60517a1eSAndroid Build Coastguard Worker
122*60517a1eSAndroid Build Coastguard WorkerAn empty list means falling back to the legacy behaviour where the host
123*60517a1eSAndroid Build Coastguard Workerplatform is the target platform.
124*60517a1eSAndroid Build Coastguard Worker
125*60517a1eSAndroid Build Coastguard WorkerWARNING: It may not work as expected in cases where the python interpreter
126*60517a1eSAndroid Build Coastguard Workerimplementation that is being used at runtime is different between different platforms.
127*60517a1eSAndroid Build Coastguard WorkerThis has been tested for CPython only.
128*60517a1eSAndroid Build Coastguard Worker
129*60517a1eSAndroid Build Coastguard WorkerFor specific target platforms use values of the form `<os>_<arch>` where `<os>`
130*60517a1eSAndroid Build Coastguard Workeris one of `linux`, `osx`, `windows` and arch is one of `x86_64`, `x86_32`,
131*60517a1eSAndroid Build Coastguard Worker`aarch64`, `s390x` and `ppc64le`.
132*60517a1eSAndroid Build Coastguard Worker
133*60517a1eSAndroid Build Coastguard WorkerYou can also target a specific Python version by using `cp3<minor_version>_<os>_<arch>`.
134*60517a1eSAndroid Build Coastguard WorkerIf multiple python versions are specified as target platforms, then select statements
135*60517a1eSAndroid Build Coastguard Workerof the `lib` and `whl` targets will include usage of version aware toolchain config
136*60517a1eSAndroid Build Coastguard Workersettings like `@rules_python//python/config_settings:is_python_3.y`.
137*60517a1eSAndroid Build Coastguard Worker
138*60517a1eSAndroid Build Coastguard WorkerSpecial values: `host` (for generating deps for the host platform only) and
139*60517a1eSAndroid Build Coastguard Worker`<prefix>_*` values. For example, `cp39_*`, `linux_*`, `cp39_linux_*`.
140*60517a1eSAndroid Build Coastguard Worker
141*60517a1eSAndroid Build Coastguard WorkerNOTE: this is not for cross-compiling Python wheels but rather for parsing the `whl` METADATA correctly.
142*60517a1eSAndroid Build Coastguard Worker""",
143*60517a1eSAndroid Build Coastguard Worker    ),
144*60517a1eSAndroid Build Coastguard Worker    "extra_pip_args": attr.string_list(
145*60517a1eSAndroid Build Coastguard Worker        doc = """Extra arguments to pass on to pip. Must not contain spaces.
146*60517a1eSAndroid Build Coastguard Worker
147*60517a1eSAndroid Build Coastguard WorkerSupports environment variables using the syntax `$VARNAME` or
148*60517a1eSAndroid Build Coastguard Worker`${VARNAME}` (expanding to empty string if unset) or
149*60517a1eSAndroid Build Coastguard Worker`${VARNAME:-default}` (expanding to default if the variable is unset
150*60517a1eSAndroid Build Coastguard Workeror empty in the environment), if `"VARNAME"` is listed in the
151*60517a1eSAndroid Build Coastguard Worker`envsubst` attribute. See also `envsubst`.
152*60517a1eSAndroid Build Coastguard Worker""",
153*60517a1eSAndroid Build Coastguard Worker    ),
154*60517a1eSAndroid Build Coastguard Worker    "isolated": attr.bool(
155*60517a1eSAndroid Build Coastguard Worker        doc = """\
156*60517a1eSAndroid Build Coastguard WorkerWhether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to
157*60517a1eSAndroid Build Coastguard Workerthe underlying pip command. Alternatively, the {envvar}`RULES_PYTHON_PIP_ISOLATED` environment variable can be used
158*60517a1eSAndroid Build Coastguard Workerto control this flag.
159*60517a1eSAndroid Build Coastguard Worker""",
160*60517a1eSAndroid Build Coastguard Worker        default = True,
161*60517a1eSAndroid Build Coastguard Worker    ),
162*60517a1eSAndroid Build Coastguard Worker    "pip_data_exclude": attr.string_list(
163*60517a1eSAndroid Build Coastguard Worker        doc = "Additional data exclusion parameters to add to the pip packages BUILD file.",
164*60517a1eSAndroid Build Coastguard Worker    ),
165*60517a1eSAndroid Build Coastguard Worker    "python_interpreter": attr.string(
166*60517a1eSAndroid Build Coastguard Worker        doc = """\
167*60517a1eSAndroid Build Coastguard WorkerThe python interpreter to use. This can either be an absolute path or the name
168*60517a1eSAndroid Build Coastguard Workerof a binary found on the host's `PATH` environment variable. If no value is set
169*60517a1eSAndroid Build Coastguard Worker`python3` is defaulted for Unix systems and `python.exe` for Windows.
170*60517a1eSAndroid Build Coastguard Worker""",
171*60517a1eSAndroid Build Coastguard Worker        # NOTE: This attribute should not have a default. See `_get_python_interpreter_attr`
172*60517a1eSAndroid Build Coastguard Worker        # default = "python3"
173*60517a1eSAndroid Build Coastguard Worker    ),
174*60517a1eSAndroid Build Coastguard Worker    "python_interpreter_target": attr.label(
175*60517a1eSAndroid Build Coastguard Worker        allow_single_file = True,
176*60517a1eSAndroid Build Coastguard Worker        doc = """
177*60517a1eSAndroid Build Coastguard WorkerIf you are using a custom python interpreter built by another repository rule,
178*60517a1eSAndroid Build Coastguard Workeruse this attribute to specify its BUILD target. This allows pip_repository to invoke
179*60517a1eSAndroid Build Coastguard Workerpip using the same interpreter as your toolchain. If set, takes precedence over
180*60517a1eSAndroid Build Coastguard Workerpython_interpreter. An example value: "@python3_x86_64-unknown-linux-gnu//:python".
181*60517a1eSAndroid Build Coastguard Worker""",
182*60517a1eSAndroid Build Coastguard Worker    ),
183*60517a1eSAndroid Build Coastguard Worker    "quiet": attr.bool(
184*60517a1eSAndroid Build Coastguard Worker        default = True,
185*60517a1eSAndroid Build Coastguard Worker        doc = """\
186*60517a1eSAndroid Build Coastguard WorkerIf True, suppress printing stdout and stderr output to the terminal.
187*60517a1eSAndroid Build Coastguard Worker
188*60517a1eSAndroid Build Coastguard WorkerIf you would like to get more diagnostic output, set
189*60517a1eSAndroid Build Coastguard Worker{envvar}`RULES_PYTHON_REPO_DEBUG=1 <RULES_PYTHON_REPO_DEBUG>`
190*60517a1eSAndroid Build Coastguard Workeror
191*60517a1eSAndroid Build Coastguard Worker{envvar}`RULES_PYTHON_REPO_DEBUG_VERBOSITY=<INFO|DEBUG|TRACE> <RULES_PYTHON_REPO_DEBUG_VERBOSITY>`
192*60517a1eSAndroid Build Coastguard Worker""",
193*60517a1eSAndroid Build Coastguard Worker    ),
194*60517a1eSAndroid Build Coastguard Worker    # 600 is documented as default here: https://docs.bazel.build/versions/master/skylark/lib/repository_ctx.html#execute
195*60517a1eSAndroid Build Coastguard Worker    "timeout": attr.int(
196*60517a1eSAndroid Build Coastguard Worker        default = 600,
197*60517a1eSAndroid Build Coastguard Worker        doc = "Timeout (in seconds) on the rule's execution duration.",
198*60517a1eSAndroid Build Coastguard Worker    ),
199*60517a1eSAndroid Build Coastguard Worker}
200*60517a1eSAndroid Build Coastguard Worker
201*60517a1eSAndroid Build Coastguard Workerdef use_isolated(ctx, attr):
202*60517a1eSAndroid Build Coastguard Worker    """Determine whether or not to pass the pip `--isolated` flag to the pip invocation.
203*60517a1eSAndroid Build Coastguard Worker
204*60517a1eSAndroid Build Coastguard Worker    Args:
205*60517a1eSAndroid Build Coastguard Worker        ctx: repository or module context
206*60517a1eSAndroid Build Coastguard Worker        attr: attributes for the repo rule or tag extension
207*60517a1eSAndroid Build Coastguard Worker
208*60517a1eSAndroid Build Coastguard Worker    Returns:
209*60517a1eSAndroid Build Coastguard Worker        True if --isolated should be passed
210*60517a1eSAndroid Build Coastguard Worker    """
211*60517a1eSAndroid Build Coastguard Worker    use_isolated = attr.isolated
212*60517a1eSAndroid Build Coastguard Worker
213*60517a1eSAndroid Build Coastguard Worker    # The environment variable will take precedence over the attribute
214*60517a1eSAndroid Build Coastguard Worker    isolated_env = ctx.os.environ.get("RULES_PYTHON_PIP_ISOLATED", None)
215*60517a1eSAndroid Build Coastguard Worker    if isolated_env != None:
216*60517a1eSAndroid Build Coastguard Worker        if isolated_env.lower() in ("0", "false"):
217*60517a1eSAndroid Build Coastguard Worker            use_isolated = False
218*60517a1eSAndroid Build Coastguard Worker        else:
219*60517a1eSAndroid Build Coastguard Worker            use_isolated = True
220*60517a1eSAndroid Build Coastguard Worker
221*60517a1eSAndroid Build Coastguard Worker    return use_isolated
222