From 585ff8d47a477e14dee40bb9eeb07ba011d271d7 Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Sat, 1 Apr 2017 19:11:16 -0700 Subject: [PATCH 1/8] Allowed use of types.ModuleType --- mypy/checkexpr.py | 2 +- mypy/checkmember.py | 2 +- test-data/unit/check-ignore.test | 4 ++-- test-data/unit/check-incremental.test | 6 ++--- test-data/unit/check-modules.test | 26 +++++++++++++------- test-data/unit/cmdline.test | 8 +++---- test-data/unit/fixtures/async_await.pyi | 6 ++++- test-data/unit/fixtures/module.pyi | 11 +++++---- test-data/unit/fixtures/module_all.pyi | 5 +++- test-data/unit/lib-stub/types.pyi | 32 ++++++++++++++++++++++++- test-data/unit/pythoneval.test | 4 ++-- 11 files changed, 77 insertions(+), 29 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index ecccd267c791..841c2e14ae3e 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -151,7 +151,7 @@ def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type: result = type_object_type(node, self.named_type) elif isinstance(node, MypyFile): # Reference to a module object. - result = self.named_type('builtins.module') + result = self.named_type('types.ModuleType') elif isinstance(node, Decorator): result = self.analyze_var_ref(node.var, e) else: diff --git a/mypy/checkmember.py b/mypy/checkmember.py index ede8b9189698..6b0baba4786d 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -413,7 +413,7 @@ def analyze_class_attribute_access(itype: Instance, if isinstance(node.node, MypyFile): # Reference to a module object. - return builtin_type('builtins.module') + return builtin_type('types.ModuleType') if is_decorated: # TODO: Return type of decorated function. This is quick hack to work around #998. diff --git a/test-data/unit/check-ignore.test b/test-data/unit/check-ignore.test index b6d127c5836e..e852028e7eaa 100644 --- a/test-data/unit/check-ignore.test +++ b/test-data/unit/check-ignore.test @@ -46,7 +46,7 @@ import b # type: ignore reveal_type(a.foo) # E: Revealed type is 'Any' reveal_type(b.foo) # E: Revealed type is 'builtins.int' a.bar() -b.bar() # E: "module" has no attribute "bar" +b.bar() # E: "ModuleType" has no attribute "bar" [file b.py] foo = 3 @@ -76,7 +76,7 @@ class B(A): import m m.x = object # type: ignore m.f() # type: ignore -m.y # E: "module" has no attribute "y" +m.y # E: "ModuleType" has no attribute "y" [file m.py] [builtins fixtures/module.pyi] diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 4ddec38618dc..7d3d6d862fe6 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -300,7 +300,7 @@ const = 3 [stale mod3] [builtins fixtures/module.pyi] [out2] -tmp/mod1.py:3: error: "module" has no attribute "mod4" +tmp/mod1.py:3: error: "ModuleType" has no attribute "mod4" [case testIncrementalLongBrokenCascade] import mod1 @@ -335,7 +335,7 @@ const = 3 [stale mod6] [builtins fixtures/module.pyi] [out2] -tmp/mod1.py:3: error: "module" has no attribute "mod7" +tmp/mod1.py:3: error: "ModuleType" has no attribute "mod7" [case testIncrementalNestedBrokenCascade] import mod1 @@ -361,7 +361,7 @@ const = 3 [stale mod2.mod3] [builtins fixtures/module.pyi] [out2] -tmp/mod1.py:3: error: "module" has no attribute "mod4" +tmp/mod1.py:3: error: "ModuleType" has no attribute "mod4" [case testIncrementalNestedBrokenCascadeWithType1] import mod1, mod2.mod3.mod5 diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index b4312de38ea3..c4d6a4695115 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -153,17 +153,18 @@ def f(c:str) -> None: pass [case testInvalidOperationsOnModules] import m import typing + class A: pass -m() # E: "module" not callable -a = m # type: A # E: Incompatible types in assignment (expression has type "module", variable has type "A") -m + None # E: Unsupported left operand type for + ("module") +m() # E: "ModuleType" not callable +a = m # type: A # E: Incompatible types in assignment (expression has type "ModuleType", variable has type "A") +m + None # E: Unsupported left operand type for + ("ModuleType") [file m.py] [builtins fixtures/module.pyi] [case testNameDefinedInDifferentModule] import m, n import typing -m.x # E: "module" has no attribute "x" +m.x # E: "ModuleType" has no attribute "x" [file m.py] y = object() [file n.py] @@ -329,7 +330,7 @@ import nonexistent [out] tmp/x.py:1: error: Cannot find module named 'nonexistent' tmp/x.py:1: note: (Perhaps setting MYPYPATH or using the "--ignore-missing-imports" flag would help) -main:3: error: "module" has no attribute "z" +main:3: error: "ModuleType" has no attribute "z" [case testUnknownModuleImportedWithinFunction] def f(): @@ -647,7 +648,7 @@ def f(x: str) -> None: pass if object(): import m else: - m = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "module") + m = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "ModuleType") [file m.py] [builtins fixtures/module.pyi] [out] @@ -751,7 +752,7 @@ value = 3.2 [case testSubmoduleImportFromDoesNotAddParents] from a import b reveal_type(b.value) # E: Revealed type is 'builtins.str' -b.c.value # E: "module" has no attribute "c" +b.c.value # E: "ModuleType" has no attribute "c" a.value # E: Name 'a' is not defined [file a/__init__.py] @@ -852,7 +853,7 @@ bar = parent.unrelated.ShouldNotLoad() [builtins fixtures/module.pyi] [out] tmp/parent/child.py:8: error: Revealed type is 'parent.common.SomeClass' -tmp/parent/child.py:9: error: "module" has no attribute "unrelated" +tmp/parent/child.py:9: error: "ModuleType" has no attribute "unrelated" [case testSubmoduleMixingImportFromAndImport2] import parent.child @@ -1406,3 +1407,12 @@ reveal_type(cb) # E: Revealed type is 'def (*Any, **Any) -> Any' from typing import Callable, Any AnyCallable = Callable[..., Any] [out] + +[case testRevealType] +import types +def f() -> types.ModuleType: + return types +reveal_type(f()) # E: Revealed type is 'types.ModuleType' +reveal_type(types) # E: Revealed type is 'types.ModuleType' + +[builtins fixtures/module.pyi] \ No newline at end of file diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 48d7a8a91002..50410cd9504e 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -365,8 +365,8 @@ x += '' # Error reported here a.py:2: error: Unsupported operand types for + ("int" and "str") main.py:3: error: Unsupported operand types for + ("int" and "str") main.py:6: error: Unsupported operand types for + ("int" and "str") -main.py:7: error: "module" has no attribute "y" -main.py:8: error: Unsupported operand types for + ("module" and "int") +main.py:7: error: "ModuleType" has no attribute "y" +main.py:8: error: Unsupported operand types for + ("ModuleType" and "int") [case testConfigFollowImportsSilent] # cmd: mypy main.py @@ -386,8 +386,8 @@ x += '' # No error reported [out] main.py:2: error: Unsupported operand types for + ("int" and "str") main.py:4: error: Unsupported operand types for + ("int" and "str") -main.py:5: error: "module" has no attribute "y" -main.py:6: error: Unsupported operand types for + ("module" and "int") +main.py:5: error: "ModuleType" has no attribute "y" +main.py:6: error: Unsupported operand types for + ("ModuleType" and "int") [case testConfigFollowImportsSkip] # cmd: mypy main.py diff --git a/test-data/unit/fixtures/async_await.pyi b/test-data/unit/fixtures/async_await.pyi index 7a1560db88c2..42c1b53eb4bd 100644 --- a/test-data/unit/fixtures/async_await.pyi +++ b/test-data/unit/fixtures/async_await.pyi @@ -1,4 +1,8 @@ import typing + +T = typing.TypeVar('T') +class list(typing.Generic[T], typing.Sequence[T]): pass + class object: def __init__(self): pass class type: pass @@ -6,7 +10,6 @@ class function: pass class int: pass class str: pass class dict: pass -class list: pass class set: pass class tuple: pass class BaseException: pass @@ -14,3 +17,4 @@ class StopIteration(BaseException): pass class StopAsyncIteration(BaseException): pass def iter(obj: typing.Any) -> typing.Any: pass def next(obj: typing.Any) -> typing.Any: pass +class ellipsis: ... diff --git a/test-data/unit/fixtures/module.pyi b/test-data/unit/fixtures/module.pyi index fb2a4c2753eb..b130d795d25c 100644 --- a/test-data/unit/fixtures/module.pyi +++ b/test-data/unit/fixtures/module.pyi @@ -1,14 +1,13 @@ -from typing import Any, Dict, Generic, TypeVar +from typing import Any, Dict, Generic, TypeVar, Sequence +from types import ModuleType T = TypeVar('T') S = TypeVar('S') +class list(Generic[T], Sequence[T]): pass + class object: def __init__(self) -> None: pass -class module: - __name__ = ... # type: str - __file__ = ... # type: str - __dict__ = ... # type: Dict[str, Any] class type: pass class function: pass class int: pass @@ -16,3 +15,5 @@ class str: pass class bool: pass class tuple: pass class dict(Generic[T, S]): pass +class ellipsis: pass + diff --git a/test-data/unit/fixtures/module_all.pyi b/test-data/unit/fixtures/module_all.pyi index cc1b552bcf08..2ab6bc66f6f0 100644 --- a/test-data/unit/fixtures/module_all.pyi +++ b/test-data/unit/fixtures/module_all.pyi @@ -1,15 +1,18 @@ from typing import Generic, Sequence, TypeVar +from types import ModuleType + _T = TypeVar('_T') class object: def __init__(self) -> None: pass -class module: pass class type: pass class function: pass class int: pass class str: pass +class bool: pass class list(Generic[_T], Sequence[_T]): def append(self, x: _T): pass def extend(self, x: Sequence[_T]): pass def __add__(self, rhs: Sequence[_T]) -> list[_T]: pass class tuple: pass +class ellipsis: pass diff --git a/test-data/unit/lib-stub/types.pyi b/test-data/unit/lib-stub/types.pyi index aa0a19fc99c2..28325cc3ddf3 100644 --- a/test-data/unit/lib-stub/types.pyi +++ b/test-data/unit/lib-stub/types.pyi @@ -1,4 +1,34 @@ -from typing import TypeVar +from typing import TypeVar, Optional, List, Any, Generic, Sequence T = TypeVar('T') + def coroutine(func: T) -> T: return func + +class bool: ... + +class ModuleSpec: + def __init__(self, name: str, loader: Optional['Loader'], *, + origin: str = None, loader_state: Any = None, + is_package: bool = None) -> None: ... + name = ... # type: str + loader = ... # type: Optional[Loader] + origin = ... # type: Optional[str] + submodule_search_locations = ... # type: Optional[List[str]] + loader_state = ... # type: Any + cached = ... # type: Optional[str] + parent = ... # type: Optional[str] + has_location = ... # type: bool + +class Loader: + def load_module(self, fullname: str) -> ModuleType: ... + def module_repr(self, module: ModuleType) -> str: ... + def create_module(self, spec: ModuleSpec) -> Optional[ModuleType]: ... + def exec_module(self, module: ModuleType) -> None: ... + +class ModuleType: + __name__ = ... # type: str + __file__ = ... # type: str + __loader__ = ... # type: Optional[Loader] + __package__ = ... # type: Optional[str] + __spec__ = ... # type: Optional[ModuleSpec] + def __init__(self, name: str, doc: Optional[str] = ...) -> None: ... diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index f8520bfdf15e..d77749478058 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -1169,8 +1169,8 @@ collections.Deque() typing.deque() [out] -_testDequeWrongCase.py:4: error: "module" has no attribute "Deque" -_testDequeWrongCase.py:5: error: "module" has no attribute "deque" +_testDequeWrongCase.py:4: error: "ModuleType" has no attribute "Deque" +_testDequeWrongCase.py:5: error: "ModuleType" has no attribute "deque" [case testDictUpdateInference] from typing import Dict, Optional From fbcb6ffc6724ad17047b93c42da597a29f564195 Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Sat, 1 Apr 2017 21:07:24 -0700 Subject: [PATCH 2/8] Allow module name override for stub files --- mypy/semanal.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mypy/semanal.py b/mypy/semanal.py index 8f285c135242..aa04a59a7804 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3353,6 +3353,14 @@ def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) - we generate dummy symbol table nodes for the imported names, and these will get resolved in later phases of semantic analysis. + + MYPY_MODULE has a special meaning in stubs. If present, its current + value will be used as the module name prefix for qualified names of + all objects found in the stub. This is to provide correct output from + reveal_type for definitions placed in the "wrong" module for circular + import reasons (e.g., the definition of ModuleType in + _importlib_modulespec.pyi instead of type.pyi). + """ sem = self.sem self.sem.options = options # Needed because we sometimes call into it @@ -3385,6 +3393,11 @@ def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) - for d in defs: d.accept(self) + if file.is_stub and isinstance(d, AssignmentStmt): + lvalue = d.lvalues[0] + if isinstance(lvalue, NameExpr) and lvalue.name == 'MYPY_MODULE': + assert isinstance(d.rvalue, StrExpr) + sem.cur_mod_id = d.rvalue.value # Add implicit definition of literals/keywords to builtins, as we # cannot define a variable with them explicitly. From 7c739df0156d4333feb1cbc38021b972c1109769 Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Sat, 1 Apr 2017 22:11:45 -0700 Subject: [PATCH 3/8] Remove superfluous class module --- mypy/semanal.py | 2 +- test-data/unit/fixtures/args.pyi | 1 - test-data/unit/fixtures/module_all_python2.pyi | 1 - test-data/unit/fixtures/ops.pyi | 2 -- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index aa04a59a7804..64c3b6ba83b7 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3359,7 +3359,7 @@ def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) - all objects found in the stub. This is to provide correct output from reveal_type for definitions placed in the "wrong" module for circular import reasons (e.g., the definition of ModuleType in - _importlib_modulespec.pyi instead of type.pyi). + _importlib_modulespec.pyi instead of types.pyi). """ sem = self.sem diff --git a/test-data/unit/fixtures/args.pyi b/test-data/unit/fixtures/args.pyi index e4a6ffe1f33b..b084fc6c68e5 100644 --- a/test-data/unit/fixtures/args.pyi +++ b/test-data/unit/fixtures/args.pyi @@ -26,4 +26,3 @@ class int: class str: pass class bool: pass class function: pass -class module: pass diff --git a/test-data/unit/fixtures/module_all_python2.pyi b/test-data/unit/fixtures/module_all_python2.pyi index ed17d4d0d387..5a48e60c512d 100644 --- a/test-data/unit/fixtures/module_all_python2.pyi +++ b/test-data/unit/fixtures/module_all_python2.pyi @@ -3,7 +3,6 @@ _T = TypeVar('_T') class object: def __init__(self) -> None: pass -class module: pass class type: pass class function: pass class int: pass diff --git a/test-data/unit/fixtures/ops.pyi b/test-data/unit/fixtures/ops.pyi index 8956b79f5660..0aa8f74ee978 100644 --- a/test-data/unit/fixtures/ops.pyi +++ b/test-data/unit/fixtures/ops.pyi @@ -54,5 +54,3 @@ class float: pass class BaseException: pass def __print(a1=None, a2=None, a3=None, a4=None): pass - -class module: pass From b53c90427c2fd94d2f7df2dae5e92610d7921d81 Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Sun, 2 Apr 2017 18:41:18 -0700 Subject: [PATCH 4/8] Hard code module renaming --- mypy/semanal.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 64c3b6ba83b7..051cc35073d0 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -112,6 +112,13 @@ 'typing.typevar': 'typing.TypeVar', } +# Rename objects placed in _importlib_modulespec due to circular imports +module_rename_map = { + '_importlib_modulespec.ModuleType': 'types.ModuleType', + '_importlib_modulespec.ModuleSpec': 'importlib.machinery.ModuleSpec', + '_importlib_modulespec.Loader': 'importlib.abc.Loader' +} + # Hard coded type promotions (shared between all Python versions). # These add extra ad-hoc edges to the subtyping relation. For example, # int is considered a subtype of float, even though there is no @@ -3354,13 +3361,6 @@ def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) - and these will get resolved in later phases of semantic analysis. - MYPY_MODULE has a special meaning in stubs. If present, its current - value will be used as the module name prefix for qualified names of - all objects found in the stub. This is to provide correct output from - reveal_type for definitions placed in the "wrong" module for circular - import reasons (e.g., the definition of ModuleType in - _importlib_modulespec.pyi instead of types.pyi). - """ sem = self.sem self.sem.options = options # Needed because we sometimes call into it @@ -3393,11 +3393,8 @@ def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) - for d in defs: d.accept(self) - if file.is_stub and isinstance(d, AssignmentStmt): - lvalue = d.lvalues[0] - if isinstance(lvalue, NameExpr) and lvalue.name == 'MYPY_MODULE': - assert isinstance(d.rvalue, StrExpr) - sem.cur_mod_id = d.rvalue.value + if isinstance(d, ClassDef): + d.info._fullname = module_rename_map.get(d.info._fullname, d.info._fullname) # Add implicit definition of literals/keywords to builtins, as we # cannot define a variable with them explicitly. From def95ce981a8fd7b9a9fa92c4ac7f70b8e9a96c8 Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Wed, 12 Apr 2017 17:13:01 -0700 Subject: [PATCH 5/8] Address CR --- test-data/unit/check-modules.test | 2 +- test-data/unit/lib-stub/types.pyi | 27 +-------------------------- typeshed | 2 +- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index c4d6a4695115..867f37c569be 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -1415,4 +1415,4 @@ def f() -> types.ModuleType: reveal_type(f()) # E: Revealed type is 'types.ModuleType' reveal_type(types) # E: Revealed type is 'types.ModuleType' -[builtins fixtures/module.pyi] \ No newline at end of file +[builtins fixtures/module.pyi] diff --git a/test-data/unit/lib-stub/types.pyi b/test-data/unit/lib-stub/types.pyi index 28325cc3ddf3..b118000e688c 100644 --- a/test-data/unit/lib-stub/types.pyi +++ b/test-data/unit/lib-stub/types.pyi @@ -6,29 +6,4 @@ def coroutine(func: T) -> T: class bool: ... -class ModuleSpec: - def __init__(self, name: str, loader: Optional['Loader'], *, - origin: str = None, loader_state: Any = None, - is_package: bool = None) -> None: ... - name = ... # type: str - loader = ... # type: Optional[Loader] - origin = ... # type: Optional[str] - submodule_search_locations = ... # type: Optional[List[str]] - loader_state = ... # type: Any - cached = ... # type: Optional[str] - parent = ... # type: Optional[str] - has_location = ... # type: bool - -class Loader: - def load_module(self, fullname: str) -> ModuleType: ... - def module_repr(self, module: ModuleType) -> str: ... - def create_module(self, spec: ModuleSpec) -> Optional[ModuleType]: ... - def exec_module(self, module: ModuleType) -> None: ... - -class ModuleType: - __name__ = ... # type: str - __file__ = ... # type: str - __loader__ = ... # type: Optional[Loader] - __package__ = ... # type: Optional[str] - __spec__ = ... # type: Optional[ModuleSpec] - def __init__(self, name: str, doc: Optional[str] = ...) -> None: ... +class ModuleType: ... diff --git a/typeshed b/typeshed index 1ea3d2de5794..f7e4cb8c7921 160000 --- a/typeshed +++ b/typeshed @@ -1 +1 @@ -Subproject commit 1ea3d2de5794c2224a1bc086aa471d0097699bf1 +Subproject commit f7e4cb8c7921cb7abd6d8293d27725854221b267 From 6e8c81ab8c4ac8092d13c96e7aebede705c6f133 Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Wed, 12 Apr 2017 19:26:42 -0700 Subject: [PATCH 6/8] Updated typeshed --- typeshed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typeshed b/typeshed index f7e4cb8c7921..26360e821b42 160000 --- a/typeshed +++ b/typeshed @@ -1 +1 @@ -Subproject commit f7e4cb8c7921cb7abd6d8293d27725854221b267 +Subproject commit 26360e821b427c29ca27117061a3ba806f63e12e From ef70f3ef956aa1b495f2ae9aef05d5c92f912094 Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Thu, 13 Apr 2017 01:35:22 -0700 Subject: [PATCH 7/8] Fix fine-grained tests --- mypy/server/deps.py | 6 ++++-- test-data/unit/fine-grained.test | 24 ++++++++++++------------ test-data/unit/fixtures/fine_grained.pyi | 4 +++- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/mypy/server/deps.py b/mypy/server/deps.py index 6710cfa49bf0..d167b86a980e 100644 --- a/mypy/server/deps.py +++ b/mypy/server/deps.py @@ -207,10 +207,12 @@ def visit_tuple_type(self, typ: TupleType) -> List[str]: raise NotImplementedError def visit_type_type(self, typ: TypeType) -> List[str]: - raise NotImplementedError + # TODO: replace with actual implementation + return [] def visit_type_var(self, typ: TypeVarType) -> List[str]: - raise NotImplementedError + # TODO: replace with actual implementation + return [] def visit_typeddict_type(self, typ: TypedDictType) -> List[str]: raise NotImplementedError diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 881315998c4c..f9c369353aa1 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -68,7 +68,7 @@ def g(x: str) -> None: pass [builtins fixtures/fine_grained.pyi] [out] == -main:3: error: "module" has no attribute "f" +main:3: error: "ModuleType" has no attribute "f" [case testTopLevelMissingModuleAttribute] import m @@ -81,7 +81,7 @@ def g(x: int) -> None: pass [builtins fixtures/fine_grained.pyi] [out] == -main:2: error: "module" has no attribute "f" +main:2: error: "ModuleType" has no attribute "f" [case testClassChangedIntoFunction] import m @@ -241,7 +241,7 @@ class A: pass [builtins fixtures/fine_grained.pyi] [out] == -main:3: error: "module" has no attribute "A" +main:3: error: "ModuleType" has no attribute "A" == [case testContinueToReportTypeCheckError] @@ -281,10 +281,10 @@ class A: pass [builtins fixtures/fine_grained.pyi] [out] == -main:3: error: "module" has no attribute "A" -main:5: error: "module" has no attribute "B" +main:3: error: "ModuleType" has no attribute "A" +main:5: error: "ModuleType" has no attribute "B" == -main:5: error: "module" has no attribute "B" +main:5: error: "ModuleType" has no attribute "B" [case testContinueToReportErrorAtTopLevel] import n @@ -348,9 +348,9 @@ def g() -> None: pass [builtins fixtures/fine_grained.pyi] [out] main:3: error: Too few arguments for "f" -main:5: error: "module" has no attribute "g" +main:5: error: "ModuleType" has no attribute "g" == -main:5: error: "module" has no attribute "g" +main:5: error: "ModuleType" has no attribute "g" == [case testKeepReportingErrorIfNoChanges] @@ -361,9 +361,9 @@ def h() -> None: [file m.py.2] [builtins fixtures/fine_grained.pyi] [out] -main:3: error: "module" has no attribute "g" +main:3: error: "ModuleType" has no attribute "g" == -main:3: error: "module" has no attribute "g" +main:3: error: "ModuleType" has no attribute "g" [case testFixErrorAndReintroduce] import m @@ -375,10 +375,10 @@ def g() -> None: pass [file m.py.3] [builtins fixtures/fine_grained.pyi] [out] -main:3: error: "module" has no attribute "g" +main:3: error: "ModuleType" has no attribute "g" == == -main:3: error: "module" has no attribute "g" +main:3: error: "ModuleType" has no attribute "g" [case testAddBaseClassMethodCausingInvalidOverride] import m diff --git a/test-data/unit/fixtures/fine_grained.pyi b/test-data/unit/fixtures/fine_grained.pyi index 5959df68835b..83429cd38314 100644 --- a/test-data/unit/fixtures/fine_grained.pyi +++ b/test-data/unit/fixtures/fine_grained.pyi @@ -3,6 +3,8 @@ # TODO: Migrate to regular stubs once fine-grained incremental is robust # enough to handle them. +import types + class Any: pass class object: @@ -21,4 +23,4 @@ class bytes: pass class tuple: pass class function: pass class ellipsis: pass -class module: pass +class list: pass From b956d46647e19b34efc5dee686cca6c63ec97c32 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Thu, 13 Apr 2017 15:27:13 +0200 Subject: [PATCH 8/8] Fix whitespace --- mypy/semanal.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 46da65cb82f7..a66e55a78e22 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3420,7 +3420,6 @@ def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) - we generate dummy symbol table nodes for the imported names, and these will get resolved in later phases of semantic analysis. - """ sem = self.sem self.sem.options = options # Needed because we sometimes call into it