Spotipy: AttributeError: 'NoneType' object has no attribute 'split' when calling util.prompt_for_user_token with a cached token of None scope

Created on 29 Mar 2017  Â·  22Comments  Â·  Source: plamere/spotipy

Minimal example:

from spotipy.util import prompt_for_user_token
token = prompt_for_user_token(some_username, None, some_client_id, some_client_secret, some_redirect_uri)
# Now a cached token with None scope exists
token2 = prompt_for_user_token(some_username, None, some_client_id, some_client_secret, some_redirect_uri)
# AttributeError occurs

(Note scope=None is default for util.prompt_for_user_token())
Traceback:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "$PYTHONPATH$\lib\site-packages\spotipy\util.py", line 56, in prompt_for_user_token
    token_info = sp_oauth.get_cached_token()
  File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 135, in get_cached_token
    if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']):
  File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 156, in _is_scope_subset
    needle_scope = set(needle_scope.split())
AttributeError: 'NoneType' object has no attribute 'split'

This breaks the program when being runned a second time with existence of cache on disk, which previously (back before last December I believe) did not happen.

bug

Most helpful comment

Simple workaround:

import os
from json.decoder import JSONDecodeError

scope = <whatever_youwant>
try:
    token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)
except (AttributeError, JSONDecodeError):
    os.remove(f".cache-{username}")
    token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)

All 22 comments

I am having the same issue. It worked the first time but it fails the second time,

Got the same issue!

I think this might be a bug. If we don't pass a valid scope the first time a user token is generated and authorized successfully, then from next time onwards, the get_cached_token() function is susceptible to returning 'None' (line 135 in oauth2.py), even if you set the scope this time. Maybe, this is it, though I need to download the library, make changes and try it out. I had used installed version till now.

Use the github version, it should be fixed.

@josduj Using Github version, now the error becomes:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "$PYTHONPATH$\lib\site-packages\spotipy\util.py", line 56, in prompt_for_user_token
    token_info = sp_oauth.get_cached_token()
  File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 135, in get_cached_token
    if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']):
  File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 161, in _is_scope_subset
    return needle_scope <= haystack_scope
TypeError: unorderable types: NoneType() <= NoneType()

It started working for me.

I just deleted the original user token and now it works every time I use it

On Mon, Apr 24, 2017 at 3:52 AM, Jason Li notifications@github.com wrote:

@josduj https://github.com/josduj Using Github version, now the error
becomes:

Traceback (most recent call last):
File "", line 1, in
File "$PYTHONPATH$\lib\site-packages\spotipy\util.py", line 56, in prompt_for_user_token
token_info = sp_oauth.get_cached_token()
File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 135, in get_cached_token
if 'scope' not in token_info or not self._is_scope_subset(self.scope, token_info['scope']):
File "$PYTHONPATH$\lib\site-packages\spotipy\oauth2.py", line 161, in _is_scope_subset
return needle_scope <= haystack_scopeTypeError: unorderable types: NoneType() <= NoneType()

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/plamere/spotipy/issues/176#issuecomment-296563244,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ASwCUVk9kg90n-lSXb-zb05VEG4A8uUsks5rzFS7gaJpZM4Mscjq
.

This issue is present on the "Shows the contents of every playlist owned by a user" example on the website documentation as well. fixed by setting scope='user-library-read' before prompting user token.

Simple workaround:

import os
from json.decoder import JSONDecodeError

scope = <whatever_youwant>
try:
    token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)
except (AttributeError, JSONDecodeError):
    os.remove(f".cache-{username}")
    token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)

Thanks @ulgens , your solution worked fine for me.

Adding the following to _is_scope_subset in oauth2.py fixes this issue. When I initially created my oauth token I did it on a create_playlist call. It seems that this creates a token with a scope of None and that breaks parsing. This is working for me but may be an incomplete fix.

     def _is_scope_subset(self, needle_scope, haystack_scope):
       if needle_scope == None and haystack_scope == None:
             return True

I can confirm that @Perolus commit works for me.

how can one delete the original user token with None scope?

import os
from json.decoder import JSONDecodeError

scope = <whatever_youwant>
try:
    token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)
except (AttributeError, JSONDecodeError):
    os.remove(f".cache-{username}")
    token = util.prompt_for_user_token(username, scope, client_id, client_secret, redirect_uri)

this does not work for me. why do I get syntax error in

os.remove(f".cache-{username}")

where is this file located?

@patalanov

os.remove(f".cache-{username}")

f strings are only supporterd after python 3.6. If you're using lower version, you should use .format() method. File is located under same folder with the code itself.

Thanks @ulgens it worked very fine.

Hey @ivancete, I'm having the same problem you had, what was the code that you inserted using the .format()? Thanks!

@jfaul The line of code using .format would be os.remove(".cache-{}".format(username))

@ulgens worked perfectly thank you

A hidden file is created called .cache-{username} can be also deleted manually

I was getting this problem because I wasn't passing the returned token when instanciating the spotipy.Spotify instance.

I was doing this....

util.prompt_for_user_token("User")
spotify = spotipy.Spotify()

When I should have been doing this...

token = util.prompt_for_user_token("User")
spotify = spotipy.Spotify(auth=token)

Many thanks to @ulgens and @wyattshapiro whos fixes outlined above saved the day!

I changed the function at line 155 with this

def _is_scope_subset(self, needle_scope, haystack_scope):
    if needle_scope:
        needle_scope = set(needle_scope.split())
    else:
        needle_scope = ""
    if haystack_scope:
        haystack_scope = set(haystack_scope.split())
    else:
        haystack_scope = ""
    return needle_scope <= haystack_scope

and it works.

Maybe I've done something wrong (I have a lot to learn in Python) but for now is working

Hello. I was using the library without any trouble, but suddenly I got the same error. I am authenticating using:

import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
from config import SPOT_CLIENT_ID, SPOT_CLIENT_SECRET
client_credentials_manager = SpotifyClientCredentials(client_id=SPOT_CLIENT_ID,
                                                      client_secret=SPOT_CLIENT_SECRET)
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

I tried deleting the hidden file without luck. I am using the latest version of the library. Any ideas on what may be happening?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AnySomebody1 picture AnySomebody1  Â·  3Comments

DylanMeeus picture DylanMeeus  Â·  4Comments

gawaineo picture gawaineo  Â·  3Comments

Kurchunk picture Kurchunk  Â·  3Comments

fortyTwo102 picture fortyTwo102  Â·  4Comments