Skip to content

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

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

Closed
bmerry opened this issue Sep 23, 2017 · 4 comments
Closed

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

bmerry opened this issue Sep 23, 2017 · 4 comments

Comments

@bmerry
Copy link
Contributor

bmerry commented Sep 23, 2017

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.

@ilevkivskyi
Copy link
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.

@bmerry
Copy link
Contributor Author

bmerry commented Sep 23, 2017

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)).

@ilevkivskyi
Copy link
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.

@bmerry
Copy link
Contributor Author

bmerry commented Mar 11, 2018

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

@bmerry bmerry closed this as completed Mar 11, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants