Skip to content

Commit 9a6be4c

Browse files
authored
refactor: split create_providers into separate functions (#3695)
The create_providers function was becoming unwieldy because it was taking all the args for all the providers. Split it up into separate functions to make it easier to see what args are going to what providers and follow the provider creation logic.
1 parent 85e4a3c commit 9a6be4c

File tree

1 file changed

+174
-111
lines changed

1 file changed

+174
-111
lines changed

python/private/py_executable.bzl

Lines changed: 174 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,29 +1252,45 @@ def py_executable_base_impl(ctx, *, semantics, is_test, inherited_environment =
12521252

12531253
app_runfiles = exec_result.app_runfiles
12541254

1255-
return _create_providers(
1256-
ctx = ctx,
1255+
providers = []
1256+
1257+
_add_provider_default_info(
1258+
providers,
1259+
ctx,
12571260
executable = executable,
1261+
default_outputs = default_outputs.build(),
12581262
runfiles_details = runfiles_details,
1263+
)
1264+
_add_provider_instrumented_files_info(providers, ctx)
1265+
_add_provider_run_environment_info(providers, ctx, inherited_environment)
1266+
_add_provider_py_executable_info(
1267+
providers,
1268+
app_runfiles = app_runfiles,
1269+
build_data_file = runfiles_details.build_data_file,
1270+
interpreter_args = ctx.attr.interpreter_args,
1271+
interpreter_path = runtime_details.executable_interpreter_path,
12591272
main_py = main_py,
1260-
imports = imports,
1273+
runfiles_without_exe = runfiles_details.runfiles_without_exe,
1274+
stage2_bootstrap = exec_result.stage2_bootstrap,
1275+
venv_interpreter_runfiles = exec_result.venv_interpreter_runfiles,
1276+
venv_interpreter_symlinks = exec_result.venv_interpreter_symlinks,
1277+
venv_python_exe = exec_result.venv_python_exe,
1278+
)
1279+
_add_provider_py_runtime_info(providers, runtime_details)
1280+
_add_provider_py_cc_link_params_info(providers, cc_details.cc_info_for_propagating)
1281+
py_info = _add_provider_py_info(
1282+
providers,
1283+
ctx = ctx,
12611284
original_sources = direct_sources,
12621285
required_py_files = required_py_files,
12631286
required_pyc_files = required_pyc_files,
12641287
implicit_pyc_files = implicit_pyc_files,
12651288
implicit_pyc_source_files = implicit_pyc_source_files,
1266-
default_outputs = default_outputs.build(),
1267-
runtime_details = runtime_details,
1268-
cc_info = cc_details.cc_info_for_propagating,
1269-
inherited_environment = inherited_environment,
1270-
output_groups = exec_result.output_groups,
1271-
stage2_bootstrap = exec_result.stage2_bootstrap,
1272-
app_runfiles = app_runfiles,
1273-
venv_python_exe = exec_result.venv_python_exe,
1274-
venv_interpreter_runfiles = exec_result.venv_interpreter_runfiles,
1275-
venv_interpreter_symlinks = exec_result.venv_interpreter_symlinks,
1276-
interpreter_args = ctx.attr.interpreter_args,
1289+
imports = imports,
12771290
)
1291+
_add_provider_output_group_info(providers, py_info, exec_result.output_groups)
1292+
1293+
return providers
12781294

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

1802-
def _create_providers(
1803-
*,
1804-
ctx,
1805-
executable,
1806-
main_py,
1807-
original_sources,
1808-
required_py_files,
1809-
required_pyc_files,
1810-
implicit_pyc_files,
1811-
implicit_pyc_source_files,
1812-
default_outputs,
1813-
runfiles_details,
1814-
imports,
1815-
cc_info,
1816-
inherited_environment,
1817-
runtime_details,
1818-
output_groups,
1819-
stage2_bootstrap,
1820-
app_runfiles,
1821-
venv_python_exe,
1822-
venv_interpreter_runfiles,
1823-
venv_interpreter_symlinks,
1824-
interpreter_args):
1825-
"""Creates the providers an executable should return.
1818+
def _add_provider_default_info(providers, ctx, *, executable, default_outputs, runfiles_details):
1819+
"""Adds the DefaultInfo provider.
18261820
18271821
Args:
1822+
providers: list of providers to append to.
18281823
ctx: The rule ctx.
18291824
executable: File; the target's executable file.
1830-
main_py: File; the main .py entry point.
1831-
original_sources: `depset[File]` the direct `.py` sources for the
1832-
target that were the original input sources.
1833-
required_py_files: `depset[File]` the direct, `.py` sources for the
1834-
target that **must** be included by downstream targets. This should
1835-
only be Python source files. It should not include pyc files.
1836-
required_pyc_files: `depset[File]` the direct `.pyc` files this target
1837-
produces.
1838-
implicit_pyc_files: `depset[File]` pyc files that are only used if pyc
1839-
collection is enabled.
1840-
implicit_pyc_source_files: `depset[File]` source files for implicit pyc
1841-
files that are used when the implicit pyc files are not.
18421825
default_outputs: depset of Files; the files for DefaultInfo.files
1843-
runfiles_details: runfiles that will become the default and data runfiles.
1844-
imports: depset of strings; the import paths to propagate
1845-
cc_info: optional CcInfo; Linking information to propagate as
1846-
PyCcLinkParamsInfo. Note that only the linking information
1847-
is propagated, not the whole CcInfo.
1826+
runfiles_details: runfiles that will become the default and data runfiles.
1827+
"""
1828+
providers.append(DefaultInfo(
1829+
executable = executable,
1830+
files = default_outputs,
1831+
default_runfiles = _py_builtins.make_runfiles_respect_legacy_external_runfiles(
1832+
ctx,
1833+
runfiles_details.default_runfiles,
1834+
),
1835+
data_runfiles = _py_builtins.make_runfiles_respect_legacy_external_runfiles(
1836+
ctx,
1837+
runfiles_details.data_runfiles,
1838+
),
1839+
))
1840+
1841+
def _add_provider_instrumented_files_info(providers, ctx):
1842+
"""Adds the InstrumentedFilesInfo provider.
1843+
1844+
Args:
1845+
providers: list of providers to append to.
1846+
ctx: The rule ctx.
1847+
"""
1848+
providers.append(create_instrumented_files_info(ctx))
1849+
1850+
def _add_provider_run_environment_info(providers, ctx, inherited_environment):
1851+
"""Adds the RunEnvironmentInfo provider.
1852+
1853+
Args:
1854+
providers: list of providers to append to.
1855+
ctx: The rule ctx.
18481856
inherited_environment: list of strings; Environment variable names
18491857
that should be inherited from the environment the executuble
18501858
is run within.
1851-
runtime_details: struct of runtime information; see _get_runtime_details()
1852-
output_groups: dict[str, depset[File]]; used to create OutputGroupInfo
1853-
stage2_bootstrap: File; the stage 2 bootstrap script.
1859+
"""
1860+
expanded_env = {}
1861+
for key, value in ctx.attr.env.items():
1862+
expanded_env[key] = _py_builtins.expand_location_and_make_variables(
1863+
ctx = ctx,
1864+
attribute_name = "env[{}]".format(key),
1865+
expression = value,
1866+
targets = ctx.attr.data,
1867+
)
1868+
if "PYTHONBREAKPOINT" not in inherited_environment:
1869+
inherited_environment = inherited_environment + ["PYTHONBREAKPOINT"]
1870+
providers.append(RunEnvironmentInfo(
1871+
environment = expanded_env,
1872+
inherited_environment = inherited_environment,
1873+
))
1874+
1875+
def _add_provider_py_executable_info(
1876+
providers,
1877+
*,
1878+
app_runfiles,
1879+
build_data_file,
1880+
interpreter_args,
1881+
interpreter_path,
1882+
main_py,
1883+
runfiles_without_exe,
1884+
stage2_bootstrap,
1885+
venv_interpreter_runfiles,
1886+
venv_interpreter_symlinks,
1887+
venv_python_exe):
1888+
"""Adds the PyExecutableInfo provider.
1889+
1890+
Args:
1891+
providers: list of providers to append to.
18541892
app_runfiles: runfiles; the runfiles for the application (deps, etc).
1855-
venv_python_exe: File; the python executable in the venv.
1856-
venv_interpreter_runfiles: runfiles; runfiles specific to the interpreter
1857-
for the venv.
1858-
venv_interpreter_symlinks: depset[ExplicitSymlink]; interpreter-specific symlinks
1859-
to create for the venv.
1893+
build_data_file: File; a file with build stamp information.
18601894
interpreter_args: list of strings; arguments to pass to the interpreter.
1895+
interpreter_path: str; path to the Python interpreter.
1896+
main_py: File; the main .py entry point.
1897+
runfiles_without_exe: runfiles; the default runfiles, but without the executable.
1898+
stage2_bootstrap: File; the stage 2 bootstrap script.
1899+
venv_interpreter_runfiles: runfiles; runfiles specific to the interpreter for the venv.
1900+
venv_interpreter_symlinks: depset[ExplicitSymlink]; interpreter-specific symlinks to create for the venv.
1901+
venv_python_exe: File; the python executable in the venv.
1902+
"""
1903+
providers.append(PyExecutableInfo(
1904+
app_runfiles = app_runfiles,
1905+
build_data_file = build_data_file,
1906+
interpreter_args = interpreter_args,
1907+
interpreter_path = interpreter_path,
1908+
main = main_py,
1909+
runfiles_without_exe = runfiles_without_exe,
1910+
stage2_bootstrap = stage2_bootstrap,
1911+
venv_interpreter_runfiles = venv_interpreter_runfiles,
1912+
venv_interpreter_symlinks = venv_interpreter_symlinks,
1913+
venv_python_exe = venv_python_exe,
1914+
))
18611915

1862-
Returns:
1863-
A list of modern providers.
1916+
def _add_provider_py_runtime_info(providers, runtime_details):
1917+
"""Adds the PyRuntimeInfo provider.
1918+
1919+
Args:
1920+
providers: list of providers to append to.
1921+
runtime_details: struct of runtime information; see _get_runtime_details()
18641922
"""
1865-
providers = [
1866-
DefaultInfo(
1867-
executable = executable,
1868-
files = default_outputs,
1869-
default_runfiles = _py_builtins.make_runfiles_respect_legacy_external_runfiles(
1870-
ctx,
1871-
runfiles_details.default_runfiles,
1872-
),
1873-
data_runfiles = _py_builtins.make_runfiles_respect_legacy_external_runfiles(
1874-
ctx,
1875-
runfiles_details.data_runfiles,
1876-
),
1877-
),
1878-
create_instrumented_files_info(ctx),
1879-
_create_run_environment_info(ctx, inherited_environment),
1880-
PyExecutableInfo(
1881-
app_runfiles = app_runfiles,
1882-
build_data_file = runfiles_details.build_data_file,
1883-
interpreter_args = interpreter_args,
1884-
interpreter_path = runtime_details.executable_interpreter_path,
1885-
main = main_py,
1886-
runfiles_without_exe = runfiles_details.runfiles_without_exe,
1887-
stage2_bootstrap = stage2_bootstrap,
1888-
venv_interpreter_runfiles = venv_interpreter_runfiles,
1889-
venv_interpreter_symlinks = venv_interpreter_symlinks,
1890-
venv_python_exe = venv_python_exe,
1891-
),
1892-
]
18931923

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

1950+
def _add_provider_py_cc_link_params_info(providers, cc_info):
1951+
"""Adds the PyCcLinkParamsInfo provider.
1952+
1953+
Args:
1954+
providers: list of providers to append to.
1955+
cc_info: optional CcInfo; Linking information to propagate as
1956+
PyCcLinkParamsInfo. Note that only the linking information
1957+
is propagated, not the whole CcInfo.
1958+
"""
1959+
19201960
# TODO(b/163083591): Remove the PyCcLinkParamsInfo once binaries-in-deps
19211961
# are cleaned up.
19221962
if cc_info:
19231963
providers.append(
19241964
PyCcLinkParamsInfo(cc_info = cc_info),
19251965
)
19261966

1967+
def _add_provider_py_info(
1968+
providers,
1969+
*,
1970+
ctx,
1971+
original_sources,
1972+
required_py_files,
1973+
required_pyc_files,
1974+
implicit_pyc_files,
1975+
implicit_pyc_source_files,
1976+
imports):
1977+
"""Adds the PyInfo provider.
1978+
1979+
Args:
1980+
providers: list of providers to append to.
1981+
ctx: The rule ctx.
1982+
original_sources: `depset[File]` the direct `.py` sources for the
1983+
target that were the original input sources.
1984+
required_py_files: `depset[File]` the direct, `.py` sources for the
1985+
target that **must** be included by downstream targets. This should
1986+
only be Python source files. It should not include pyc files.
1987+
required_pyc_files: `depset[File]` the direct `.pyc` files this target
1988+
produces.
1989+
implicit_pyc_files: `depset[File]` pyc files that are only used if pyc
1990+
collection is enabled.
1991+
implicit_pyc_source_files: `depset[File]` source files for implicit pyc
1992+
files that are used when the implicit pyc files are not.
1993+
imports: depset of strings; the import paths to propagate
1994+
1995+
Returns:
1996+
PyInfo.
1997+
"""
19271998
py_info, builtin_py_info = create_py_info(
19281999
ctx,
19292000
original_sources = original_sources,
@@ -1933,28 +2004,20 @@ def _create_providers(
19332004
implicit_pyc_source_files = implicit_pyc_source_files,
19342005
imports = imports,
19352006
)
1936-
19372007
providers.append(py_info)
19382008
if builtin_py_info:
19392009
providers.append(builtin_py_info)
1940-
providers.append(create_output_group_info(py_info.transitive_sources, output_groups))
1941-
return providers
2010+
return py_info
19422011

1943-
def _create_run_environment_info(ctx, inherited_environment):
1944-
expanded_env = {}
1945-
for key, value in ctx.attr.env.items():
1946-
expanded_env[key] = _py_builtins.expand_location_and_make_variables(
1947-
ctx = ctx,
1948-
attribute_name = "env[{}]".format(key),
1949-
expression = value,
1950-
targets = ctx.attr.data,
1951-
)
1952-
if "PYTHONBREAKPOINT" not in inherited_environment:
1953-
inherited_environment = inherited_environment + ["PYTHONBREAKPOINT"]
1954-
return RunEnvironmentInfo(
1955-
environment = expanded_env,
1956-
inherited_environment = inherited_environment,
1957-
)
2012+
def _add_provider_output_group_info(providers, py_info, output_groups):
2013+
"""Adds the OutputGroupInfo provider.
2014+
2015+
Args:
2016+
providers: list of providers to append to.
2017+
py_info: PyInfo; the PyInfo provider.
2018+
output_groups: dict[str, depset[File]]; used to create OutputGroupInfo
2019+
"""
2020+
providers.append(create_output_group_info(py_info.transitive_sources, output_groups))
19582021

19592022
def _add_config_setting_defaults(kwargs):
19602023
config_settings = kwargs.get("config_settings", None)

0 commit comments

Comments
 (0)