Skip to content

bytes(obj) rejected even when obj implements __bytes__ #3989

Description

@bmerry

Sample code:

#!/usr/bin/env python3

class A(object):
    def __bytes__(self) -> bytes:
        return b'An A'

print(bytes(A()))

Output from mypy 0.521, Python 3.5.2:

test.py:7: error: No overload variant of "bytes" matches argument types [test.A]

Looking in typeshed, it has this overload:

class bytes(ByteString):
    @overload
    def __init__(self, o: SupportsBytes) -> None: ...

which doesn't seem to be matching.

Activity

  1. ilevkivskyi commented on Sep 23, 2017

    @ilevkivskyi
    Member

    The problem is that SupportsBytes (and several other classes) is not yet defined as a protocol. This will be fixed by python/typeshed#1220, a temporary workaround is to explicitly inherit A from typing.SupportsBytes.

  2. bmerry commented on Sep 23, 2017

    @bmerry
    ContributorAuthor

    Unfortunately the workaround breaks using isinstance with the class:

    #!/usr/bin/env python3
    
    import typing
    
    class A(typing.SupportsBytes):
        def __bytes__(self) -> bytes:
            return b'An A'
    
    print(bytes(A()))
    assert isinstance(None, A)

    at runtime gives

    b'An A'
    Traceback (most recent call last):
      File "./test.py", line 10, in <module>
        assert isinstance(None, A)
      File "/usr/lib/python3.5/typing.py", line 1269, in __instancecheck__
        raise TypeError("Protocols cannot be used with isinstance().")
    TypeError: Protocols cannot be used with isinstance().
    

    I managed to work around it by replacing bytes(a) with bytes(cast(SupportsBytes, a)).

  3. ilevkivskyi commented on Sep 23, 2017

    @ilevkivskyi
    Member

    Concerning the isinstance() error, it looks like you are using an older version of typing, this is fixed in latest version. You could try updating Python (or upgrading to 3.6), but your workaround (using cast) is perfectly OK.

  4. bmerry commented on Mar 11, 2018

    @bmerry
    ContributorAuthor

    It works with the current version of mypy (0.570), so closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions