diff --git a/docs/source/revision_history.rst b/docs/source/revision_history.rst index d31012d27b02..dadc7952e518 100644 --- a/docs/source/revision_history.rst +++ b/docs/source/revision_history.rst @@ -4,6 +4,8 @@ Revision history List of major changes: - July 2017 + * Publish ``mypy`` version 0.521 on PyPI. + * Publish ``mypy`` version 0.520 on PyPI. * Add :ref:`fine-grained control of Any types `. diff --git a/mypy/build.py b/mypy/build.py index 18811bf3a967..471f819f0d45 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -860,16 +860,17 @@ def find_cache_meta(id: str, path: str, manager: BuildManager) -> Optional[Cache """ # TODO: May need to take more build options into account meta_json, data_json = get_cache_names(id, path, manager) - manager.trace('Looking for {} {}'.format(id, data_json)) + manager.trace('Looking for {} at {}'.format(id, meta_json)) if not os.path.exists(meta_json): - manager.trace('Could not load cache for {}: could not find {}'.format(id, meta_json)) + manager.log('Could not load cache for {}: could not find {}'.format(id, meta_json)) return None with open(meta_json, 'r') as f: meta_str = f.read() manager.trace('Meta {} {}'.format(id, meta_str.rstrip())) meta = json.loads(meta_str) # TODO: Errors if not isinstance(meta, dict): - manager.trace('Could not load cache for {}: meta cache is not a dict'.format(id)) + manager.log('Could not load cache for {}: meta cache is not a dict: {}' + .format(id, repr(meta))) return None m = CacheMeta( meta.get('id'), @@ -891,27 +892,36 @@ def find_cache_meta(id: str, path: str, manager: BuildManager) -> Optional[Cache if (m.id != id or m.mtime is None or m.size is None or m.dependencies is None or m.data_mtime is None): - manager.trace('Metadata abandoned for {}: attributes are missing'.format(id)) + manager.log('Metadata abandoned for {}: attributes are missing'.format(id)) return None # Ignore cache if generated by an older mypy version. if ((m.version_id != manager.version_id and not manager.options.skip_version_check) or m.options is None or len(m.dependencies) != len(m.dep_prios)): - manager.trace('Metadata abandoned for {}: new attributes are missing'.format(id)) + manager.log('Metadata abandoned for {}: new attributes are missing'.format(id)) return None # Ignore cache if (relevant) options aren't the same. + # Note that it's fine to mutilate cached_options since it's only used here. cached_options = m.options current_options = manager.options.clone_for_module(id).select_options_affecting_cache() if manager.options.quick_and_dirty: # In quick_and_dirty mode allow non-quick_and_dirty cache files. cached_options['quick_and_dirty'] = True - if not cached_options.get('platform') and manager.options.skip_version_check: - # Older versions didn't write platform. - cached_options['platform'] = manager.options.platform + if manager.options.skip_version_check: + # When we're lax about version we're also lax about platform. + cached_options['platform'] = current_options['platform'] + if 'debug_cache' in cached_options: + # Older versions included debug_cache, but it's silly to compare it. + del cached_options['debug_cache'] if cached_options != current_options: - manager.trace('Metadata abandoned for {}: options differ'.format(id)) + manager.log('Metadata abandoned for {}: options differ'.format(id)) + if manager.options.verbosity >= 2: + for key in sorted(set(cached_options) | set(current_options)): + if cached_options.get(key) != current_options.get(key): + manager.trace(' {}: {} != {}' + .format(key, cached_options.get(key), current_options.get(key))) return None return m @@ -948,41 +958,63 @@ def validate_meta(meta: Optional[CacheMeta], id: str, path: str, # we use cache data file mtime to propagate information about changes in the dependencies. if meta is None: + manager.log('Metadata not found for {}'.format(id)) + return None + + # Check data_json; assume if its mtime matches it's good. + # TODO: stat() errors + data_mtime = getmtime(meta.data_json) + if data_mtime != meta.data_mtime: + manager.log('Metadata abandoned for {}: data cache is modified'.format(id)) return None # TODO: Share stat() outcome with find_module() path = os.path.abspath(path) st = manager.get_stat(path) # TODO: Errors - if st.st_size != meta.size: + size = st.st_size + if size != meta.size: manager.log('Metadata abandoned for {}: file {} has different size'.format(id, path)) return None - if int(st.st_mtime) != meta.mtime or path != meta.path: + mtime = int(st.st_mtime) + if mtime != meta.mtime or path != meta.path: with open(path, 'rb') as f: source_hash = hashlib.md5(f.read()).hexdigest() if source_hash != meta.hash: manager.log('Metadata abandoned for {}: file {} has different hash'.format(id, path)) return None else: - manager.log('Metadata ok for {}: file {} (match on path, size, hash)'.format(id, path)) # Optimization: update mtime and path (otherwise, this mismatch will reappear). - meta = meta._replace(mtime=int(st.st_mtime), path=path) + meta = meta._replace(mtime=mtime, path=path) + # Construct a dict we can pass to json.dumps() (compare to write_cache()). + meta_dict = { + 'id': id, + 'path': path, + 'mtime': mtime, + 'size': size, + 'hash': source_hash, + 'data_mtime': data_mtime, + 'dependencies': meta.dependencies, + 'suppressed': meta.suppressed, + 'child_modules': meta.child_modules, + 'options': (manager.options.clone_for_module(id) + .select_options_affecting_cache()), + 'dep_prios': meta.dep_prios, + 'interface_hash': meta.interface_hash, + 'version_id': manager.version_id, + } if manager.options.debug_cache: - meta_str = json.dumps(meta, indent=2, sort_keys=True) + meta_str = json.dumps(meta_dict, indent=2, sort_keys=True) else: - meta_str = json.dumps(meta) + meta_str = json.dumps(meta_dict) meta_json, _ = get_cache_names(id, path, manager) manager.log('Updating mtime for {}: file {}, meta {}, mtime {}' .format(id, path, meta_json, meta.mtime)) - atomic_write(meta_json, meta_str) # Ignore errors, since this is just an optimization. + atomic_write(meta_json, meta_str, '\n') # Ignore errors, it's just an optimization. + return meta - # It's a match on (id, path, mtime/hash, size). - # Check data_json; assume if its mtime matches it's good. - # TODO: stat() errors - if getmtime(meta.data_json) != meta.data_mtime: - manager.log('Metadata abandoned for {}: data cache is modified'.format(id)) - return None - manager.log('Found {} {} (metadata is fresh)'.format(id, meta.data_json)) + # It's a match on (id, path, size, hash, mtime). + manager.log('Metadata fresh for {}: file {}'.format(id, path)) return meta @@ -1096,7 +1128,7 @@ def write_cache(id: str, path: str, tree: MypyFile, meta_str = json.dumps(meta, indent=2, sort_keys=True) else: meta_str = json.dumps(meta) - if not atomic_write(meta_json, meta_str): + if not atomic_write(meta_json, meta_str, '\n'): # Most likely the error is the replace() call # (see https://github.com/python/mypy/issues/3215). # The next run will simply find the cache entry out of date. diff --git a/mypy/checker.py b/mypy/checker.py index 68284c4ee19d..aab56b5fe01e 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1413,8 +1413,11 @@ def lvalue_type_from_base(self, expr_node: Var, if base_type: if not has_no_typevars(base_type): - # TODO: Handle TupleType, don't cast - instance = cast(Instance, self.scope.active_self_type()) + self_type = self.scope.active_self_type() + if isinstance(self_type, TupleType): + instance = self_type.fallback + else: + instance = self_type itype = map_instance_to_supertype(instance, base) base_type = expand_type_by_instance(base_type, itype) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 58835c6de810..26a4abe45610 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -390,7 +390,7 @@ def do_func_def(self, n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef], return func_def def set_type_optional(self, type: Type, initializer: Expression) -> None: - if self.options.no_implicit_optional or not experiments.STRICT_OPTIONAL: + if self.options.no_implicit_optional: return # Indicate that type should be wrapped in an Optional if arg is initialized to None. optional = isinstance(initializer, NameExpr) and initializer.name == 'None' diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 109dfe407cf2..0f1bd6330ea9 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -364,7 +364,7 @@ def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement: return func_def def set_type_optional(self, type: Type, initializer: Expression) -> None: - if self.options.no_implicit_optional or not experiments.STRICT_OPTIONAL: + if self.options.no_implicit_optional: return # Indicate that type should be wrapped in an Optional if arg is initialized to None. optional = isinstance(initializer, NameExpr) and initializer.name == 'None' diff --git a/mypy/fixup.py b/mypy/fixup.py index 5cb1188072cc..d60ac5556d7e 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -88,6 +88,9 @@ def visit_symbol_table(self, symtab: SymbolTable) -> None: if stnode is not None: value.node = stnode.node value.type_override = stnode.type_override + if (self.quick_and_dirty and value.kind == TYPE_ALIAS and + stnode.type_override is None): + value.type_override = Instance(stale_info(), []) value.alias_tvars = stnode.alias_tvars or [] elif not self.quick_and_dirty: assert stnode is not None, "Could not find cross-ref %s" % (cross_ref,) diff --git a/mypy/nodes.py b/mypy/nodes.py index 6cc75f5b8f22..796e809d25b3 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -2279,11 +2279,14 @@ class SymbolTableNode: cross_ref = None # type: Optional[str] # Was this node created by normalŃ–ze_type_alias? normalized = False # type: bool + # Was this defined by assignment to self attribute? + implicit = False # type: bool def __init__(self, kind: int, node: Optional[SymbolNode], mod_id: str = None, typ: 'mypy.types.Type' = None, module_public: bool = True, normalized: bool = False, - alias_tvars: Optional[List[str]] = None) -> None: + alias_tvars: Optional[List[str]] = None, + implicit: bool = False) -> None: self.kind = kind self.node = node self.type_override = typ @@ -2291,6 +2294,7 @@ def __init__(self, kind: int, node: Optional[SymbolNode], mod_id: str = None, self.module_public = module_public self.normalized = normalized self.alias_tvars = alias_tvars + self.implicit = implicit @property def fullname(self) -> Optional[str]: @@ -2334,6 +2338,10 @@ def serialize(self, prefix: str, name: str) -> JsonDict: } # type: JsonDict if not self.module_public: data['module_public'] = False + if self.normalized: + data['normalized'] = True + if self.implicit: + data['implicit'] = True if self.kind == MODULE_REF: assert self.node is not None, "Missing module cross ref in %s for %s" % (prefix, name) data['cross_ref'] = self.node.fullname() @@ -2371,6 +2379,10 @@ def deserialize(cls, data: JsonDict) -> 'SymbolTableNode': stnode.alias_tvars = data['alias_tvars'] if 'module_public' in data: stnode.module_public = data['module_public'] + if 'normalized' in data: + stnode.normalized = data['normalized'] + if 'implicit' in data: + stnode.implicit = data['implicit'] return stnode diff --git a/mypy/options.py b/mypy/options.py index af7837de9ada..7d0fe098cd62 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -34,7 +34,8 @@ class Options: "strict_optional", } - OPTIONS_AFFECTING_CACHE = (PER_MODULE_OPTIONS | {"quick_and_dirty", "platform"}) + OPTIONS_AFFECTING_CACHE = ((PER_MODULE_OPTIONS | {"quick_and_dirty", "platform"}) + - {"debug_cache"}) def __init__(self) -> None: # -- build options -- diff --git a/mypy/semanal.py b/mypy/semanal.py index bcbe495e1c93..15ccbe559c19 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1809,11 +1809,12 @@ def analyze_member_lvalue(self, lval: MemberExpr) -> None: lval.is_def = True v = Var(lval.name) v.set_line(lval) + v._fullname = self.qualified_name(lval.name) v.info = self.type v.is_ready = False lval.def_var = v lval.node = v - self.type.names[lval.name] = SymbolTableNode(MDEF, v) + self.type.names[lval.name] = SymbolTableNode(MDEF, v, implicit=True) self.check_lvalue_validity(lval.node, lval) def is_self_member_ref(self, memberexpr: MemberExpr) -> bool: @@ -3383,6 +3384,7 @@ def tvar_scope_frame(self, frame: TypeVarScope) -> Iterator[None]: def lookup(self, name: str, ctx: Context) -> SymbolTableNode: """Look up an unqualified name in all active namespaces.""" + implicit_name = False # 1a. Name declared using 'global x' takes precedence if name in self.global_decls[-1]: if name in self.globals: @@ -3400,7 +3402,11 @@ def lookup(self, name: str, ctx: Context) -> SymbolTableNode: return None # 2. Class attributes (if within class definition) if self.is_class_scope() and name in self.type.names: - return self.type.names[name] + node = self.type.names[name] + if not node.implicit: + return node + implicit_name = True + implicit_node = node # 3. Local (function) scopes for table in reversed(self.locals): if table is not None and name in table: @@ -3420,8 +3426,11 @@ def lookup(self, name: str, ctx: Context) -> SymbolTableNode: node = table[name] return node # Give up. - self.name_not_defined(name, ctx) - self.check_for_obsolete_short_name(name, ctx) + if not implicit_name: + self.name_not_defined(name, ctx) + self.check_for_obsolete_short_name(name, ctx) + else: + return implicit_node return None def check_for_obsolete_short_name(self, name: str, ctx: Context) -> None: diff --git a/mypy/version.py b/mypy/version.py index 1ac3f8a5a955..7fe262087faf 100644 --- a/mypy/version.py +++ b/mypy/version.py @@ -1,7 +1,7 @@ import os from mypy import git -__version__ = '0.520-dev' +__version__ = '0.521' base_version = __version__ mypy_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index c7e6f52070c7..0b4b0f52bdd3 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -198,6 +198,43 @@ class A: main:6: error: Incompatible types in assignment (expression has type "str", variable has type "int") main:8: error: Incompatible types in assignment (expression has type "str", variable has type "int") +[case testClassNamesDefinedOnSelUsedInClassBody] +class A(object): + def f(self): + self.attr = 1 + attr = 0 + +class B(object): + attr = 0 + def f(self): + self.attr = 1 + +class C(object): + attr = 0 + def f(self): + self.attr = 1 + attr = 0 + +class D(object): + def g(self): + self.attr = 1 + attr = 0 + def f(self): + self.attr = 1 +[out] + +[case testClassNamesDefinedOnSelUsedInClassBodyReveal] +class A(object): + def f(self) -> None: + self.attr = 1 + reveal_type(attr) # E: Revealed type is 'builtins.int' + +class B(object): + attr = 0 + def f(self) -> None: + reveal_type(self.attr) # E: Revealed type is 'builtins.int' +[out] + -- Method overriding -- ----------------- @@ -3386,9 +3423,7 @@ NT([]) [builtins fixtures/dict.pyi] [out] --- The two tests below will not crash after --- https://github.com/python/mypy/issues/3319 is fixed -[case testCrashForwardSyntheticClassSyntax-skip] +[case testCrashForwardSyntheticClassSyntax] from typing import NamedTuple from mypy_extensions import TypedDict class A1(NamedTuple): @@ -3406,7 +3441,7 @@ reveal_type(y['b']) # E: Revealed type is '__main__.B' [builtins fixtures/dict.pyi] [out] -[case testCrashForwardSyntheticFunctionSyntax-skip] +[case testCrashForwardSyntheticFunctionSyntax] from typing import NamedTuple from mypy_extensions import TypedDict A1 = NamedTuple('A1', [('b', 'B'), ('x', int)]) diff --git a/test-data/unit/check-fastparse.test b/test-data/unit/check-fastparse.test index bea5efbaeb8d..7aa1521e320b 100644 --- a/test-data/unit/check-fastparse.test +++ b/test-data/unit/check-fastparse.test @@ -124,9 +124,9 @@ def f(a, # type: A **kwargs # type: F ): reveal_type(a) # E: Revealed type is '__main__.A' - reveal_type(b) # E: Revealed type is '__main__.B' + reveal_type(b) # E: Revealed type is 'Union[__main__.B, builtins.None]' reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]' - reveal_type(d) # E: Revealed type is '__main__.D' + reveal_type(d) # E: Revealed type is 'Union[__main__.D, builtins.None]' reveal_type(e) # E: Revealed type is '__main__.E' reveal_type(kwargs) # E: Revealed type is 'builtins.dict[builtins.str, __main__.F]' [builtins fixtures/dict.pyi] @@ -149,9 +149,9 @@ def f(a, # type: A ): # type: (...) -> int reveal_type(a) # E: Revealed type is '__main__.A' - reveal_type(b) # E: Revealed type is '__main__.B' + reveal_type(b) # E: Revealed type is 'Union[__main__.B, builtins.None]' reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]' - reveal_type(d) # E: Revealed type is '__main__.D' + reveal_type(d) # E: Revealed type is 'Union[__main__.D, builtins.None]' reveal_type(e) # E: Revealed type is '__main__.E' reveal_type(kwargs) # E: Revealed type is 'builtins.dict[builtins.str, __main__.F]' return "not an int" # E: Incompatible return value type (got "str", expected "int") @@ -191,7 +191,7 @@ def f(a, # type: A # kwargs not tested due to lack of 2.7 dict fixtures ): reveal_type(a) # E: Revealed type is '__main__.A' - reveal_type(b) # E: Revealed type is '__main__.B' + reveal_type(b) # E: Revealed type is 'Union[__main__.B, builtins.None]' reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]' [builtins fixtures/dict.pyi] [out] @@ -209,7 +209,7 @@ def f(a, # type: A ): # type: (...) -> int reveal_type(a) # E: Revealed type is '__main__.A' - reveal_type(b) # E: Revealed type is '__main__.B' + reveal_type(b) # E: Revealed type is 'Union[__main__.B, builtins.None]' reveal_type(args) # E: Revealed type is 'builtins.tuple[__main__.C]' return "not an int" # E: Incompatible return value type (got "str", expected "int") [builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-flags.test b/test-data/unit/check-flags.test index fdaa3b456cf0..dc856f6a89d8 100644 --- a/test-data/unit/check-flags.test +++ b/test-data/unit/check-flags.test @@ -482,6 +482,24 @@ def f() -> None: x = [] # type: Union[List[Optional[str]], str] [builtins fixtures/list.pyi] +[case testPerFileStrictOptionalNoneArguments] +# flags: --config-file tmp/mypy.ini +import standard, optional + +[file standard.py] +def f(x: int = None) -> None: pass + +[file optional.py] +import standard +def f(x: int = None) -> None: pass +standard.f(None) + +[file mypy.ini] +[[mypy] +strict_optional = False +[[mypy-optional] +strict_optional = True + [case testDisallowImplicitTypesIgnoreMissingTypes] # flags: --ignore-missing-imports --disallow-any=unimported from missing import MyType diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index 9fd0a43719a9..8f358215ed73 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -363,7 +363,7 @@ y = x # E: Incompatible types in assignment (expression has type Callable[..., a, b = None, None # type: (A, B) a = f() # E: Incompatible types in assignment (expression has type "B", variable has type "A") -b = f(b) # E: Argument 1 to "f" has incompatible type "B"; expected "A" +b = f(b) # E: Argument 1 to "f" has incompatible type "B"; expected "Optional[A]" b = f(a, a) # E: Too many arguments for "f" b = f() diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index 7ac5add3e707..557d42a1ec42 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -2707,6 +2707,29 @@ b.x.y tmp/c.py:2: error: Revealed type is '' tmp/c.py:5: error: "" has no attribute "y" +[case testNoCrashOnDoubleImportAliasQuick] +# cmd: mypy -m e +# cmd2: mypy -m c +# cmd3: mypy -m e +# flags: --quick +[file c.py] +from typing import List +Alias = List[int] +[file c.py.2] +from typing import List +Alias = int + +[file d.py] +from c import Alias + +[file e.py] +from d import Alias +[file e.py.3] +from d import Alias +x: Alias +[out3] +[builtins fixtures/list.pyi] + [case testSerializeAbstractPropertyIncremental] from abc import abstractmethod import typing @@ -2735,3 +2758,85 @@ class A: pass a = A() [builtins fixtures/property.pyi] + +[case testClassNamesResolutionCrashAccess] +import mod + +[file mod.py] +class C: + def __init__(self) -> None: + self.int = '' + + def f(self, f: int) -> None: + pass + +[file mod.py.2] +class C: + def __init__(self) -> None: + self.int = '' + + def f(self, f: int) -> None: + f.x + +[out] +[out2] +tmp/mod.py:6: error: "int" has no attribute "x" + +[case testClassNamesResolutionCrashReadCache] +import mod + +[file mod.py] +import submod + +[file mod.py.2] +from submod import C + +c = C() +reveal_type(c.int) +reveal_type(c.y) + +[file submod.py] +from typing import List + +class C: + def __init__(self) -> None: + self.int = [] # type: List[int] + + def f(self, f: int) -> None: + self.y = f + +[builtins fixtures/list.pyi] +[out] +[out2] +tmp/mod.py:4: error: Revealed type is 'builtins.list[builtins.int]' +tmp/mod.py:5: error: Revealed type is 'builtins.int' + +[case testClassNamesResolutionCrashReveal] +import mod + +[file mod.py] +class Foo(object): + + def __init__(self) -> None: + self.bytes = b"foo" + + def bar(self, f: bytes): + pass + +foo = Foo() +foo.bar(b"test") + +[file mod.py.2] +class Foo(object): + + def __init__(self) -> None: + self.bytes = b"foo" + + def bar(self, f: bytes): + reveal_type(f) + +foo = Foo() +foo.bar(b"test") +[out] +[out2] +tmp/mod.py:7: error: Revealed type is 'builtins.bytes' diff --git a/test-data/unit/check-kwargs.test b/test-data/unit/check-kwargs.test index fa35c8002079..6d921b8b0285 100644 --- a/test-data/unit/check-kwargs.test +++ b/test-data/unit/check-kwargs.test @@ -30,10 +30,10 @@ f(a=A()) f(b=B()) f(c=C()) f(b=B(), c=C()) -f(a=B()) # E: Argument 1 to "f" has incompatible type "B"; expected "A" -f(b=A()) # E: Argument 1 to "f" has incompatible type "A"; expected "B" -f(c=B()) # E: Argument 1 to "f" has incompatible type "B"; expected "C" -f(b=B(), c=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "C" +f(a=B()) # E: Argument 1 to "f" has incompatible type "B"; expected "Optional[A]" +f(b=A()) # E: Argument 1 to "f" has incompatible type "A"; expected "Optional[B]" +f(c=B()) # E: Argument 1 to "f" has incompatible type "B"; expected "Optional[C]" +f(b=B(), c=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "Optional[C]" class A: pass class B: pass class C: pass @@ -182,7 +182,7 @@ f(A(), b=B()) f(A(), A(), b=B()) f(B()) # E: Argument 1 to "f" has incompatible type "B"; expected "A" f(A(), B()) # E: Argument 2 to "f" has incompatible type "B"; expected "A" -f(b=A()) # E: Argument 1 to "f" has incompatible type "A"; expected "B" +f(b=A()) # E: Argument 1 to "f" has incompatible type "A"; expected "Optional[B]" class A: pass class B: pass [builtins fixtures/list.pyi] @@ -197,8 +197,8 @@ f(b=B()) f(*a, b=B()) f(A(), *a, b=B()) f(A(), B()) # E: Argument 2 to "f" has incompatible type "B"; expected "A" -f(A(), b=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "B" -f(*a, b=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "B" +f(A(), b=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "Optional[B]" +f(*a, b=A()) # E: Argument 2 to "f" has incompatible type "A"; expected "Optional[B]" class A: pass class B: pass [builtins fixtures/list.pyi] diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index 81aa3f6957e6..7d313da71452 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -412,6 +412,12 @@ b = B._make(['']) # type: B [builtins fixtures/list.pyi] +[case testNamedTupleIncompatibleRedefinition] +from typing import NamedTuple +class Crash(NamedTuple): + count: int # E: Incompatible types in assignment (expression has type "int", base class "tuple" defined the type as Callable[[Tuple[Any, ...], Any], int]) +[builtins fixtures/tuple.pyi] + [case testNamedTupleInClassNamespace] # https://github.com/python/mypy/pull/2553#issuecomment-266474341 from typing import NamedTuple diff --git a/test-data/unit/check-varargs.test b/test-data/unit/check-varargs.test index 566841888693..73dddd51d6a2 100644 --- a/test-data/unit/check-varargs.test +++ b/test-data/unit/check-varargs.test @@ -86,7 +86,7 @@ a = None # type: A b = None # type: B c = None # type: C -f(a) # E: Argument 1 to "f" has incompatible type "A"; expected "C" +f(a) # E: Argument 1 to "f" has incompatible type "A"; expected "Optional[C]" f(c, c) # E: Argument 2 to "f" has incompatible type "C"; expected "A" f(c, a, b, c) # E: Argument 4 to "f" has incompatible type "C"; expected "A" f() @@ -377,9 +377,10 @@ class B: pass [builtins fixtures/list.pyi] [out] main:3: error: Too few arguments for "f" +main:4: error: Argument 2 to "f" has incompatible type *List[A]; expected "Optional[B]" main:4: error: Argument 2 to "f" has incompatible type *List[A]; expected "B" main:5: error: Argument 3 to "f" has incompatible type *List[A]; expected "B" -main:6: error: Argument 1 to "f" has incompatible type *"Tuple[A, A, B]"; expected "B" +main:6: error: Argument 1 to "f" has incompatible type *"Tuple[A, A, B]"; expected "Optional[B]" [case testVarArgsAfterKeywordArgInCall1-skip] # see: mypy issue #2729 diff --git a/test-data/unit/fixtures/tuple.pyi b/test-data/unit/fixtures/tuple.pyi index 0e45a776504b..4e53d12f76e6 100644 --- a/test-data/unit/fixtures/tuple.pyi +++ b/test-data/unit/fixtures/tuple.pyi @@ -1,6 +1,6 @@ # Builtins stub used in tuple-related test cases. -from typing import Iterable, Iterator, TypeVar, Generic, Sequence +from typing import Iterable, Iterator, TypeVar, Generic, Sequence, Any Tco = TypeVar('Tco', covariant=True) @@ -13,6 +13,7 @@ class type: class tuple(Sequence[Tco], Generic[Tco]): def __iter__(self) -> Iterator[Tco]: pass def __getitem__(self, x: int) -> Tco: pass + def count(self, obj: Any) -> int: pass class function: pass # We need int and slice for indexing tuples. diff --git a/test-data/unit/lib-stub/typing.pyi b/test-data/unit/lib-stub/typing.pyi index 274f3da76164..02412c77a7b8 100644 --- a/test-data/unit/lib-stub/typing.pyi +++ b/test-data/unit/lib-stub/typing.pyi @@ -50,15 +50,6 @@ class Iterator(Iterable[T], Generic[T]): def __next__(self) -> T: pass class Generator(Iterator[T], Generic[T, U, V]): - @abstractmethod - def send(self, value: U) -> T: pass - - @abstractmethod - def throw(self, typ: Any, val: Any = None, tb: Any = None) -> None: pass - - @abstractmethod - def close(self) -> None: pass - @abstractmethod def __iter__(self) -> 'Generator[T, U, V]': pass diff --git a/typeshed b/typeshed index 0e26c1f9361b..056dbbbe4388 160000 --- a/typeshed +++ b/typeshed @@ -1 +1 @@ -Subproject commit 0e26c1f9361bd2d57b9f361c4fbd8185243afb21 +Subproject commit 056dbbbe4388b790a1e7ee4137b5040ed3066eb6