Skip to content

bytes should implement __new__ #2630

Closed
Closed

Description

@mystor

This seems like a similar issue to #2091. The bytes type implements __init__ but doesn't appear to provide an overload for __new__. This makes it harder for subclasses of bytes to define their own behaviour for __new__.

class bytes(ByteString):
@overload
def __init__(self, ints: Iterable[int]) -> None: ...
@overload
def __init__(self, string: str, encoding: str,
errors: str = ...) -> None: ...
@overload
def __init__(self, length: int) -> None: ...
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, o: SupportsBytes) -> None: ...

This also appears to be the case for some of the other builtins (e.g. str)

class str(Sequence[str]):
@overload
def __init__(self, o: object = ...) -> None: ...
@overload
def __init__(self, o: bytes, encoding: str = ..., errors: str = ...) -> None: ...

Activity

  1. srittau commented on Nov 29, 2018

    @srittau
    Collaborator

    Could you give an example where this is a problem? bytes and str should inherit __new__ from object if I am not mistaken.

  2. mystor commented on Nov 29, 2018

    @mystor
    Author

    They do, but the argument list is wrong. As a strawman example:

    class SHA1Hash(bytes):
        def __new__(cls, b: bytes) -> 'SHA1Hash':
            if len(b) != 20:
                raise ValueError("Invalid SHA1Hash value!")
            return super().__new__(cls, b)

    This doesn't typecheck, because the call to super().__new__(cls, b) is inferred to be object.__new__(cls, b) which is incorrect as object.__new__ takes only the cls argument. bytes, on the other hand, takes an argument to create the object.

    This is also a bit like the tuple case again in that __init__ doesn't make much sense for bytes or str, as they are non-mutable and can only be constructed with __new__ in the first place.

  3. srittau commented on Nov 29, 2018

    @srittau
    Collaborator

    Thanks for the explanation. Makes sense. We appreciate pull requests!

  4. sproshev commented on Nov 30, 2018

    @sproshev
    Contributor

    str.__new__ had been added in #1352 but then reverted

  5. mystor commented on Nov 30, 2018

    @mystor
    Author

    Figure I should add a ref to the reason it was backed out: #1464

    It appears it was backed out because the addition of __new__ to str caused problems for classes deriving from both str and Enum, as the str's __new__ would now take priority rather than the Enum's. I'm guessing this is caused by some magic wrt how str is actually implemented within python :-/

    Perhaps there needs to be a special case for these builtins to make constructing them work correctly?

  6. added
    stubs: incompleteAnnotations or sub-modules missing from an existing package or module
    and removed on Sep 17, 2020
  7. hauntsaninja commented on Sep 30, 2020

    @hauntsaninja
    Collaborator

    Closed by #4555 (and thank you for git-revise!)

  8. added a commit that references this issue on Dec 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stubs: incompleteAnnotations or sub-modules missing from an existing package or module

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions