Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions crates/ty_python_semantic/resources/mdtest/import/basic.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,26 @@ from string.templatelib import Template # error: [unresolved-import]
from importlib.resources import abc # error: [unresolved-import]
```

## Attempting to import a stdlib submodule when both parts haven't yet been added

`compression` and `compression.zstd` were both added in 3.14 so there is a typeshed `VERSIONS` entry
for `compression` but not `compression.zstd`. We can't be confident `compression.zstd` exists but we
do know `compression` does and can still give good diagnostics about it.

<!-- snapshot-diagnostics -->

```toml
[environment]
python-version = "3.10"
```

```py
import compression.zstd # error: [unresolved-import]
from compression import zstd # error: [unresolved-import]
import compression.fakebutwhocansay # error: [unresolved-import]
from compression import fakebutwhocansay # error: [unresolved-import]
```

## Attempting to import a stdlib module that was previously removed

<!-- snapshot-diagnostics -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
source: crates/ty_test/src/lib.rs
expression: snapshot
---
---
mdtest name: basic.md - Structures - Attempting to import a stdlib submodule when both parts haven't yet been added
mdtest path: crates/ty_python_semantic/resources/mdtest/import/basic.md
---

# Python source files

## mdtest_snippet.py

```
1 | import compression.zstd # error: [unresolved-import]
2 | from compression import zstd # error: [unresolved-import]
3 | import compression.fakebutwhocansay # error: [unresolved-import]
4 | from compression import fakebutwhocansay # error: [unresolved-import]
```

# Diagnostics

```
error[unresolved-import]: Cannot resolve imported module `compression.zstd`
--> src/mdtest_snippet.py:1:8
|
1 | import compression.zstd # error: [unresolved-import]
| ^^^^^^^^^^^^^^^^
2 | from compression import zstd # error: [unresolved-import]
3 | import compression.fakebutwhocansay # error: [unresolved-import]
|
info: The stdlib module `compression` is only available on Python 3.14+
info: Python 3.10 was assumed when resolving modules because it was specified on the command line
info: rule `unresolved-import` is enabled by default

```

```
error[unresolved-import]: Cannot resolve imported module `compression`
--> src/mdtest_snippet.py:2:6
|
1 | import compression.zstd # error: [unresolved-import]
2 | from compression import zstd # error: [unresolved-import]
| ^^^^^^^^^^^
3 | import compression.fakebutwhocansay # error: [unresolved-import]
4 | from compression import fakebutwhocansay # error: [unresolved-import]
|
info: The stdlib module `compression` is only available on Python 3.14+
info: Python 3.10 was assumed when resolving modules because it was specified on the command line
info: rule `unresolved-import` is enabled by default

```

```
error[unresolved-import]: Cannot resolve imported module `compression.fakebutwhocansay`
--> src/mdtest_snippet.py:3:8
|
1 | import compression.zstd # error: [unresolved-import]
2 | from compression import zstd # error: [unresolved-import]
3 | import compression.fakebutwhocansay # error: [unresolved-import]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 | from compression import fakebutwhocansay # error: [unresolved-import]
|
info: The stdlib module `compression` is only available on Python 3.14+
info: Python 3.10 was assumed when resolving modules because it was specified on the command line
info: rule `unresolved-import` is enabled by default

```

```
error[unresolved-import]: Cannot resolve imported module `compression`
--> src/mdtest_snippet.py:4:6
|
2 | from compression import zstd # error: [unresolved-import]
3 | import compression.fakebutwhocansay # error: [unresolved-import]
4 | from compression import fakebutwhocansay # error: [unresolved-import]
| ^^^^^^^^^^^
|
info: The stdlib module `compression` is only available on Python 3.14+
info: Python 3.10 was assumed when resolving modules because it was specified on the command line
info: rule `unresolved-import` is enabled by default

```
35 changes: 20 additions & 15 deletions crates/ty_python_semantic/src/types/infer/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4790,21 +4790,26 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
let program = Program::get(self.db());
let typeshed_versions = program.search_paths(self.db()).typeshed_versions();

if let Some(version_range) = typeshed_versions.exact(&module_name) {
// We know it is a stdlib module on *some* Python versions...
let python_version = program.python_version(self.db());
if !version_range.contains(python_version) {
// ...But not on *this* Python version.
diagnostic.info(format_args!(
"The stdlib module `{module_name}` is only available on Python {version_range}",
version_range = version_range.diagnostic_display(),
));
add_inferred_python_version_hint_to_diagnostic(
self.db(),
&mut diagnostic,
"resolving modules",
);
return;
// Loop over ancestors in case we have info on the parent module but not submodule
for module_name in module_name.ancestors() {
if let Some(version_range) = typeshed_versions.exact(&module_name) {
// We know it is a stdlib module on *some* Python versions...
let python_version = program.python_version(self.db());
if !version_range.contains(python_version) {
// ...But not on *this* Python version.
diagnostic.info(format_args!(
"The stdlib module `{module_name}` is only available on Python {version_range}",
version_range = version_range.diagnostic_display(),
));
add_inferred_python_version_hint_to_diagnostic(
self.db(),
&mut diagnostic,
"resolving modules",
);
return;
}
// We found the most precise answer we could, stop searching
break;
}
}
}
Expand Down
Loading