@@ -86,17 +86,25 @@ def _set_requirement_extras(req: Requirement, new_extras: set[str]) -> Requireme
86
86
return get_requirement (f"{ pre } { extras } { post } " )
87
87
88
88
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
99
105
106
+
107
+ def _parse_pip_syntax_editable (editable_req : str ) -> tuple [str | None , str , set [str ]]:
100
108
url = editable_req
101
109
102
110
# 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]]:
122
130
url = f"{ version_control } +{ url } "
123
131
break
124
132
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
+
125
151
link = Link (url )
126
152
127
- if not link .is_vcs :
153
+ if not link .is_vcs and not link . url . startswith ( "file:" ) :
128
154
backends = ", " .join (vcs .all_schemes )
129
155
raise InstallationError (
130
156
f"{ editable_req } is not a valid editable requirement. "
131
157
f"It should either be a path to a local project or a VCS URL "
132
158
f"(beginning with { backends } )."
133
159
)
134
160
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:" ) :
137
163
raise InstallationError (
138
164
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 "
140
166
)
141
- return package_name , url , set ()
167
+ return package_name , url , extras
142
168
143
169
144
170
def check_first_requirement_in_file (filename : str ) -> None :
0 commit comments