Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1091321

Browse files
authored
Infer empty list without annotation for__slots__ and module__all__ (#19348)
Fixes#10870,fixes#10103.This adds a fake `Iterable[str]` context when checking the following: * `__all__ = []` at top level* `__slots__ = []` at class level (also works for sets but not fordicts)Additionally, this fixes a bug with `__slots__` being mistakenly checkedin other contexts (at top level or in function bodies), so e.g. thefollowing is now accepted:```pythondef foo() -> None: __slots__ = 1```
1 parent5d59e43 commit1091321

File tree

4 files changed

+63
-2
lines changed

4 files changed

+63
-2
lines changed

‎mypy/checker.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3138,7 +3138,7 @@ def check_assignment(
31383138
else:
31393139
self.check_getattr_method(signature,lvalue,name)
31403140

3141-
ifname=="__slots__":
3141+
ifname=="__slots__"andself.scope.active_class()isnotNone:
31423142
typ=lvalue_typeorself.expr_checker.accept(rvalue)
31433143
self.check_slots_definition(typ,lvalue)
31443144
ifname=="__match_args__"andinferredisnotNone:
@@ -3317,6 +3317,12 @@ def get_variable_type_context(self, inferred: Var, rvalue: Expression) -> Type |
33173317
type_contexts.append(base_type)
33183318
# Use most derived supertype as type context if available.
33193319
ifnottype_contexts:
3320+
ifinferred.name=="__slots__"andself.scope.active_class()isnotNone:
3321+
str_type=self.named_type("builtins.str")
3322+
returnself.named_generic_type("typing.Iterable", [str_type])
3323+
ifinferred.name=="__all__"andself.scope.is_top_level():
3324+
str_type=self.named_type("builtins.str")
3325+
returnself.named_generic_type("typing.Sequence", [str_type])
33203326
returnNone
33213327
candidate=type_contexts[0]
33223328
forotherintype_contexts:

‎mypy/checker_shared.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,10 @@ def current_self_type(self) -> Instance | TupleType | None:
334334
returnfill_typevars(item)
335335
returnNone
336336

337+
defis_top_level(self)->bool:
338+
"""Is current scope top-level (no classes or functions)?"""
339+
returnlen(self.stack)==1
340+
337341
@contextmanager
338342
defpush_function(self,item:FuncItem)->Iterator[None]:
339343
self.stack.append(item)

‎test-data/unit/check-modules.test

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,35 @@ import typing
423423
__all__ = [1, 2, 3]
424424
[builtins fixtures/module_all.pyi]
425425
[out]
426-
main:2: error: Type of __all__ must be "Sequence[str]", not "list[int]"
426+
main:2: error: List item 0 has incompatible type "int"; expected "str"
427+
main:2: error: List item 1 has incompatible type "int"; expected "str"
428+
main:2: error: List item 2 has incompatible type "int"; expected "str"
429+
430+
[case testAllMustBeSequenceStr2]
431+
import typing
432+
__all__ = 1 # E: Type of __all__ must be "Sequence[str]", not "int"
433+
reveal_type(__all__) # N: Revealed type is "builtins.int"
434+
[builtins fixtures/module_all.pyi]
435+
436+
[case testAllMustBeSequenceStr3]
437+
import typing
438+
__all__ = set() # E: Need type annotation for "__all__" (hint: "__all__: set[<type>] = ...") \
439+
# E: Type of __all__ must be "Sequence[str]", not "set[Any]"
440+
reveal_type(__all__) # N: Revealed type is "builtins.set[Any]"
441+
[builtins fixtures/set.pyi]
442+
443+
[case testModuleAllEmptyList]
444+
__all__ = []
445+
reveal_type(__all__) # N: Revealed type is "builtins.list[builtins.str]"
446+
[builtins fixtures/module_all.pyi]
447+
448+
[case testDunderAllNotGlobal]
449+
class A:
450+
__all__ = 1
451+
452+
def foo() -> None:
453+
__all__ = 1
454+
[builtins fixtures/module_all.pyi]
427455

428456
[case testUnderscoreExportedValuesInImportAll]
429457
import typing

‎test-data/unit/check-slots.test

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,29 @@ class A:
496496
self.missing = 3
497497
[builtins fixtures/dict.pyi]
498498

499+
[case testSlotsNotInClass]
500+
# Shouldn't be triggered
501+
__slots__ = [1, 2]
502+
reveal_type(__slots__) # N: Revealed type is "builtins.list[builtins.int]"
503+
504+
def foo() -> None:
505+
__slots__ = 1
506+
reveal_type(__slots__) # N: Revealed type is "builtins.int"
507+
508+
[case testSlotsEmptyList]
509+
class A:
510+
__slots__ = []
511+
reveal_type(__slots__) # N: Revealed type is "builtins.list[builtins.str]"
512+
513+
reveal_type(A.__slots__) # N: Revealed type is "builtins.list[builtins.str]"
514+
515+
[case testSlotsEmptySet]
516+
class A:
517+
__slots__ = set()
518+
reveal_type(__slots__) # N: Revealed type is "builtins.set[builtins.str]"
519+
520+
reveal_type(A.__slots__) # N: Revealed type is "builtins.set[builtins.str]"
521+
[builtins fixtures/set.pyi]
499522

500523
[case testSlotsWithAny]
501524
from typing import Any

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp