Skip to content

Commit 2d34f6c

Browse files
authored
refactor: move PyInfo into separate file (bazel-contrib#2249)
Both PyInfo and providers.bzl are fairly large, and some upcoming PRs will be adding more PyInfo-specific code. To keep them manageable, move PyInfo into its own file.
1 parent 387c2f6 commit 2d34f6c

File tree

10 files changed

+148
-112
lines changed

10 files changed

+148
-112
lines changed

python/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ bzl_library(
167167
name = "py_info_bzl",
168168
srcs = ["py_info.bzl"],
169169
deps = [
170+
"//python/private:py_info_bzl",
170171
"//python/private:reexports_bzl",
171-
"//python/private/common:providers_bzl",
172172
"@rules_python_internal//:rules_python_config_bzl",
173173
],
174174
)

python/private/BUILD.bazel

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,15 @@ bzl_library(
266266
srcs = ["py_executable_info.bzl"],
267267
)
268268

269+
bzl_library(
270+
name = "py_info_bzl",
271+
srcs = ["py_info.bzl"],
272+
deps = [
273+
":reexports_bzl",
274+
":util_bzl",
275+
],
276+
)
277+
269278
bzl_library(
270279
name = "py_interpreter_program_bzl",
271280
srcs = ["py_interpreter_program.bzl"],

python/private/common/BUILD.bazel

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ bzl_library(
2929
srcs = ["attributes.bzl"],
3030
deps = [
3131
":common_bzl",
32-
":providers_bzl",
3332
":py_internal_bzl",
3433
":semantics_bzl",
3534
"//python/private:enum_bzl",
3635
"//python/private:flags_bzl",
36+
"//python/private:py_info_bzl",
3737
"//python/private:reexports_bzl",
3838
"//python/private:rules_cc_srcs_bzl",
3939
"@bazel_skylib//rules:common_settings",
@@ -68,6 +68,7 @@ bzl_library(
6868
":providers_bzl",
6969
":py_internal_bzl",
7070
":semantics_bzl",
71+
"//python/private:py_info_bzl",
7172
"//python/private:reexports_bzl",
7273
"//python/private:rules_cc_srcs_bzl",
7374
],
@@ -133,6 +134,7 @@ bzl_library(
133134
":py_internal_bzl",
134135
"//python/private:flags_bzl",
135136
"//python/private:py_executable_info_bzl",
137+
"//python/private:py_info_bzl",
136138
"//python/private:rules_cc_srcs_bzl",
137139
"//python/private:toolchain_types_bzl",
138140
"@bazel_skylib//lib:dicts",

python/private/common/attributes.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
1717
load("@rules_cc//cc:defs.bzl", "CcInfo")
1818
load("//python/private:enum.bzl", "enum")
1919
load("//python/private:flags.bzl", "PrecompileFlag", "PrecompileSourceRetentionFlag")
20+
load("//python/private:py_info.bzl", "PyInfo")
2021
load("//python/private:reexports.bzl", "BuiltinPyInfo")
2122
load(":common.bzl", "union_attrs")
22-
load(":providers.bzl", "PyInfo")
2323
load(":py_internal.bzl", "py_internal")
2424
load(
2525
":semantics.bzl",

python/private/common/common.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
# limitations under the License.
1414
"""Various things common to Bazel and Google rule implementations."""
1515

16+
load("//python/private:py_info.bzl", "PyInfo")
1617
load("//python/private:reexports.bzl", "BuiltinPyInfo")
1718
load(":cc_helper.bzl", "cc_helper")
18-
load(":providers.bzl", "PyInfo")
1919
load(":py_internal.bzl", "py_internal")
2020
load(
2121
":semantics.bzl",

python/private/common/providers.bzl

Lines changed: 3 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,14 @@
1414
"""Providers for Python rules."""
1515

1616
load("@rules_cc//cc:defs.bzl", "CcInfo")
17-
load("//python/private:util.bzl", "IS_BAZEL_6_OR_HIGHER")
17+
load("//python/private:util.bzl", "define_bazel_6_provider")
1818

1919
DEFAULT_STUB_SHEBANG = "#!/usr/bin/env python3"
2020

2121
DEFAULT_BOOTSTRAP_TEMPLATE = Label("//python/private:bootstrap_template")
2222

2323
_PYTHON_VERSION_VALUES = ["PY2", "PY3"]
2424

25-
# Helper to make the provider definitions not crash under Bazel 5.4:
26-
# Bazel 5.4 doesn't support the `init` arg of `provider()`, so we have to
27-
# not pass that when using Bazel 5.4. But, not passing the `init` arg
28-
# changes the return value from a two-tuple to a single value, which then
29-
# breaks Bazel 6+ code.
30-
# This isn't actually used under Bazel 5.4, so just stub out the values
31-
# to get past the loading phase.
32-
def _define_provider(doc, fields, **kwargs):
33-
if not IS_BAZEL_6_OR_HIGHER:
34-
return provider("Stub, not used", fields = []), None
35-
return provider(doc = doc, fields = fields, **kwargs)
36-
3725
def _optional_int(value):
3826
return int(value) if value != None else None
3927

@@ -133,9 +121,7 @@ def _PyRuntimeInfo_init(
133121
"zip_main_template": zip_main_template,
134122
}
135123

136-
# TODO(#15897): Rename this to PyRuntimeInfo when we're ready to replace the Java
137-
# implemented provider with the Starlark one.
138-
PyRuntimeInfo, _unused_raw_py_runtime_info_ctor = _define_provider(
124+
PyRuntimeInfo, _unused_raw_py_runtime_info_ctor = define_bazel_6_provider(
139125
doc = """Contains information about a Python runtime, as returned by the `py_runtime`
140126
rule.
141127
@@ -314,102 +300,13 @@ The following substitutions are made during template expansion:
314300
},
315301
)
316302

317-
def _check_arg_type(name, required_type, value):
318-
value_type = type(value)
319-
if value_type != required_type:
320-
fail("parameter '{}' got value of type '{}', want '{}'".format(
321-
name,
322-
value_type,
323-
required_type,
324-
))
325-
326-
def _PyInfo_init(
327-
*,
328-
transitive_sources,
329-
uses_shared_libraries = False,
330-
imports = depset(),
331-
has_py2_only_sources = False,
332-
has_py3_only_sources = False,
333-
direct_pyc_files = depset(),
334-
transitive_pyc_files = depset()):
335-
_check_arg_type("transitive_sources", "depset", transitive_sources)
336-
337-
# Verify it's postorder compatible, but retain is original ordering.
338-
depset(transitive = [transitive_sources], order = "postorder")
339-
340-
_check_arg_type("uses_shared_libraries", "bool", uses_shared_libraries)
341-
_check_arg_type("imports", "depset", imports)
342-
_check_arg_type("has_py2_only_sources", "bool", has_py2_only_sources)
343-
_check_arg_type("has_py3_only_sources", "bool", has_py3_only_sources)
344-
_check_arg_type("direct_pyc_files", "depset", direct_pyc_files)
345-
_check_arg_type("transitive_pyc_files", "depset", transitive_pyc_files)
346-
return {
347-
"direct_pyc_files": direct_pyc_files,
348-
"has_py2_only_sources": has_py2_only_sources,
349-
"has_py3_only_sources": has_py2_only_sources,
350-
"imports": imports,
351-
"transitive_pyc_files": transitive_pyc_files,
352-
"transitive_sources": transitive_sources,
353-
"uses_shared_libraries": uses_shared_libraries,
354-
}
355-
356-
PyInfo, _unused_raw_py_info_ctor = _define_provider(
357-
doc = "Encapsulates information provided by the Python rules.",
358-
init = _PyInfo_init,
359-
fields = {
360-
"direct_pyc_files": """
361-
:type: depset[File]
362-
363-
Precompiled Python files that are considered directly provided
364-
by the target.
365-
""",
366-
"has_py2_only_sources": """
367-
:type: bool
368-
369-
Whether any of this target's transitive sources requires a Python 2 runtime.
370-
""",
371-
"has_py3_only_sources": """
372-
:type: bool
373-
374-
Whether any of this target's transitive sources requires a Python 3 runtime.
375-
""",
376-
"imports": """\
377-
:type: depset[str]
378-
379-
A depset of import path strings to be added to the `PYTHONPATH` of executable
380-
Python targets. These are accumulated from the transitive `deps`.
381-
The order of the depset is not guaranteed and may be changed in the future. It
382-
is recommended to use `default` order (the default).
383-
""",
384-
"transitive_pyc_files": """
385-
:type: depset[File]
386-
387-
Direct and transitive precompiled Python files that are provided by the target.
388-
""",
389-
"transitive_sources": """\
390-
:type: depset[File]
391-
392-
A (`postorder`-compatible) depset of `.py` files appearing in the target's
393-
`srcs` and the `srcs` of the target's transitive `deps`.
394-
""",
395-
"uses_shared_libraries": """
396-
:type: bool
397-
398-
Whether any of this target's transitive `deps` has a shared library file (such
399-
as a `.so` file).
400-
401-
This field is currently unused in Bazel and may go away in the future.
402-
""",
403-
},
404-
)
405-
406303
def _PyCcLinkParamsProvider_init(cc_info):
407304
return {
408305
"cc_info": CcInfo(linking_context = cc_info.linking_context),
409306
}
410307

411308
# buildifier: disable=name-conventions
412-
PyCcLinkParamsProvider, _unused_raw_py_cc_link_params_provider_ctor = _define_provider(
309+
PyCcLinkParamsProvider, _unused_raw_py_cc_link_params_provider_ctor = define_bazel_6_provider(
413310
doc = ("Python-wrapper to forward {obj}`CcInfo.linking_context`. This is to " +
414311
"allow Python targets to propagate C++ linking information, but " +
415312
"without the Python target appearing to be a valid C++ rule dependency"),

python/private/common/py_executable.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
1919
load("@rules_cc//cc:defs.bzl", "cc_common")
2020
load("//python/private:flags.bzl", "PrecompileAddToRunfilesFlag")
2121
load("//python/private:py_executable_info.bzl", "PyExecutableInfo")
22+
load("//python/private:py_info.bzl", "PyInfo")
2223
load("//python/private:reexports.bzl", "BuiltinPyRuntimeInfo")
2324
load(
2425
"//python/private:toolchain_types.bzl",
@@ -52,7 +53,6 @@ load(
5253
load(
5354
":providers.bzl",
5455
"PyCcLinkParamsProvider",
55-
"PyInfo",
5656
"PyRuntimeInfo",
5757
)
5858
load(":py_internal.bzl", "py_internal")

python/private/py_info.bzl

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Copyright 2024 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+
"""Implementation of PyInfo provider and PyInfo-specific utilities."""
15+
16+
load(":util.bzl", "define_bazel_6_provider")
17+
18+
def _check_arg_type(name, required_type, value):
19+
"""Check that a value is of an expected type."""
20+
value_type = type(value)
21+
if value_type != required_type:
22+
fail("parameter '{}' got value of type '{}', want '{}'".format(
23+
name,
24+
value_type,
25+
required_type,
26+
))
27+
28+
def _PyInfo_init(
29+
*,
30+
transitive_sources,
31+
uses_shared_libraries = False,
32+
imports = depset(),
33+
has_py2_only_sources = False,
34+
has_py3_only_sources = False,
35+
direct_pyc_files = depset(),
36+
transitive_pyc_files = depset()):
37+
_check_arg_type("transitive_sources", "depset", transitive_sources)
38+
39+
# Verify it's postorder compatible, but retain is original ordering.
40+
depset(transitive = [transitive_sources], order = "postorder")
41+
42+
_check_arg_type("uses_shared_libraries", "bool", uses_shared_libraries)
43+
_check_arg_type("imports", "depset", imports)
44+
_check_arg_type("has_py2_only_sources", "bool", has_py2_only_sources)
45+
_check_arg_type("has_py3_only_sources", "bool", has_py3_only_sources)
46+
_check_arg_type("direct_pyc_files", "depset", direct_pyc_files)
47+
_check_arg_type("transitive_pyc_files", "depset", transitive_pyc_files)
48+
49+
return {
50+
"direct_pyc_files": direct_pyc_files,
51+
"has_py2_only_sources": has_py2_only_sources,
52+
"has_py3_only_sources": has_py2_only_sources,
53+
"imports": imports,
54+
"transitive_pyc_files": transitive_pyc_files,
55+
"transitive_sources": transitive_sources,
56+
"uses_shared_libraries": uses_shared_libraries,
57+
}
58+
59+
PyInfo, _unused_raw_py_info_ctor = define_bazel_6_provider(
60+
doc = "Encapsulates information provided by the Python rules.",
61+
init = _PyInfo_init,
62+
fields = {
63+
"direct_pyc_files": """
64+
:type: depset[File]
65+
66+
Precompiled Python files that are considered directly provided
67+
by the target and **must be included**.
68+
69+
These files usually come from, e.g., a library setting {attr}`precompile=enabled`
70+
to forcibly enable precompiling for itself. Downstream binaries are expected
71+
to always include these files, as the originating target expects them to exist.
72+
""",
73+
"has_py2_only_sources": """
74+
:type: bool
75+
76+
Whether any of this target's transitive sources requires a Python 2 runtime.
77+
""",
78+
"has_py3_only_sources": """
79+
:type: bool
80+
81+
Whether any of this target's transitive sources requires a Python 3 runtime.
82+
""",
83+
"imports": """\
84+
:type: depset[str]
85+
86+
A depset of import path strings to be added to the `PYTHONPATH` of executable
87+
Python targets. These are accumulated from the transitive `deps`.
88+
The order of the depset is not guaranteed and may be changed in the future. It
89+
is recommended to use `default` order (the default).
90+
""",
91+
"transitive_pyc_files": """
92+
:type: depset[File]
93+
94+
The transitive set of precompiled files that must be included.
95+
96+
These files usually come from, e.g., a library setting {attr}`precompile=enabled`
97+
to forcibly enable precompiling for itself. Downstream binaries are expected
98+
to always include these files, as the originating target expects them to exist.
99+
""",
100+
"transitive_sources": """\
101+
:type: depset[File]
102+
103+
A (`postorder`-compatible) depset of `.py` files appearing in the target's
104+
`srcs` and the `srcs` of the target's transitive `deps`.
105+
""",
106+
"uses_shared_libraries": """
107+
:type: bool
108+
109+
Whether any of this target's transitive `deps` has a shared library file (such
110+
as a `.so` file).
111+
112+
This field is currently unused in Bazel and may go away in the future.
113+
""",
114+
},
115+
)

python/private/util.bzl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ def add_tag(attrs, tag):
8484
else:
8585
attrs["tags"] = [tag]
8686

87+
# Helper to make the provider definitions not crash under Bazel 5.4:
88+
# Bazel 5.4 doesn't support the `init` arg of `provider()`, so we have to
89+
# not pass that when using Bazel 5.4. But, not passing the `init` arg
90+
# changes the return value from a two-tuple to a single value, which then
91+
# breaks Bazel 6+ code.
92+
# This isn't actually used under Bazel 5.4, so just stub out the values
93+
# to get past the loading phase.
94+
def define_bazel_6_provider(doc, fields, **kwargs):
95+
"""Define a provider, or a stub for pre-Bazel 7."""
96+
if not IS_BAZEL_6_OR_HIGHER:
97+
return provider("Stub, not used", fields = []), None
98+
return provider(doc = doc, fields = fields, **kwargs)
99+
87100
IS_BAZEL_7_OR_HIGHER = hasattr(native, "starlark_doc_extract")
88101

89102
# Bazel 5.4 has a bug where every access of testing.ExecutionInfo is a

python/py_info.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"""Public entry point for PyInfo."""
1616

1717
load("@rules_python_internal//:rules_python_config.bzl", "config")
18+
load("//python/private:py_info.bzl", _starlark_PyInfo = "PyInfo")
1819
load("//python/private:reexports.bzl", "BuiltinPyInfo")
19-
load("//python/private/common:providers.bzl", _starlark_PyInfo = "PyInfo")
2020

2121
PyInfo = _starlark_PyInfo if config.enable_pystar else BuiltinPyInfo

0 commit comments

Comments
 (0)