@@ -202,37 +202,45 @@ def parse_line(cls, line):
202
202
req .hash_name , req .hash = get_hash_info (fragment )
203
203
req .subdirectory = fragment .get ('subdirectory' )
204
204
req .path = groups ['path' ]
205
- elif os .path .exists (line ):
206
- if os .path .isfile (line ) and line .lower ().endswith (".whl" ):
207
- match = re .match (WHL_FILE_REGEX , os .path .basename (line ))
208
- if match :
209
- req .name = match .group ("name" )
210
- elif os .path .isdir (line ):
211
- setup_file = open (os .path .join (line , "setup.py" ), "r" )
212
- setup_content = setup_file .read ()
213
- name_search = NAME_EQ_REGEX .search (setup_content )
214
- if name_search :
215
- req .name = name_search .group (1 )
205
+ elif os .path .isfile (line ) and line .lower ().endswith (".whl" ):
206
+ match = re .match (WHL_FILE_REGEX , os .path .basename (line ))
207
+ if match :
208
+ req .name = match .group ("name" )
209
+ req .local_file = True
210
+ # Attempts to determine if the line refers to a local directory that could be
211
+ # an installable Python package
212
+ elif os .path .isdir (line ) and os .path .isfile (os .path .join (line , "setup.py" )):
213
+ setup_file = open (os .path .join (line , "setup.py" ), "r" )
214
+ setup_content = setup_file .read ()
215
+ name_search = NAME_EQ_REGEX .search (setup_content )
216
+ if name_search :
217
+ req .name = name_search .group (1 )
216
218
req .local_file = True
217
219
else :
218
- # This is a requirement specifier.
219
- # Delegate to pkg_resources and hope for the best
220
- req .specifier = True
221
-
222
- # an optional per-requirement param is not part of the req specifier
223
- # see https://pip.pypa.io/en/stable/reference/pip_install/#per-requirement-overrides
224
- # and https://pip.pypa.io/en/stable/reference/pip_install/#hash-checking-mode
225
- line = PER_REQ_PARAM_REGEX .sub ('' , line )
226
-
227
- pkg_req = Req .parse (line )
228
- req .name = pkg_req .unsafe_name
229
- req .original_name = pkg_req .name
230
- req .extras = list (pkg_req .extras )
231
- req .specs = pkg_req .specs
220
+ try :
221
+ # This is a requirement specifier.
222
+ # Delegate to pkg_resources and hope for the best
223
+ req .specifier = True
224
+
225
+ # an optional per-requirement param is not part of the req specifier
226
+ # see https://pip.pypa.io/en/stable/reference/pip_install/#per-requirement-overrides
227
+ # and https://pip.pypa.io/en/stable/reference/pip_install/#hash-checking-mode
228
+ line = PER_REQ_PARAM_REGEX .sub ('' , line )
229
+
230
+ pkg_req = Req .parse (line )
231
+ req .name = pkg_req .unsafe_name
232
+ req .original_name = pkg_req .name
233
+ req .extras = list (pkg_req .extras )
234
+ req .specs = pkg_req .specs
235
+ except Exception as e :
236
+ if os .path .exists (line ):
237
+ raise ValueError (f'Requirement line { line } is a local path, but could not be parsed' )
238
+ else :
239
+ raise e
232
240
if not req .original_name :
233
241
req .original_name = req .name
234
242
return req
235
-
243
+
236
244
@classmethod
237
245
def parse (cls , line ):
238
246
"""
0 commit comments