Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: move PyInfo into separate file #2249

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion python/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ bzl_library(
name = "py_info_bzl",
srcs = ["py_info.bzl"],
deps = [
"//python/private:py_info_bzl",
"//python/private:reexports_bzl",
"//python/private/common:providers_bzl",
"@rules_python_internal//:rules_python_config_bzl",
],
)
Expand Down
9 changes: 9 additions & 0 deletions python/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,15 @@ bzl_library(
srcs = ["py_executable_info.bzl"],
)

bzl_library(
name = "py_info_bzl",
srcs = ["py_info.bzl"],
deps = [
":reexports_bzl",
":util_bzl",
],
)

bzl_library(
name = "py_interpreter_program_bzl",
srcs = ["py_interpreter_program.bzl"],
Expand Down
4 changes: 3 additions & 1 deletion python/private/common/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ bzl_library(
srcs = ["attributes.bzl"],
deps = [
":common_bzl",
":providers_bzl",
":py_internal_bzl",
":semantics_bzl",
"//python/private:enum_bzl",
"//python/private:flags_bzl",
"//python/private:py_info_bzl",
"//python/private:reexports_bzl",
"//python/private:rules_cc_srcs_bzl",
"@bazel_skylib//rules:common_settings",
Expand Down Expand Up @@ -68,6 +68,7 @@ bzl_library(
":providers_bzl",
":py_internal_bzl",
":semantics_bzl",
"//python/private:py_info_bzl",
"//python/private:reexports_bzl",
"//python/private:rules_cc_srcs_bzl",
],
Expand Down Expand Up @@ -133,6 +134,7 @@ bzl_library(
":py_internal_bzl",
"//python/private:flags_bzl",
"//python/private:py_executable_info_bzl",
"//python/private:py_info_bzl",
"//python/private:rules_cc_srcs_bzl",
"//python/private:toolchain_types_bzl",
"@bazel_skylib//lib:dicts",
Expand Down
2 changes: 1 addition & 1 deletion python/private/common/attributes.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@rules_cc//cc:defs.bzl", "CcInfo")
load("//python/private:enum.bzl", "enum")
load("//python/private:flags.bzl", "PrecompileFlag", "PrecompileSourceRetentionFlag")
load("//python/private:py_info.bzl", "PyInfo")
load("//python/private:reexports.bzl", "BuiltinPyInfo")
load(":common.bzl", "union_attrs")
load(":providers.bzl", "PyInfo")
load(":py_internal.bzl", "py_internal")
load(
":semantics.bzl",
Expand Down
2 changes: 1 addition & 1 deletion python/private/common/common.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
# limitations under the License.
"""Various things common to Bazel and Google rule implementations."""

load("//python/private:py_info.bzl", "PyInfo")
load("//python/private:reexports.bzl", "BuiltinPyInfo")
load(":cc_helper.bzl", "cc_helper")
load(":providers.bzl", "PyInfo")
load(":py_internal.bzl", "py_internal")
load(
":semantics.bzl",
Expand Down
109 changes: 3 additions & 106 deletions python/private/common/providers.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,14 @@
"""Providers for Python rules."""

load("@rules_cc//cc:defs.bzl", "CcInfo")
load("//python/private:util.bzl", "IS_BAZEL_6_OR_HIGHER")
load("//python/private:util.bzl", "define_bazel_6_provider")

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

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

_PYTHON_VERSION_VALUES = ["PY2", "PY3"]

# Helper to make the provider definitions not crash under Bazel 5.4:
# Bazel 5.4 doesn't support the `init` arg of `provider()`, so we have to
# not pass that when using Bazel 5.4. But, not passing the `init` arg
# changes the return value from a two-tuple to a single value, which then
# breaks Bazel 6+ code.
# This isn't actually used under Bazel 5.4, so just stub out the values
# to get past the loading phase.
def _define_provider(doc, fields, **kwargs):
if not IS_BAZEL_6_OR_HIGHER:
return provider("Stub, not used", fields = []), None
return provider(doc = doc, fields = fields, **kwargs)

def _optional_int(value):
return int(value) if value != None else None

Expand Down Expand Up @@ -133,9 +121,7 @@ def _PyRuntimeInfo_init(
"zip_main_template": zip_main_template,
}

# TODO(#15897): Rename this to PyRuntimeInfo when we're ready to replace the Java
# implemented provider with the Starlark one.
PyRuntimeInfo, _unused_raw_py_runtime_info_ctor = _define_provider(
PyRuntimeInfo, _unused_raw_py_runtime_info_ctor = define_bazel_6_provider(
doc = """Contains information about a Python runtime, as returned by the `py_runtime`
rule.

Expand Down Expand Up @@ -314,102 +300,13 @@ The following substitutions are made during template expansion:
},
)

def _check_arg_type(name, required_type, value):
value_type = type(value)
if value_type != required_type:
fail("parameter '{}' got value of type '{}', want '{}'".format(
name,
value_type,
required_type,
))

def _PyInfo_init(
*,
transitive_sources,
uses_shared_libraries = False,
imports = depset(),
has_py2_only_sources = False,
has_py3_only_sources = False,
direct_pyc_files = depset(),
transitive_pyc_files = depset()):
_check_arg_type("transitive_sources", "depset", transitive_sources)

# Verify it's postorder compatible, but retain is original ordering.
depset(transitive = [transitive_sources], order = "postorder")

_check_arg_type("uses_shared_libraries", "bool", uses_shared_libraries)
_check_arg_type("imports", "depset", imports)
_check_arg_type("has_py2_only_sources", "bool", has_py2_only_sources)
_check_arg_type("has_py3_only_sources", "bool", has_py3_only_sources)
_check_arg_type("direct_pyc_files", "depset", direct_pyc_files)
_check_arg_type("transitive_pyc_files", "depset", transitive_pyc_files)
return {
"direct_pyc_files": direct_pyc_files,
"has_py2_only_sources": has_py2_only_sources,
"has_py3_only_sources": has_py2_only_sources,
"imports": imports,
"transitive_pyc_files": transitive_pyc_files,
"transitive_sources": transitive_sources,
"uses_shared_libraries": uses_shared_libraries,
}

PyInfo, _unused_raw_py_info_ctor = _define_provider(
doc = "Encapsulates information provided by the Python rules.",
init = _PyInfo_init,
fields = {
"direct_pyc_files": """
:type: depset[File]

Precompiled Python files that are considered directly provided
by the target.
""",
"has_py2_only_sources": """
:type: bool

Whether any of this target's transitive sources requires a Python 2 runtime.
""",
"has_py3_only_sources": """
:type: bool

Whether any of this target's transitive sources requires a Python 3 runtime.
""",
"imports": """\
:type: depset[str]

A depset of import path strings to be added to the `PYTHONPATH` of executable
Python targets. These are accumulated from the transitive `deps`.
The order of the depset is not guaranteed and may be changed in the future. It
is recommended to use `default` order (the default).
""",
"transitive_pyc_files": """
:type: depset[File]

Direct and transitive precompiled Python files that are provided by the target.
""",
"transitive_sources": """\
:type: depset[File]

A (`postorder`-compatible) depset of `.py` files appearing in the target's
`srcs` and the `srcs` of the target's transitive `deps`.
""",
"uses_shared_libraries": """
:type: bool

Whether any of this target's transitive `deps` has a shared library file (such
as a `.so` file).

This field is currently unused in Bazel and may go away in the future.
""",
},
)

def _PyCcLinkParamsProvider_init(cc_info):
return {
"cc_info": CcInfo(linking_context = cc_info.linking_context),
}

# buildifier: disable=name-conventions
PyCcLinkParamsProvider, _unused_raw_py_cc_link_params_provider_ctor = _define_provider(
PyCcLinkParamsProvider, _unused_raw_py_cc_link_params_provider_ctor = define_bazel_6_provider(
doc = ("Python-wrapper to forward {obj}`CcInfo.linking_context`. This is to " +
"allow Python targets to propagate C++ linking information, but " +
"without the Python target appearing to be a valid C++ rule dependency"),
Expand Down
2 changes: 1 addition & 1 deletion python/private/common/py_executable.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@rules_cc//cc:defs.bzl", "cc_common")
load("//python/private:flags.bzl", "PrecompileAddToRunfilesFlag")
load("//python/private:py_executable_info.bzl", "PyExecutableInfo")
load("//python/private:py_info.bzl", "PyInfo")
load("//python/private:reexports.bzl", "BuiltinPyRuntimeInfo")
load(
"//python/private:toolchain_types.bzl",
Expand Down Expand Up @@ -52,7 +53,6 @@ load(
load(
":providers.bzl",
"PyCcLinkParamsProvider",
"PyInfo",
"PyRuntimeInfo",
)
load(":py_internal.bzl", "py_internal")
Expand Down
115 changes: 115 additions & 0 deletions python/private/py_info.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Copyright 2024 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Implementation of PyInfo provider and PyInfo-specific utilities."""

load(":util.bzl", "define_bazel_6_provider")

def _check_arg_type(name, required_type, value):
"""Check that a value is of an expected type."""
value_type = type(value)
if value_type != required_type:
fail("parameter '{}' got value of type '{}', want '{}'".format(
name,
value_type,
required_type,
))

def _PyInfo_init(
*,
transitive_sources,
uses_shared_libraries = False,
imports = depset(),
has_py2_only_sources = False,
has_py3_only_sources = False,
direct_pyc_files = depset(),
transitive_pyc_files = depset()):
_check_arg_type("transitive_sources", "depset", transitive_sources)

# Verify it's postorder compatible, but retain is original ordering.
depset(transitive = [transitive_sources], order = "postorder")

_check_arg_type("uses_shared_libraries", "bool", uses_shared_libraries)
_check_arg_type("imports", "depset", imports)
_check_arg_type("has_py2_only_sources", "bool", has_py2_only_sources)
_check_arg_type("has_py3_only_sources", "bool", has_py3_only_sources)
_check_arg_type("direct_pyc_files", "depset", direct_pyc_files)
_check_arg_type("transitive_pyc_files", "depset", transitive_pyc_files)

return {
"direct_pyc_files": direct_pyc_files,
"has_py2_only_sources": has_py2_only_sources,
"has_py3_only_sources": has_py2_only_sources,
"imports": imports,
"transitive_pyc_files": transitive_pyc_files,
"transitive_sources": transitive_sources,
"uses_shared_libraries": uses_shared_libraries,
}

PyInfo, _unused_raw_py_info_ctor = define_bazel_6_provider(
doc = "Encapsulates information provided by the Python rules.",
init = _PyInfo_init,
fields = {
"direct_pyc_files": """
:type: depset[File]

Precompiled Python files that are considered directly provided
by the target and **must be included**.

These files usually come from, e.g., a library setting {attr}`precompile=enabled`
to forcibly enable precompiling for itself. Downstream binaries are expected
to always include these files, as the originating target expects them to exist.
""",
"has_py2_only_sources": """
:type: bool

Whether any of this target's transitive sources requires a Python 2 runtime.
""",
"has_py3_only_sources": """
:type: bool

Whether any of this target's transitive sources requires a Python 3 runtime.
""",
"imports": """\
:type: depset[str]

A depset of import path strings to be added to the `PYTHONPATH` of executable
Python targets. These are accumulated from the transitive `deps`.
The order of the depset is not guaranteed and may be changed in the future. It
is recommended to use `default` order (the default).
""",
"transitive_pyc_files": """
:type: depset[File]

The transitive set of precompiled files that must be included.

These files usually come from, e.g., a library setting {attr}`precompile=enabled`
to forcibly enable precompiling for itself. Downstream binaries are expected
to always include these files, as the originating target expects them to exist.
""",
"transitive_sources": """\
:type: depset[File]

A (`postorder`-compatible) depset of `.py` files appearing in the target's
`srcs` and the `srcs` of the target's transitive `deps`.
""",
"uses_shared_libraries": """
:type: bool

Whether any of this target's transitive `deps` has a shared library file (such
as a `.so` file).

This field is currently unused in Bazel and may go away in the future.
""",
},
)
13 changes: 13 additions & 0 deletions python/private/util.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@ def add_tag(attrs, tag):
else:
attrs["tags"] = [tag]

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

IS_BAZEL_7_OR_HIGHER = hasattr(native, "starlark_doc_extract")

# Bazel 5.4 has a bug where every access of testing.ExecutionInfo is a
Expand Down
2 changes: 1 addition & 1 deletion python/py_info.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"""Public entry point for PyInfo."""

load("@rules_python_internal//:rules_python_config.bzl", "config")
load("//python/private:py_info.bzl", _starlark_PyInfo = "PyInfo")
load("//python/private:reexports.bzl", "BuiltinPyInfo")
load("//python/private/common:providers.bzl", _starlark_PyInfo = "PyInfo")

PyInfo = _starlark_PyInfo if config.enable_pystar else BuiltinPyInfo