[ty] Improve diagnostics if the user attempts to import a stdlib module that does not exist on their configured Python version (#18403)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / mkdocs (push) Waiting to run
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run

This commit is contained in:
Alex Waygood 2025-06-02 11:52:26 +01:00 committed by GitHub
parent 384e80ec80
commit e2d96df501
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 300 additions and 38 deletions

View file

@ -369,7 +369,7 @@ impl SearchPaths {
})
}
pub(super) fn typeshed_versions(&self) -> &TypeshedVersions {
pub(crate) fn typeshed_versions(&self) -> &TypeshedVersions {
&self.typeshed_versions
}

View file

@ -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 {