Tuesday, 16 February 2021

Calling __new__ on an Any

I'm trying to implement this answer for custom deepcopy, but with type hints, and mypy's not happy with the Any type that I'm using from a third party library. Here's the smallest bit of code I can get to fail

# I'm actually using tensorflow.Module, not Any,
# but afaik that's the same thing. See context below
T = TypeVar("T", bound=Any)

def foo(x: T) -> None:
    cls = type(x)
    cls.__new__(cls)

I see

 error: No overload variant of "__new__" of "type" matches argument type "Type[Any]"
 note: Possible overload variants:
 note:     def __new__(cls, cls: Type[type], o: object) -> type
 note:     def __new__(cls, cls: Type[type], name: str, bases: Tuple[type, ...], namespace: Dict[str, Any]) -> type

It passes if I bound T to something typed, like int, str or a custom class. I'm confused about this, cos neither of these overloads matches the __new__ docs. My knowledge of __new__ is fairly basic.

I'm after either a fix, or if it's a limitation/bug in mypy, an explanation of what that is.

Context

The actual function is

import tensorflow as tf

T = TypeVar("T", bound=tf.Module)  # tf.Module is untyped

def my_copy(x: T, memo: Dict[int, object]) -> T:
    do_something_with_a_tf_module(x)

    cls = type(x)
    new = cls.__new__(cls)
    memo[id(self)] = new

    for name, value in x.__dict__.items():
        setattr(new, name, copy.deepcopy(value, memo))

    return new 

curiously, If I instead make this a method

class Mixin(tf.Module):
    def __deepcopy__(self: T, memo: Dict[int, object]) -> T:
        ...  # the same implementation as `my_copy` above

there's no error



from Calling __new__ on an Any

No comments:

Post a Comment