Rename custom-typeshed-dir, target-version and current-directory CLI options (#14930)

## Summary

This PR renames the `--custom-typeshed-dir`, `target-version`, and
`--current-directory` cli options to `--typeshed`,
`--python-version`, and `--project` as discussed in the CLI proposal
document.
I added aliases for `--target-version` (for Ruff compat) and
`--custom-typeshed-dir` (for Alex)

## Test Plan

Long help

```
An extremely fast Python type checker.

Usage: red_knot [OPTIONS] [COMMAND]

Commands:
  server  Start the language server
  help    Print this message or the help of the given subcommand(s)

Options:
      --project <PROJECT>
          Run the command within the given project directory.
          
          All `pyproject.toml` files will be discovered by walking up the directory tree from the project root, as will the project's virtual environment (`.venv`).
          
          Other command-line arguments (such as relative paths) will be resolved relative to the current working directory."#,

      --venv-path <PATH>
          Path to the virtual environment the project uses.
          
          If provided, red-knot will use the `site-packages` directory of this virtual environment to resolve type information for the project's third-party dependencies.

      --typeshed-path <PATH>
          Custom directory to use for stdlib typeshed stubs

      --extra-search-path <PATH>
          Additional path to use as a module-resolution source (can be passed multiple times)

      --python-version <VERSION>
          Python version to assume when resolving types
          
          [possible values: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13]

  -v, --verbose...
          Use verbose output (or `-vv` and `-vvv` for more verbose output)

  -W, --watch
          Run in watch mode by re-running whenever files change

  -h, --help
          Print help (see a summary with '-h')

  -V, --version
          Print version
```

Short help 

```
An extremely fast Python type checker.

Usage: red_knot [OPTIONS] [COMMAND]

Commands:
  server  Start the language server
  help    Print this message or the help of the given subcommand(s)

Options:
      --project <PROJECT>         Run the command within the given project directory
      --venv-path <PATH>          Path to the virtual environment the project uses
      --typeshed-path <PATH>      Custom directory to use for stdlib typeshed stubs
      --extra-search-path <PATH>  Additional path to use as a module-resolution source (can be passed multiple times)
      --python-version <VERSION>  Python version to assume when resolving types [possible values: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13]
  -v, --verbose...                Use verbose output (or `-vv` and `-vvv` for more verbose output)
  -W, --watch                     Run in watch mode by re-running whenever files change
  -h, --help                      Print help (see more with '--help')
  -V, --version                   Print version

```

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
Micha Reiser 2024-12-13 09:21:52 +01:00 committed by GitHub
parent d7ce548893
commit c1837e4189
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 280 additions and 297 deletions

View file

@ -5,6 +5,7 @@ use anyhow::{anyhow, Context};
use clap::Parser;
use colored::Colorize;
use crossbeam::channel as crossbeam_channel;
use python_version::PythonVersion;
use red_knot_python_semantic::SitePackages;
use red_knot_server::run_server;
use red_knot_workspace::db::RootDatabase;
@ -15,12 +16,11 @@ use red_knot_workspace::workspace::WorkspaceMetadata;
use ruff_db::diagnostic::Diagnostic;
use ruff_db::system::{OsSystem, System, SystemPath, SystemPathBuf};
use salsa::plumbing::ZalsaDatabase;
use target_version::TargetVersion;
use crate::logging::{setup_tracing, Verbosity};
mod logging;
mod target_version;
mod python_version;
mod verbosity;
#[derive(Debug, Parser)]
@ -34,54 +34,39 @@ struct Args {
#[command(subcommand)]
pub(crate) command: Option<Command>,
#[arg(
long,
help = "Changes the current working directory.",
long_help = "Changes the current working directory before any specified operations. This affects the workspace and configuration discovery.",
value_name = "PATH"
)]
current_directory: Option<SystemPathBuf>,
/// Run the command within the given project directory.
///
/// All `pyproject.toml` files will be discovered by walking up the directory tree from the given project directory,
/// as will the project's virtual environment (`.venv`) unless the `venv-path` option is set.
///
/// Other command-line arguments (such as relative paths) will be resolved relative to the current working directory.
#[arg(long, value_name = "PROJECT")]
project: Option<SystemPathBuf>,
#[arg(
long,
help = "Path to the virtual environment the project uses",
long_help = "\
Path to the virtual environment the project uses. \
If provided, red-knot will use the `site-packages` directory of this virtual environment \
to resolve type information for the project's third-party dependencies.",
value_name = "PATH"
)]
/// Path to the virtual environment the project uses.
///
/// If provided, red-knot will use the `site-packages` directory of this virtual environment
/// to resolve type information for the project's third-party dependencies.
#[arg(long, value_name = "PATH")]
venv_path: Option<SystemPathBuf>,
#[arg(
long,
value_name = "DIRECTORY",
help = "Custom directory to use for stdlib typeshed stubs"
)]
custom_typeshed_dir: Option<SystemPathBuf>,
/// Custom directory to use for stdlib typeshed stubs.
#[arg(long, value_name = "PATH", alias = "custom-typeshed-dir")]
typeshed: Option<SystemPathBuf>,
#[arg(
long,
value_name = "PATH",
help = "Additional path to use as a module-resolution source (can be passed multiple times)"
)]
/// Additional path to use as a module-resolution source (can be passed multiple times).
#[arg(long, value_name = "PATH")]
extra_search_path: Option<Vec<SystemPathBuf>>,
#[arg(
long,
help = "Python version to assume when resolving types",
value_name = "VERSION"
)]
target_version: Option<TargetVersion>,
/// Python version to assume when resolving types.
#[arg(long, value_name = "VERSION", alias = "target-version")]
python_version: Option<PythonVersion>,
#[clap(flatten)]
verbosity: Verbosity,
#[arg(
long,
help = "Run in watch mode by re-running whenever files change",
short = 'W'
)]
/// Run in watch mode by re-running whenever files change.
#[arg(long, short = 'W')]
watch: bool,
}
@ -89,8 +74,8 @@ impl Args {
fn to_configuration(&self, cli_cwd: &SystemPath) -> Configuration {
let mut configuration = Configuration::default();
if let Some(target_version) = self.target_version {
configuration.target_version = Some(target_version.into());
if let Some(python_version) = self.python_version {
configuration.python_version = Some(python_version.into());
}
if let Some(venv_path) = &self.venv_path {
@ -99,9 +84,8 @@ impl Args {
});
}
if let Some(custom_typeshed_dir) = &self.custom_typeshed_dir {
configuration.search_paths.custom_typeshed =
Some(SystemPath::absolute(custom_typeshed_dir, cli_cwd));
if let Some(typeshed) = &self.typeshed {
configuration.search_paths.typeshed = Some(SystemPath::absolute(typeshed, cli_cwd));
}
if let Some(extra_search_paths) = &self.extra_search_path {
@ -167,15 +151,13 @@ fn run() -> anyhow::Result<ExitStatus> {
};
let cwd = args
.current_directory
.project
.as_ref()
.map(|cwd| {
if cwd.as_std_path().is_dir() {
Ok(SystemPath::absolute(cwd, &cli_base_path))
} else {
Err(anyhow!(
"Provided current-directory path `{cwd}` is not a directory"
))
Err(anyhow!("Provided project path `{cwd}` is not a directory"))
}
})
.transpose()?

View file

@ -0,0 +1,68 @@
/// Enumeration of all supported Python versions
///
/// TODO: unify with the `PythonVersion` enum in the linter/formatter crates?
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Default, clap::ValueEnum)]
pub enum PythonVersion {
#[value(name = "3.7")]
Py37,
#[value(name = "3.8")]
Py38,
#[default]
#[value(name = "3.9")]
Py39,
#[value(name = "3.10")]
Py310,
#[value(name = "3.11")]
Py311,
#[value(name = "3.12")]
Py312,
#[value(name = "3.13")]
Py313,
}
impl PythonVersion {
const fn as_str(self) -> &'static str {
match self {
Self::Py37 => "3.7",
Self::Py38 => "3.8",
Self::Py39 => "3.9",
Self::Py310 => "3.10",
Self::Py311 => "3.11",
Self::Py312 => "3.12",
Self::Py313 => "3.13",
}
}
}
impl std::fmt::Display for PythonVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
impl From<PythonVersion> for red_knot_python_semantic::PythonVersion {
fn from(value: PythonVersion) -> Self {
match value {
PythonVersion::Py37 => Self::PY37,
PythonVersion::Py38 => Self::PY38,
PythonVersion::Py39 => Self::PY39,
PythonVersion::Py310 => Self::PY310,
PythonVersion::Py311 => Self::PY311,
PythonVersion::Py312 => Self::PY312,
PythonVersion::Py313 => Self::PY313,
}
}
}
#[cfg(test)]
mod tests {
use crate::python_version::PythonVersion;
#[test]
fn same_default_as_python_version() {
assert_eq!(
red_knot_python_semantic::PythonVersion::from(PythonVersion::default()),
red_knot_python_semantic::PythonVersion::default()
);
}
}

View file

@ -1,62 +0,0 @@
/// Enumeration of all supported Python versions
///
/// TODO: unify with the `PythonVersion` enum in the linter/formatter crates?
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Default, clap::ValueEnum)]
pub enum TargetVersion {
Py37,
Py38,
#[default]
Py39,
Py310,
Py311,
Py312,
Py313,
}
impl TargetVersion {
const fn as_str(self) -> &'static str {
match self {
Self::Py37 => "py37",
Self::Py38 => "py38",
Self::Py39 => "py39",
Self::Py310 => "py310",
Self::Py311 => "py311",
Self::Py312 => "py312",
Self::Py313 => "py313",
}
}
}
impl std::fmt::Display for TargetVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
impl From<TargetVersion> for red_knot_python_semantic::PythonVersion {
fn from(value: TargetVersion) -> Self {
match value {
TargetVersion::Py37 => Self::PY37,
TargetVersion::Py38 => Self::PY38,
TargetVersion::Py39 => Self::PY39,
TargetVersion::Py310 => Self::PY310,
TargetVersion::Py311 => Self::PY311,
TargetVersion::Py312 => Self::PY312,
TargetVersion::Py313 => Self::PY313,
}
}
}
#[cfg(test)]
mod tests {
use crate::target_version::TargetVersion;
use red_knot_python_semantic::PythonVersion;
#[test]
fn same_default_as_python_version() {
assert_eq!(
PythonVersion::from(TargetVersion::default()),
PythonVersion::default()
);
}
}

