Skip to content

Commit 8146a88

Browse files
committed
Unify editable and unnamed URL parsing
1 parent 8c11f99 commit 8146a88

File tree

12 files changed

+1137
-831
lines changed

12 files changed

+1137
-831
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/pep508-rs/src/unnamed.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,12 @@ fn parse_unnamed_requirement<Url: UnnamedRequirementUrl>(
214214

215215
/// Create a `VerbatimUrl` to represent the requirement, and extracts any extras at the end of the
216216
/// URL, to comply with the non-PEP 508 extensions.
217+
///
218+
/// For example:
219+
/// - `file:///home/ferris/project/scripts/...`
220+
/// - `file:../editable/`
221+
/// - `../editable/`
222+
/// - `https://download.pytorch.org/whl/torch_stable.html`
217223
fn preprocess_unnamed_url<Url: UnnamedRequirementUrl>(
218224
url: &str,
219225
#[cfg_attr(not(feature = "non-pep508-extensions"), allow(unused))] working_dir: Option<&Path>,
@@ -356,8 +362,39 @@ fn parse_unnamed_url<Url: UnnamedRequirementUrl>(
356362
) -> Result<(Url, Vec<ExtraName>), Pep508Error<Url>> {
357363
// wsp*
358364
cursor.eat_whitespace();
365+
359366
// <URI_reference>
360-
let (start, len) = cursor.take_while(|char| !char.is_whitespace());
367+
let (start, len) = {
368+
let start = cursor.pos();
369+
let mut len = 0;
370+
let mut backslash = false;
371+
let mut depth = 0u32;
372+
while let Some((_, c)) = cursor.next() {
373+
if backslash {
374+
backslash = false;
375+
} else if c == '\\' {
376+
backslash = true;
377+
} else if c == '[' {
378+
depth = depth.saturating_add(1);
379+
} else if c == ']' {
380+
depth = depth.saturating_sub(1);
381+
}
382+
383+
// If we see top-level whitespace, we're done.
384+
if depth == 0 && c.is_whitespace() {
385+
break;
386+
}
387+
388+
// If we see a line break, we're done.
389+
if matches!(c, '\r' | '\n') {
390+
break;
391+
}
392+
393+
len += c.len_utf8();
394+
}
395+
(start, len)
396+
};
397+
361398
let url = cursor.slice(start, len);
362399
if url.is_empty() {
363400
return Err(Pep508Error {

crates/requirements-txt/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ fs-err = { workspace = true }
2626
regex = { workspace = true }
2727
reqwest = { workspace = true, optional = true }
2828
reqwest-middleware = { workspace = true, optional = true }
29+
thiserror = { workspace = true }
2930
tracing = { workspace = true }
3031
unscanny = { workspace = true }
3132
url = { workspace = true }

0 commit comments

Comments
 (0)