mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 05:15:12 +00:00
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:
parent
d7ce548893
commit
c1837e4189
33 changed files with 280 additions and 297 deletions
|
@ -5,6 +5,7 @@ use anyhow::{anyhow, Context};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use crossbeam::channel as crossbeam_channel;
|
use crossbeam::channel as crossbeam_channel;
|
||||||
|
use python_version::PythonVersion;
|
||||||
use red_knot_python_semantic::SitePackages;
|
use red_knot_python_semantic::SitePackages;
|
||||||
use red_knot_server::run_server;
|
use red_knot_server::run_server;
|
||||||
use red_knot_workspace::db::RootDatabase;
|
use red_knot_workspace::db::RootDatabase;
|
||||||
|
@ -15,12 +16,11 @@ use red_knot_workspace::workspace::WorkspaceMetadata;
|
||||||
use ruff_db::diagnostic::Diagnostic;
|
use ruff_db::diagnostic::Diagnostic;
|
||||||
use ruff_db::system::{OsSystem, System, SystemPath, SystemPathBuf};
|
use ruff_db::system::{OsSystem, System, SystemPath, SystemPathBuf};
|
||||||
use salsa::plumbing::ZalsaDatabase;
|
use salsa::plumbing::ZalsaDatabase;
|
||||||
use target_version::TargetVersion;
|
|
||||||
|
|
||||||
use crate::logging::{setup_tracing, Verbosity};
|
use crate::logging::{setup_tracing, Verbosity};
|
||||||
|
|
||||||
mod logging;
|
mod logging;
|
||||||
mod target_version;
|
mod python_version;
|
||||||
mod verbosity;
|
mod verbosity;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
|
@ -34,54 +34,39 @@ struct Args {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
pub(crate) command: Option<Command>,
|
pub(crate) command: Option<Command>,
|
||||||
|
|
||||||
#[arg(
|
/// Run the command within the given project directory.
|
||||||
long,
|
///
|
||||||
help = "Changes the current working directory.",
|
/// All `pyproject.toml` files will be discovered by walking up the directory tree from the given project directory,
|
||||||
long_help = "Changes the current working directory before any specified operations. This affects the workspace and configuration discovery.",
|
/// as will the project's virtual environment (`.venv`) unless the `venv-path` option is set.
|
||||||
value_name = "PATH"
|
///
|
||||||
)]
|
/// Other command-line arguments (such as relative paths) will be resolved relative to the current working directory.
|
||||||
current_directory: Option<SystemPathBuf>,
|
#[arg(long, value_name = "PROJECT")]
|
||||||
|
project: Option<SystemPathBuf>,
|
||||||
|
|
||||||
#[arg(
|
/// 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
|
||||||
long_help = "\
|
/// to resolve type information for the project's third-party dependencies.
|
||||||
Path to the virtual environment the project uses. \
|
#[arg(long, value_name = "PATH")]
|
||||||
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"
|
|
||||||
)]
|
|
||||||
venv_path: Option<SystemPathBuf>,
|
venv_path: Option<SystemPathBuf>,
|
||||||
|
|
||||||
#[arg(
|
/// Custom directory to use for stdlib typeshed stubs.
|
||||||
long,
|
#[arg(long, value_name = "PATH", alias = "custom-typeshed-dir")]
|
||||||
value_name = "DIRECTORY",
|
typeshed: Option<SystemPathBuf>,
|
||||||
help = "Custom directory to use for stdlib typeshed stubs"
|
|
||||||
)]
|
|
||||||
custom_typeshed_dir: Option<SystemPathBuf>,
|
|
||||||
|
|
||||||
#[arg(
|
/// Additional path to use as a module-resolution source (can be passed multiple times).
|
||||||
long,
|
#[arg(long, value_name = "PATH")]
|
||||||
value_name = "PATH",
|
|
||||||
help = "Additional path to use as a module-resolution source (can be passed multiple times)"
|
|
||||||
)]
|
|
||||||
extra_search_path: Option<Vec<SystemPathBuf>>,
|
extra_search_path: Option<Vec<SystemPathBuf>>,
|
||||||
|
|
||||||
#[arg(
|
/// Python version to assume when resolving types.
|
||||||
long,
|
#[arg(long, value_name = "VERSION", alias = "target-version")]
|
||||||
help = "Python version to assume when resolving types",
|
python_version: Option<PythonVersion>,
|
||||||
value_name = "VERSION"
|
|
||||||
)]
|
|
||||||
target_version: Option<TargetVersion>,
|
|
||||||
|
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
verbosity: Verbosity,
|
verbosity: Verbosity,
|
||||||
|
|
||||||
#[arg(
|
/// Run in watch mode by re-running whenever files change.
|
||||||
long,
|
#[arg(long, short = 'W')]
|
||||||
help = "Run in watch mode by re-running whenever files change",
|
|
||||||
short = 'W'
|
|
||||||
)]
|
|
||||||
watch: bool,
|
watch: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,8 +74,8 @@ impl Args {
|
||||||
fn to_configuration(&self, cli_cwd: &SystemPath) -> Configuration {
|
fn to_configuration(&self, cli_cwd: &SystemPath) -> Configuration {
|
||||||
let mut configuration = Configuration::default();
|
let mut configuration = Configuration::default();
|
||||||
|
|
||||||
if let Some(target_version) = self.target_version {
|
if let Some(python_version) = self.python_version {
|
||||||
configuration.target_version = Some(target_version.into());
|
configuration.python_version = Some(python_version.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(venv_path) = &self.venv_path {
|
if let Some(venv_path) = &self.venv_path {
|
||||||
|
@ -99,9 +84,8 @@ impl Args {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(custom_typeshed_dir) = &self.custom_typeshed_dir {
|
if let Some(typeshed) = &self.typeshed {
|
||||||
configuration.search_paths.custom_typeshed =
|
configuration.search_paths.typeshed = Some(SystemPath::absolute(typeshed, cli_cwd));
|
||||||
Some(SystemPath::absolute(custom_typeshed_dir, cli_cwd));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(extra_search_paths) = &self.extra_search_path {
|
if let Some(extra_search_paths) = &self.extra_search_path {
|
||||||
|
@ -167,15 +151,13 @@ fn run() -> anyhow::Result<ExitStatus> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let cwd = args
|
let cwd = args
|
||||||
.current_directory
|
.project
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|cwd| {
|
.map(|cwd| {
|
||||||
if cwd.as_std_path().is_dir() {
|
if cwd.as_std_path().is_dir() {
|
||||||
Ok(SystemPath::absolute(cwd, &cli_base_path))
|
Ok(SystemPath::absolute(cwd, &cli_base_path))
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow!(
|
Err(anyhow!("Provided project path `{cwd}` is not a directory"))
|
||||||
"Provided current-directory path `{cwd}` is not a directory"
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.transpose()?
|
.transpose()?
|
||||||
|
|
68
crates/red_knot/src/python_version.rs
Normal file
68
crates/red_knot/src/python_version.rs
Normal 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()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -282,7 +282,7 @@ where
|
||||||
.extra_paths
|
.extra_paths
|
||||||
.iter()
|
.iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.chain(search_paths.custom_typeshed.iter())
|
.chain(search_paths.typeshed.iter())
|
||||||
.chain(search_paths.site_packages.iter().flat_map(|site_packages| {
|
.chain(search_paths.site_packages.iter().flat_map(|site_packages| {
|
||||||
if let SitePackages::Known(path) = site_packages {
|
if let SitePackages::Known(path) = site_packages {
|
||||||
path.as_slice()
|
path.as_slice()
|
||||||
|
@ -296,7 +296,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
let configuration = Configuration {
|
let configuration = Configuration {
|
||||||
target_version: Some(PythonVersion::PY312),
|
python_version: Some(PythonVersion::PY312),
|
||||||
search_paths,
|
search_paths,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -888,7 +888,7 @@ fn changed_versions_file() -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|root_path, _workspace_path| SearchPathConfiguration {
|
|root_path, _workspace_path| SearchPathConfiguration {
|
||||||
custom_typeshed: Some(root_path.join("typeshed")),
|
typeshed: Some(root_path.join("typeshed")),
|
||||||
..SearchPathConfiguration::default()
|
..SearchPathConfiguration::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -135,7 +135,7 @@ if "" < lorem == "ipsum":
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[environment]
|
[environment]
|
||||||
target-version = "3.11"
|
python-version = "3.11"
|
||||||
```
|
```
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
|
|
@ -51,7 +51,7 @@ def f():
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[environment]
|
[environment]
|
||||||
target-version = "3.11"
|
python-version = "3.11"
|
||||||
```
|
```
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
|
|
@ -5,7 +5,7 @@ The following configuration will be attached to the *root* section (without any
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[environment]
|
[environment]
|
||||||
target-version = "3.10"
|
python-version = "3.10"
|
||||||
```
|
```
|
||||||
|
|
||||||
# Basic
|
# Basic
|
||||||
|
@ -34,7 +34,7 @@ Here, we make sure that we can overwrite the global configuration in a child sec
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[environment]
|
[environment]
|
||||||
target-version = "3.11"
|
python-version = "3.11"
|
||||||
```
|
```
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
@ -55,7 +55,7 @@ Children in this section should all use the section configuration:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[environment]
|
[environment]
|
||||||
target-version = "3.12"
|
python-version = "3.12"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Child
|
## Child
|
||||||
|
|
|
@ -77,7 +77,7 @@ def _(m: int, n: int):
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[environment]
|
[environment]
|
||||||
target-version = "3.9"
|
python-version = "3.9"
|
||||||
```
|
```
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[environment]
|
[environment]
|
||||||
target-version = "3.9"
|
python-version = "3.9"
|
||||||
```
|
```
|
||||||
|
|
||||||
## The type of `sys.version_info`
|
## The type of `sys.version_info`
|
||||||
|
|
|
@ -166,12 +166,12 @@ pub(crate) mod tests {
|
||||||
.context("Failed to write test files")?;
|
.context("Failed to write test files")?;
|
||||||
|
|
||||||
let mut search_paths = SearchPathSettings::new(src_root);
|
let mut search_paths = SearchPathSettings::new(src_root);
|
||||||
search_paths.custom_typeshed = self.custom_typeshed;
|
search_paths.typeshed = self.custom_typeshed;
|
||||||
|
|
||||||
Program::from_settings(
|
Program::from_settings(
|
||||||
&db,
|
&db,
|
||||||
&ProgramSettings {
|
&ProgramSettings {
|
||||||
target_version: self.python_version,
|
python_version: self.python_version,
|
||||||
search_paths,
|
search_paths,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -283,9 +283,9 @@ fn query_stdlib_version(
|
||||||
let Some(module_name) = stdlib_path_to_module_name(relative_path) else {
|
let Some(module_name) = stdlib_path_to_module_name(relative_path) else {
|
||||||
return TypeshedVersionsQueryResult::DoesNotExist;
|
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.
|
/// Enumeration describing the various ways in which validation of a search path might fail.
|
||||||
|
@ -658,7 +658,7 @@ mod tests {
|
||||||
let TestCase {
|
let TestCase {
|
||||||
db, src, stdlib, ..
|
db, src, stdlib, ..
|
||||||
} = TestCaseBuilder::new()
|
} = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(MockedTypeshed::default())
|
.with_mocked_typeshed(MockedTypeshed::default())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -779,7 +779,7 @@ mod tests {
|
||||||
#[should_panic(expected = "Extension must be `pyi`; got `py`")]
|
#[should_panic(expected = "Extension must be `pyi`; got `py`")]
|
||||||
fn stdlib_path_invalid_join_py() {
|
fn stdlib_path_invalid_join_py() {
|
||||||
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(MockedTypeshed::default())
|
.with_mocked_typeshed(MockedTypeshed::default())
|
||||||
.build();
|
.build();
|
||||||
SearchPath::custom_stdlib(&db, stdlib.parent().unwrap())
|
SearchPath::custom_stdlib(&db, stdlib.parent().unwrap())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -791,7 +791,7 @@ mod tests {
|
||||||
#[should_panic(expected = "Extension must be `pyi`; got `rs`")]
|
#[should_panic(expected = "Extension must be `pyi`; got `rs`")]
|
||||||
fn stdlib_path_invalid_join_rs() {
|
fn stdlib_path_invalid_join_rs() {
|
||||||
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(MockedTypeshed::default())
|
.with_mocked_typeshed(MockedTypeshed::default())
|
||||||
.build();
|
.build();
|
||||||
SearchPath::custom_stdlib(&db, stdlib.parent().unwrap())
|
SearchPath::custom_stdlib(&db, stdlib.parent().unwrap())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -822,7 +822,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn relativize_stdlib_path_errors() {
|
fn relativize_stdlib_path_errors() {
|
||||||
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(MockedTypeshed::default())
|
.with_mocked_typeshed(MockedTypeshed::default())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let root = SearchPath::custom_stdlib(&db, stdlib.parent().unwrap()).unwrap();
|
let root = SearchPath::custom_stdlib(&db, stdlib.parent().unwrap()).unwrap();
|
||||||
|
@ -867,11 +867,11 @@ mod tests {
|
||||||
|
|
||||||
fn typeshed_test_case(
|
fn typeshed_test_case(
|
||||||
typeshed: MockedTypeshed,
|
typeshed: MockedTypeshed,
|
||||||
target_version: PythonVersion,
|
python_version: PythonVersion,
|
||||||
) -> (TestDb, SearchPath) {
|
) -> (TestDb, SearchPath) {
|
||||||
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(typeshed)
|
.with_mocked_typeshed(typeshed)
|
||||||
.with_target_version(target_version)
|
.with_python_version(python_version)
|
||||||
.build();
|
.build();
|
||||||
let stdlib = SearchPath::custom_stdlib(&db, stdlib.parent().unwrap()).unwrap();
|
let stdlib = SearchPath::custom_stdlib(&db, stdlib.parent().unwrap()).unwrap();
|
||||||
(db, stdlib)
|
(db, stdlib)
|
||||||
|
|
|
@ -160,7 +160,7 @@ impl SearchPaths {
|
||||||
let SearchPathSettings {
|
let SearchPathSettings {
|
||||||
extra_paths,
|
extra_paths,
|
||||||
src_root,
|
src_root,
|
||||||
custom_typeshed,
|
typeshed,
|
||||||
site_packages: site_packages_paths,
|
site_packages: site_packages_paths,
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
|
@ -180,17 +180,13 @@ impl SearchPaths {
|
||||||
tracing::debug!("Adding first-party search path '{src_root}'");
|
tracing::debug!("Adding first-party search path '{src_root}'");
|
||||||
static_paths.push(SearchPath::first_party(system, src_root.to_path_buf())?);
|
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 (typeshed_versions, stdlib_path) = if let Some(typeshed) = typeshed {
|
||||||
let custom_typeshed = canonicalize(custom_typeshed, system);
|
let typeshed = canonicalize(typeshed, system);
|
||||||
tracing::debug!("Adding custom-stdlib search path '{custom_typeshed}'");
|
tracing::debug!("Adding custom-stdlib search path '{typeshed}'");
|
||||||
|
|
||||||
files.try_add_root(
|
files.try_add_root(db.upcast(), &typeshed, FileRootKind::LibrarySearchPath);
|
||||||
db.upcast(),
|
|
||||||
&custom_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| {
|
let versions_content = system.read_to_string(&versions_path).map_err(|error| {
|
||||||
SearchPathValidationError::FailedToReadVersionsFile {
|
SearchPathValidationError::FailedToReadVersionsFile {
|
||||||
|
@ -201,7 +197,7 @@ impl SearchPaths {
|
||||||
|
|
||||||
let parsed: TypeshedVersions = versions_content.parse()?;
|
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)
|
(parsed, search_path)
|
||||||
} else {
|
} else {
|
||||||
|
@ -530,10 +526,10 @@ struct ModuleNameIngredient<'db> {
|
||||||
/// attempt to resolve the module name
|
/// attempt to resolve the module name
|
||||||
fn resolve_name(db: &dyn Db, name: &ModuleName) -> Option<(SearchPath, File, ModuleKind)> {
|
fn resolve_name(db: &dyn Db, name: &ModuleName) -> Option<(SearchPath, File, ModuleKind)> {
|
||||||
let program = Program::get(db);
|
let program = Program::get(db);
|
||||||
let target_version = program.target_version(db);
|
let python_version = program.python_version(db);
|
||||||
let resolver_state = ResolverContext::new(db, target_version);
|
let resolver_state = ResolverContext::new(db, python_version);
|
||||||
let is_builtin_module =
|
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) {
|
for search_path in search_paths(db) {
|
||||||
// When a builtin module is imported, standard module resolution is bypassed:
|
// When a builtin module is imported, standard module resolution is bypassed:
|
||||||
|
@ -690,12 +686,12 @@ impl PackageKind {
|
||||||
|
|
||||||
pub(super) struct ResolverContext<'db> {
|
pub(super) struct ResolverContext<'db> {
|
||||||
pub(super) db: &'db dyn Db,
|
pub(super) db: &'db dyn Db,
|
||||||
pub(super) target_version: PythonVersion,
|
pub(super) python_version: PythonVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'db> ResolverContext<'db> {
|
impl<'db> ResolverContext<'db> {
|
||||||
pub(super) fn new(db: &'db dyn Db, target_version: PythonVersion) -> Self {
|
pub(super) fn new(db: &'db dyn Db, python_version: PythonVersion) -> Self {
|
||||||
Self { db, target_version }
|
Self { db, python_version }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn vendored(&self) -> &VendoredFileSystem {
|
pub(super) fn vendored(&self) -> &VendoredFileSystem {
|
||||||
|
@ -771,8 +767,8 @@ mod tests {
|
||||||
|
|
||||||
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
||||||
.with_src_files(SRC)
|
.with_src_files(SRC)
|
||||||
.with_custom_typeshed(TYPESHED)
|
.with_mocked_typeshed(TYPESHED)
|
||||||
.with_target_version(PythonVersion::PY38)
|
.with_python_version(PythonVersion::PY38)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let builtins_module_name = ModuleName::new_static("builtins").unwrap();
|
let builtins_module_name = ModuleName::new_static("builtins").unwrap();
|
||||||
|
@ -789,8 +785,8 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(TYPESHED)
|
.with_mocked_typeshed(TYPESHED)
|
||||||
.with_target_version(PythonVersion::PY38)
|
.with_python_version(PythonVersion::PY38)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let functools_module_name = ModuleName::new_static("functools").unwrap();
|
let functools_module_name = ModuleName::new_static("functools").unwrap();
|
||||||
|
@ -842,8 +838,8 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(TYPESHED)
|
.with_mocked_typeshed(TYPESHED)
|
||||||
.with_target_version(PythonVersion::PY38)
|
.with_python_version(PythonVersion::PY38)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let existing_modules = create_module_names(&["asyncio", "functools", "xml.etree"]);
|
let existing_modules = create_module_names(&["asyncio", "functools", "xml.etree"]);
|
||||||
|
@ -887,8 +883,8 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let TestCase { db, .. } = TestCaseBuilder::new()
|
let TestCase { db, .. } = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(TYPESHED)
|
.with_mocked_typeshed(TYPESHED)
|
||||||
.with_target_version(PythonVersion::PY38)
|
.with_python_version(PythonVersion::PY38)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let nonexisting_modules = create_module_names(&[
|
let nonexisting_modules = create_module_names(&[
|
||||||
|
@ -931,8 +927,8 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(TYPESHED)
|
.with_mocked_typeshed(TYPESHED)
|
||||||
.with_target_version(PythonVersion::PY39)
|
.with_python_version(PythonVersion::PY39)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let existing_modules = create_module_names(&[
|
let existing_modules = create_module_names(&[
|
||||||
|
@ -973,8 +969,8 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let TestCase { db, .. } = TestCaseBuilder::new()
|
let TestCase { db, .. } = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(TYPESHED)
|
.with_mocked_typeshed(TYPESHED)
|
||||||
.with_target_version(PythonVersion::PY39)
|
.with_python_version(PythonVersion::PY39)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let nonexisting_modules = create_module_names(&["importlib", "xml", "xml.etree"]);
|
let nonexisting_modules = create_module_names(&["importlib", "xml", "xml.etree"]);
|
||||||
|
@ -997,8 +993,8 @@ mod tests {
|
||||||
|
|
||||||
let TestCase { db, src, .. } = TestCaseBuilder::new()
|
let TestCase { db, src, .. } = TestCaseBuilder::new()
|
||||||
.with_src_files(SRC)
|
.with_src_files(SRC)
|
||||||
.with_custom_typeshed(TYPESHED)
|
.with_mocked_typeshed(TYPESHED)
|
||||||
.with_target_version(PythonVersion::PY38)
|
.with_python_version(PythonVersion::PY38)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let functools_module_name = ModuleName::new_static("functools").unwrap();
|
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() {
|
fn stdlib_uses_vendored_typeshed_when_no_custom_typeshed_supplied() {
|
||||||
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
|
||||||
.with_vendored_typeshed()
|
.with_vendored_typeshed()
|
||||||
.with_target_version(PythonVersion::default())
|
.with_python_version(PythonVersion::default())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let pydoc_data_topics_name = ModuleName::new_static("pydoc_data.topics").unwrap();
|
let pydoc_data_topics_name = ModuleName::new_static("pydoc_data.topics").unwrap();
|
||||||
|
@ -1290,11 +1286,11 @@ mod tests {
|
||||||
Program::from_settings(
|
Program::from_settings(
|
||||||
&db,
|
&db,
|
||||||
&ProgramSettings {
|
&ProgramSettings {
|
||||||
target_version: PythonVersion::PY38,
|
python_version: PythonVersion::PY38,
|
||||||
search_paths: SearchPathSettings {
|
search_paths: SearchPathSettings {
|
||||||
extra_paths: vec![],
|
extra_paths: vec![],
|
||||||
src_root: src.clone(),
|
src_root: src.clone(),
|
||||||
custom_typeshed: Some(custom_typeshed),
|
typeshed: Some(custom_typeshed),
|
||||||
site_packages: SitePackages::Known(vec![site_packages]),
|
site_packages: SitePackages::Known(vec![site_packages]),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1333,7 +1329,7 @@ mod tests {
|
||||||
fn deleting_an_unrelated_file_doesnt_change_module_resolution() {
|
fn deleting_an_unrelated_file_doesnt_change_module_resolution() {
|
||||||
let TestCase { mut db, src, .. } = TestCaseBuilder::new()
|
let TestCase { mut db, src, .. } = TestCaseBuilder::new()
|
||||||
.with_src_files(&[("foo.py", "x = 1"), ("bar.py", "x = 2")])
|
.with_src_files(&[("foo.py", "x = 1"), ("bar.py", "x = 2")])
|
||||||
.with_target_version(PythonVersion::PY38)
|
.with_python_version(PythonVersion::PY38)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let foo_module_name = ModuleName::new_static("foo").unwrap();
|
let foo_module_name = ModuleName::new_static("foo").unwrap();
|
||||||
|
@ -1420,8 +1416,8 @@ mod tests {
|
||||||
site_packages,
|
site_packages,
|
||||||
..
|
..
|
||||||
} = TestCaseBuilder::new()
|
} = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(TYPESHED)
|
.with_mocked_typeshed(TYPESHED)
|
||||||
.with_target_version(PythonVersion::PY38)
|
.with_python_version(PythonVersion::PY38)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let functools_module_name = ModuleName::new_static("functools").unwrap();
|
let functools_module_name = ModuleName::new_static("functools").unwrap();
|
||||||
|
@ -1468,8 +1464,8 @@ mod tests {
|
||||||
src,
|
src,
|
||||||
..
|
..
|
||||||
} = TestCaseBuilder::new()
|
} = TestCaseBuilder::new()
|
||||||
.with_custom_typeshed(TYPESHED)
|
.with_mocked_typeshed(TYPESHED)
|
||||||
.with_target_version(PythonVersion::PY38)
|
.with_python_version(PythonVersion::PY38)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let functools_module_name = ModuleName::new_static("functools").unwrap();
|
let functools_module_name = ModuleName::new_static("functools").unwrap();
|
||||||
|
@ -1508,8 +1504,8 @@ mod tests {
|
||||||
..
|
..
|
||||||
} = TestCaseBuilder::new()
|
} = TestCaseBuilder::new()
|
||||||
.with_src_files(SRC)
|
.with_src_files(SRC)
|
||||||
.with_custom_typeshed(TYPESHED)
|
.with_mocked_typeshed(TYPESHED)
|
||||||
.with_target_version(PythonVersion::PY38)
|
.with_python_version(PythonVersion::PY38)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let functools_module_name = ModuleName::new_static("functools").unwrap();
|
let functools_module_name = ModuleName::new_static("functools").unwrap();
|
||||||
|
@ -1795,11 +1791,11 @@ not_a_directory
|
||||||
Program::from_settings(
|
Program::from_settings(
|
||||||
&db,
|
&db,
|
||||||
&ProgramSettings {
|
&ProgramSettings {
|
||||||
target_version: PythonVersion::default(),
|
python_version: PythonVersion::default(),
|
||||||
search_paths: SearchPathSettings {
|
search_paths: SearchPathSettings {
|
||||||
extra_paths: vec![],
|
extra_paths: vec![],
|
||||||
src_root: SystemPathBuf::from("/src"),
|
src_root: SystemPathBuf::from("/src"),
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: SitePackages::Known(vec![
|
site_packages: SitePackages::Known(vec![
|
||||||
venv_site_packages,
|
venv_site_packages,
|
||||||
system_site_packages,
|
system_site_packages,
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub(crate) struct TestCase<T> {
|
||||||
// so this is a single directory instead of a `Vec` of directories,
|
// so this is a single directory instead of a `Vec` of directories,
|
||||||
// like it is in `ruff_db::Program`.
|
// like it is in `ruff_db::Program`.
|
||||||
pub(crate) site_packages: SystemPathBuf,
|
pub(crate) site_packages: SystemPathBuf,
|
||||||
pub(crate) target_version: PythonVersion,
|
pub(crate) python_version: PythonVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `(file_name, file_contents)` tuple
|
/// A `(file_name, file_contents)` tuple
|
||||||
|
@ -67,7 +67,7 @@ pub(crate) struct UnspecifiedTypeshed;
|
||||||
/// ```rs
|
/// ```rs
|
||||||
/// let test_case = TestCaseBuilder::new()
|
/// let test_case = TestCaseBuilder::new()
|
||||||
/// .with_src_files(...)
|
/// .with_src_files(...)
|
||||||
/// .with_target_version(...)
|
/// .with_python_version(...)
|
||||||
/// .build();
|
/// .build();
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -85,13 +85,13 @@ pub(crate) struct UnspecifiedTypeshed;
|
||||||
/// const TYPESHED = MockedTypeshed { ... };
|
/// const TYPESHED = MockedTypeshed { ... };
|
||||||
///
|
///
|
||||||
/// let test_case = resolver_test_case()
|
/// let test_case = resolver_test_case()
|
||||||
/// .with_custom_typeshed(TYPESHED)
|
/// .with_mocked_typeshed(TYPESHED)
|
||||||
/// .with_target_version(...)
|
/// .with_python_version(...)
|
||||||
/// .build();
|
/// .build();
|
||||||
///
|
///
|
||||||
/// let test_case2 = resolver_test_case()
|
/// let test_case2 = resolver_test_case()
|
||||||
/// .with_vendored_typeshed()
|
/// .with_vendored_typeshed()
|
||||||
/// .with_target_version(...)
|
/// .with_python_version(...)
|
||||||
/// .build();
|
/// .build();
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -100,7 +100,7 @@ pub(crate) struct UnspecifiedTypeshed;
|
||||||
/// to `()`.
|
/// to `()`.
|
||||||
pub(crate) struct TestCaseBuilder<T> {
|
pub(crate) struct TestCaseBuilder<T> {
|
||||||
typeshed_option: T,
|
typeshed_option: T,
|
||||||
target_version: PythonVersion,
|
python_version: PythonVersion,
|
||||||
first_party_files: Vec<FileSpec>,
|
first_party_files: Vec<FileSpec>,
|
||||||
site_packages_files: Vec<FileSpec>,
|
site_packages_files: Vec<FileSpec>,
|
||||||
}
|
}
|
||||||
|
@ -118,9 +118,9 @@ impl<T> TestCaseBuilder<T> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify the target Python version the module resolver should assume
|
/// Specify the Python version the module resolver should assume
|
||||||
pub(crate) fn with_target_version(mut self, target_version: PythonVersion) -> Self {
|
pub(crate) fn with_python_version(mut self, python_version: PythonVersion) -> Self {
|
||||||
self.target_version = target_version;
|
self.python_version = python_version;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ impl TestCaseBuilder<UnspecifiedTypeshed> {
|
||||||
pub(crate) fn new() -> TestCaseBuilder<UnspecifiedTypeshed> {
|
pub(crate) fn new() -> TestCaseBuilder<UnspecifiedTypeshed> {
|
||||||
Self {
|
Self {
|
||||||
typeshed_option: UnspecifiedTypeshed,
|
typeshed_option: UnspecifiedTypeshed,
|
||||||
target_version: PythonVersion::default(),
|
python_version: PythonVersion::default(),
|
||||||
first_party_files: vec![],
|
first_party_files: vec![],
|
||||||
site_packages_files: vec![],
|
site_packages_files: vec![],
|
||||||
}
|
}
|
||||||
|
@ -156,33 +156,33 @@ impl TestCaseBuilder<UnspecifiedTypeshed> {
|
||||||
pub(crate) fn with_vendored_typeshed(self) -> TestCaseBuilder<VendoredTypeshed> {
|
pub(crate) fn with_vendored_typeshed(self) -> TestCaseBuilder<VendoredTypeshed> {
|
||||||
let TestCaseBuilder {
|
let TestCaseBuilder {
|
||||||
typeshed_option: _,
|
typeshed_option: _,
|
||||||
target_version,
|
python_version,
|
||||||
first_party_files,
|
first_party_files,
|
||||||
site_packages_files,
|
site_packages_files,
|
||||||
} = self;
|
} = self;
|
||||||
TestCaseBuilder {
|
TestCaseBuilder {
|
||||||
typeshed_option: VendoredTypeshed,
|
typeshed_option: VendoredTypeshed,
|
||||||
target_version,
|
python_version,
|
||||||
first_party_files,
|
first_party_files,
|
||||||
site_packages_files,
|
site_packages_files,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use a mock typeshed directory for this test case
|
/// Use a mock typeshed directory for this test case
|
||||||
pub(crate) fn with_custom_typeshed(
|
pub(crate) fn with_mocked_typeshed(
|
||||||
self,
|
self,
|
||||||
typeshed: MockedTypeshed,
|
typeshed: MockedTypeshed,
|
||||||
) -> TestCaseBuilder<MockedTypeshed> {
|
) -> TestCaseBuilder<MockedTypeshed> {
|
||||||
let TestCaseBuilder {
|
let TestCaseBuilder {
|
||||||
typeshed_option: _,
|
typeshed_option: _,
|
||||||
target_version,
|
python_version,
|
||||||
first_party_files,
|
first_party_files,
|
||||||
site_packages_files,
|
site_packages_files,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
TestCaseBuilder {
|
TestCaseBuilder {
|
||||||
typeshed_option: typeshed,
|
typeshed_option: typeshed,
|
||||||
target_version,
|
python_version,
|
||||||
first_party_files,
|
first_party_files,
|
||||||
site_packages_files,
|
site_packages_files,
|
||||||
}
|
}
|
||||||
|
@ -194,15 +194,15 @@ impl TestCaseBuilder<UnspecifiedTypeshed> {
|
||||||
src,
|
src,
|
||||||
stdlib: _,
|
stdlib: _,
|
||||||
site_packages,
|
site_packages,
|
||||||
target_version,
|
python_version,
|
||||||
} = self.with_custom_typeshed(MockedTypeshed::default()).build();
|
} = self.with_mocked_typeshed(MockedTypeshed::default()).build();
|
||||||
|
|
||||||
TestCase {
|
TestCase {
|
||||||
db,
|
db,
|
||||||
src,
|
src,
|
||||||
stdlib: (),
|
stdlib: (),
|
||||||
site_packages,
|
site_packages,
|
||||||
target_version,
|
python_version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ impl TestCaseBuilder<MockedTypeshed> {
|
||||||
pub(crate) fn build(self) -> TestCase<SystemPathBuf> {
|
pub(crate) fn build(self) -> TestCase<SystemPathBuf> {
|
||||||
let TestCaseBuilder {
|
let TestCaseBuilder {
|
||||||
typeshed_option,
|
typeshed_option,
|
||||||
target_version,
|
python_version,
|
||||||
first_party_files,
|
first_party_files,
|
||||||
site_packages_files,
|
site_packages_files,
|
||||||
} = self;
|
} = self;
|
||||||
|
@ -226,11 +226,11 @@ impl TestCaseBuilder<MockedTypeshed> {
|
||||||
Program::from_settings(
|
Program::from_settings(
|
||||||
&db,
|
&db,
|
||||||
&ProgramSettings {
|
&ProgramSettings {
|
||||||
target_version,
|
python_version,
|
||||||
search_paths: SearchPathSettings {
|
search_paths: SearchPathSettings {
|
||||||
extra_paths: vec![],
|
extra_paths: vec![],
|
||||||
src_root: src.clone(),
|
src_root: src.clone(),
|
||||||
custom_typeshed: Some(typeshed.clone()),
|
typeshed: Some(typeshed.clone()),
|
||||||
site_packages: SitePackages::Known(vec![site_packages.clone()]),
|
site_packages: SitePackages::Known(vec![site_packages.clone()]),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -242,7 +242,7 @@ impl TestCaseBuilder<MockedTypeshed> {
|
||||||
src,
|
src,
|
||||||
stdlib: typeshed.join("stdlib"),
|
stdlib: typeshed.join("stdlib"),
|
||||||
site_packages,
|
site_packages,
|
||||||
target_version,
|
python_version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ impl TestCaseBuilder<VendoredTypeshed> {
|
||||||
pub(crate) fn build(self) -> TestCase<VendoredPathBuf> {
|
pub(crate) fn build(self) -> TestCase<VendoredPathBuf> {
|
||||||
let TestCaseBuilder {
|
let TestCaseBuilder {
|
||||||
typeshed_option: VendoredTypeshed,
|
typeshed_option: VendoredTypeshed,
|
||||||
target_version,
|
python_version,
|
||||||
first_party_files,
|
first_party_files,
|
||||||
site_packages_files,
|
site_packages_files,
|
||||||
} = self;
|
} = self;
|
||||||
|
@ -282,7 +282,7 @@ impl TestCaseBuilder<VendoredTypeshed> {
|
||||||
Program::from_settings(
|
Program::from_settings(
|
||||||
&db,
|
&db,
|
||||||
&ProgramSettings {
|
&ProgramSettings {
|
||||||
target_version,
|
python_version,
|
||||||
search_paths: SearchPathSettings {
|
search_paths: SearchPathSettings {
|
||||||
site_packages: SitePackages::Known(vec![site_packages.clone()]),
|
site_packages: SitePackages::Known(vec![site_packages.clone()]),
|
||||||
..SearchPathSettings::new(src.clone())
|
..SearchPathSettings::new(src.clone())
|
||||||
|
@ -296,7 +296,7 @@ impl TestCaseBuilder<VendoredTypeshed> {
|
||||||
src,
|
src,
|
||||||
stdlib: VendoredPathBuf::from("stdlib"),
|
stdlib: VendoredPathBuf::from("stdlib"),
|
||||||
site_packages,
|
site_packages,
|
||||||
target_version,
|
python_version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,10 +112,10 @@ impl TypeshedVersions {
|
||||||
pub(in crate::module_resolver) fn query_module(
|
pub(in crate::module_resolver) fn query_module(
|
||||||
&self,
|
&self,
|
||||||
module: &ModuleName,
|
module: &ModuleName,
|
||||||
target_version: PythonVersion,
|
python_version: PythonVersion,
|
||||||
) -> TypeshedVersionsQueryResult {
|
) -> TypeshedVersionsQueryResult {
|
||||||
if let Some(range) = self.exact(module) {
|
if let Some(range) = self.exact(module) {
|
||||||
if range.contains(target_version) {
|
if range.contains(python_version) {
|
||||||
TypeshedVersionsQueryResult::Exists
|
TypeshedVersionsQueryResult::Exists
|
||||||
} else {
|
} else {
|
||||||
TypeshedVersionsQueryResult::DoesNotExist
|
TypeshedVersionsQueryResult::DoesNotExist
|
||||||
|
@ -125,7 +125,7 @@ impl TypeshedVersions {
|
||||||
while let Some(module_to_try) = module {
|
while let Some(module_to_try) = module {
|
||||||
if let Some(range) = self.exact(&module_to_try) {
|
if let Some(range) = self.exact(&module_to_try) {
|
||||||
return {
|
return {
|
||||||
if range.contains(target_version) {
|
if range.contains(python_version) {
|
||||||
TypeshedVersionsQueryResult::MaybeExists
|
TypeshedVersionsQueryResult::MaybeExists
|
||||||
} else {
|
} else {
|
||||||
TypeshedVersionsQueryResult::DoesNotExist
|
TypeshedVersionsQueryResult::DoesNotExist
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::Db;
|
||||||
|
|
||||||
#[salsa::input(singleton)]
|
#[salsa::input(singleton)]
|
||||||
pub struct Program {
|
pub struct Program {
|
||||||
pub target_version: PythonVersion,
|
pub python_version: PythonVersion,
|
||||||
|
|
||||||
#[return_ref]
|
#[return_ref]
|
||||||
pub(crate) search_paths: SearchPaths,
|
pub(crate) search_paths: SearchPaths,
|
||||||
|
@ -19,16 +19,16 @@ pub struct Program {
|
||||||
impl Program {
|
impl Program {
|
||||||
pub fn from_settings(db: &dyn Db, settings: &ProgramSettings) -> anyhow::Result<Self> {
|
pub fn from_settings(db: &dyn Db, settings: &ProgramSettings) -> anyhow::Result<Self> {
|
||||||
let ProgramSettings {
|
let ProgramSettings {
|
||||||
target_version,
|
python_version,
|
||||||
search_paths,
|
search_paths,
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
tracing::info!("Target version: Python {target_version}");
|
tracing::info!("Python version: Python {python_version}");
|
||||||
|
|
||||||
let search_paths = SearchPaths::from_settings(db, search_paths)
|
let search_paths = SearchPaths::from_settings(db, search_paths)
|
||||||
.with_context(|| "Invalid search path settings")?;
|
.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)
|
.durability(Durability::HIGH)
|
||||||
.new(db))
|
.new(db))
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ impl Program {
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||||
pub struct ProgramSettings {
|
pub struct ProgramSettings {
|
||||||
pub target_version: PythonVersion,
|
pub python_version: PythonVersion,
|
||||||
pub search_paths: SearchPathSettings,
|
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.
|
/// 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,
|
/// If this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,
|
||||||
/// bundled as a zip file in the binary
|
/// 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.
|
/// The path to the user's `site-packages` directory, where third-party packages from ``PyPI`` are installed.
|
||||||
pub site_packages: SitePackages,
|
pub site_packages: SitePackages,
|
||||||
|
@ -86,7 +86,7 @@ impl SearchPathSettings {
|
||||||
Self {
|
Self {
|
||||||
src_root,
|
src_root,
|
||||||
extra_paths: vec![],
|
extra_paths: vec![],
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: SitePackages::Known(vec![]),
|
site_packages: SitePackages::Known(vec![]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,7 +321,7 @@ fn site_packages_directory_from_sys_prefix(
|
||||||
// the parsed version
|
// the parsed version
|
||||||
//
|
//
|
||||||
// Note: the `python3.x` part of the `site-packages` path can't be computed from
|
// 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.
|
// even if they've requested that we type check their code "as if" they're running 3.8.
|
||||||
for entry_result in system
|
for entry_result in system
|
||||||
.read_directory(&sys_prefix_path.join("lib"))
|
.read_directory(&sys_prefix_path.join("lib"))
|
||||||
|
|
|
@ -1344,10 +1344,10 @@ impl<'db> Type<'db> {
|
||||||
Type::Instance(InstanceType { class }) => {
|
Type::Instance(InstanceType { class }) => {
|
||||||
let ty = match (class.known(db), name) {
|
let ty = match (class.known(db), name) {
|
||||||
(Some(KnownClass::VersionInfo), "major") => {
|
(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") => {
|
(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 MRO? get_own_instance_member, get_instance_member
|
||||||
_ => todo_type!("instance attributes"),
|
_ => 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,
|
/// 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.
|
/// 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 {
|
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);
|
let int_instance_ty = KnownClass::Int.to_instance(db);
|
||||||
|
|
||||||
// TODO: just grab this type from typeshed (it's a `sys._ReleaseLevel` type alias there)
|
// 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 = &[
|
let version_info_elements = &[
|
||||||
Type::IntLiteral(target_version.major.into()),
|
Type::IntLiteral(python_version.major.into()),
|
||||||
Type::IntLiteral(target_version.minor.into()),
|
Type::IntLiteral(python_version.minor.into()),
|
||||||
int_instance_ty,
|
int_instance_ty,
|
||||||
release_level_ty,
|
release_level_ty,
|
||||||
int_instance_ty,
|
int_instance_ty,
|
||||||
|
@ -2035,7 +2035,7 @@ impl<'db> KnownClass {
|
||||||
CoreStdlibModule::Typing
|
CoreStdlibModule::Typing
|
||||||
}
|
}
|
||||||
Self::NoDefaultType => {
|
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`
|
// typing_extensions has a 3.13+ re-export for the `typing.NoDefault`
|
||||||
// singleton, but not for `typing._NoDefaultType`. So we need to switch
|
// singleton, but not for `typing._NoDefaultType`. So we need to switch
|
||||||
|
|
|
@ -234,7 +234,7 @@ language tag:
|
||||||
````markdown
|
````markdown
|
||||||
```toml
|
```toml
|
||||||
[environment]
|
[environment]
|
||||||
target-version = "3.10"
|
python-version = "3.10"
|
||||||
```
|
```
|
||||||
````
|
````
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//!
|
//!
|
||||||
//! ```toml
|
//! ```toml
|
||||||
//! [environment]
|
//! [environment]
|
||||||
//! target-version = "3.10"
|
//! python-version = "3.10"
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
@ -22,7 +22,7 @@ impl MarkdownTestConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub(crate) struct Environment {
|
pub(crate) struct Environment {
|
||||||
#[serde(rename = "target-version")]
|
pub(crate) python_version: String,
|
||||||
pub(crate) target_version: String,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ impl Db {
|
||||||
Program::from_settings(
|
Program::from_settings(
|
||||||
&db,
|
&db,
|
||||||
&ProgramSettings {
|
&ProgramSettings {
|
||||||
target_version: PythonVersion::default(),
|
python_version: PythonVersion::default(),
|
||||||
search_paths: SearchPathSettings::new(db.workspace_root.clone()),
|
search_paths: SearchPathSettings::new(db.workspace_root.clone()),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -43,8 +43,8 @@ pub fn run(path: &Utf8Path, long_title: &str, short_title: &str, test_name: &str
|
||||||
}
|
}
|
||||||
|
|
||||||
Program::get(&db)
|
Program::get(&db)
|
||||||
.set_target_version(&mut db)
|
.set_python_version(&mut db)
|
||||||
.to(test.target_version());
|
.to(test.python_version());
|
||||||
|
|
||||||
// Remove all files so that the db is in a "fresh" state.
|
// Remove all files so that the db is in a "fresh" state.
|
||||||
db.memory_file_system().remove_all();
|
db.memory_file_system().remove_all();
|
||||||
|
|
|
@ -74,8 +74,8 @@ impl<'m, 's> MarkdownTest<'m, 's> {
|
||||||
self.files.iter()
|
self.files.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn target_version(&self) -> PythonVersion {
|
pub(crate) fn python_version(&self) -> PythonVersion {
|
||||||
self.section.target_version
|
self.section.python_version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ struct Section<'s> {
|
||||||
title: &'s str,
|
title: &'s str,
|
||||||
level: u8,
|
level: u8,
|
||||||
parent_id: Option<SectionId>,
|
parent_id: Option<SectionId>,
|
||||||
target_version: PythonVersion,
|
python_version: PythonVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[newtype_index]
|
#[newtype_index]
|
||||||
|
@ -222,7 +222,7 @@ impl<'s> Parser<'s> {
|
||||||
title,
|
title,
|
||||||
level: 0,
|
level: 0,
|
||||||
parent_id: None,
|
parent_id: None,
|
||||||
target_version: PythonVersion::default(),
|
python_version: PythonVersion::default(),
|
||||||
});
|
});
|
||||||
Self {
|
Self {
|
||||||
sections,
|
sections,
|
||||||
|
@ -305,7 +305,7 @@ impl<'s> Parser<'s> {
|
||||||
title,
|
title,
|
||||||
level: header_level.try_into()?,
|
level: header_level.try_into()?,
|
||||||
parent_id: Some(parent),
|
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() {
|
if self.current_section_files.is_some() {
|
||||||
|
@ -399,22 +399,22 @@ impl<'s> Parser<'s> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let config = MarkdownTestConfig::from_str(code)?;
|
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('.')
|
.split('.')
|
||||||
.map(str::parse)
|
.map(str::parse)
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
.context(format!(
|
.context(format!(
|
||||||
"Invalid 'target-version' component: '{target_version}'"
|
"Invalid 'python-version' component: '{python_version}'"
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
if parts.len() != 2 {
|
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()];
|
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;
|
self.current_section_has_config = true;
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ impl Workspace {
|
||||||
SystemPath::new(root),
|
SystemPath::new(root),
|
||||||
&system,
|
&system,
|
||||||
Some(&Configuration {
|
Some(&Configuration {
|
||||||
target_version: Some(settings.target_version.into()),
|
python_version: Some(settings.python_version.into()),
|
||||||
..Configuration::default()
|
..Configuration::default()
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
@ -170,19 +170,19 @@ impl FileHandle {
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub target_version: TargetVersion,
|
pub python_version: PythonVersion,
|
||||||
}
|
}
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
impl Settings {
|
impl Settings {
|
||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
pub fn new(target_version: TargetVersion) -> Self {
|
pub fn new(python_version: PythonVersion) -> Self {
|
||||||
Self { target_version }
|
Self { python_version }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
|
||||||
pub enum TargetVersion {
|
pub enum PythonVersion {
|
||||||
Py37,
|
Py37,
|
||||||
Py38,
|
Py38,
|
||||||
#[default]
|
#[default]
|
||||||
|
@ -193,16 +193,16 @@ pub enum TargetVersion {
|
||||||
Py313,
|
Py313,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TargetVersion> for red_knot_python_semantic::PythonVersion {
|
impl From<PythonVersion> for red_knot_python_semantic::PythonVersion {
|
||||||
fn from(value: TargetVersion) -> Self {
|
fn from(value: PythonVersion) -> Self {
|
||||||
match value {
|
match value {
|
||||||
TargetVersion::Py37 => Self::PY37,
|
PythonVersion::Py37 => Self::PY37,
|
||||||
TargetVersion::Py38 => Self::PY38,
|
PythonVersion::Py38 => Self::PY38,
|
||||||
TargetVersion::Py39 => Self::PY39,
|
PythonVersion::Py39 => Self::PY39,
|
||||||
TargetVersion::Py310 => Self::PY310,
|
PythonVersion::Py310 => Self::PY310,
|
||||||
TargetVersion::Py311 => Self::PY311,
|
PythonVersion::Py311 => Self::PY311,
|
||||||
TargetVersion::Py312 => Self::PY312,
|
PythonVersion::Py312 => Self::PY312,
|
||||||
TargetVersion::Py313 => Self::PY313,
|
PythonVersion::Py313 => Self::PY313,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,7 @@ impl System for WasmSystem {
|
||||||
fn read_virtual_path_to_notebook(
|
fn read_virtual_path_to_notebook(
|
||||||
&self,
|
&self,
|
||||||
_path: &SystemVirtualPath,
|
_path: &SystemVirtualPath,
|
||||||
) -> Result<ruff_notebook::Notebook, ruff_notebook::NotebookError> {
|
) -> Result<Notebook, ruff_notebook::NotebookError> {
|
||||||
Err(ruff_notebook::NotebookError::Io(not_found()))
|
Err(ruff_notebook::NotebookError::Io(not_found()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ impl System for WasmSystem {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,14 +294,13 @@ fn not_found() -> std::io::Error {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::TargetVersion;
|
use crate::PythonVersion;
|
||||||
use red_knot_python_semantic::PythonVersion;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn same_default_as_python_version() {
|
fn same_default_as_python_version() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
PythonVersion::from(TargetVersion::default()),
|
red_knot_python_semantic::PythonVersion::from(PythonVersion::default()),
|
||||||
PythonVersion::default()
|
red_knot_python_semantic::PythonVersion::default()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
use wasm_bindgen_test::wasm_bindgen_test;
|
use wasm_bindgen_test::wasm_bindgen_test;
|
||||||
|
|
||||||
use red_knot_wasm::{Settings, TargetVersion, Workspace};
|
use red_knot_wasm::{PythonVersion, Settings, Workspace};
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn check() {
|
fn check() {
|
||||||
let settings = Settings {
|
let settings = Settings {
|
||||||
target_version: TargetVersion::Py312,
|
python_version: PythonVersion::Py312,
|
||||||
};
|
};
|
||||||
let mut workspace = Workspace::new("/", &settings).expect("Workspace to be created");
|
let mut workspace = Workspace::new("/", &settings).expect("Workspace to be created");
|
||||||
|
|
||||||
|
|
|
@ -21,14 +21,14 @@ impl WorkspaceSettings {
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(test, derive(serde::Serialize))]
|
#[cfg_attr(test, derive(serde::Serialize))]
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
pub target_version: Option<PythonVersion>,
|
pub python_version: Option<PythonVersion>,
|
||||||
pub search_paths: SearchPathConfiguration,
|
pub search_paths: SearchPathConfiguration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Configuration {
|
impl Configuration {
|
||||||
/// Extends this configuration by using the values from `with` for all values that are absent in `self`.
|
/// Extends this configuration by using the values from `with` for all values that are absent in `self`.
|
||||||
pub fn extend(&mut self, with: Configuration) {
|
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);
|
self.search_paths.extend(with.search_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ impl Configuration {
|
||||||
) -> WorkspaceSettings {
|
) -> WorkspaceSettings {
|
||||||
WorkspaceSettings {
|
WorkspaceSettings {
|
||||||
program: ProgramSettings {
|
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),
|
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.
|
/// The root of the workspace, used for finding first-party modules.
|
||||||
pub src_root: Option<SystemPathBuf>,
|
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,
|
/// If this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,
|
||||||
/// bundled as a zip file in the binary
|
/// 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.
|
/// The path to the user's `site-packages` directory, where third-party packages from ``PyPI`` are installed.
|
||||||
pub site_packages: Option<SitePackages>,
|
pub site_packages: Option<SitePackages>,
|
||||||
|
@ -79,7 +79,7 @@ impl SearchPathConfiguration {
|
||||||
.clone()
|
.clone()
|
||||||
.src_root
|
.src_root
|
||||||
.unwrap_or_else(|| workspace_root.to_path_buf()),
|
.unwrap_or_else(|| workspace_root.to_path_buf()),
|
||||||
custom_typeshed: self.custom_typeshed.clone(),
|
typeshed: self.typeshed.clone(),
|
||||||
site_packages,
|
site_packages,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,8 +91,8 @@ impl SearchPathConfiguration {
|
||||||
if let Some(src_root) = with.src_root {
|
if let Some(src_root) = with.src_root {
|
||||||
self.src_root.get_or_insert(src_root);
|
self.src_root.get_or_insert(src_root);
|
||||||
}
|
}
|
||||||
if let Some(custom_typeshed) = with.custom_typeshed {
|
if let Some(typeshed) = with.typeshed {
|
||||||
self.custom_typeshed.get_or_insert(custom_typeshed);
|
self.typeshed.get_or_insert(typeshed);
|
||||||
}
|
}
|
||||||
if let Some(site_packages) = with.site_packages {
|
if let Some(site_packages) = with.site_packages {
|
||||||
self.site_packages.get_or_insert(site_packages);
|
self.site_packages.get_or_insert(site_packages);
|
||||||
|
|
|
@ -10,11 +10,11 @@ WorkspaceMetadata(
|
||||||
name: Name("workspace-root"),
|
name: Name("workspace-root"),
|
||||||
root: "/app",
|
root: "/app",
|
||||||
configuration: Configuration(
|
configuration: Configuration(
|
||||||
target_version: None,
|
python_version: None,
|
||||||
search_paths: SearchPathConfiguration(
|
search_paths: SearchPathConfiguration(
|
||||||
extra_paths: None,
|
extra_paths: None,
|
||||||
src_root: None,
|
src_root: None,
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: None,
|
site_packages: None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -22,14 +22,14 @@ WorkspaceMetadata(
|
||||||
],
|
],
|
||||||
settings: WorkspaceSettings(
|
settings: WorkspaceSettings(
|
||||||
program: ProgramSettings(
|
program: ProgramSettings(
|
||||||
target_version: PythonVersion(
|
python_version: PythonVersion(
|
||||||
major: 3,
|
major: 3,
|
||||||
minor: 9,
|
minor: 9,
|
||||||
),
|
),
|
||||||
search_paths: SearchPathSettings(
|
search_paths: SearchPathSettings(
|
||||||
extra_paths: [],
|
extra_paths: [],
|
||||||
src_root: "/app",
|
src_root: "/app",
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: Known([]),
|
site_packages: Known([]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -10,11 +10,11 @@ WorkspaceMetadata(
|
||||||
name: Name("workspace-root"),
|
name: Name("workspace-root"),
|
||||||
root: "/app",
|
root: "/app",
|
||||||
configuration: Configuration(
|
configuration: Configuration(
|
||||||
target_version: None,
|
python_version: None,
|
||||||
search_paths: SearchPathConfiguration(
|
search_paths: SearchPathConfiguration(
|
||||||
extra_paths: None,
|
extra_paths: None,
|
||||||
src_root: None,
|
src_root: None,
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: None,
|
site_packages: None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -22,14 +22,14 @@ WorkspaceMetadata(
|
||||||
],
|
],
|
||||||
settings: WorkspaceSettings(
|
settings: WorkspaceSettings(
|
||||||
program: ProgramSettings(
|
program: ProgramSettings(
|
||||||
target_version: PythonVersion(
|
python_version: PythonVersion(
|
||||||
major: 3,
|
major: 3,
|
||||||
minor: 9,
|
minor: 9,
|
||||||
),
|
),
|
||||||
search_paths: SearchPathSettings(
|
search_paths: SearchPathSettings(
|
||||||
extra_paths: [],
|
extra_paths: [],
|
||||||
src_root: "/app",
|
src_root: "/app",
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: Known([]),
|
site_packages: Known([]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -10,11 +10,11 @@ WorkspaceMetadata(
|
||||||
name: Name("app"),
|
name: Name("app"),
|
||||||
root: "/app",
|
root: "/app",
|
||||||
configuration: Configuration(
|
configuration: Configuration(
|
||||||
target_version: None,
|
python_version: None,
|
||||||
search_paths: SearchPathConfiguration(
|
search_paths: SearchPathConfiguration(
|
||||||
extra_paths: None,
|
extra_paths: None,
|
||||||
src_root: None,
|
src_root: None,
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: None,
|
site_packages: None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -22,14 +22,14 @@ WorkspaceMetadata(
|
||||||
],
|
],
|
||||||
settings: WorkspaceSettings(
|
settings: WorkspaceSettings(
|
||||||
program: ProgramSettings(
|
program: ProgramSettings(
|
||||||
target_version: PythonVersion(
|
python_version: PythonVersion(
|
||||||
major: 3,
|
major: 3,
|
||||||
minor: 9,
|
minor: 9,
|
||||||
),
|
),
|
||||||
search_paths: SearchPathSettings(
|
search_paths: SearchPathSettings(
|
||||||
extra_paths: [],
|
extra_paths: [],
|
||||||
src_root: "/app",
|
src_root: "/app",
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: Known([]),
|
site_packages: Known([]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -10,11 +10,11 @@ WorkspaceMetadata(
|
||||||
name: Name("backend"),
|
name: Name("backend"),
|
||||||
root: "/app",
|
root: "/app",
|
||||||
configuration: Configuration(
|
configuration: Configuration(
|
||||||
target_version: None,
|
python_version: None,
|
||||||
search_paths: SearchPathConfiguration(
|
search_paths: SearchPathConfiguration(
|
||||||
extra_paths: None,
|
extra_paths: None,
|
||||||
src_root: None,
|
src_root: None,
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: None,
|
site_packages: None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -22,14 +22,14 @@ WorkspaceMetadata(
|
||||||
],
|
],
|
||||||
settings: WorkspaceSettings(
|
settings: WorkspaceSettings(
|
||||||
program: ProgramSettings(
|
program: ProgramSettings(
|
||||||
target_version: PythonVersion(
|
python_version: PythonVersion(
|
||||||
major: 3,
|
major: 3,
|
||||||
minor: 9,
|
minor: 9,
|
||||||
),
|
),
|
||||||
search_paths: SearchPathSettings(
|
search_paths: SearchPathSettings(
|
||||||
extra_paths: [],
|
extra_paths: [],
|
||||||
src_root: "/app",
|
src_root: "/app",
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: Known([]),
|
site_packages: Known([]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -10,11 +10,11 @@ WorkspaceMetadata(
|
||||||
name: Name("workspace-root"),
|
name: Name("workspace-root"),
|
||||||
root: "/app",
|
root: "/app",
|
||||||
configuration: Configuration(
|
configuration: Configuration(
|
||||||
target_version: None,
|
python_version: None,
|
||||||
search_paths: SearchPathConfiguration(
|
search_paths: SearchPathConfiguration(
|
||||||
extra_paths: None,
|
extra_paths: None,
|
||||||
src_root: None,
|
src_root: None,
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: None,
|
site_packages: None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -23,11 +23,11 @@ WorkspaceMetadata(
|
||||||
name: Name("member-a"),
|
name: Name("member-a"),
|
||||||
root: "/app/packages/a",
|
root: "/app/packages/a",
|
||||||
configuration: Configuration(
|
configuration: Configuration(
|
||||||
target_version: None,
|
python_version: None,
|
||||||
search_paths: SearchPathConfiguration(
|
search_paths: SearchPathConfiguration(
|
||||||
extra_paths: None,
|
extra_paths: None,
|
||||||
src_root: None,
|
src_root: None,
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: None,
|
site_packages: None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -35,14 +35,14 @@ WorkspaceMetadata(
|
||||||
],
|
],
|
||||||
settings: WorkspaceSettings(
|
settings: WorkspaceSettings(
|
||||||
program: ProgramSettings(
|
program: ProgramSettings(
|
||||||
target_version: PythonVersion(
|
python_version: PythonVersion(
|
||||||
major: 3,
|
major: 3,
|
||||||
minor: 9,
|
minor: 9,
|
||||||
),
|
),
|
||||||
search_paths: SearchPathSettings(
|
search_paths: SearchPathSettings(
|
||||||
extra_paths: [],
|
extra_paths: [],
|
||||||
src_root: "/app",
|
src_root: "/app",
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: Known([]),
|
site_packages: Known([]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -10,11 +10,11 @@ WorkspaceMetadata(
|
||||||
name: Name("workspace-root"),
|
name: Name("workspace-root"),
|
||||||
root: "/app",
|
root: "/app",
|
||||||
configuration: Configuration(
|
configuration: Configuration(
|
||||||
target_version: None,
|
python_version: None,
|
||||||
search_paths: SearchPathConfiguration(
|
search_paths: SearchPathConfiguration(
|
||||||
extra_paths: None,
|
extra_paths: None,
|
||||||
src_root: None,
|
src_root: None,
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: None,
|
site_packages: None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -23,11 +23,11 @@ WorkspaceMetadata(
|
||||||
name: Name("member-a"),
|
name: Name("member-a"),
|
||||||
root: "/app/packages/a",
|
root: "/app/packages/a",
|
||||||
configuration: Configuration(
|
configuration: Configuration(
|
||||||
target_version: None,
|
python_version: None,
|
||||||
search_paths: SearchPathConfiguration(
|
search_paths: SearchPathConfiguration(
|
||||||
extra_paths: None,
|
extra_paths: None,
|
||||||
src_root: None,
|
src_root: None,
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: None,
|
site_packages: None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -36,11 +36,11 @@ WorkspaceMetadata(
|
||||||
name: Name("member-x"),
|
name: Name("member-x"),
|
||||||
root: "/app/packages/x",
|
root: "/app/packages/x",
|
||||||
configuration: Configuration(
|
configuration: Configuration(
|
||||||
target_version: None,
|
python_version: None,
|
||||||
search_paths: SearchPathConfiguration(
|
search_paths: SearchPathConfiguration(
|
||||||
extra_paths: None,
|
extra_paths: None,
|
||||||
src_root: None,
|
src_root: None,
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: None,
|
site_packages: None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -48,14 +48,14 @@ WorkspaceMetadata(
|
||||||
],
|
],
|
||||||
settings: WorkspaceSettings(
|
settings: WorkspaceSettings(
|
||||||
program: ProgramSettings(
|
program: ProgramSettings(
|
||||||
target_version: PythonVersion(
|
python_version: PythonVersion(
|
||||||
major: 3,
|
major: 3,
|
||||||
minor: 9,
|
minor: 9,
|
||||||
),
|
),
|
||||||
search_paths: SearchPathSettings(
|
search_paths: SearchPathSettings(
|
||||||
extra_paths: [],
|
extra_paths: [],
|
||||||
src_root: "/app",
|
src_root: "/app",
|
||||||
custom_typeshed: None,
|
typeshed: None,
|
||||||
site_packages: Known([]),
|
site_packages: Known([]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -79,7 +79,7 @@ fn setup_case() -> Case {
|
||||||
src_root,
|
src_root,
|
||||||
&system,
|
&system,
|
||||||
Some(&Configuration {
|
Some(&Configuration {
|
||||||
target_version: Some(PythonVersion::PY312),
|
python_version: Some(PythonVersion::PY312),
|
||||||
..Configuration::default()
|
..Configuration::default()
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl ModuleDb {
|
||||||
/// Initialize a [`ModuleDb`] from the given source root.
|
/// Initialize a [`ModuleDb`] from the given source root.
|
||||||
pub fn from_src_roots(
|
pub fn from_src_roots(
|
||||||
mut src_roots: impl Iterator<Item = SystemPathBuf>,
|
mut src_roots: impl Iterator<Item = SystemPathBuf>,
|
||||||
target_version: PythonVersion,
|
python_version: PythonVersion,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let search_paths = {
|
let search_paths = {
|
||||||
// Use the first source root.
|
// Use the first source root.
|
||||||
|
@ -48,7 +48,7 @@ impl ModuleDb {
|
||||||
Program::from_settings(
|
Program::from_settings(
|
||||||
&db,
|
&db,
|
||||||
&ProgramSettings {
|
&ProgramSettings {
|
||||||
target_version,
|
python_version,
|
||||||
search_paths,
|
search_paths,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue