Skip to content

Commit

Permalink
[red-knot] Use vendored typeshed stubs for stdlib module resolution (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexWaygood authored Jul 9, 2024
1 parent 000dabc commit 6fa4e32
Show file tree
Hide file tree
Showing 9 changed files with 622 additions and 303 deletions.
119 changes: 70 additions & 49 deletions crates/red_knot_module_resolver/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ pub(crate) mod tests {
use salsa::DebugWithDb;

use ruff_db::files::Files;
use ruff_db::system::TestSystem;
use ruff_db::system::{DbWithTestSystem, SystemPathBuf};
use ruff_db::system::{
DbWithTestSystem, MemoryFileSystem, SystemPath, SystemPathBuf, TestSystem,
};
use ruff_db::vendored::VendoredFileSystem;

use crate::resolver::{set_module_resolution_settings, RawModuleResolutionSettings};
Expand Down Expand Up @@ -130,9 +131,9 @@ pub(crate) mod tests {
pub(crate) struct TestCaseBuilder {
db: TestDb,
src: SystemPathBuf,
custom_typeshed: SystemPathBuf,
site_packages: SystemPathBuf,
target_version: Option<TargetVersion>,
with_vendored_stubs: bool,
}

impl TestCaseBuilder {
Expand All @@ -142,31 +143,88 @@ pub(crate) mod tests {
self
}

pub(crate) fn build(self) -> TestCase {
#[must_use]
pub(crate) fn with_vendored_stubs_used(mut self) -> Self {
self.with_vendored_stubs = true;
self
}

fn create_mocked_typeshed(
typeshed_dir: &SystemPath,
fs: &MemoryFileSystem,
) -> std::io::Result<()> {
static VERSIONS_DATA: &str = "\
asyncio: 3.8- # 'Regular' package on py38+
asyncio.tasks: 3.9-3.11
collections: 3.9- # 'Regular' package on py39+
functools: 3.8-
importlib: 3.9- # Namespace package on py39+
xml: 3.8-3.8 # Namespace package on py38 only
";

fs.create_directory_all(typeshed_dir)?;
fs.write_file(typeshed_dir.join("stdlib/VERSIONS"), VERSIONS_DATA)?;

// Regular package on py38+
fs.create_directory_all(typeshed_dir.join("stdlib/asyncio"))?;
fs.touch(typeshed_dir.join("stdlib/asyncio/__init__.pyi"))?;
fs.write_file(
typeshed_dir.join("stdlib/asyncio/tasks.pyi"),
"class Task: ...",
)?;

// Regular package on py39+
fs.create_directory_all(typeshed_dir.join("stdlib/collections"))?;
fs.touch(typeshed_dir.join("stdlib/collections/__init__.pyi"))?;

// Namespace package on py38 only
fs.create_directory_all(typeshed_dir.join("stdlib/xml"))?;
fs.touch(typeshed_dir.join("stdlib/xml/etree.pyi"))?;

// Namespace package on py39+
fs.create_directory_all(typeshed_dir.join("stdlib/importlib"))?;
fs.touch(typeshed_dir.join("stdlib/importlib/abc.pyi"))?;

fs.write_file(
typeshed_dir.join("stdlib/functools.pyi"),
"def update_wrapper(): ...",
)
}

pub(crate) fn build(self) -> std::io::Result<TestCase> {
let TestCaseBuilder {
mut db,
src,
custom_typeshed,
with_vendored_stubs,
site_packages,
target_version,
} = self;

let typeshed_dir = SystemPathBuf::from("/typeshed");

let custom_typeshed = if with_vendored_stubs {
None
} else {
Self::create_mocked_typeshed(&typeshed_dir, db.memory_file_system())?;
Some(typeshed_dir.clone())
};

let settings = RawModuleResolutionSettings {
target_version: target_version.unwrap_or_default(),
extra_paths: vec![],
workspace_root: src.clone(),
custom_typeshed: Some(custom_typeshed.clone()),
custom_typeshed: custom_typeshed.clone(),
site_packages: Some(site_packages.clone()),
};

set_module_resolution_settings(&mut db, settings);

TestCase {
Ok(TestCase {
db,
src,
custom_typeshed,
site_packages,
}
src: src.clone(),
custom_typeshed: typeshed_dir,
site_packages: site_packages.clone(),
})
}
}

Expand All @@ -178,57 +236,20 @@ pub(crate) mod tests {
}

pub(crate) fn create_resolver_builder() -> std::io::Result<TestCaseBuilder> {
static VERSIONS_DATA: &str = "\
asyncio: 3.8- # 'Regular' package on py38+
asyncio.tasks: 3.9-3.11
collections: 3.9- # 'Regular' package on py39+
functools: 3.8-
importlib: 3.9- # Namespace package on py39+
xml: 3.8-3.8 # Namespace package on py38 only
";

let db = TestDb::new();

let src = SystemPathBuf::from("/src");
let site_packages = SystemPathBuf::from("/site_packages");
let custom_typeshed = SystemPathBuf::from("/typeshed");

let fs = db.memory_file_system();

fs.create_directory_all(&src)?;
fs.create_directory_all(&site_packages)?;
fs.create_directory_all(&custom_typeshed)?;
fs.write_file(custom_typeshed.join("stdlib/VERSIONS"), VERSIONS_DATA)?;

// Regular package on py38+
fs.create_directory_all(custom_typeshed.join("stdlib/asyncio"))?;
fs.touch(custom_typeshed.join("stdlib/asyncio/__init__.pyi"))?;
fs.write_file(
custom_typeshed.join("stdlib/asyncio/tasks.pyi"),
"class Task: ...",
)?;

// Regular package on py39+
fs.create_directory_all(custom_typeshed.join("stdlib/collections"))?;
fs.touch(custom_typeshed.join("stdlib/collections/__init__.pyi"))?;

// Namespace package on py38 only
fs.create_directory_all(custom_typeshed.join("stdlib/xml"))?;
fs.touch(custom_typeshed.join("stdlib/xml/etree.pyi"))?;

// Namespace package on py39+
fs.create_directory_all(custom_typeshed.join("stdlib/importlib"))?;
fs.touch(custom_typeshed.join("stdlib/importlib/abc.pyi"))?;

fs.write_file(
custom_typeshed.join("stdlib/functools.pyi"),
"def update_wrapper(): ...",
)?;

Ok(TestCaseBuilder {
db,
src,
custom_typeshed,
with_vendored_stubs: false,
site_packages,
target_version: None,
})
Expand Down
Loading

0 comments on commit 6fa4e32

Please sign in to comment.