@@ -86,17 +86,25 @@ def _set_requirement_extras(req: Requirement, new_extras: set[str]) -> Requireme
8686 return get_requirement (f"{ pre } { extras } { post } " )
8787
8888
89- def parse_editable (editable_req : str ) -> tuple [str | None , str , set [str ]]:
90- """Parses an editable requirement into:
91- - a requirement name
92- - an URL
93- - extras
94- - editable options
95- Accepted requirements:
96- svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir
97- .[some_extra]
98- """
89+ def _parse_direct_url_editable (editable_req : str ) -> tuple [str | None , str , set [str ]]:
90+ try :
91+ req = Requirement (editable_req )
92+ except InvalidRequirement :
93+ pass
94+ else :
95+ if req .url :
96+ # Join the marker back into the name part. This will be parsed out
97+ # later into a Requirement again.
98+ if req .marker :
99+ name = f"{ req .name } ; { req .marker } "
100+ else :
101+ name = req .name
102+ return (name , req .url , req .extras )
103+
104+ raise ValueError
99105
106+
107+ def _parse_pip_syntax_editable (editable_req : str ) -> tuple [str | None , str , set [str ]]:
100108 url = editable_req
101109
102110 # If a file path is specified with extras, strip off the extras.
@@ -122,23 +130,41 @@ def parse_editable(editable_req: str) -> tuple[str | None, str, set[str]]:
122130 url = f"{ version_control } +{ url } "
123131 break
124132
133+ return Link (url ).egg_fragment , url , set ()
134+
135+
136+ def parse_editable (editable_req : str ) -> tuple [str | None , str , set [str ]]:
137+ """Parses an editable requirement into:
138+ - a requirement name
139+ - an URL
140+ - extras
141+ Accepted requirements:
142+ - svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir
143+ - local_path[some_extra]
144+ - Foobar[extra] @ svn+http://blahblah@rev#subdirectory=subdir ; markers
145+ """
146+ try :
147+ package_name , url , extras = _parse_direct_url_editable (editable_req )
148+ except ValueError :
149+ package_name , url , extras = _parse_pip_syntax_editable (editable_req )
150+
125151 link = Link (url )
126152
127- if not link .is_vcs :
153+ if not link .is_vcs and not link . url . startswith ( "file:" ) :
128154 backends = ", " .join (vcs .all_schemes )
129155 raise InstallationError (
130156 f"{ editable_req } is not a valid editable requirement. "
131157 f"It should either be a path to a local project or a VCS URL "
132158 f"(beginning with { backends } )."
133159 )
134160
135- package_name = link . egg_fragment
136- if not package_name :
161+ # The project name can be inferred from local file URIs easily.
162+ if not package_name and not link . url . startswith ( "file:" ) :
137163 raise InstallationError (
138164 f"Could not detect requirement name for '{ editable_req } ', "
139- "please specify one with #egg= your_package_name"
165+ "please specify one with your_package_name @ URL "
140166 )
141- return package_name , url , set ()
167+ return package_name , url , extras
142168
143169
144170def check_first_requirement_in_file (filename : str ) -> None :
0 commit comments