Remove red_knot_python_semantic::python_version::TargetVersion (#12790)

This commit is contained in:
Alex Waygood 2024-08-10 14:28:31 +01:00 committed by GitHub
parent 597c5f9124
commit cf1a57df5a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 148 additions and 217 deletions

View file

@ -13,22 +13,36 @@ pub enum TargetVersion {
Py313,
}
impl std::fmt::Display for TargetVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
red_knot_python_semantic::TargetVersion::from(*self).fmt(f)
}
}
impl From<TargetVersion> for red_knot_python_semantic::TargetVersion {
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,
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,
}
}
}

View file

@ -7,7 +7,7 @@ use anyhow::{anyhow, Context};
use salsa::Setter;
use red_knot_python_semantic::{
resolve_module, ModuleName, Program, ProgramSettings, SearchPathSettings, TargetVersion,
resolve_module, ModuleName, Program, ProgramSettings, PythonVersion, SearchPathSettings,
};
use red_knot_workspace::db::RootDatabase;
use red_knot_workspace::watch;
@ -234,7 +234,7 @@ where
}
let settings = ProgramSettings {
target_version: TargetVersion::default(),
target_version: PythonVersion::default(),
search_paths,
};

View file

@ -6,7 +6,7 @@ pub use db::Db;
pub use module_name::ModuleName;
pub use module_resolver::{resolve_module, system_module_search_paths, vendored_typeshed_stubs};
pub use program::{Program, ProgramSettings, SearchPathSettings};
pub use python_version::{PythonVersion, TargetVersion, UnsupportedPythonVersion};
pub use python_version::PythonVersion;
pub use semantic_model::{HasTy, SemanticModel};
pub mod ast_node_ref;

View file

