Skip to content

Commit

Permalink
Support overloaded __new__
Browse files Browse the repository at this point in the history
  • Loading branch information
JukkaL committed Nov 29, 2015
1 parent bb4043d commit 2eb5181
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 17 deletions.
33 changes: 16 additions & 17 deletions mypy/checkmember.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,23 +281,29 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) ->
# Must be an invalid class definition.
return AnyType()
else:
fallback = builtin_type('builtins.type')
if init_method.info.fullname() == 'builtins.object':
# No non-default __init__ -> look at __new__ instead.
new_method = info.get_method('__new__')
if new_method and new_method.info.fullname() != 'builtins.object':
# Found one! Get signature from __new__.
return type_object_type_from_new(new_method, info, builtin_type)
return type_object_type_from_function(new_method, info, fallback)
# Construct callable type based on signature of __init__. Adjust
# return type and insert type arguments.
init_type = method_type_with_fallback(init_method, builtin_type('builtins.function'))
if isinstance(init_type, CallableType):
return class_callable(init_type, info, builtin_type('builtins.type'))
else:
# Overloaded __init__.
items = [] # type: List[CallableType]
for it in cast(Overloaded, init_type).items():
items.append(class_callable(it, info, builtin_type('builtins.type')))
return Overloaded(items)
return type_object_type_from_function(init_method, info, fallback)


def type_object_type_from_function(init_or_new: FuncBase, info: TypeInfo,
fallback: Instance) -> FunctionLike:
signature = method_type_with_fallback(init_or_new, fallback)
if isinstance(signature, CallableType):
return class_callable(signature, info, fallback)
else:
# Overloaded __init__/__new__.
items = [] # type: List[CallableType]
for item in cast(Overloaded, signature).items():
items.append(class_callable(item, info, fallback))
return Overloaded(items)


def class_callable(init_type: CallableType, info: TypeInfo, type_type: Instance) -> CallableType:
Expand Down Expand Up @@ -345,10 +351,3 @@ def translate_variables(self,
else:
items.append(v)
return items


def type_object_type_from_new(new_method: FuncBase, info: TypeInfo,
builtin_type: Callable[[str], Type]) -> Type:
"""Return a type object type based on __new__."""
new_type = method_type_with_fallback(new_method, builtin_type('builtins.type'))
return class_callable(new_type, info, builtin_type('builtins.type'))
17 changes: 17 additions & 0 deletions mypy/test/data/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,23 @@ c.set('')
c.set(1) # E: Argument 1 to "set" of "C" has incompatible type "int"; expected "str"
[builtins fixtures/__new__.py]

[case testOverloaded__new__]
from typing import overload
class C:
@overload
def __new__(cls, foo: int) -> 'C':
obj = object.__new__(cls)
return obj
@overload
def __new__(cls, x: str, y: str) -> 'C':
obj = object.__new__(cls)
return obj
c = C(1)
c.a # E: "C" has no attribute "a"
C('', '')
C('') # E: No overload variant of "C" matches argument types [builtins.str]
[builtins fixtures/__new__.py]


-- Special cases
-- -------------
Expand Down

0 comments on commit 2eb5181

Please sign in to comment.