8000 Make overloads support classmethod and staticmethod by Michael0x2a · Pull Request #5224 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Make overloads support classmethod and staticmethod #5224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Respond to code review; add tests for self types
  • Loading branch information
Michael0x2a committed Jun 16, 2018
commit 563748a7a0aed26f83aa6d96726420f193297aa8
2 changes: 1 addition & 1 deletion mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3923,4 +3923,4 @@ def is_static(func: Union[FuncBase, Decorator]) -> bool:
return is_static(func.func)
elif isinstance(func, FuncBase):
return func.is_static
raise AssertionError("Unexpected func type: {}".format(type(func)))
assert False, "Unexpected func type: {}".format(type(func))
4 changes: 2 additions & 2 deletions mypy/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,8 @@ class FuncBase(Node):
'unanalyzed_type',
'info',
'is_property',
'is_class',
'is_static',
'is_class', # Uses "@classmethod"
'is_static', # USes "@staticmethod"
'_fullname',
)

Expand Down
2 changes: 1 addition & 1 deletion
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ def _visit_overloaded_func_def(self, defn: OverloadedFuncDef) -> None:
elif isinstance(defn.impl, FuncDef):
inner = defn.impl
else:
raise AssertionError()
assert False, "Unexpected impl type: {}".format(type(defn.impl))
class_status.append(inner.is_class)
static_status.append(inner.is_static)

Expand Down
6 changes: 3 additions & 3 deletions mypy/server/astdiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class level -- these are handled at attribute level (say, 'mod.Cls.method'

from mypy.nodes import (
SymbolTable, TypeInfo, Var, SymbolNode, Decorator, TypeVarExpr,
OverloadedFuncDef, FuncItem, MODULE_REF, TYPE_ALIAS, UNBOUND_IMPORTED, TVAR
FuncBase, OverloadedFuncDef, FuncItem, MODULE_REF, TYPE_ALIAS, UNBOUND_IMPORTED, TVAR
)
from mypy.types import (
Type, TypeVisitor, UnboundType, AnyType, NoneTyp, UninhabitedType,
Expand Down Expand Up @@ -167,13 +167,13 @@ def snapshot_definition(node: Optional[SymbolNode],
The representation is nested tuples and dicts. Only externally
visible attributes are included.
"""
if isinstance(node, (OverloadedFuncDef, FuncItem)):
if isinstance(node, FuncBase):
# TODO: info
if node.type:
signature = snapshot_type(node.type)
else:
signature = snapshot_untyped_signature(node)
return ('Func', common, node.is_property, node.is_class, node.is_property, signature)
return ('Func', common, node.is_property, node.is_class, node.is_static, signature)
elif isinstance(node, Var):
return ('Var', common, snapshot_optional_type(node.type))
elif isinstance(node, Decorator):
Expand Down
59 changes: 59 additions & 0 deletions test-data/unit/check-overloading.test
Original file line number Diff line number Diff line change
Expand Up @@ -3350,3 +3350,62 @@ class Wrapper:
return 3 # E: Incompatible return value type (got "int", expected "str")

[builtins fixtures/staticmethod.pyi]

[case testOverloadAndSelfTypes]
from typing import overload, Union, TypeVar, Type

T = TypeVar('T', bound='Parent')
class Parent:
@overload
def foo(self: T, x: int) -> T: pass

@overload
def foo(self, x: str) -> str: pass

def foo(self: T, x: Union[int, str]) -> Union[T, str]:
reveal_type(self.bar()) # E: Revealed type is 'builtins.str'
return self

def bar(self) -> str: pass

class Child(Parent):
def child_only(self) -> int: pass

x: Union[int, str]
reveal_type(Parent().foo(3)) # E: Revealed type is '__main__.Parent*'
reveal_type(Child().foo(3)) # E: Revealed type is '__main__.Child*'
reveal_type(Child().foo("...")) # E: Revealed type is 'builtins.str'
reveal_type(Child().foo(x)) # E: Revealed type is 'Union[__main__.Child*, builtins.str]'
reveal_type(Child().foo(3).child_only()) # E: Revealed type is 'builtins.int'

[case testOverloadAndClassTypes]
from typing import overload, Union, TypeVar, Type

T = TypeVar('T', bound='Parent')
class Parent:
@overload
@classmethod
def foo(cls: Type[T], x: int) -> Type[T]: pass

@overload
@classmethod
def foo(cls, x: str) -> str: pass

@classmethod
def foo(cls: Type[T], x: Union[int, str]) -> Union[Type[T], str]:
reveal_type(cls.bar()) # E: Revealed type is 'builtins.str'
return cls

@classmethod
def bar(cls) -> str: pass

class Child(Parent):
def child_only(self) -> int: pass

x: Union[int, str]
reveal_type(Parent.foo(3)) # E: Revealed type is 'Type[__main__.Parent*]'
reveal_type(Child.foo(3)) # E: Revealed type is 'Type[__main__.Child*]'
reveal_type(Child.foo("...")) # E: Revealed type is 'builtins.str'
reveal_type(Child.foo(x)) # E: Revealed type is 'Union[Type[__main__.Child*], builtins.str]'
reveal_type(Child.foo(3)().child_only()) # E: Revealed type is 'builtins.int'
[builtins fixtures/classmethod.pyi]
0