@@ -35,30 +35,18 @@ async def install(
35
35
36
36
@dataclass
37
37
class RequirementsContext :
38
- """Track state while parsing requirements files.
38
+ """Track state while parsing requirements files."""
39
39
40
- This class maintains state about requirements and their associated index URLs.
41
- Multiple index URLs can be tracked to support searching in multiple indices
42
- in order of specification.
43
- """
44
-
45
- index_urls : List [str ] = None
40
+ index_url : Optional [str ] = None
46
41
requirements : List [str ] = None
47
42
48
43
def __post_init__ (self ):
49
44
if self .requirements is None :
50
45
self .requirements = []
51
- if self .index_urls is None :
52
- self .index_urls = []
53
-
54
- def add_index_url (self , url : str ) -> None :
55
- """Add an index URL to the list of URLs to search from."""
56
- if url not in self .index_urls :
57
- self .index_urls .append (url )
58
46
59
47
def add_requirement (self , req : str ):
60
- """Add a requirement that will use the current index URLs ."""
61
- self .requirements .append ((req , self .index_urls [:] if self . index_urls else None ))
48
+ """Add a requirement with the currently active index URL ."""
49
+ self .requirements .append ((req , self .index_url ))
62
50
63
51
64
52
REQ_FILE_PREFIX = r"^(-r|--requirements)\s*=?\s*(.*)\s*"
@@ -153,52 +141,60 @@ async def get_action_kwargs(argv: list[str]) -> tuple[typing.Optional[str], dict
153
141
action = args .action
154
142
155
143
if action == "install" :
156
- all_index_urls = []
157
- if args .index_url :
158
- all_index_urls .append (args .index_url )
159
-
144
+ # CLI index URL, if provided, is the only one we'll use
145
+ cli_index_url = args .index_url
160
146
all_requirements = []
147
+ last_seen_file_index = None
161
148
162
149
if args .packages :
163
- all_requirements .extend ((pkg , all_index_urls [:] ) for pkg in args .packages )
150
+ all_requirements .extend ((pkg , cli_index_url ) for pkg in args .packages )
164
151
165
152
# Process requirements files
166
153
for req_file in args .requirements or []:
167
- try :
168
- requirements , file_index_urls = await _packages_from_requirements_file (
169
- Path (req_file )
170
- )
154
+ context = RequirementsContext ()
171
155
172
- # If CLI provided an index URL, it should override the file's index URL
173
- # We update all requirements to use the CLI index URL instead. Or, we use
174
- # whatever index URL was found in the file (if any).
175
- if args .index_url :
176
- all_requirements .extend (
177
- (req , all_index_urls ) for req , _ in requirements
178
- )
179
- else :
180
- for url in file_index_urls :
181
- if url not in all_index_urls :
182
- all_index_urls .append (url )
183
- all_requirements .extend (requirements )
184
- except Exception as e :
185
- warn (f"Error processing requirements file { req_file } : { e } " )
156
+ if not Path (req_file ).exists ():
157
+ warn (f"piplite could not find requirements file { req_file } " )
186
158
continue
187
159
160
+ # Process the file and capture any index URL it contains
161
+ for line_no , line in enumerate (
162
+ Path (req_file ).read_text (encoding = "utf-8" ).splitlines ()
163
+ ):
164
+ await _packages_from_requirements_line (
165
+ Path (req_file ), line_no + 1 , line , context
166
+ )
167
+
168
+ # Keep track of the last index URL we saw in any requirements file
169
+ if context .index_url is not None :
170
+ last_seen_file_index = context .index_url
171
+
172
+ # Add requirements - if CLI provided an index URL, use that instead
173
+ if cli_index_url :
174
+ all_requirements .extend (
175
+ (req , cli_index_url ) for req , _ in context .requirements
176
+ )
177
+ else :
178
+ all_requirements .extend (context .requirements )
179
+
188
180
if all_requirements :
189
181
kwargs ["requirements" ] = []
182
+
183
+ # Add all requirements
190
184
kwargs ["requirements" ].extend (req for req , _ in all_requirements )
191
185
192
- # Set the final index URLs, if we found any
193
- if all_index_urls :
194
- kwargs ["index_urls" ] = all_index_urls
186
+ # Use index URL with proper precedence:
187
+ # 1. CLI index URL if provided
188
+ # 2. Otherwise, last seen index URL from any requirements file
189
+ effective_index = cli_index_url or last_seen_file_index
190
+ if effective_index :
191
+ kwargs ["index_urls" ] = effective_index
195
192
193
+ # Other CLI flags remain unchanged
196
194
if args .pre :
197
195
kwargs ["pre" ] = True
198
-
199
196
if args .no_deps :
200
197
kwargs ["deps" ] = False
201
-
202
198
if args .verbose :
203
199
kwargs ["keep_going" ] = True
204
200
@@ -244,28 +240,26 @@ async def _packages_from_requirements_line(
244
240
if not req :
245
241
return
246
242
247
- # Check for nested requirements file
243
+ # Handle nested requirements file
248
244
req_file_match = re .match (REQ_FILE_PREFIX , req )
249
245
if req_file_match :
250
246
sub_path = req_file_match [2 ]
251
247
if sub_path .startswith ("/" ):
252
248
sub_req = Path (sub_path )
253
249
else :
254
250
sub_req = req_path .parent / sub_path
255
- # Create a new context for the nested file to maintain its own index URLs.
256
251
nested_context = RequirementsContext ()
257
- nested_context .index_urls = context .index_urls [
258
- :
259
- ] # i nherit parent's index URLs
260
252
await _packages_from_requirements_file (sub_req , nested_context )
261
- # Extend our requirements with the nested ones
253
+ # Use the last index URL from nested file, if one was found
254
+ if nested_context .index_url :
255
+ context .index_url = nested_context .index_url
262
256
context .requirements .extend (nested_context .requirements )
263
257
return
264
258
265
- # Check for index URL specification
259
+ # Check for index URL - this becomes the new active index URL.
266
260
index_match = re .match (INDEX_URL_PREFIX , req )
267
261
if index_match :
268
- context .add_index_url ( index_match [2 ].strip () )
262
+ context .index_url = index_match [2 ].strip ()
269
263
return
270
264
271
265
if req .startswith ("-" ):
0 commit comments