Skip to content
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

Support special object.__new__ and object.__init__ in super. #794

Closed
o11c opened this issue Aug 18, 2015 · 6 comments
Closed

Support special object.__new__ and object.__init__ in super. #794

o11c opened this issue Aug 18, 2015 · 6 comments
Labels

Comments

@o11c
Copy link
Contributor

o11c commented Aug 18, 2015

Currently, __new__ is not special at all. While full support is complicated, it is particularly irritating that object.__new__ cannot be added to stubs at all, since subclasses need to override it with different signatures and that is an error.

object.__new__ and object.__init__ are special in another way. For the object class itself, their signatures are (Subclass[T]) -> T and (T) -> None. However, when called from subclass constructors via super(), the signatures are (Subclass[T], *args, **kwargs) -> T and (T, *args, **kwargs) -> None.

In the above, T is a TypeVar that is bounded by the current class, and Subclass[T] is basically Intersection[type, Callable[..., T]] (i.e. supports duck typing once the Protocol stuff works).

(In my notes I am using use the term Class[T] to refer to Intersection[type, Callable[[signature of __init__], T]])

As an icky workaround, I tried using cast(Any, super()), but that says that super is not defined, before settling on # type: ignore

@JukkaL JukkaL added the feature label Aug 19, 2015
JukkaL added a commit that referenced this issue Nov 22, 2015
This partially addresses #794.
@ddfisher ddfisher added this to the 0.4.0 milestone Mar 2, 2016
@ddfisher
Copy link
Collaborator

ddfisher commented Mar 2, 2016

This is probably partially out of date -- we should investigate what the current situation is.

@Syeberman
Copy link

I believe this issue still exists. The following code:

class IntSubclass(int):
    def __new__(cls, v: int) -> IntSubclass:
        return super().__new__(cls, v)

Produces these errors:

[C:\Projects]python -m mypy --version
mypy 0.501

[C:\Projects]python -m mypy --strict syetest.py
syetest.py:3: warning: Returning Any from function with declared return type "syetest.IntSubclass"
syetest.py:3: error: Too many arguments for "__new__" of "object"

@gvanrossum gvanrossum removed this from the 0.5 milestone Mar 29, 2017
@frankcarey
Copy link

Yes, also getting an error..

class VersionID(bytes):
    """A byte string of len 32 that only allows a-z, 0-9, and underscores."""
    vid: bytes

    # Must use __new__ since bytes is immutable.
    def __new__(cls, version_id: Union[bytes, str]) -> 'VersionID':
        # Allow passing as a string and then convert to ascii bytes.
        if isinstance(version_id, str):
            vid = version_id.encode('ascii')
        else:
            vid = version_id
        assert isinstance(vid, bytes), \
            "version_id should be bytes-like, but found {}".format(
                type(vid))
        assert len(vid) > 0, \
            "version_id should be at least one character."
        assert len(vid) <= 32, \
            "version_id should be less than 32 characters."
        assert re.match(b'^[a-z0-9_]*$', vid), \
            "version_id should only contain lowercase letters, numbers, " \
            "and underscores."
        ## noinspection PyArgumentList
        return super().__new__(cls, vid)

    def __str__(self) -> str:
        return self.decode('ascii')

Produces: error: Too many arguments for "__new__" of "object"

mypy version: 0.560

@Syeberman
Copy link

I believe that is a separate issue, @frankcarey. It looks like mypy is interpreting super().__new__(cls, vid) as object.__new__(cls, vid), when really it's bytes.__new__(cls, vid). You should log a separate issue for this (or add to an existing issue if it has already been reported).

Incidentally, I would remove the line vid: bytes, which suggests that VersionID().vid is a valid attribute containing the ID, when actually VersionID() itself is the ID.

@ilevkivskyi
Copy link
Member

@JukkaL Is something still needed here? We already allow incompatible overrides of __init__ and __new__, and there is a separate issue for inferring attributes from __new__ body.

@JukkaL
Copy link
Collaborator

JukkaL commented Dec 13, 2018

The original issue seems to be resolved. Any remaining problems can be reported as separate issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants