@@ -31,6 +31,7 @@ load("//python/private:repo_utils.bzl", "repo_utils")
3131load (":argparse.bzl" , "argparse" )
3232load (":index_sources.bzl" , "index_sources" )
3333load (":parse_requirements_txt.bzl" , "parse_requirements_txt" )
34+ load (":pep508_evaluate.bzl" , "evaluate" )
3435load (":pep508_requirement.bzl" , "requirement" )
3536load (":select_whl.bzl" , "select_whl" )
3637
@@ -41,7 +42,6 @@ def parse_requirements(
4142 extra_pip_args = [],
4243 platforms = {},
4344 get_index_urls = None ,
44- evaluate_markers = None ,
4545 extract_url_srcs = True ,
4646 logger ):
4747 """Get the requirements with platforms that the requirements apply to.
@@ -57,11 +57,6 @@ def parse_requirements(
5757 get_index_urls: Callable[[ctx, dict[str, list[str]]], dict], a callable to get all
5858 of the distribution URLs from a PyPI index. Accepts ctx and
5959 distribution names to query.
60- evaluate_markers: A function to use to evaluate the requirements.
61- Accepts a dict where keys are requirement lines to evaluate against
62- the platforms stored as values in the input dict. Returns the same
63- dict, but with values being platforms that are compatible with the
64- requirements line.
6560 extract_url_srcs: A boolean to enable extracting URLs from requirement
6661 lines to enable using bazel downloader.
6762 logger: repo_utils.logger, a simple struct to log diagnostic messages.
@@ -86,11 +81,9 @@ def parse_requirements(
8681
8782 The second element is extra_pip_args should be passed to `whl_library`.
8883 """
89- evaluate_markers = evaluate_markers or (lambda _requirements : {})
9084 options = {}
9185 requirements = {}
9286 all_files_parsed = {}
93- reqs_with_env_markers = {}
9487 index_url = None
9588 extra_index_urls = []
9689 for file , plats in requirements_by_platform .items ():
@@ -114,39 +107,31 @@ def parse_requirements(
114107 tokenized_options .append (p )
115108
116109 pip_args = tokenized_options + extra_pip_args
110+
111+ # Parse the index URL from the requirement files once per file
112+ index_url = argparse .index_url (pip_args , index_url )
113+ extra_index_urls = argparse .extra_index_url (pip_args , [])
114+ if argparse .platform (pip_args , []):
115+ # No use of downloader if the user specifies "--platform" pip arg. This means that
116+ # they intend to use pip to download the wheels
117+ #
118+ # TODO @aignas 2026-04-11: consider removing this line in the next major release
119+ # (3.0).
120+ get_index_urls = None
121+
122+ # Pre-parse requirements once per file to avoid redundant parsing in loops
123+ parsed_reqs = [(entry , requirement (entry [1 ])) for entry in parse_result .requirements ]
124+
117125 for plat in plats :
118- requirements [plat ] = parse_result .requirements
119- for entry in parse_result .requirements :
120- requirement_line = entry [1 ]
126+ plat_env = platforms .get (plat )
121127
122- # output all of the requirement lines that have a marker
123- if ";" in requirement_line :
124- reqs_with_env_markers .setdefault (requirement_line , []).append (plat )
125- options [plat ] = pip_args
128+ requirements [plat ] = [
129+ entry
130+ for entry , req in parsed_reqs
131+ if not req .marker or (plat_env and evaluate (req .marker , env = plat_env .env ))
132+ ]
126133
127- # Parse the index URL from the requirement files
128- index_url = argparse .index_url (pip_args , index_url )
129- extra_index_urls = argparse .extra_index_url (pip_args , [])
130- platform = argparse .platform (pip_args , [])
131- if platform :
132- # No use of downloader if the user specifies "--platform" pip arg. This means that
133- # they intend to use pip to download the wheels
134- #
135- # TODO @aignas 2026-04-11: consider removing this line in the next major release
136- # (3.0).
137- get_index_urls = None
138-
139- # This may call to Python, so execute it early (before calling to the
140- # internet below) and ensure that we call it only once.
141- #
142- # TODO @aignas 2026-05-10: remove this assumption in the code because we
143- # are always using pipstar, so we can do the marker evaluation when we are
144- # parsing the files.
145- resolved_marker_platforms = evaluate_markers (reqs_with_env_markers )
146- logger .trace (lambda : "Evaluated env markers from:\n {}\n \n To:\n {}" .format (
147- reqs_with_env_markers ,
148- resolved_marker_platforms ,
149- ))
134+ options [plat ] = pip_args
150135
151136 requirements_by_platform = {}
152137 for plat , parse_results in requirements .items ():
@@ -170,9 +155,6 @@ def parse_requirements(
170155 req_line = entry [1 ]
171156 req = requirement (req_line )
172157
173- if req .marker and plat not in resolved_marker_platforms .get (req_line , []):
174- continue
175-
176158 requirements_dict [req .name ] = entry
177159
178160 extra_pip_args = options [plat ]
0 commit comments