mirror of
https://github.com/astral-sh/ruff
synced 2026-01-23 14:30:53 -05:00
[ty] Improve diagnostics if the user attempts to import a stdlib module that does not exist on their configured Python version (#18403)
This commit is contained in:
@@ -369,7 +369,7 @@ impl SearchPaths {
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn typeshed_versions(&self) -> &TypeshedVersions {
|
||||
pub(crate) fn typeshed_versions(&self) -> &TypeshedVersions {
|
||||
&self.typeshed_versions
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ impl std::error::Error for TypeshedVersionsParseError {
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub(super) enum TypeshedVersionsParseErrorKind {
|
||||
pub(crate) enum TypeshedVersionsParseErrorKind {
|
||||
TooManyLines(NonZeroUsize),
|
||||
UnexpectedNumberOfColons,
|
||||
InvalidModuleName(String),
|
||||
@@ -105,7 +105,7 @@ pub(crate) struct TypeshedVersions(FxHashMap<ModuleName, PyVersionRange>);
|
||||
|
||||
impl TypeshedVersions {
|
||||
#[must_use]
|
||||
fn exact(&self, module_name: &ModuleName) -> Option<&PyVersionRange> {
|
||||
pub(crate) fn exact(&self, module_name: &ModuleName) -> Option<&PyVersionRange> {
|
||||
self.0.get(module_name)
|
||||
}
|
||||
|
||||
@@ -257,19 +257,44 @@ impl fmt::Display for TypeshedVersions {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
enum PyVersionRange {
|
||||
pub(crate) enum PyVersionRange {
|
||||
AvailableFrom(RangeFrom<PythonVersion>),
|
||||
AvailableWithin(RangeInclusive<PythonVersion>),
|
||||
}
|
||||
|
||||
impl PyVersionRange {
|
||||
#[must_use]
|
||||
fn contains(&self, version: PythonVersion) -> bool {
|
||||
pub(crate) fn contains(&self, version: PythonVersion) -> bool {
|
||||
match self {
|
||||
Self::AvailableFrom(inner) => inner.contains(&version),
|
||||
Self::AvailableWithin(inner) => inner.contains(&version),
|
||||
}
|
||||
}
|
||||
|
||||
/// Display the version range in a way that is suitable for rendering in user-facing diagnostics.
|
||||
pub(crate) fn diagnostic_display(&self) -> impl std::fmt::Display {
|
||||
struct DiagnosticDisplay<'a>(&'a PyVersionRange);
|
||||
|
||||
impl fmt::Display for DiagnosticDisplay<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {
|
||||
PyVersionRange::AvailableFrom(range_from) => write!(f, "{}+", range_from.start),
|
||||
PyVersionRange::AvailableWithin(range_inclusive) => {
|
||||
// Don't trust the start Python version if it's 3.0 or lower.
|
||||
// Typeshed doesn't attempt to give accurate start versions if a module was added
|
||||
// in the Python 2 era.
|
||||
if range_inclusive.start() <= &(PythonVersion { major: 3, minor: 0 }) {
|
||||
write!(f, "<={}", range_inclusive.end())
|
||||
} else {
|
||||
write!(f, "{}-{}", range_inclusive.start(), range_inclusive.end())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DiagnosticDisplay(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for PyVersionRange {
|
||||
|
||||
Reference in New Issue
Block a user