View file

@ -282,7 +282,7 @@ where
.extra_paths
.iter()
.flatten()
.chain(search_paths.custom_typeshed.iter())
.chain(search_paths.typeshed.iter())
.chain(search_paths.site_packages.iter().flat_map(|site_packages| {
if let SitePackages::Known(path) = site_packages {
path.as_slice()
@ -296,7 +296,7 @@ where
}
let configuration = Configuration {
target_version: Some(PythonVersion::PY312),
python_version: Some(PythonVersion::PY312),
search_paths,
};
@ -888,7 +888,7 @@ fn changed_versions_file() -> anyhow::Result<()> {
Ok(())
},
|root_path, _workspace_path| SearchPathConfiguration {
custom_typeshed: Some(root_path.join("typeshed")),
typeshed: Some(root_path.join("typeshed")),
..SearchPathConfiguration::default()
},
)?;

View file

@ -135,7 +135,7 @@ if "" < lorem == "ipsum":
```toml
[environment]
target-version = "3.11"
python-version = "3.11"
```
```py

View file

@ -51,7 +51,7 @@ def f():
```toml
[environment]
target-version = "3.11"
python-version = "3.11"
```
```py

View file

@ -5,7 +5,7 @@ The following configuration will be attached to the *root* section (without any
```toml
[environment]
target-version = "3.10"
python-version = "3.10"
```
# Basic
@ -34,7 +34,7 @@ Here, we make sure that we can overwrite the global configuration in a child sec
```toml
[environment]
target-version = "3.11"
python-version = "3.11"
```
```py
@ -55,7 +55,7 @@ Children in this section should all use the section configuration:
```toml
[environment]
target-version = "3.12"
python-version = "3.12"
```
## Child

View file

@ -77,7 +77,7 @@ def _(m: int, n: int):
```toml
[environment]
target-version = "3.9"
python-version = "3.9"
```
```py

View file

@ -2,7 +2,7 @@
```toml
[environment]
target-version = "3.9"
python-version = "3.9"
```
## The type of `sys.version_info`

View file

@ -166,12 +166,12 @@ pub(crate) mod tests {
.context("Failed to write test files")?;
let mut search_paths = SearchPathSettings::new(src_root);
search_paths.custom_typeshed = self.custom_typeshed;
search_paths.typeshed = self.custom_typeshed;
Program::from_settings(
&db,
&ProgramSettings {
target_version: self.python_version,
python_version: self.python_version,
search_paths,
},
)

View file

@ -283,9 +283,9 @@ fn query_stdlib_version(
let Some(module_name) = stdlib_path_to_module_name(relative_path) else {
return TypeshedVersionsQueryResult::DoesNotExist;
};
let ResolverContext { db, target_version } = context;
let ResolverContext { db, python_version } = context;
typeshed_versions(*db).query_module(&module_name, *target_version)
typeshed_versions(*db).query_module(&module_name, *python_version)
}
/// Enumeration describing the various ways in which validation of a search path might fail.
@ -658,7 +658,7 @@ mod tests {
let TestCase {
db, src, stdlib, ..
} = TestCaseBuilder::new()
.with_custom_typeshed(MockedTypeshed::default())
.with_mocked_typeshed(MockedTypeshed::default())
.build();
assert_eq!(
@ -779,7 +779,7 @@ mod tests {
#[should_panic(expected = "Extension must be `pyi`; got `py`")]
fn stdlib_path_invalid_join_py() {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(MockedTypeshed::default())
.with_mocked_typeshed(MockedTypeshed::default())
.build();
SearchPath::custom_stdlib(&db, stdlib.parent().unwrap())
.unwrap()
@ -791,7 +791,7 @@ mod tests {
#[should_panic(expected = "Extension must be `pyi`; got `rs`")]
fn stdlib_path_invalid_join_rs() {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(MockedTypeshed::default())
.with_mocked_typeshed(MockedTypeshed::default())
.build();
SearchPath::custom_stdlib(&db, stdlib.parent().unwrap())
.unwrap()
@ -822,7 +822,7 @@ mod tests {
#[test]
fn relativize_stdlib_path_errors() {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(MockedTypeshed::default())
.with_mocked_typeshed(MockedTypeshed::default())
.build();
let root = SearchPath::custom_stdlib(&db, stdlib.parent().unwrap()).unwrap();
@ -867,11 +867,11 @@ mod tests {
fn typeshed_test_case(
typeshed: MockedTypeshed,
target_version: PythonVersion,
python_version: PythonVersion,
) -> (TestDb, SearchPath) {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(typeshed)
.with_target_version(target_version)
.with_mocked_typeshed(typeshed)
.with_python_version(python_version)
.build();
let stdlib = SearchPath::custom_stdlib(&db, stdlib.parent().unwrap()).unwrap();
(db, stdlib)

View file

@ -160,7 +160,7 @@ impl SearchPaths {
let SearchPathSettings {
extra_paths,
src_root,
custom_typeshed,
typeshed,
site_packages: site_packages_paths,
} = settings;
@ -180,17 +180,13 @@ impl SearchPaths {
tracing::debug!("Adding first-party search path '{src_root}'");
static_paths.push(SearchPath::first_party(system, src_root.to_path_buf())?);
let (typeshed_versions, stdlib_path) = if let Some(custom_typeshed) = custom_typeshed {
let custom_typeshed = canonicalize(custom_typeshed, system);
tracing::debug!("Adding custom-stdlib search path '{custom_typeshed}'");
let (typeshed_versions, stdlib_path) = if let Some(typeshed) = typeshed {
let typeshed = canonicalize(typeshed, system);
tracing::debug!("Adding custom-stdlib search path '{typeshed}'");
files.try_add_root(
db.upcast(),
&custom_typeshed,
FileRootKind::LibrarySearchPath,
);
files.try_add_root(db.upcast(), &typeshed, FileRootKind::LibrarySearchPath);
let versions_path = custom_typeshed.join("stdlib/VERSIONS");
let versions_path = typeshed.join("stdlib/VERSIONS");
let versions_content = system.read_to_string(&versions_path).map_err(|error| {
SearchPathValidationError::FailedToReadVersionsFile {
@ -201,7 +197,7 @@ impl SearchPaths {
let parsed: TypeshedVersions = versions_content.parse()?;
let search_path = SearchPath::custom_stdlib(db, &custom_typeshed)?;
let search_path = SearchPath::custom_stdlib(db, &typeshed)?;
(parsed, search_path)
} else {
@ -530,10 +526,10 @@ struct ModuleNameIngredient<'db> {
/// attempt to resolve the module name
fn resolve_name(db: &dyn Db, name: &ModuleName) -> Option<(SearchPath, File, ModuleKind)> {
let program = Program::get(db);
let target_version = program.target_version(db);
let resolver_state = ResolverContext::new(db, target_version);
let python_version = program.python_version(db);
let resolver_state = ResolverContext::new(db, python_version);
let is_builtin_module =
ruff_python_stdlib::sys::is_builtin_module(target_version.minor, name.as_str());
ruff_python_stdlib::sys::is_builtin_module(python_version.minor, name.as_str());
for search_path in search_paths(db) {
// When a builtin module is imported, standard module resolution is bypassed:
@ -690,12 +686,12 @@ impl PackageKind {
pub(super) struct ResolverContext<'db> {
pub(super) db: &'db dyn Db,
pub(super) target_version: PythonVersion,
pub(super) python_version: PythonVersion,
}
impl<'db> ResolverContext<'db> {
pub(super) fn new(db: &'db dyn Db, target_version: PythonVersion) -> Self {
Self { db, target_version }
pub(super) fn new(db: &'db dyn Db, python_version: PythonVersion) -> Self {
Self { db, python_version }
}
pub(super) fn vendored(&self) -> &VendoredFileSystem {
@ -771,8 +767,8 @@ mod tests {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_src_files(SRC)
.with_custom_typeshed(TYPESHED)
.with_target_version(PythonVersion::PY38)
.with_mocked_typeshed(TYPESHED)
.with_python_version(PythonVersion::PY38)
.build();
let builtins_module_name = ModuleName::new_static("builtins").unwrap();
@ -789,8 +785,8 @@ mod tests {
};
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(PythonVersion::PY38)
.with_mocked_typeshed(TYPESHED)
.with_python_version(PythonVersion::PY38)
.build();
let functools_module_name = ModuleName::new_static("functools").unwrap();
@ -842,8 +838,8 @@ mod tests {
};
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(PythonVersion::PY38)
.with_mocked_typeshed(TYPESHED)
.with_python_version(PythonVersion::PY38)
.build();
let existing_modules = create_module_names(&["asyncio", "functools", "xml.etree"]);
@ -887,8 +883,8 @@ mod tests {
};
let TestCase { db, .. } = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(PythonVersion::PY38)
.with_mocked_typeshed(TYPESHED)
.with_python_version(PythonVersion::PY38)
.build();
let nonexisting_modules = create_module_names(&[
@ -931,8 +927,8 @@ mod tests {
};
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(PythonVersion::PY39)
.with_mocked_typeshed(TYPESHED)
.with_python_version(PythonVersion::PY39)
.build();
let existing_modules = create_module_names(&[
@ -973,8 +969,8 @@ mod tests {
};
let TestCase { db, .. } = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(PythonVersion::PY39)
.with_mocked_typeshed(TYPESHED)
.with_python_version(PythonVersion::PY39)
.build();
let nonexisting_modules = create_module_names(&["importlib", "xml", "xml.etree"]);
@ -997,8 +993,8 @@ mod tests {
let TestCase { db, src, .. } = TestCaseBuilder::new()
.with_src_files(SRC)
.with_custom_typeshed(TYPESHED)
.with_target_version(PythonVersion::PY38)
.with_mocked_typeshed(TYPESHED)
.with_python_version(PythonVersion::PY38)
.build();
let functools_module_name = ModuleName::new_static("functools").unwrap();
@ -1022,7 +1018,7 @@ mod tests {
fn stdlib_uses_vendored_typeshed_when_no_custom_typeshed_supplied() {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_vendored_typeshed()
.with_target_version(PythonVersion::default())
.with_python_version(PythonVersion::default())
.build();
let pydoc_data_topics_name = ModuleName::new_static("pydoc_data.topics").unwrap();
@ -1290,11 +1286,11 @@ mod tests {
Program::from_settings(
&db,
&ProgramSettings {
target_version: PythonVersion::PY38,
python_version: PythonVersion::PY38,
search_paths: SearchPathSettings {
extra_paths: vec![],
src_root: src.clone(),
custom_typeshed: Some(custom_typeshed),
typeshed: Some(custom_typeshed),
site_packages: SitePackages::Known(vec![site_packages]),
},
},
@ -1333,7 +1329,7 @@ mod tests {
fn deleting_an_unrelated_file_doesnt_change_module_resolution() {
let TestCase { mut db, src, .. } = TestCaseBuilder::new()
.with_src_files(&[("foo.py", "x = 1"), ("bar.py", "x = 2")])
.with_target_version(PythonVersion::PY38)
.with_python_version(PythonVersion::PY38)
.build();
let foo_module_name = ModuleName::new_static("foo").unwrap();
@ -1420,8 +1416,8 @@ mod tests {
site_packages,
..
} = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(PythonVersion::PY38)
.with_mocked_typeshed(TYPESHED)
.with_python_version(PythonVersion::PY38)
.build();
let functools_module_name = ModuleName::new_static("functools").unwrap();
@ -1468,8 +1464,8 @@ mod tests {
src,
..
} = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(PythonVersion::PY38)
.with_mocked_typeshed(TYPESHED)
.with_python_version(PythonVersion::PY38)
.build();
let functools_module_name = ModuleName::new_static("functools").unwrap();
@ -1508,8 +1504,8 @@ mod tests {
..
} = TestCaseBuilder::new()
.with_src_files(SRC)
.with_custom_typeshed(TYPESHED)
.with_target_version(PythonVersion::PY38)
.with_mocked_typeshed(TYPESHED)
.with_python_version(PythonVersion::PY38)
.build();
let functools_module_name = ModuleName::new_static("functools").unwrap();
@ -1795,11 +1791,11 @@ not_a_directory
Program::from_settings(
&db,
&ProgramSettings {
target_version: PythonVersion::default(),
python_version: PythonVersion::default(),
search_paths: SearchPathSettings {
extra_paths: vec![],
src_root: SystemPathBuf::from("/src"),
custom_typeshed: None,
typeshed: None,
site_packages: SitePackages::Known(vec![
venv_site_packages,
system_site_packages,

View file

@ -18,7 +18,7 @@ pub(crate) struct TestCase<T> {
// so this is a single directory instead of a `Vec` of directories,
// like it is in `ruff_db::Program`.
pub(crate) site_packages: SystemPathBuf,
pub(crate) target_version: PythonVersion,
pub(crate) python_version: PythonVersion,
}
/// A `(file_name, file_contents)` tuple
@ -67,7 +67,7 @@ pub(crate) struct UnspecifiedTypeshed;
/// ```rs
/// let test_case = TestCaseBuilder::new()
/// .with_src_files(...)
/// .with_target_version(...)
/// .with_python_version(...)
/// .build();
/// ```
///
@ -85,13 +85,13 @@ pub(crate) struct UnspecifiedTypeshed;
/// const TYPESHED = MockedTypeshed { ... };
///
/// let test_case = resolver_test_case()
/// .with_custom_typeshed(TYPESHED)
/// .with_target_version(...)
/// .with_mocked_typeshed(TYPESHED)
/// .with_python_version(...)
/// .build();
///
/// let test_case2 = resolver_test_case()
/// .with_vendored_typeshed()
/// .with_target_version(...)
/// .with_python_version(...)
/// .build();
/// ```
///
@ -100,7 +100,7 @@ pub(crate) struct UnspecifiedTypeshed;
/// to `()`.
pub(crate) struct TestCaseBuilder<T> {
typeshed_option: T,
target_version: PythonVersion,
python_version: PythonVersion,
first_party_files: Vec<FileSpec>,
site_packages_files: Vec<FileSpec>,
}
@ -118,9 +118,9 @@ impl<T> TestCaseBuilder<T> {
self
}
/// Specify the target Python version the module resolver should assume
pub(crate) fn with_target_version(mut self, target_version: PythonVersion) -> Self {
self.target_version = target_version;
/// Specify the Python version the module resolver should assume
pub(crate) fn with_python_version(mut self, python_version: PythonVersion) -> Self {
self.python_version = python_version;
self
}
@ -146,7 +146,7 @@ impl TestCaseBuilder<UnspecifiedTypeshed> {
pub(crate) fn new() -> TestCaseBuilder<UnspecifiedTypeshed> {
Self {
typeshed_option: UnspecifiedTypeshed,
target_version: PythonVersion::default(),
python_version: PythonVersion::default(),
first_party_files: vec![],
site_packages_files: vec![],
}
@ -156,33 +156,33 @@ impl TestCaseBuilder<UnspecifiedTypeshed> {
pub(crate) fn with_vendored_typeshed(self) -> TestCaseBuilder<VendoredTypeshed> {
let TestCaseBuilder {
typeshed_option: _,
target_version,
python_version,
first_party_files,
site_packages_files,
} = self;
TestCaseBuilder {
typeshed_option: VendoredTypeshed,
target_version,
python_version,
first_party_files,
site_packages_files,
}
}
/// Use a mock typeshed directory for this test case
pub(crate) fn with_custom_typeshed(
pub(crate) fn with_mocked_typeshed(
self,
typeshed: MockedTypeshed,
) -> TestCaseBuilder<MockedTypeshed> {
let TestCaseBuilder {
typeshed_option: _,
target_version,
python_version,
first_party_files,
site_packages_files,
} = self;
TestCaseBuilder {
typeshed_option: typeshed,
target_version,
python_version,
first_party_files,
site_packages_files,
}
@ -194,15 +194,15 @@ impl TestCaseBuilder<UnspecifiedTypeshed> {
src,
stdlib: _,
site_packages,
target_version,
} = self.with_custom_typeshed(MockedTypeshed::default()).build();
python_version,
} = self.with_mocked_typeshed(MockedTypeshed::default()).build();
TestCase {
db,
src,
stdlib: (),
site_packages,
target_version,
python_version,
}
}
}
@ -211,7 +211,7 @@ impl TestCaseBuilder<MockedTypeshed> {
pub(crate) fn build(self) -> TestCase<SystemPathBuf> {
let TestCaseBuilder {
typeshed_option,
target_version,
python_version,
first_party_files,
site_packages_files,
} = self;
@ -226,11 +226,11 @@ impl TestCaseBuilder<MockedTypeshed> {
Program::from_settings(
&db,
&ProgramSettings {
target_version,
python_version,
search_paths: SearchPathSettings {
extra_paths: vec![],
src_root: src.clone(),
custom_typeshed: Some(typeshed.clone()),
typeshed: Some(typeshed.clone()),
site_packages: SitePackages::Known(vec![site_packages.clone()]),
},
},
@ -242,7 +242,7 @@ impl TestCaseBuilder<MockedTypeshed> {
src,
stdlib: typeshed.join("stdlib"),
site_packages,
target_version,
python_version,
}
}
@ -268,7 +268,7 @@ impl TestCaseBuilder<VendoredTypeshed> {
pub(crate) fn build(self) -> TestCase<VendoredPathBuf> {
let TestCaseBuilder {
typeshed_option: VendoredTypeshed,
target_version,
python_version,
first_party_files,
site_packages_files,
} = self;
@ -282,7 +282,7 @@ impl TestCaseBuilder<VendoredTypeshed> {
Program::from_settings(
&db,
&ProgramSettings {
target_version,
python_version,
search_paths: SearchPathSettings {
site_packages: SitePackages::Known(vec![site_packages.clone()]),
..SearchPathSettings::new(src.clone())
@ -296,7 +296,7 @@ impl TestCaseBuilder<VendoredTypeshed> {
src,
stdlib: VendoredPathBuf::from("stdlib"),
site_packages,
target_version,
python_version,
}
}
}

View file

@ -112,10 +112,10 @@ impl TypeshedVersions {
pub(in crate::module_resolver) fn query_module(
&self,
module: &ModuleName,
target_version: PythonVersion,
python_version: PythonVersion,
) -> TypeshedVersionsQueryResult {
if let Some(range) = self.exact(module) {
if range.contains(target_version) {
if range.contains(python_version) {
TypeshedVersionsQueryResult::Exists
} else {
TypeshedVersionsQueryResult::DoesNotExist
@ -125,7 +125,7 @@ impl TypeshedVersions {
while let Some(module_to_try) = module {
if let Some(range) = self.exact(&module_to_try) {
return {
if range.contains(target_version) {
if range.contains(python_version) {
TypeshedVersionsQueryResult::MaybeExists
} else {
TypeshedVersionsQueryResult::DoesNotExist

View file

@ -10,7 +10,7 @@ use crate::Db;
#[salsa::input(singleton)]
pub struct Program {
pub target_version: PythonVersion,
pub python_version: PythonVersion,
#[return_ref]
pub(crate) search_paths: SearchPaths,
@ -19,16 +19,16 @@ pub struct Program {
impl Program {
pub fn from_settings(db: &dyn Db, settings: &ProgramSettings) -> anyhow::Result<Self> {
let ProgramSettings {
target_version,
python_version,
search_paths,
} = settings;
tracing::info!("Target version: Python {target_version}");
tracing::info!("Python version: Python {python_version}");
let search_paths = SearchPaths::from_settings(db, search_paths)
.with_context(|| "Invalid search path settings")?;
Ok(Program::builder(settings.target_version, search_paths)
Ok(Program::builder(settings.python_version, search_paths)
.durability(Durability::HIGH)
.new(db))
}
@ -56,7 +56,7 @@ impl Program {
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ProgramSettings {
pub target_version: PythonVersion,
pub python_version: PythonVersion,
pub search_paths: SearchPathSettings,
}
@ -75,7 +75,7 @@ pub struct SearchPathSettings {
/// Optional path to a "custom typeshed" directory on disk for us to use for standard-library types.
/// If this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,
/// bundled as a zip file in the binary
pub custom_typeshed: Option<SystemPathBuf>,
pub typeshed: Option<SystemPathBuf>,
/// The path to the user's `site-packages` directory, where third-party packages from ``PyPI`` are installed.
pub site_packages: SitePackages,
@ -86,7 +86,7 @@ impl SearchPathSettings {
Self {
src_root,
extra_paths: vec![],
custom_typeshed: None,
typeshed: None,
site_packages: SitePackages::Known(vec![]),
}
}

View file

@ -321,7 +321,7 @@ fn site_packages_directory_from_sys_prefix(
// the parsed version
//
// Note: the `python3.x` part of the `site-packages` path can't be computed from
// the `--target-version` the user has passed, as they might be running Python 3.12 locally
// the `--python-version` the user has passed, as they might be running Python 3.12 locally
// even if they've requested that we type check their code "as if" they're running 3.8.
for entry_result in system
.read_directory(&sys_prefix_path.join("lib"))

View file

@ -1344,10 +1344,10 @@ impl<'db> Type<'db> {
Type::Instance(InstanceType { class }) => {
let ty = match (class.known(db), name) {
(Some(KnownClass::VersionInfo), "major") => {
Type::IntLiteral(Program::get(db).target_version(db).major.into())
Type::IntLiteral(Program::get(db).python_version(db).major.into())
}
(Some(KnownClass::VersionInfo), "minor") => {
Type::IntLiteral(Program::get(db).target_version(db).minor.into())
Type::IntLiteral(Program::get(db).python_version(db).minor.into())
}
// TODO MRO? get_own_instance_member, get_instance_member
_ => todo_type!("instance attributes"),
@ -1799,7 +1799,7 @@ impl<'db> Type<'db> {
/// This is not exactly the type that `sys.version_info` has at runtime,
/// but it's a useful fallback for us in order to infer `Literal` types from `sys.version_info` comparisons.
fn version_info_tuple(db: &'db dyn Db) -> Self {
let target_version = Program::get(db).target_version(db);
let python_version = Program::get(db).python_version(db);
let int_instance_ty = KnownClass::Int.to_instance(db);
// TODO: just grab this type from typeshed (it's a `sys._ReleaseLevel` type alias there)
@ -1817,8 +1817,8 @@ impl<'db> Type<'db> {
};
let version_info_elements = &[
Type::IntLiteral(target_version.major.into()),
Type::IntLiteral(target_version.minor.into()),
Type::IntLiteral(python_version.major.into()),
Type::IntLiteral(python_version.minor.into()),
int_instance_ty,
release_level_ty,
int_instance_ty,
@ -2035,7 +2035,7 @@ impl<'db> KnownClass {
CoreStdlibModule::Typing
}
Self::NoDefaultType => {
let python_version = Program::get(db).target_version(db);
let python_version = Program::get(db).python_version(db);
// typing_extensions has a 3.13+ re-export for the `typing.NoDefault`
// singleton, but not for `typing._NoDefaultType`. So we need to switch

View file

@ -234,7 +234,7 @@ language tag:
````markdown
```toml
[environment]
target-version = "3.10"
python-version = "3.10"
```
````

View file

@ -4,7 +4,7 @@
//!
//! ```toml
//! [environment]
//! target-version = "3.10"
//! python-version = "3.10"
//! ```
use anyhow::Context;
@ -22,7 +22,7 @@ impl MarkdownTestConfig {
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub(crate) struct Environment {
#[serde(rename = "target-version")]
pub(crate) target_version: String,
pub(crate) python_version: String,
}

View file

@ -38,7 +38,7 @@ impl Db {
Program::from_settings(
&db,
&ProgramSettings {
target_version: PythonVersion::default(),
python_version: PythonVersion::default(),
search_paths: SearchPathSettings::new(db.workspace_root.clone()),
},
)

View file

@ -43,8 +43,8 @@ pub fn run(path: &Utf8Path, long_title: &str, short_title: &str, test_name: &str
}
Program::get(&db)
.set_target_version(&mut db)
.to(test.target_version());
.set_python_version(&mut db)
.to(test.python_version());
// Remove all files so that the db is in a "fresh" state.
db.memory_file_system().remove_all();

View file

@ -74,8 +74,8 @@ impl<'m, 's> MarkdownTest<'m, 's> {
self.files.iter()
}
pub(crate) fn target_version(&self) -> PythonVersion {
self.section.target_version
pub(crate) fn python_version(&self) -> PythonVersion {
self.section.python_version
}
}
@ -125,7 +125,7 @@ struct Section<'s> {
title: &'s str,
level: u8,
parent_id: Option<SectionId>,
target_version: PythonVersion,
python_version: PythonVersion,
}
#[newtype_index]
@ -222,7 +222,7 @@ impl<'s> Parser<'s> {
title,
level: 0,
parent_id: None,
target_version: PythonVersion::default(),
python_version: PythonVersion::default(),
});
Self {
sections,
@ -305,7 +305,7 @@ impl<'s> Parser<'s> {
title,
level: header_level.try_into()?,
parent_id: Some(parent),
target_version: self.sections[parent].target_version,
python_version: self.sections[parent].python_version,
};
if self.current_section_files.is_some() {
@ -399,22 +399,22 @@ impl<'s> Parser<'s> {
}
let config = MarkdownTestConfig::from_str(code)?;
let target_version = config.environment.target_version;
let python_version = config.environment.python_version;
let parts = target_version
let parts = python_version
.split('.')
.map(str::parse)
.collect::<Result<Vec<_>, _>>()
.context(format!(
"Invalid 'target-version' component: '{target_version}'"
"Invalid 'python-version' component: '{python_version}'"
))?;
if parts.len() != 2 {
bail!("Invalid 'target-version': expected MAJOR.MINOR, got '{target_version}'.",);
bail!("Invalid 'python-version': expected MAJOR.MINOR, got '{python_version}'.",);
}
let current_section = &mut self.sections[self.stack.top()];
current_section.target_version = PythonVersion::from((parts[0], parts[1]));
current_section.python_version = PythonVersion::from((parts[0], parts[1]));
self.current_section_has_config = true;

View file

@ -46,7 +46,7 @@ impl Workspace {
SystemPath::new(root),
&system,
Some(&Configuration {
target_version: Some(settings.target_version.into()),
python_version: Some(settings.python_version.into()),
..Configuration::default()
}),
)
@ -170,19 +170,19 @@ impl FileHandle {
#[wasm_bindgen]
pub struct Settings {
pub target_version: TargetVersion,
pub python_version: PythonVersion,
}
#[wasm_bindgen]
impl Settings {
#[wasm_bindgen(constructor)]
pub fn new(target_version: TargetVersion) -> Self {
Self { target_version }
pub fn new(python_version: PythonVersion) -> Self {
Self { python_version }
}
}
#[wasm_bindgen]
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum TargetVersion {
pub enum PythonVersion {
Py37,
Py38,
#[default]
@ -193,16 +193,16 @@ pub enum TargetVersion {
Py313,
}
impl From<TargetVersion> for red_knot_python_semantic::PythonVersion {
fn from(value: TargetVersion) -> Self {
impl From<PythonVersion> for red_knot_python_semantic::PythonVersion {
fn from(value: PythonVersion) -> Self {
match value {
TargetVersion::Py37 => Self::PY37,
TargetVersion::Py38 => Self::PY38,
TargetVersion::Py39 => Self::PY39,
TargetVersion::Py310 => Self::PY310,
TargetVersion::Py311 => Self::PY311,
TargetVersion::Py312 => Self::PY312,
TargetVersion::Py313 => Self::PY313,
PythonVersion::Py37 => Self::PY37,
PythonVersion::Py38 => Self::PY38,
PythonVersion::Py39 => Self::PY39,
PythonVersion::Py310 => Self::PY310,
PythonVersion::Py311 => Self::PY311,
PythonVersion::Py312 => Self::PY312,
PythonVersion::Py313 => Self::PY313,
}
}
}
@ -251,7 +251,7 @@ impl System for WasmSystem {
fn read_virtual_path_to_notebook(
&self,
_path: &SystemVirtualPath,
) -> Result<ruff_notebook::Notebook, ruff_notebook::NotebookError> {
) -> Result<Notebook, ruff_notebook::NotebookError> {
Err(ruff_notebook::NotebookError::Io(not_found()))
}
@ -283,7 +283,7 @@ impl System for WasmSystem {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
@ -294,14 +294,13 @@ fn not_found() -> std::io::Error {
#[cfg(test)]
mod tests {
use crate::TargetVersion;
use red_knot_python_semantic::PythonVersion;
use crate::PythonVersion;
#[test]
fn same_default_as_python_version() {
assert_eq!(
PythonVersion::from(TargetVersion::default()),
PythonVersion::default()
red_knot_python_semantic::PythonVersion::from(PythonVersion::default()),
red_knot_python_semantic::PythonVersion::default()
);
}
}

View file

@ -2,12 +2,12 @@
use wasm_bindgen_test::wasm_bindgen_test;
use red_knot_wasm::{Settings, TargetVersion, Workspace};
use red_knot_wasm::{PythonVersion, Settings, Workspace};
#[wasm_bindgen_test]
fn check() {
let settings = Settings {
target_version: TargetVersion::Py312,
python_version: PythonVersion::Py312,
};
let mut workspace = Workspace::new("/", &settings).expect("Workspace to be created");

View file

@ -21,14 +21,14 @@ impl WorkspaceSettings {
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize))]
pub struct Configuration {
pub target_version: Option<PythonVersion>,
pub python_version: Option<PythonVersion>,
pub search_paths: SearchPathConfiguration,
}
impl Configuration {
/// Extends this configuration by using the values from `with` for all values that are absent in `self`.
pub fn extend(&mut self, with: Configuration) {
self.target_version = self.target_version.or(with.target_version);
self.python_version = self.python_version.or(with.python_version);
self.search_paths.extend(with.search_paths);
}
@ -39,7 +39,7 @@ impl Configuration {
) -> WorkspaceSettings {
WorkspaceSettings {
program: ProgramSettings {
target_version: self.target_version.unwrap_or_default(),
python_version: self.python_version.unwrap_or_default(),
search_paths: self.search_paths.to_settings(workspace_root),
},
}
@ -57,10 +57,10 @@ pub struct SearchPathConfiguration {
/// The root of the workspace, used for finding first-party modules.
pub src_root: Option<SystemPathBuf>,
/// Optional path to a "custom typeshed" directory on disk for us to use for standard-library types.
/// Optional path to a "typeshed" directory on disk for us to use for standard-library types.
/// If this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,
/// bundled as a zip file in the binary
pub custom_typeshed: Option<SystemPathBuf>,
pub typeshed: Option<SystemPathBuf>,
/// The path to the user's `site-packages` directory, where third-party packages from ``PyPI`` are installed.
pub site_packages: Option<SitePackages>,
@ -79,7 +79,7 @@ impl SearchPathConfiguration {
.clone()
.src_root
.unwrap_or_else(|| workspace_root.to_path_buf()),
custom_typeshed: self.custom_typeshed.clone(),
typeshed: self.typeshed.clone(),
site_packages,
}
}
@ -91,8 +91,8 @@ impl SearchPathConfiguration {
if let Some(src_root) = with.src_root {
self.src_root.get_or_insert(src_root);
}
if let Some(custom_typeshed) = with.custom_typeshed {
self.custom_typeshed.get_or_insert(custom_typeshed);
if let Some(typeshed) = with.typeshed {
self.typeshed.get_or_insert(typeshed);
}
if let Some(site_packages) = with.site_packages {
self.site_packages.get_or_insert(site_packages);

View file

@ -10,11 +10,11 @@ WorkspaceMetadata(
name: Name("workspace-root"),
root: "/app",
configuration: Configuration(
target_version: None,
python_version: None,
search_paths: SearchPathConfiguration(
extra_paths: None,
src_root: None,
custom_typeshed: None,
typeshed: None,
site_packages: None,
),
),
@ -22,14 +22,14 @@ WorkspaceMetadata(
],
settings: WorkspaceSettings(
program: ProgramSettings(
target_version: PythonVersion(
python_version: PythonVersion(
major: 3,
minor: 9,
),
search_paths: SearchPathSettings(
extra_paths: [],
src_root: "/app",
custom_typeshed: None,
typeshed: None,
site_packages: Known([]),
),
),

View file

@ -10,11 +10,11 @@ WorkspaceMetadata(
name: Name("workspace-root"),
root: "/app",
configuration: Configuration(
target_version: None,
python_version: None,
search_paths: SearchPathConfiguration(
extra_paths: None,
src_root: None,
custom_typeshed: None,
typeshed: None,
site_packages: None,
),
),
@ -22,14 +22,14 @@ WorkspaceMetadata(
],
settings: WorkspaceSettings(
program: ProgramSettings(
target_version: PythonVersion(
python_version: PythonVersion(
major: 3,
minor: 9,
),
search_paths: SearchPathSettings(
extra_paths: [],
src_root: "/app",
custom_typeshed: None,
typeshed: None,
site_packages: Known([]),
),
),

View file

@ -10,11 +10,11 @@ WorkspaceMetadata(
name: Name("app"),
root: "/app",
configuration: Configuration(
target_version: None,
python_version: None,
search_paths: SearchPathConfiguration(
extra_paths: None,
src_root: None,
custom_typeshed: None,
typeshed: None,
site_packages: None,
),
),
@ -22,14 +22,14 @@ WorkspaceMetadata(
],
settings: WorkspaceSettings(
program: ProgramSettings(
target_version: PythonVersion(
python_version: PythonVersion(
major: 3,
minor: 9,
),
search_paths: SearchPathSettings(
extra_paths: [],
src_root: "/app",
custom_typeshed: None,
typeshed: None,
site_packages: Known([]),
),
),

View file

@ -10,11 +10,11 @@ WorkspaceMetadata(
name: Name("backend"),
root: "/app",
configuration: Configuration(
target_version: None,
python_version: None,
search_paths: SearchPathConfiguration(
extra_paths: None,
src_root: None,
custom_typeshed: None,
typeshed: None,
site_packages: None,
),
),
@ -22,14 +22,14 @@ WorkspaceMetadata(
],
settings: WorkspaceSettings(
program: ProgramSettings(
target_version: PythonVersion(
python_version: PythonVersion(
major: 3,
minor: 9,
),
search_paths: SearchPathSettings(
extra_paths: [],
src_root: "/app",
custom_typeshed: None,
typeshed: None,
site_packages: Known([]),
),
),

View file

@ -10,11 +10,11 @@ WorkspaceMetadata(
name: Name("workspace-root"),
root: "/app",
configuration: Configuration(
target_version: None,
python_version: None,
search_paths: SearchPathConfiguration(
extra_paths: None,
src_root: None,
custom_typeshed: None,
typeshed: None,
site_packages: None,
),
),
@ -23,11 +23,11 @@ WorkspaceMetadata(
name: Name("member-a"),
root: "/app/packages/a",
configuration: Configuration(
target_version: None,
python_version: None,
search_paths: SearchPathConfiguration(
extra_paths: None,
src_root: None,
custom_typeshed: None,
typeshed: None,
site_packages: None,
),
),
@ -35,14 +35,14 @@ WorkspaceMetadata(
],
settings: WorkspaceSettings(
program: ProgramSettings(
target_version: PythonVersion(
python_version: PythonVersion(
major: 3,
minor: 9,
),
search_paths: SearchPathSettings(
extra_paths: [],
src_root: "/app",
custom_typeshed: None,
typeshed: None,
site_packages: Known([]),
),
),

View file

@ -10,11 +10,11 @@ WorkspaceMetadata(
name: Name("workspace-root"),
root: "/app",
configuration: Configuration(
target_version: None,
python_version: None,
search_paths: SearchPathConfiguration(
extra_paths: None,
src_root: None,
custom_typeshed: None,
typeshed: None,
site_packages: None,
),
),
@ -23,11 +23,11 @@ WorkspaceMetadata(
name: Name("member-a"),
root: "/app/packages/a",
configuration: Configuration(
target_version: None,
python_version: None,
search_paths: SearchPathConfiguration(
extra_paths: None,
src_root: None,
custom_typeshed: None,
typeshed: None,
site_packages: None,
),
),
@ -36,11 +36,11 @@ WorkspaceMetadata(
name: Name("member-x"),
root: "/app/packages/x",
configuration: Configuration(
target_version: None,
python_version: None,
search_paths: SearchPathConfiguration(
extra_paths: None,
src_root: None,
custom_typeshed: None,
typeshed: None,
site_packages: None,
),
),
@ -48,14 +48,14 @@ WorkspaceMetadata(
],
settings: WorkspaceSettings(
program: ProgramSettings(
target_version: PythonVersion(
python_version: PythonVersion(
major: 3,
minor: 9,
),
search_paths: SearchPathSettings(
extra_paths: [],
src_root: "/app",
custom_typeshed: None,
typeshed: None,
site_packages: Known([]),
),
),

View file

@ -79,7 +79,7 @@ fn setup_case() -> Case {
src_root,
&system,
Some(&Configuration {
target_version: Some(PythonVersion::PY312),
python_version: Some(PythonVersion::PY312),
..Configuration::default()
}),
)

View file

@ -28,7 +28,7 @@ impl ModuleDb {
/// Initialize a [`ModuleDb`] from the given source root.
pub fn from_src_roots(
mut src_roots: impl Iterator<Item = SystemPathBuf>,
target_version: PythonVersion,
python_version: PythonVersion,
) -> Result<Self> {
let search_paths = {
// Use the first source root.
@ -48,7 +48,7 @@ impl ModuleDb {
Program::from_settings(
&db,
&ProgramSettings {
target_version,
python_version,
search_paths,
},
)?;