mirror of
https://github.com/astral-sh/ruff.git
synced 2025-12-23 09:19:39 +00:00
Merge c4344cbc2b into 5ea30c4c53
This commit is contained in:
commit
578424d8ef
3 changed files with 89 additions and 21 deletions
|
|
@ -76,3 +76,63 @@ def reveal_type(obj, /): ...
|
|||
```py
|
||||
reveal_type(foo) # revealed: Unknown
|
||||
```
|
||||
|
||||
## Builtins imported from custom project-level stubs
|
||||
|
||||
The project can add or replace builtins with the `__builtins__.pyi` stub. They will take precedence
|
||||
over the typeshed ones.
|
||||
|
||||
```py
|
||||
reveal_type(foo) # revealed: int
|
||||
reveal_type(bar) # revealed: str
|
||||
reveal_type(quux(1)) # revealed: int
|
||||
b = baz # error: [unresolved-reference]
|
||||
|
||||
reveal_type(ord(100)) # revealed: bool
|
||||
a = ord("a") # error: [invalid-argument-type]
|
||||
|
||||
bar = int(123)
|
||||
reveal_type(bar) # revealed: int
|
||||
```
|
||||
|
||||
`__builtins__.pyi`:
|
||||
|
||||
```pyi
|
||||
foo: int = ...
|
||||
bar: str = ...
|
||||
|
||||
def quux(value: int) -> int: ...
|
||||
|
||||
unused: str = ...
|
||||
|
||||
def ord(x: int) -> bool: ...
|
||||
```
|
||||
|
||||
Builtins stubs are searched relative to the project root, not the file using them.
|
||||
|
||||
`under/some/folder.py`:
|
||||
|
||||
```py
|
||||
reveal_type(foo) # revealed: int
|
||||
reveal_type(bar) # revealed: str
|
||||
```
|
||||
|
||||
## Assigning custom builtins
|
||||
|
||||
```py
|
||||
import builtins
|
||||
|
||||
builtins.foo = 123
|
||||
builtins.bar = 456 # error: [unresolved-attribute]
|
||||
builtins.baz = 789 # error: [invalid-assignment]
|
||||
builtins.chr = lambda x: str(x) # error: [invalid-assignment]
|
||||
builtins.chr = 10
|
||||
```
|
||||
|
||||
`__builtins__.pyi`:
|
||||
|
||||
```pyi
|
||||
foo: int
|
||||
baz: str
|
||||
chr: int
|
||||
```
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use crate::types::{
|
|||
Truthiness, Type, TypeAndQualifiers, TypeQualifiers, UnionBuilder, UnionType, binding_type,
|
||||
declaration_type, todo_type,
|
||||
};
|
||||
use crate::{Db, FxOrderSet, Program};
|
||||
use crate::{Db, FxOrderSet, Module, ModuleName, Program};
|
||||
|
||||
pub(crate) use implicit_globals::{
|
||||
module_type_implicit_global_declaration, module_type_implicit_global_symbol,
|
||||
|
|
@ -380,25 +380,29 @@ pub(crate) fn imported_symbol<'db>(
|
|||
/// and should not be used when a symbol is being explicitly imported from the `builtins` module
|
||||
/// (e.g. `from builtins import int`).
|
||||
pub(crate) fn builtins_symbol<'db>(db: &'db dyn Db, symbol: &str) -> PlaceAndQualifiers<'db> {
|
||||
resolve_module_confident(db, &KnownModule::Builtins.name())
|
||||
.and_then(|module| {
|
||||
let file = module.file(db)?;
|
||||
Some(
|
||||
symbol_impl(
|
||||
db,
|
||||
global_scope(db, file),
|
||||
symbol,
|
||||
RequiresExplicitReExport::Yes,
|
||||
ConsideredDefinitions::EndOfScope,
|
||||
)
|
||||
.or_fall_back_to(db, || {
|
||||
// We're looking up in the builtins namespace and not the module, so we should
|
||||
// do the normal lookup in `types.ModuleType` and not the special one as in
|
||||
// `imported_symbol`.
|
||||
module_type_implicit_global_symbol(db, symbol)
|
||||
}),
|
||||
)
|
||||
})
|
||||
let resolver = |module: Module<'_>| {
|
||||
let file = module.file(db)?;
|
||||
let found_symbol = symbol_impl(
|
||||
db,
|
||||
global_scope(db, file),
|
||||
symbol,
|
||||
RequiresExplicitReExport::Yes,
|
||||
ConsideredDefinitions::EndOfScope,
|
||||
)
|
||||
.or_fall_back_to(db, || {
|
||||
// We're looking up in the builtins namespace and not the module, so we should
|
||||
// do the normal lookup in `types.ModuleType` and not the special one as in
|
||||
// `imported_symbol`.
|
||||
module_type_implicit_global_symbol(db, symbol)
|
||||
});
|
||||
// If this symbol is not present in project-level builtins, search in the default ones.
|
||||
found_symbol
|
||||
.ignore_possibly_undefined()
|
||||
.map(|_| found_symbol)
|
||||
};
|
||||
resolve_module_confident(db, &ModuleName::new("__builtins__").unwrap())
|
||||
.and_then(&resolver)
|
||||
.or_else(|| resolve_module_confident(db, &KnownModule::Builtins.name()).and_then(resolver))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4963,7 +4963,11 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
}
|
||||
|
||||
Type::ModuleLiteral(module) => {
|
||||
if let Place::Defined(attr_ty, _, _) = module.static_member(db, attribute).place {
|
||||
let sym = match module.module(db).name(db).as_str() {
|
||||
"builtins" => builtins_symbol(db, attribute),
|
||||
_ => module.static_member(db, attribute),
|
||||
};
|
||||
if let Place::Defined(attr_ty, _, _) = sym.place {
|
||||
let value_ty = infer_value_ty(self, TypeContext::new(Some(attr_ty)));
|
||||
|
||||
let assignable = value_ty.is_assignable_to(db, attr_ty);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue