pythonpython-3.xoauthipythondiscogs-api

TypeError: __repr__ returned non-string (type bytes)


I am trying to access the Discogs API using their Python client library.

Here is a minimal example of my attempts to interact with the Discogs API:

from SensitiveInformation.discogs_application_info import provide_discogs_auth, provide_verifier
import discogs_client

discogs_consumer_key, discogs_consumer_secret = provide_discogs_auth()
discogs = discogs_client.Client(user_agent="ThoughfulMachineLearning",
                                consumer_key=discogs_consumer_key,
                          consumer_secret=discogs_consumer_secret)
discogs_auth_url = discogs.get_authorize_url()
discogs.get_access_token(verifier=provide_verifier())
discogs.identity()

The functions provide_discogs_auth and provide_verifier simply return the consumer key & secret and the verifier from user authorization. get_access_token returns the access key and secret as expected.

However, on the last line, when I make an API call, I get:

Out[38]: In[39]: discogs.identity()
Traceback (most recent call last):
Out[39]:   File "/usr/local/lib/python3.4/dist-packages/IPython/core/formatters.py", line 219, in catch_format_error
    r = method(self, *args, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/IPython/core/formatters.py", line 690, in __call__
    printer.pretty(obj)
  File "/usr/local/lib/python3.4/dist-packages/IPython/lib/pretty.py", line 407, in pretty
    return _default_pprint(obj, self, cycle)
  File "/usr/local/lib/python3.4/dist-packages/IPython/lib/pretty.py", line 527, in _default_pprint
    _repr_pprint(obj, p, cycle)
  File "/usr/local/lib/python3.4/dist-packages/IPython/lib/pretty.py", line 709, in _repr_pprint
    output = repr(obj)
TypeError: __repr__ returned non-string (type bytes)

Not sure if this is related to IPython or the client library, but would appreciate help either way. Thanks.


Solution

  • This is a bug in the library; the User.__repr__ method returns bytes on Python 3:

    def __repr__(self):
        return '<User {0!r} {1!r}>'.format(self.id, self.username).encode('utf-8')
    

    You already filed a bug report with the project, which is great!

    You can avoid the issue you see in IPython or any other interactive Python console by assigning the result of discogs.identity() to a variable:

    user = discogs.identity()
    

    Try to avoid echoing the result.

    You can patch the method on the fly with:

    import six
    from discogs_client import models
    
    orig_repr = models.User.__repr__
    
    def fixed_repr(self):
        r = orig_repr(self)
        if six.PY3 and isinstance(r, bytes):
            r = r.decode('utf8')
        return r
    
    models.User.__repr__ = fixed_repr
    

    You probably have to do this for other models as well; I see more __repr__ implementations with .encode('utf8') calls in the models module.