Skip to content

Commit 84f151a

Browse files
committed
Simplifications thanks to Micha
1 parent 45e067a commit 84f151a

File tree

3 files changed

+31
-28
lines changed

3 files changed

+31
-28
lines changed

crates/ty/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ wild = { workspace = true }
4141
ruff_db = { workspace = true, features = ["testing"] }
4242
ruff_python_trivia = { workspace = true }
4343

44-
dunce ={ workspace = true}
44+
dunce = { workspace = true }
4545
insta = { workspace = true, features = ["filters"] }
4646
insta-cmd = { workspace = true }
4747
filetime = { workspace = true }

crates/ty_python_semantic/src/program.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ impl Program {
107107
pub fn update_search_paths(
108108
self,
109109
db: &mut dyn Db,
110-
search_paths: &SearchPathSettings,
110+
search_path_settings: &SearchPathSettings,
111111
) -> anyhow::Result<()> {
112-
let search_paths = SearchPaths::from_settings(db, search_paths)?;
112+
let search_paths = SearchPaths::from_settings(db, search_path_settings)?;
113113

114114
let current_python_version = self.python_version_with_source(db);
115115
let python_version_from_environment =

crates/ty_python_semantic/src/site_packages.rs

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,6 @@ impl VirtualEnvironment {
283283
Arc::new(pyvenv_cfg_path),
284284
Some(range),
285285
));
286-
287286
Some(PythonVersionWithSource { version, source })
288287
});
289288

@@ -382,6 +381,7 @@ System site-packages will not be used for module resolution.",
382381
/// See also: <https://snarky.ca/how-virtual-environments-work/>
383382
#[derive(Debug)]
384383
struct PyvenvCfgParser<'s> {
384+
source: &'s str,
385385
cursor: Cursor<'s>,
386386
line_number: NonZeroUsize,
387387
data: RawPyvenvCfg<'s>,
@@ -390,6 +390,7 @@ struct PyvenvCfgParser<'s> {
390390
impl<'s> PyvenvCfgParser<'s> {
391391
fn new(source: &'s str) -> Self {
392392
Self {
393+
source,
393394
cursor: Cursor::new(source),
394395
line_number: NonZeroUsize::new(1).unwrap(),
395396
data: RawPyvenvCfg::default(),
@@ -409,6 +410,7 @@ impl<'s> PyvenvCfgParser<'s> {
409410
/// to the beginning of the next line.
410411
fn parse_line(&mut self) -> Result<(), PyvenvCfgParseErrorKind> {
411412
let PyvenvCfgParser {
413+
source,
412414
cursor,
413415
line_number,
414416
data,
@@ -418,35 +420,24 @@ impl<'s> PyvenvCfgParser<'s> {
418420

419421
cursor.eat_while(|c| c.is_whitespace() && c != '\n');
420422

421-
let remaining_file = cursor.chars().as_str();
422-
423-
let next_newline_position = remaining_file
424-
.find('\n')
425-
.unwrap_or(cursor.text_len().to_usize());
423+
let key_start = cursor.offset();
424+
cursor.eat_while(|c| !matches!(c, '\n' | '='));
425+
let key_end = cursor.offset();
426426

427-
// The Python standard-library's `site` module parses these files by splitting each line on
428-
// '=' characters, so that's what we should do as well.
429-
let Some(eq_position) = remaining_file[..next_newline_position].find('=') else {
427+
if !cursor.eat_char('=') {
430428
// Skip over any lines that do not contain '=' characters, same as the CPython stdlib
431429
// <https://github.com/python/cpython/blob/e64395e8eb8d3a9e35e3e534e87d427ff27ab0a5/Lib/site.py#L625-L632>
432-
cursor.skip_bytes(next_newline_position);
433-
434-
debug_assert!(
435-
matches!(cursor.first(), '\n' | ruff_python_trivia::EOF_CHAR,),
436-
"{}",
437-
cursor.first()
438-
);
439-
440430
cursor.eat_char('\n');
441431
return Ok(());
442-
};
432+
}
443433

444-
let key = remaining_file[..eq_position].trim();
434+
let key = source[TextRange::new(key_start, key_end)].trim();
445435

446-
cursor.skip_bytes(eq_position + 1);
447436
cursor.eat_while(|c| c.is_whitespace() && c != '\n');
448-
449-
let value = remaining_file[eq_position + 1..next_newline_position].trim();
437+
let value_start = cursor.offset();
438+
cursor.eat_while(|c| c != '\n');
439+
let value = source[TextRange::new(value_start, cursor.offset())].trim();
440+
cursor.eat_char('\n');
450441

451442
if value.is_empty() {
452443
return Err(PyvenvCfgParseErrorKind::MalformedKeyValuePair { line_number });
@@ -460,7 +451,7 @@ impl<'s> PyvenvCfgParser<'s> {
460451
// `virtualenv` and `uv` call this key `version_info`,
461452
// but the stdlib venv module calls it `version`
462453
"version" | "version_info" => {
463-
let version_range = TextRange::at(cursor.offset(), value.text_len());
454+
let version_range = TextRange::at(value_start, value.text_len());
464455
data.version = Some((value, version_range));
465456
}
466457
"implementation" => {
@@ -479,8 +470,6 @@ impl<'s> PyvenvCfgParser<'s> {
479470
_ => {}
480471
}
481472

482-
cursor.eat_while(|c| c != '\n');
483-
cursor.eat_char('\n');
484473
Ok(())
485474
}
486475
}
@@ -1581,4 +1570,18 @@ mod tests {
15811570
assert_eq!(&pyvenv_cfg[version.1], version.0);
15821571
assert_eq!(parsed.implementation, PythonImplementation::PyPy);
15831572
}
1573+
1574+
#[test]
1575+
fn pyvenv_cfg_with_strange_whitespace_parses() {
1576+
let pyvenv_cfg = " home= /a path with whitespace/python\t \t \nversion_info = 3.13 \n\n\n\nimplementation =PyPy";
1577+
let parsed = PyvenvCfgParser::new(pyvenv_cfg).parse().unwrap();
1578+
assert_eq!(
1579+
parsed.base_executable_home_path,
1580+
Some("/a path with whitespace/python")
1581+
);
1582+
let version = parsed.version.unwrap();
1583+
assert_eq!(version.0, "3.13");
1584+
assert_eq!(&pyvenv_cfg[version.1], version.0);
1585+
assert_eq!(parsed.implementation, PythonImplementation::PyPy);
1586+
}
15841587
}

0 commit comments

Comments
 (0)