@ -626,7 +626,7 @@ mod tests {
use super::*;
use crate::module_resolver::testing::{FileSpec, MockedTypeshed, TestCase, TestCaseBuilder};
use crate::TargetVersion;
use crate::python_version::PythonVersion;
impl ModulePath {
#[must_use]
@ -866,7 +866,7 @@ mod tests {
fn typeshed_test_case(
typeshed: MockedTypeshed,
target_version: TargetVersion,
target_version: PythonVersion,
) -> (TestDb, SearchPath) {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(typeshed)
@ -878,11 +878,11 @@ mod tests {
}
fn py38_typeshed_test_case(typeshed: MockedTypeshed) -> (TestDb, SearchPath) {
typeshed_test_case(typeshed, TargetVersion::Py38)
typeshed_test_case(typeshed, PythonVersion::PY38)
}
fn py39_typeshed_test_case(typeshed: MockedTypeshed) -> (TestDb, SearchPath) {
typeshed_test_case(typeshed, TargetVersion::Py39)
typeshed_test_case(typeshed, PythonVersion::PY39)
}
#[test]
@ -898,7 +898,7 @@ mod tests {
};
let (db, stdlib_path) = py38_typeshed_test_case(TYPESHED);
let resolver = ResolverState::new(&db, TargetVersion::Py38);
let resolver = ResolverState::new(&db, PythonVersion::PY38);
let asyncio_regular_package = stdlib_path.join("asyncio");
assert!(asyncio_regular_package.is_directory(&resolver));
@ -926,7 +926,7 @@ mod tests {
};
let (db, stdlib_path) = py38_typeshed_test_case(TYPESHED);
let resolver = ResolverState::new(&db, TargetVersion::Py38);
let resolver = ResolverState::new(&db, PythonVersion::PY38);
let xml_namespace_package = stdlib_path.join("xml");
assert!(xml_namespace_package.is_directory(&resolver));
@ -948,7 +948,7 @@ mod tests {
};
let (db, stdlib_path) = py38_typeshed_test_case(TYPESHED);
let resolver = ResolverState::new(&db, TargetVersion::Py38);
let resolver = ResolverState::new(&db, PythonVersion::PY38);
let functools_module = stdlib_path.join("functools.pyi");
assert!(functools_module.to_file(&resolver).is_some());
@ -964,7 +964,7 @@ mod tests {
};
let (db, stdlib_path) = py38_typeshed_test_case(TYPESHED);
let resolver = ResolverState::new(&db, TargetVersion::Py38);
let resolver = ResolverState::new(&db, PythonVersion::PY38);
let collections_regular_package = stdlib_path.join("collections");
assert_eq!(collections_regular_package.to_file(&resolver), None);
@ -980,7 +980,7 @@ mod tests {
};
let (db, stdlib_path) = py38_typeshed_test_case(TYPESHED);
let resolver = ResolverState::new(&db, TargetVersion::Py38);
let resolver = ResolverState::new(&db, PythonVersion::PY38);
let importlib_namespace_package = stdlib_path.join("importlib");
assert_eq!(importlib_namespace_package.to_file(&resolver), None);
@ -1001,7 +1001,7 @@ mod tests {
};
let (db, stdlib_path) = py38_typeshed_test_case(TYPESHED);
let resolver = ResolverState::new(&db, TargetVersion::Py38);
let resolver = ResolverState::new(&db, PythonVersion::PY38);
let non_existent = stdlib_path.join("doesnt_even_exist");
assert_eq!(non_existent.to_file(&resolver), None);
@ -1029,7 +1029,7 @@ mod tests {
};
let (db, stdlib_path) = py39_typeshed_test_case(TYPESHED);
let resolver = ResolverState::new(&db, TargetVersion::Py39);
let resolver = ResolverState::new(&db, PythonVersion::PY39);
// Since we've set the target version to Py39,
// `collections` should now exist as a directory, according to VERSIONS...
@ -1058,7 +1058,7 @@ mod tests {
};
let (db, stdlib_path) = py39_typeshed_test_case(TYPESHED);
let resolver = ResolverState::new(&db, TargetVersion::Py39);
let resolver = ResolverState::new(&db, PythonVersion::PY39);
// The `importlib` directory now also exists
let importlib_namespace_package = stdlib_path.join("importlib");
@ -1082,7 +1082,7 @@ mod tests {
};
let (db, stdlib_path) = py39_typeshed_test_case(TYPESHED);
let resolver = ResolverState::new(&db, TargetVersion::Py39);
let resolver = ResolverState::new(&db, PythonVersion::PY39);
// The `xml` package no longer exists on py39:
let xml_namespace_package = stdlib_path.join("xml");

View file

@ -12,7 +12,7 @@ use super::path::{ModulePath, SearchPath, SearchPathValidationError};
use super::state::ResolverState;
use crate::db::Db;
use crate::module_name::ModuleName;
use crate::{Program, SearchPathSettings, TargetVersion};
use crate::{Program, PythonVersion, SearchPathSettings};
/// Resolves a module name to a module.
pub fn resolve_module(db: &dyn Db, module_name: ModuleName) -> Option<Module> {
@ -451,7 +451,7 @@ impl<'db> Iterator for PthFileIterator<'db> {
/// Validated and normalized module-resolution settings.
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct ModuleResolutionSettings {
target_version: TargetVersion,
target_version: PythonVersion,
/// Search paths that have been statically determined purely from reading Ruff's configuration settings.
/// These shouldn't ever change unless the config settings themselves change.
@ -467,7 +467,7 @@ pub(crate) struct ModuleResolutionSettings {
}
impl ModuleResolutionSettings {
fn target_version(&self) -> TargetVersion {
fn target_version(&self) -> PythonVersion {
self.target_version
}
@ -496,7 +496,7 @@ fn resolve_name(db: &dyn Db, name: &ModuleName) -> Option<(SearchPath, File, Mod
let target_version = resolver_settings.target_version();
let resolver_state = ResolverState::new(db, target_version);
let is_builtin_module =
ruff_python_stdlib::sys::is_builtin_module(target_version.minor_version(), name.as_str());
ruff_python_stdlib::sys::is_builtin_module(target_version.minor, name.as_str());
for search_path in resolver_settings.search_paths(db) {
// When a builtin module is imported, standard module resolution is bypassed:
@ -706,7 +706,7 @@ mod tests {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_src_files(SRC)
.with_custom_typeshed(TYPESHED)
.with_target_version(TargetVersion::Py38)
.with_target_version(PythonVersion::PY38)
.build();
let builtins_module_name = ModuleName::new_static("builtins").unwrap();
@ -724,7 +724,7 @@ mod tests {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(TargetVersion::Py38)
.with_target_version(PythonVersion::PY38)
.build();
let functools_module_name = ModuleName::new_static("functools").unwrap();
@ -777,7 +777,7 @@ mod tests {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(TargetVersion::Py38)
.with_target_version(PythonVersion::PY38)
.build();
let existing_modules = create_module_names(&["asyncio", "functools", "xml.etree"]);
@ -822,7 +822,7 @@ mod tests {
let TestCase { db, .. } = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(TargetVersion::Py38)
.with_target_version(PythonVersion::PY38)
.build();
let nonexisting_modules = create_module_names(&[
@ -866,7 +866,7 @@ mod tests {
let TestCase { db, stdlib, .. } = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(TargetVersion::Py39)
.with_target_version(PythonVersion::PY39)
.build();
let existing_modules = create_module_names(&[
@ -908,7 +908,7 @@ mod tests {
let TestCase { db, .. } = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(TargetVersion::Py39)
.with_target_version(PythonVersion::PY39)
.build();
let nonexisting_modules = create_module_names(&["importlib", "xml", "xml.etree"]);
@ -932,7 +932,7 @@ mod tests {
let TestCase { db, src, .. } = TestCaseBuilder::new()
.with_src_files(SRC)
.with_custom_typeshed(TYPESHED)
.with_target_version(TargetVersion::Py38)
.with_target_version(PythonVersion::PY38)
.build();
let functools_module_name = ModuleName::new_static("functools").unwrap();
@ -956,7 +956,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(TargetVersion::default())
.with_target_version(PythonVersion::default())
.build();
let pydoc_data_topics_name = ModuleName::new_static("pydoc_data.topics").unwrap();
@ -1209,7 +1209,7 @@ mod tests {
site_packages: vec![site_packages],
};
Program::new(&db, TargetVersion::Py38, search_paths);
Program::new(&db, PythonVersion::PY38, search_paths);
let foo_module = resolve_module(&db, ModuleName::new_static("foo").unwrap()).unwrap();
let bar_module = resolve_module(&db, ModuleName::new_static("bar").unwrap()).unwrap();
@ -1243,7 +1243,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(TargetVersion::Py38)
.with_target_version(PythonVersion::PY38)
.build();
let foo_module_name = ModuleName::new_static("foo").unwrap();
@ -1331,7 +1331,7 @@ mod tests {
..
} = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(TargetVersion::Py38)
.with_target_version(PythonVersion::PY38)
.build();
let functools_module_name = ModuleName::new_static("functools").unwrap();
@ -1379,7 +1379,7 @@ mod tests {
..
} = TestCaseBuilder::new()
.with_custom_typeshed(TYPESHED)
.with_target_version(TargetVersion::Py38)
.with_target_version(PythonVersion::PY38)
.build();
let functools_module_name = ModuleName::new_static("functools").unwrap();
@ -1419,7 +1419,7 @@ mod tests {
} = TestCaseBuilder::new()
.with_src_files(SRC)
.with_custom_typeshed(TYPESHED)
.with_target_version(TargetVersion::Py38)
.with_target_version(PythonVersion::PY38)
.build();
let functools_module_name = ModuleName::new_static("functools").unwrap();
@ -1705,7 +1705,7 @@ not_a_directory
Program::new(
&db,
TargetVersion::default(),
PythonVersion::default(),
SearchPathSettings {
extra_paths: vec![],
src_root: SystemPathBuf::from("/src"),

View file

@ -2,16 +2,16 @@ use ruff_db::vendored::VendoredFileSystem;
use super::typeshed::LazyTypeshedVersions;
use crate::db::Db;
use crate::TargetVersion;
use crate::python_version::PythonVersion;
pub(crate) struct ResolverState<'db> {
pub(crate) db: &'db dyn Db,
pub(crate) typeshed_versions: LazyTypeshedVersions<'db>,
pub(crate) target_version: TargetVersion,
pub(crate) target_version: PythonVersion,
}
impl<'db> ResolverState<'db> {
pub(crate) fn new(db: &'db dyn Db, target_version: TargetVersion) -> Self {
pub(crate) fn new(db: &'db dyn Db, target_version: PythonVersion) -> Self {
Self {
db,
typeshed_versions: LazyTypeshedVersions::new(),

View file

@ -3,7 +3,7 @@ use ruff_db::vendored::VendoredPathBuf;
use crate::db::tests::TestDb;
use crate::program::{Program, SearchPathSettings};
use crate::python_version::TargetVersion;
use crate::python_version::PythonVersion;
/// A test case for the module resolver.
///
@ -17,7 +17,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: TargetVersion,
pub(crate) target_version: PythonVersion,
}
/// A `(file_name, file_contents)` tuple
@ -99,7 +99,7 @@ pub(crate) struct UnspecifiedTypeshed;
/// to `()`.
pub(crate) struct TestCaseBuilder<T> {
typeshed_option: T,
target_version: TargetVersion,
target_version: PythonVersion,
first_party_files: Vec<FileSpec>,
site_packages_files: Vec<FileSpec>,
}
@ -118,7 +118,7 @@ impl<T> TestCaseBuilder<T> {
}
/// Specify the target Python version the module resolver should assume
pub(crate) fn with_target_version(mut self, target_version: TargetVersion) -> Self {
pub(crate) fn with_target_version(mut self, target_version: PythonVersion) -> Self {
self.target_version = target_version;
self
}
@ -145,7 +145,7 @@ impl TestCaseBuilder<UnspecifiedTypeshed> {
pub(crate) fn new() -> TestCaseBuilder<UnspecifiedTypeshed> {
Self {
typeshed_option: UnspecifiedTypeshed,
target_version: TargetVersion::default(),
target_version: PythonVersion::default(),
first_party_files: vec![],
site_packages_files: vec![],
}

View file

@ -14,7 +14,7 @@ use ruff_db::files::{system_path_to_file, File};
use super::vendored::vendored_typeshed_stubs;
use crate::db::Db;
use crate::module_name::ModuleName;
use crate::python_version::{PythonVersion, TargetVersion};
use crate::python_version::PythonVersion;
#[derive(Debug)]
pub(crate) struct LazyTypeshedVersions<'db>(OnceCell<&'db TypeshedVersions>);
@ -43,7 +43,7 @@ impl<'db> LazyTypeshedVersions<'db> {
db: &'db dyn Db,
module: &ModuleName,
stdlib_root: Option<&SystemPath>,
target_version: TargetVersion,
target_version: PythonVersion,
) -> TypeshedVersionsQueryResult {
let versions = self.0.get_or_init(|| {
let versions_path = if let Some(system_path) = stdlib_root {
@ -63,7 +63,7 @@ impl<'db> LazyTypeshedVersions<'db> {
// Unwrapping here is not correct...
parse_typeshed_versions(db, versions_file).as_ref().unwrap()
});
versions.query_module(module, PythonVersion::from(target_version))
versions.query_module(module, target_version)
}
}
@ -427,27 +427,27 @@ mod tests {
assert!(versions.contains_exact(&asyncio));
assert_eq!(
versions.query_module(&asyncio, TargetVersion::Py310.into()),
versions.query_module(&asyncio, PythonVersion::PY310),
TypeshedVersionsQueryResult::Exists
);
assert!(versions.contains_exact(&asyncio_staggered));
assert_eq!(
versions.query_module(&asyncio_staggered, TargetVersion::Py38.into()),
versions.query_module(&asyncio_staggered, PythonVersion::PY38),
TypeshedVersionsQueryResult::Exists
);
assert_eq!(
versions.query_module(&asyncio_staggered, TargetVersion::Py37.into()),
versions.query_module(&asyncio_staggered, PythonVersion::PY37),
TypeshedVersionsQueryResult::DoesNotExist
);
assert!(versions.contains_exact(&audioop));
assert_eq!(
versions.query_module(&audioop, TargetVersion::Py312.into()),
versions.query_module(&audioop, PythonVersion::PY312),
TypeshedVersionsQueryResult::Exists
);
assert_eq!(
versions.query_module(&audioop, TargetVersion::Py313.into()),
versions.query_module(&audioop, PythonVersion::PY313),
TypeshedVersionsQueryResult::DoesNotExist
);
}
@ -539,15 +539,15 @@ foo: 3.8- # trailing comment
assert!(parsed_versions.contains_exact(&bar));
assert_eq!(
parsed_versions.query_module(&bar, TargetVersion::Py37.into()),
parsed_versions.query_module(&bar, PythonVersion::PY37),
TypeshedVersionsQueryResult::Exists
);
assert_eq!(
parsed_versions.query_module(&bar, TargetVersion::Py310.into()),
parsed_versions.query_module(&bar, PythonVersion::PY310),
TypeshedVersionsQueryResult::Exists
);
assert_eq!(
parsed_versions.query_module(&bar, TargetVersion::Py311.into()),
parsed_versions.query_module(&bar, PythonVersion::PY311),
TypeshedVersionsQueryResult::DoesNotExist
);
}
@ -559,15 +559,15 @@ foo: 3.8- # trailing comment
assert!(parsed_versions.contains_exact(&foo));
assert_eq!(
parsed_versions.query_module(&foo, TargetVersion::Py37.into()),
parsed_versions.query_module(&foo, PythonVersion::PY37),
TypeshedVersionsQueryResult::DoesNotExist
);
assert_eq!(
parsed_versions.query_module(&foo, TargetVersion::Py38.into()),
parsed_versions.query_module(&foo, PythonVersion::PY38),
TypeshedVersionsQueryResult::Exists
);
assert_eq!(
parsed_versions.query_module(&foo, TargetVersion::Py311.into()),
parsed_versions.query_module(&foo, PythonVersion::PY311),
TypeshedVersionsQueryResult::Exists
);
}
@ -579,15 +579,15 @@ foo: 3.8- # trailing comment
assert!(parsed_versions.contains_exact(&bar_baz));
assert_eq!(
parsed_versions.query_module(&bar_baz, TargetVersion::Py37.into()),
parsed_versions.query_module(&bar_baz, PythonVersion::PY37),
TypeshedVersionsQueryResult::Exists
);
assert_eq!(
parsed_versions.query_module(&bar_baz, TargetVersion::Py39.into()),
parsed_versions.query_module(&bar_baz, PythonVersion::PY39),
TypeshedVersionsQueryResult::Exists
);
assert_eq!(
parsed_versions.query_module(&bar_baz, TargetVersion::Py310.into()),
parsed_versions.query_module(&bar_baz, PythonVersion::PY310),
TypeshedVersionsQueryResult::DoesNotExist
);
}
@ -599,15 +599,15 @@ foo: 3.8- # trailing comment
assert!(!parsed_versions.contains_exact(&bar_eggs));
assert_eq!(
parsed_versions.query_module(&bar_eggs, TargetVersion::Py37.into()),
parsed_versions.query_module(&bar_eggs, PythonVersion::PY37),
TypeshedVersionsQueryResult::MaybeExists
);
assert_eq!(
parsed_versions.query_module(&bar_eggs, TargetVersion::Py310.into()),
parsed_versions.query_module(&bar_eggs, PythonVersion::PY310),
TypeshedVersionsQueryResult::MaybeExists
);
assert_eq!(
parsed_versions.query_module(&bar_eggs, TargetVersion::Py311.into()),
parsed_versions.query_module(&bar_eggs, PythonVersion::PY311),
TypeshedVersionsQueryResult::DoesNotExist
);
}
@ -619,11 +619,11 @@ foo: 3.8- # trailing comment
assert!(!parsed_versions.contains_exact(&spam));
assert_eq!(
parsed_versions.query_module(&spam, TargetVersion::Py37.into()),
parsed_versions.query_module(&spam, PythonVersion::PY37),
TypeshedVersionsQueryResult::DoesNotExist
);
assert_eq!(
parsed_versions.query_module(&spam, TargetVersion::Py313.into()),
parsed_versions.query_module(&spam, PythonVersion::PY313),
TypeshedVersionsQueryResult::DoesNotExist
);
}

View file

@ -1,11 +1,11 @@
use crate::python_version::TargetVersion;
use crate::python_version::PythonVersion;
use crate::Db;
use ruff_db::system::SystemPathBuf;
use salsa::Durability;
#[salsa::input(singleton)]
pub struct Program {
pub target_version: TargetVersion,
pub target_version: PythonVersion,
#[return_ref]
pub search_paths: SearchPathSettings,
@ -21,7 +21,7 @@ impl Program {
#[derive(Debug, Eq, PartialEq)]
pub struct ProgramSettings {
pub target_version: TargetVersion,
pub target_version: PythonVersion,
pub search_paths: SearchPathSettings,
}

View file

@ -1,58 +1,9 @@
use std::fmt;
/// Enumeration of all supported Python versions
/// Representation of a Python version.
///
/// TODO: unify with the `PythonVersion` enum in the linter/formatter crates?
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum TargetVersion {
Py37,
#[default]
Py38,
Py39,
Py310,
Py311,
Py312,
Py313,
}
impl TargetVersion {
pub fn major_version(self) -> u8 {
PythonVersion::from(self).major
}
pub fn minor_version(self) -> u8 {
PythonVersion::from(self).minor
}
const fn as_display_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 fmt::Display for TargetVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_display_str())
}
}
impl fmt::Debug for TargetVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
/// Generic representation for a Python version.
///
/// Unlike [`TargetVersion`], this does not necessarily represent
/// a Python version that we actually support.
/// Unlike the `TargetVersion` enums in the CLI crates,
/// this does not necessarily represent a Python version that we actually support.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct PythonVersion {
pub major: u8,
@ -60,11 +11,34 @@ pub struct PythonVersion {
}
impl PythonVersion {
pub const PY37: PythonVersion = PythonVersion { major: 3, minor: 7 };
pub const PY38: PythonVersion = PythonVersion { major: 3, minor: 8 };
pub const PY39: PythonVersion = PythonVersion { major: 3, minor: 9 };
pub const PY310: PythonVersion = PythonVersion {
major: 3,
minor: 10,
};
pub const PY311: PythonVersion = PythonVersion {
major: 3,
minor: 11,
};
pub const PY312: PythonVersion = PythonVersion {
major: 3,
minor: 12,
};
pub const PY313: PythonVersion = PythonVersion {
major: 3,
minor: 13,
};
pub fn free_threaded_build_available(self) -> bool {
self >= PythonVersion {
major: 3,
minor: 13,
}
self >= PythonVersion::PY313
}
}
impl Default for PythonVersion {
fn default() -> Self {
Self::PY38
}
}
@ -86,60 +60,3 @@ impl fmt::Display for PythonVersion {
write!(f, "{major}.{minor}")
}
}
impl From<TargetVersion> for PythonVersion {
fn from(value: TargetVersion) -> Self {
match value {
TargetVersion::Py37 => PythonVersion { major: 3, minor: 7 },
TargetVersion::Py38 => PythonVersion { major: 3, minor: 8 },
TargetVersion::Py39 => PythonVersion { major: 3, minor: 9 },
TargetVersion::Py310 => PythonVersion {
major: 3,
minor: 10,
},
TargetVersion::Py311 => PythonVersion {
major: 3,
minor: 11,
},
TargetVersion::Py312 => PythonVersion {
major: 3,
minor: 12,
},
TargetVersion::Py313 => PythonVersion {
major: 3,
minor: 13,
},
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct UnsupportedPythonVersion(PythonVersion);
impl fmt::Display for UnsupportedPythonVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Python version {} is unsupported", self.0)
}
}
impl std::error::Error for UnsupportedPythonVersion {}
impl TryFrom<PythonVersion> for TargetVersion {
type Error = UnsupportedPythonVersion;
fn try_from(value: PythonVersion) -> Result<Self, Self::Error> {
let PythonVersion { major: 3, minor } = value else {
return Err(UnsupportedPythonVersion(value));
};
match minor {
7 => Ok(TargetVersion::Py37),
8 => Ok(TargetVersion::Py38),
9 => Ok(TargetVersion::Py39),
10 => Ok(TargetVersion::Py310),
11 => Ok(TargetVersion::Py311),
12 => Ok(TargetVersion::Py312),
13 => Ok(TargetVersion::Py313),
_ => Err(UnsupportedPythonVersion(value)),
}
}
}

View file

@ -169,7 +169,7 @@ mod tests {
use crate::db::tests::TestDb;
use crate::program::{Program, SearchPathSettings};
use crate::python_version::TargetVersion;
use crate::python_version::PythonVersion;
use crate::types::Type;
use crate::{HasTy, SemanticModel};
@ -177,7 +177,7 @@ mod tests {
let db = TestDb::new();
Program::new(
&db,
TargetVersion::Py38,
PythonVersion::default(),
SearchPathSettings {
extra_paths: vec![],
src_root: SystemPathBuf::from("/src"),

View file

@ -1503,7 +1503,7 @@ mod tests {
use crate::builtins::builtins_scope;
use crate::db::tests::TestDb;
use crate::program::{Program, SearchPathSettings};
use crate::python_version::TargetVersion;
use crate::python_version::PythonVersion;
use crate::semantic_index::definition::Definition;
use crate::semantic_index::symbol::FileScopeId;
use crate::semantic_index::{global_scope, semantic_index, symbol_table, use_def_map};
@ -1515,7 +1515,7 @@ mod tests {
Program::new(
&db,
TargetVersion::Py38,
PythonVersion::default(),
SearchPathSettings {
extra_paths: Vec::new(),
src_root: SystemPathBuf::from("/src"),
@ -1532,7 +1532,7 @@ mod tests {
Program::new(
&db,
TargetVersion::Py38,
PythonVersion::default(),
SearchPathSettings {
extra_paths: Vec::new(),
src_root: SystemPathBuf::from("/src"),

View file

@ -8,7 +8,7 @@ use std::sync::Arc;
use anyhow::anyhow;
use lsp_types::{ClientCapabilities, Url};
use red_knot_python_semantic::{ProgramSettings, SearchPathSettings, TargetVersion};
use red_knot_python_semantic::{ProgramSettings, PythonVersion, SearchPathSettings};
use red_knot_workspace::db::RootDatabase;
use red_knot_workspace::workspace::WorkspaceMetadata;
use ruff_db::files::{system_path_to_file, File};
@ -70,7 +70,7 @@ impl Session {
let metadata = WorkspaceMetadata::from_path(system_path, &system)?;
// TODO(dhruvmanila): Get the values from the client settings
let program_settings = ProgramSettings {
target_version: TargetVersion::default(),
target_version: PythonVersion::default(),
search_paths: SearchPathSettings {
extra_paths: vec![],
src_root: system_path.to_path_buf(),

View file

@ -184,16 +184,16 @@ pub enum TargetVersion {
Py313,
}
impl From<TargetVersion> for red_knot_python_semantic::TargetVersion {
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,
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,
}
}
}

View file

@ -305,7 +305,7 @@ enum AnyImportRef<'a> {
#[cfg(test)]
mod tests {
use red_knot_python_semantic::{Program, SearchPathSettings, TargetVersion};
use red_knot_python_semantic::{Program, PythonVersion, SearchPathSettings};
use ruff_db::files::system_path_to_file;
use ruff_db::system::{DbWithTestSystem, SystemPathBuf};
@ -322,7 +322,7 @@ mod tests {
Program::new(
&db,
TargetVersion::Py38,
PythonVersion::default(),
SearchPathSettings {
extra_paths: Vec::new(),
src_root,

View file

@ -1,4 +1,4 @@
use red_knot_python_semantic::{ProgramSettings, SearchPathSettings, TargetVersion};
use red_knot_python_semantic::{ProgramSettings, PythonVersion, SearchPathSettings};
use red_knot_workspace::db::RootDatabase;
use red_knot_workspace::lint::lint_semantic;
use red_knot_workspace::workspace::WorkspaceMetadata;
@ -17,7 +17,7 @@ fn setup_db(workspace_root: SystemPathBuf) -> anyhow::Result<RootDatabase> {
site_packages: vec![],
};
let settings = ProgramSettings {
target_version: TargetVersion::default(),
target_version: PythonVersion::default(),
search_paths,
};
let db = RootDatabase::new(workspace, settings, system);

View file

@ -1,6 +1,6 @@
#![allow(clippy::disallowed_names)]
use red_knot_python_semantic::{ProgramSettings, SearchPathSettings, TargetVersion};
use red_knot_python_semantic::{ProgramSettings, PythonVersion, SearchPathSettings};
use red_knot_workspace::db::RootDatabase;
use red_knot_workspace::workspace::WorkspaceMetadata;
use ruff_benchmark::criterion::{criterion_group, criterion_main, BatchSize, Criterion};
@ -43,7 +43,7 @@ fn setup_case() -> Case {
let src_root = SystemPath::new("/src");
let metadata = WorkspaceMetadata::from_path(src_root, &system).unwrap();
let settings = ProgramSettings {
target_version: TargetVersion::Py312,
target_version: PythonVersion::PY312,
search_paths: SearchPathSettings {
extra_paths: vec![],
src_root: src_root.to_path_buf(),