Skip to content
Open
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
285 changes: 174 additions & 111 deletions python/private/py_executable.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -1252,29 +1252,45 @@ def py_executable_base_impl(ctx, *, semantics, is_test, inherited_environment =

app_runfiles = exec_result.app_runfiles

return _create_providers(
ctx = ctx,
providers = []

_add_provider_default_info(
providers,
ctx,
executable = executable,
default_outputs = default_outputs.build(),
runfiles_details = runfiles_details,
)
_add_provider_instrumented_files_info(providers, ctx)
_add_provider_run_environment_info(providers, ctx, inherited_environment)
_add_provider_py_executable_info(
providers,
app_runfiles = app_runfiles,
build_data_file = runfiles_details.build_data_file,
interpreter_args = ctx.attr.interpreter_args,
interpreter_path = runtime_details.executable_interpreter_path,
main_py = main_py,
imports = imports,
runfiles_without_exe = runfiles_details.runfiles_without_exe,
stage2_bootstrap = exec_result.stage2_bootstrap,
venv_interpreter_runfiles = exec_result.venv_interpreter_runfiles,
venv_interpreter_symlinks = exec_result.venv_interpreter_symlinks,
venv_python_exe = exec_result.venv_python_exe,
)
_add_provider_py_runtime_info(providers, runtime_details)
_add_provider_py_cc_link_params_info(providers, cc_details.cc_info_for_propagating)
py_info, builtin_py_info = _add_provider_py_info(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The builtin_py_info variable is assigned here but never used in the rest of the function. Since _add_provider_py_info already appends it to the providers list if it exists, you can use _ to ignore the second return value and improve code clarity.

Suggested change
py_info, builtin_py_info = _add_provider_py_info(
py_info, _ = _add_provider_py_info(

providers,
ctx = ctx,
original_sources = direct_sources,
required_py_files = required_py_files,
required_pyc_files = required_pyc_files,
implicit_pyc_files = implicit_pyc_files,
implicit_pyc_source_files = implicit_pyc_source_files,
default_outputs = default_outputs.build(),
runtime_details = runtime_details,
cc_info = cc_details.cc_info_for_propagating,
inherited_environment = inherited_environment,
output_groups = exec_result.output_groups,
stage2_bootstrap = exec_result.stage2_bootstrap,
app_runfiles = app_runfiles,
venv_python_exe = exec_result.venv_python_exe,
venv_interpreter_runfiles = exec_result.venv_interpreter_runfiles,
venv_interpreter_symlinks = exec_result.venv_interpreter_symlinks,
interpreter_args = ctx.attr.interpreter_args,
imports = imports,
)
_add_provider_output_group_info(providers, py_info, exec_result.output_groups)

return providers

def _get_build_info(ctx, cc_toolchain):
build_info_files = py_internal.cc_toolchain_build_info_files(cc_toolchain)
Expand Down Expand Up @@ -1799,97 +1815,111 @@ def _is_tool_config(ctx):
# a more public API. Until that's available, py_internal to the rescue.
return py_internal.is_tool_configuration(ctx)

def _create_providers(
*,
ctx,
executable,
main_py,
original_sources,
required_py_files,
required_pyc_files,
implicit_pyc_files,
implicit_pyc_source_files,
default_outputs,
runfiles_details,
imports,
cc_info,
inherited_environment,
runtime_details,
output_groups,
stage2_bootstrap,
app_runfiles,
venv_python_exe,
venv_interpreter_runfiles,
venv_interpreter_symlinks,
interpreter_args):
"""Creates the providers an executable should return.
def _add_provider_default_info(providers, ctx, *, executable, default_outputs, runfiles_details):
"""Adds the DefaultInfo provider.

Args:
providers: list of providers to append to.
ctx: The rule ctx.
executable: File; the target's executable file.
main_py: File; the main .py entry point.
original_sources: `depset[File]` the direct `.py` sources for the
target that were the original input sources.
required_py_files: `depset[File]` the direct, `.py` sources for the
target that **must** be included by downstream targets. This should
only be Python source files. It should not include pyc files.
required_pyc_files: `depset[File]` the direct `.pyc` files this target
produces.
implicit_pyc_files: `depset[File]` pyc files that are only used if pyc
collection is enabled.
implicit_pyc_source_files: `depset[File]` source files for implicit pyc
files that are used when the implicit pyc files are not.
default_outputs: depset of Files; the files for DefaultInfo.files
runfiles_details: runfiles that will become the default and data runfiles.
imports: depset of strings; the import paths to propagate
cc_info: optional CcInfo; Linking information to propagate as
PyCcLinkParamsInfo. Note that only the linking information
is propagated, not the whole CcInfo.
runfiles_details: runfiles that will become the default and data runfiles.
"""
providers.append(DefaultInfo(
executable = executable,
files = default_outputs,
default_runfiles = _py_builtins.make_runfiles_respect_legacy_external_runfiles(
ctx,
runfiles_details.default_runfiles,
),
data_runfiles = _py_builtins.make_runfiles_respect_legacy_external_runfiles(
ctx,
runfiles_details.data_runfiles,
),
))

def _add_provider_instrumented_files_info(providers, ctx):
"""Adds the InstrumentedFilesInfo provider.

Args:
providers: list of providers to append to.
ctx: The rule ctx.
"""
providers.append(create_instrumented_files_info(ctx))

def _add_provider_run_environment_info(providers, ctx, inherited_environment):
"""Adds the RunEnvironmentInfo provider.

Args:
providers: list of providers to append to.
ctx: The rule ctx.
inherited_environment: list of strings; Environment variable names
that should be inherited from the environment the executuble
is run within.
runtime_details: struct of runtime information; see _get_runtime_details()
output_groups: dict[str, depset[File]]; used to create OutputGroupInfo
stage2_bootstrap: File; the stage 2 bootstrap script.
"""
expanded_env = {}
for key, value in ctx.attr.env.items():
expanded_env[key] = _py_builtins.expand_location_and_make_variables(
ctx = ctx,
attribute_name = "env[{}]".format(key),
expression = value,
targets = ctx.attr.data,
)
if "PYTHONBREAKPOINT" not in inherited_environment:
inherited_environment = inherited_environment + ["PYTHONBREAKPOINT"]
providers.append(RunEnvironmentInfo(
environment = expanded_env,
inherited_environment = inherited_environment,
))

def _add_provider_py_executable_info(
providers,
*,
app_runfiles,
build_data_file,
interpreter_args,
interpreter_path,
main_py,
runfiles_without_exe,
stage2_bootstrap,
venv_interpreter_runfiles,
venv_interpreter_symlinks,
venv_python_exe):
"""Adds the PyExecutableInfo provider.

Args:
providers: list of providers to append to.
app_runfiles: runfiles; the runfiles for the application (deps, etc).
venv_python_exe: File; the python executable in the venv.
venv_interpreter_runfiles: runfiles; runfiles specific to the interpreter
for the venv.
venv_interpreter_symlinks: depset[ExplicitSymlink]; interpreter-specific symlinks
to create for the venv.
build_data_file: File; a file with build stamp information.
interpreter_args: list of strings; arguments to pass to the interpreter.
interpreter_path: str; path to the Python interpreter.
main_py: File; the main .py entry point.
runfiles_without_exe: runfiles; the default runfiles, but without the executable.
stage2_bootstrap: File; the stage 2 bootstrap script.
venv_interpreter_runfiles: runfiles; runfiles specific to the interpreter for the venv.
venv_interpreter_symlinks: depset[ExplicitSymlink]; interpreter-specific symlinks to create for the venv.
venv_python_exe: File; the python executable in the venv.
"""
providers.append(PyExecutableInfo(
app_runfiles = app_runfiles,
build_data_file = build_data_file,
interpreter_args = interpreter_args,
interpreter_path = interpreter_path,
main = main_py,
runfiles_without_exe = runfiles_without_exe,
stage2_bootstrap = stage2_bootstrap,
venv_interpreter_runfiles = venv_interpreter_runfiles,
venv_interpreter_symlinks = venv_interpreter_symlinks,
venv_python_exe = venv_python_exe,
))

Returns:
A list of modern providers.
def _add_provider_py_runtime_info(providers, runtime_details):
"""Adds the PyRuntimeInfo provider.

Args:
providers: list of providers to append to.
runtime_details: struct of runtime information; see _get_runtime_details()
"""
providers = [
DefaultInfo(
executable = executable,
files = default_outputs,
default_runfiles = _py_builtins.make_runfiles_respect_legacy_external_runfiles(
ctx,
runfiles_details.default_runfiles,
),
data_runfiles = _py_builtins.make_runfiles_respect_legacy_external_runfiles(
ctx,
runfiles_details.data_runfiles,
),
),
create_instrumented_files_info(ctx),
_create_run_environment_info(ctx, inherited_environment),
PyExecutableInfo(
app_runfiles = app_runfiles,
build_data_file = runfiles_details.build_data_file,
interpreter_args = interpreter_args,
interpreter_path = runtime_details.executable_interpreter_path,
main = main_py,
runfiles_without_exe = runfiles_details.runfiles_without_exe,
stage2_bootstrap = stage2_bootstrap,
venv_interpreter_runfiles = venv_interpreter_runfiles,
venv_interpreter_symlinks = venv_interpreter_symlinks,
venv_python_exe = venv_python_exe,
),
]

# TODO - The effective runtime can be None for Windows + auto detecting toolchain.
# This can be removed once that's fixed; see maybe_get_runtime_from_ctx().
Expand Down Expand Up @@ -1917,13 +1947,54 @@ def _create_providers(
bootstrap_template = py_runtime_info.bootstrap_template,
))

def _add_provider_py_cc_link_params_info(providers, cc_info):
"""Adds the PyCcLinkParamsInfo provider.

Args:
providers: list of providers to append to.
cc_info: optional CcInfo; Linking information to propagate as
PyCcLinkParamsInfo. Note that only the linking information
is propagated, not the whole CcInfo.
"""

# TODO(b/163083591): Remove the PyCcLinkParamsInfo once binaries-in-deps
# are cleaned up.
if cc_info:
providers.append(
PyCcLinkParamsInfo(cc_info = cc_info),
)

def _add_provider_py_info(
providers,
*,
ctx,
original_sources,
required_py_files,
required_pyc_files,
implicit_pyc_files,
implicit_pyc_source_files,
imports):
"""Adds the PyInfo provider.

Args:
providers: list of providers to append to.
ctx: The rule ctx.
original_sources: `depset[File]` the direct `.py` sources for the
target that were the original input sources.
required_py_files: `depset[File]` the direct, `.py` sources for the
target that **must** be included by downstream targets. This should
only be Python source files. It should not include pyc files.
required_pyc_files: `depset[File]` the direct `.pyc` files this target
produces.
implicit_pyc_files: `depset[File]` pyc files that are only used if pyc
collection is enabled.
implicit_pyc_source_files: `depset[File]` source files for implicit pyc
files that are used when the implicit pyc files are not.
imports: depset of strings; the import paths to propagate

Returns:
tuple of (PyInfo, BuiltinPyInfo|None).
"""
py_info, builtin_py_info = create_py_info(
ctx,
original_sources = original_sources,
Expand All @@ -1933,28 +2004,20 @@ def _create_providers(
implicit_pyc_source_files = implicit_pyc_source_files,
imports = imports,
)

providers.append(py_info)
if builtin_py_info:
providers.append(builtin_py_info)
providers.append(create_output_group_info(py_info.transitive_sources, output_groups))
return providers
return py_info, builtin_py_info

def _create_run_environment_info(ctx, inherited_environment):
expanded_env = {}
for key, value in ctx.attr.env.items():
expanded_env[key] = _py_builtins.expand_location_and_make_variables(
ctx = ctx,
attribute_name = "env[{}]".format(key),
expression = value,
targets = ctx.attr.data,
)
if "PYTHONBREAKPOINT" not in inherited_environment:
inherited_environment = inherited_environment + ["PYTHONBREAKPOINT"]
return RunEnvironmentInfo(
environment = expanded_env,
inherited_environment = inherited_environment,
)
def _add_provider_output_group_info(providers, py_info, output_groups):
"""Adds the OutputGroupInfo provider.

Args:
providers: list of providers to append to.
py_info: PyInfo; the PyInfo provider.
output_groups: dict[str, depset[File]]; used to create OutputGroupInfo
"""
providers.append(create_output_group_info(py_info.transitive_sources, output_groups))

def _add_config_setting_defaults(kwargs):
config_settings = kwargs.get("config_settings", None)
Expand Down