Skip to content

Commit 522222a

Browse files
authored
Add exports for core Python logic that's bundled with Bazel (bazel-contrib#202)
* Introduce defs.bzl as the official home of the core Python rules The "core" Python rules are the rules that traditionally have been bundled with Bazel. This includes native rules like `py_binary`, and Starlark-defined rules under `@bazel_tools` like `py_runtime_pair`. These should all live in or around `@rules_python//python:defs.bzl`. Currently we re-export the native rules here, with a magic tag to allow them to survive the flag flip for `--incompatible_load_python_rules_from_bzl`. When native rules are ported to Starlark their definitions will live here. * Add re-exports for Starlark-defined symbols This adds export definitions for built-in symbols like `PyInfo` and `@bazel_tools`-defined symbols like py_runtime_pair. * Vendor in runfiles library This vendors in the @bazel_tools//tools/python/runfiles target as //python/runfiles. See comment in the BUILD file for why we couldn't re-export the bundled implementation. * Fix README to prefer defs.bzl over python.bzl
1 parent d1596a3 commit 522222a

File tree

8 files changed

+612
-11
lines changed

8 files changed

+612
-11
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Then in your `BUILD` files load the python rules with:
4646

4747
``` python
4848
load(
49-
"@rules_python//python:python.bzl",
49+
"@rules_python//python:defs.bzl",
5050
"py_binary", "py_library", "py_test",
5151
)
5252

python/BUILD

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,104 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
15+
"""This package contains two sets of rules:
16+
17+
1) the "core" Python rules, which were historically bundled with Bazel and
18+
are now either re-exported or copied into this repository; and
19+
20+
2) the packaging rules, which were historically simply known as
21+
rules_python.
22+
23+
In an ideal renaming, we'd move the packaging rules to a different package so
24+
that @rules_python//python is only concerned with the core rules.
25+
"""
26+
1427
package(default_visibility = ["//visibility:public"])
1528

1629
licenses(["notice"]) # Apache 2.0
1730

31+
# ========= Core rules =========
32+
33+
exports_files([
34+
"defs.bzl",
35+
"python.bzl", # Deprecated, please use defs.bzl
36+
])
37+
38+
# This target can be used to inspect the current Python major version. To use,
39+
# put it in the `flag_values` attribute of a `config_setting` and test it
40+
# against the values "PY2" or "PY3". It will always match one or the other.
41+
#
42+
# If you do not need to test any other flags in combination with the Python
43+
# version, then as a convenience you may use the predefined `config_setting`s
44+
# `@rules_python//python:PY2` and `@rules_python//python:PY3`.
45+
#
46+
# Example usage:
47+
#
48+
# config_setting(
49+
# name = "py3_on_arm",
50+
# values = {"cpu": "arm"},
51+
# flag_values = {"@rules_python//python:python_version": "PY3"},
52+
# )
53+
#
54+
# my_target(
55+
# ...
56+
# some_attr = select({
57+
# ":py3_on_arm": ...,
58+
# ...
59+
# }),
60+
# ...
61+
# )
62+
#
63+
# Caution: Do not `select()` on the built-in command-line flags `--force_python`
64+
# or `--python_version`, as they do not always reflect the true Python version
65+
# of the current target. `select()`-ing on them can lead to action conflicts and
66+
# will be disallowed.
67+
alias(
68+
name = "python_version",
69+
actual = "@bazel_tools//tools/python:python_version",
70+
)
71+
72+
alias(
73+
name = "PY2",
74+
actual = "@bazel_tools//tools/python:PY2",
75+
)
76+
77+
alias(
78+
name = "PY3",
79+
actual = "@bazel_tools//tools/python:PY3",
80+
)
81+
82+
# The toolchain type for Python rules. Provides a Python 2 and/or Python 3
83+
# runtime.
84+
alias(
85+
name = "toolchain_type",
86+
actual = "@bazel_tools//tools/python:toolchain_type",
87+
)
88+
89+
# Definitions for a Python toolchain that, at execution time, attempts to detect
90+
# a platform runtime having the appropriate major Python version. Consider this
91+
# a toolchain of last resort.
92+
#
93+
# The non-strict version allows using a Python 2 interpreter for PY3 targets,
94+
# and vice versa. The only reason to use this is if you're working around
95+
# spurious failures due to PY2 vs PY3 validation. Even then, using this is only
96+
# safe if you know for a fact that your build is completely compatible with the
97+
# version of the `python` command installed on the target platform.
98+
99+
alias(
100+
name = "autodetecting_toolchain",
101+
actual = "@bazel_tools//tools/python:autodetecting_toolchain",
102+
)
103+
104+
alias(
105+
name = "autodetecting_toolchain_nonstrict",
106+
actual = "@bazel_tools//tools/python:autodetecting_toolchain_nonstrict",
107+
)
108+
109+
# ========= Packaging rules =========
110+
18111
exports_files([
19112
"pip.bzl",
20-
"python.bzl",
21113
"whl.bzl",
22114
])

