@@ -19,6 +19,11 @@ load(":py_package.bzl", "py_package_lib")
1919load (":py_wheel_normalize_pep440.bzl" , "normalize_pep440" )
2020load (":stamp.bzl" , "is_stamping_enabled" )
2121
22+ RequirementInfo = provider (
23+ """Information about the requirements of a Python package.""" ,
24+ fields = ["metadatafiles" ],
25+ )
26+
2227PyWheelInfo = provider (
2328 doc = "Information about a wheel produced by `py_wheel`" ,
2429 fields = {
@@ -29,6 +34,44 @@ PyWheelInfo = provider(
2934 "wheel" : "File: The wheel file itself." ,
3035 },
3136)
37+ DistInfo = provider (
38+ """Information about the requirements of a Python package.""" ,
39+ fields = ["metadata" ],
40+ )
41+
42+ def _aspect_impl (target , ctx ):
43+ """
44+ The main implementation of the aspect, orchestrating the collection and archiving of files.
45+
46+ Args:
47+ target: The target being processed.
48+ ctx: The context for this aspect's execution.
49+
50+ Returns:
51+ A list of `TarInfo` providers indicating the tar archives created by this aspect.
52+ """
53+
54+ metadata = []
55+ if target .label .workspace_root == "" :
56+ for dep in getattr (ctx .rule .attr , "deps" , []):
57+ if dep .label .workspace_root == "" :
58+ continue
59+ workspace_root = dep .label .workspace_root
60+ for file in dep [DefaultInfo ].data_runfiles .files .to_list ():
61+ if file .path .startswith (workspace_root ) and file .path .endswith (".dist-info/METADATA" ):
62+ metadata .append (file )
63+
64+ return [DistInfo (metadata = metadata )]
65+
66+ # The aspect itself, specifying how it applies to targets and what attributes it uses.
67+ distinfo_aspect = aspect (
68+ implementation = _aspect_impl ,
69+ attr_aspects = ["deps" ], # Indicates that this aspect should propagate along 'deps' attributes.
70+ toolchains = [
71+ str (Label ("@bazel_tools//tools/python:toolchain_type" )),
72+ ],
73+ doc = "An aspect for creating tar archives of transitive external dependencies, facilitating the bundling of these dependencies for container images or other deployment artifacts." ,
74+ )
3275
3376_distribution_attrs = {
3477 "abi" : attr .string (
@@ -231,6 +274,44 @@ _DESCRIPTION_FILE_EXTENSION_TO_TYPE = {
231274}
232275_DEFAULT_DESCRIPTION_FILE_TYPE = "text/plain"
233276
277+ def create_requirements_file (ctx ):
278+ """Write requirements to a file
279+
280+ Args:
281+ ctx: The context object.
282+ Returns:
283+ The file containing the requirements.
284+
285+ """
286+ all_metadatafiles = []
287+ args = ctx .actions .args ()
288+ for dep in ctx .attr .deps :
289+ if DistInfo in dep :
290+ all_metadatafiles .extend (dep [DistInfo ].metadata )
291+
292+ if len (all_metadatafiles ) == 0 :
293+ return None
294+
295+ for m in all_metadatafiles :
296+ args .add ("--metadata_file" , m )
297+ args .use_param_file (param_file_arg = "--param-file=%s" , use_always = True )
298+
299+ if hasattr (ctx .outputs , "out" ):
300+ requirements_file = ctx .outputs .out
301+ else :
302+ requirements_file = ctx .actions .declare_file (ctx .attr .name + "_requirements.txt" )
303+ args .add ("--output" , requirements_file )
304+
305+ ctx .actions .run (
306+ inputs = depset (direct = all_metadatafiles ),
307+ outputs = [requirements_file ],
308+ arguments = [args ],
309+ use_default_shell_env = True ,
310+ executable = ctx .executable ._extract_requirements ,
311+ progress_message = "Building requirements" ,
312+ )
313+ return requirements_file
314+
234315def _escape_filename_distribution_name (name ):
235316 """Escape the distribution name component of a filename.
236317
@@ -358,6 +439,10 @@ def _py_wheel_impl(ctx):
358439 other_inputs .extend ([ctx .version_file , ctx .info_file ])
359440
360441 args .add ("--input_file_list" , packageinputfile )
442+ requirements_file = create_requirements_file (ctx )
443+ if requirements_file :
444+ args .add ("--requirements" , requirements_file )
445+ other_inputs .append (requirements_file )
361446
362447 # Note: Description file and version are not embedded into metadata.txt yet,
363448 # it will be done later by wheelmaker script.
@@ -547,6 +632,7 @@ py_wheel_lib = struct(
547632 attrs = _concat_dicts (
548633 {
549634 "deps" : attr .label_list (
635+ aspects = [distinfo_aspect ],
550636 doc = """\
551637 Targets to be included in the distribution.
552638
0 commit comments