python/constraints/BUILD

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright 2019 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
package(default_visibility = ["//visibility:public"])
16+
17+
licenses(["notice"])
18+
19+
# A constraint_setting to use for constraints related to the location of the
20+
# system Python 2 interpreter on a platform.
21+
alias(
22+
name = "py2_interpreter_path",
23+
actual = "@bazel_tools//tools/python:py2_interpreter_path",
24+
)
25+
26+
# A constraint_setting to use for constraints related to the location of the
27+
# system Python 3 interpreter on a platform.
28+
alias(
29+
name = "py3_interpreter_path",
30+
actual = "@bazel_tools//tools/python:py3_interpreter_path",
31+
)

python/defs.bzl

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Copyright 2019 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Core rules for building Python projects.
16+
17+
Currently the definitions here are re-exports of the native rules, "blessed" to
18+
work under `--incompatible_load_python_rules_from_bzl`. As the native rules get
19+
migrated to Starlark, their implementations will be moved here.
20+
"""
21+
22+
load("@bazel_tools//tools/python:toolchain.bzl", _py_runtime_pair = "py_runtime_pair")
23+
load("@bazel_tools//tools/python:srcs_version.bzl", _find_requirements = "find_requirements")
24+
load(":private/reexports.bzl", "internal_PyInfo", "internal_PyRuntimeInfo")
25+
26+
# Exports of native-defined providers.
27+
28+
PyInfo = internal_PyInfo
29+
30+
PyRuntimeInfo = internal_PyRuntimeInfo
31+
32+
# The implementation of the macros and tagging mechanism follows the example
33+
# set by rules_cc and rules_java.
34+
35+
_MIGRATION_TAG = "__PYTHON_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__"
36+
37+
def _add_tags(attrs):
38+
if "tags" in attrs and attrs["tags"] != None:
39+
attrs["tags"] += [_MIGRATION_TAG]
40+
else:
41+
attrs["tags"] = [_MIGRATION_TAG]
42+
return attrs
43+
44+
def py_library(**attrs):
45+
"""See the Bazel core [py_library](
46+
https://docs.bazel.build/versions/master/be/python.html#py_library)
47+
documentation.
48+
49+
Args:
50+
**attrs: Rule attributes
51+
"""
52+
native.py_library(**_add_tags(attrs))
53+
54+
def py_binary(**attrs):
55+
"""See the Bazel core [py_binary](
56+
https://docs.bazel.build/versions/master/be/python.html#py_binary)
57+
documentation.
58+
59+
Args:
60+
**attrs: Rule attributes
61+
"""
62+
native.py_binary(**_add_tags(attrs))
63+
64+
def py_test(**attrs):
65+
"""See the Bazel core [py_test](
66+
https://docs.bazel.build/versions/master/be/python.html#py_test)
67+
documentation.
68+
69+
Args:
70+
**attrs: Rule attributes
71+
"""
72+
native.py_test(**_add_tags(attrs))
73+
74+
def py_runtime(**attrs):
75+
"""See the Bazel core [py_runtime](
76+
https://docs.bazel.build/versions/master/be/python.html#py_runtime)
77+
documentation.
78+
79+
Args:
80+
**attrs: Rule attributes
81+
"""
82+
native.py_runtime(**_add_tags(attrs))
83+
84+
# Re-exports of Starlark-defined symbols in @bazel_tools//tools/python.
85+
86+
py_runtime_pair = _py_runtime_pair
87+
88+
find_requirements = _find_requirements

python/private/reexports.bzl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright 2019 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Internal re-exports of built-in symbols.
16+
17+
We want to re-export a built-in symbol as if it were defined in a Starlark
18+
file, so that users can for instance do:
19+
20+
```
21+
load("@rules_python//python:defs.bzl", "PyInfo")
22+
```
23+
24+
Unfortunately, we can't just write in defs.bzl
25+
26+
```
27+
PyInfo = PyInfo
28+
```
29+
30+
because the declaration of module-level symbol `PyInfo` makes the builtin
31+
inaccessible. So instead we access the builtin here and export it under a
32+
different name. Then we can load it from defs.bzl and export it there under
33+
the original name.
34+
"""
35+
36+
# Don't use underscore prefix, since that would make the symbol local to this
37+
# file only.
38+
39+
internal_PyInfo = PyInfo
40+
internal_PyRuntimeInfo = PyRuntimeInfo

python/python.bzl

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,44 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
"""Re-exports for some of the core Bazel Python rules.
16+
17+
This file is deprecated; please use the exports in defs.bzl instead. This is to
18+
follow the new naming convention of putting core rules for a language
19+
underneath @rules_<LANG>//<LANG>:defs.bzl. The exports in this file will be
20+
disallowed in a future Bazel release by
21+
`--incompatible_load_python_rules_from_bzl`.
22+
"""
23+
1524
def py_library(*args, **kwargs):
16-
"""See the Bazel core py_library documentation.
25+
"""See the Bazel core [py_library](
26+
https://docs.bazel.build/versions/master/be/python.html#py_library)
27+
documentation.
1728
18-
[available here](
19-
https://docs.bazel.build/versions/master/be/python.html#py_library).
29+
Deprecated: This symbol will become unusuable when
30+
`--incompatible_load_python_rules_from_bzl` is enabled. Please use the
31+
symbols in `@rules_python//python:defs.bzl` instead.
2032
"""
2133
native.py_library(*args, **kwargs)
2234

2335
def py_binary(*args, **kwargs):
24-
"""See the Bazel core py_binary documentation.
36+
"""See the Bazel core [py_binary](
37+
https://docs.bazel.build/versions/master/be/python.html#py_binary)
38+
documentation.
2539
26-
[available here](
27-
https://docs.bazel.build/versions/master/be/python.html#py_binary).
40+
Deprecated: This symbol will become unusuable when
41+
`--incompatible_load_python_rules_from_bzl` is enabled. Please use the
42+
symbols in `@rules_python//python:defs.bzl` instead.
2843
"""
2944
native.py_binary(*args, **kwargs)
3045

3146
def py_test(*args, **kwargs):
32-
"""See the Bazel core py_test documentation.
47+
"""See the Bazel core [py_test](
48+
https://docs.bazel.build/versions/master/be/python.html#py_test)
49+
documentation.
3350
34-
[available here](
35-
https://docs.bazel.build/versions/master/be/python.html#py_test).
51+
Deprecated: This symbol will become unusuable when
52+
`--incompatible_load_python_rules_from_bzl` is enabled. Please use the
53+
symbols in `@rules_python//python:defs.bzl` instead.
3654
"""
3755
native.py_test(*args, **kwargs)

python/runfiles/BUILD

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2019 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
# We'd like to alias the runfiles target @bazel_tools//tools/python/runfiles.
17+
# However, we need its source file to exist in the runfiles tree under this
18+
# repo's name, so that it can be imported as
19+
#
20+
# from rules_python.python.runfiles import runfiles
21+
#
22+
# in user code. This requires either adding a symlink to runfiles or copying
23+
# the file with an action.
24+
#
25+
# Both solutions are made more difficult by the fact that runfiles.py is not
26+
# directly exported by its package. We could try to get a handle on its File
27+
# object by unpacking the runfiles target's providers, but this seems hacky
28+
# and is probably more effort than it's worth. Also, it's not trivial to copy
29+
# files in a cross-platform (i.e. Windows-friendly) way.
30+
#
31+
# So instead, we just vendor in runfiles.py here.
32+
33+
load("//python:defs.bzl", "py_library")
34+
35+
py_library(
36+
name = "runfiles",
37+
srcs = ["runfiles.py"],
38+
visibility = ["//visibility:public"],
39+
)

0 commit comments

Comments
 (0)