`session.playlist_container.append(some_string)` ends with `spotify.error.LibError: Invalid input` #175

Closed
AndydeCleyre opened this Issue Sep 4, 2015 · 5 comments

Projects

None yet

2 participants

@AndydeCleyre

Hi,

I'm trying to get the hang of pyspotify 2.0.2, and am probably doing a few things wrong. My current goal is to create a new playlist populated with tracks. When it hits session.playlist_container.append I get the following traceback:

Traceback (most recent call last):
  File "./make_spotify_playlist.py", line 115, in <module>
    '4Tdu8PriujHnDfSoHmA2jQ']
  File "./make_spotify_playlist.py", line 53, in new_playlist_from_track_ids
    self.session.playlist_container.append(name)
  File "/usr/lib/python3.4/_collections_abc.py", line 708, in append
    self.insert(len(self), value)
  File "/home/<user/project>/env/lib/python3.4/site-packages/spotify/playlist_container.py", line 393, in insert
    self[index:index] = [value]
  File "/home/<user/project>/env/lib/python3.4/site-packages/spotify/playlist_container.py", line 219, in __setitem__
    self.add_new_playlist(val, index=i)
  File "/home/<user/project>/env/lib/python3.4/site-packages/spotify/__init__.py", line 58, in wrapper
    return f(*args, **kwargs)
  File "/home/<user/project>/env/lib/python3.4/site-packages/spotify/playlist_container.py", line 261, in add_new_playlist
    self.move_playlist(self.__len__() - 1, index)
  File "/home/<user/project>/env/lib/python3.4/site-packages/spotify/playlist_container.py", line 361, in move_playlist
    self._sp_playlistcontainer, from_index, to_index, int(dry_run)))
  File "/home/<user/project>/env/lib/python3.4/site-packages/spotify/error.py", line 31, in maybe_raise
    raise LibError(error_type)
spotify.error.LibError: Invalid input

Here are the entire contents of the offending script:

#!/usr/bin/env python3

# This is a modified copy from the pyspotify examples folder
# Original license can be read at https://github.com/mopidy/pyspotify/blob/v2.x/develop/LICENSE

from sys import argv
from threading import Event
from collections import defaultdict
from contextlib import suppress
from time import time

from spotify import Session, EventLoop, SessionEvent, AlsaSink, ConnectionState, PlayerState

from _private import USER, PASSWORD


class SpotifyPlayer:

    def __init__(self, username=USER, password=PASSWORD, track_id=None, track_uri=None, session=None, event_loop=None, events=None):
        self.session = session or Session()

        self.loop = event_loop or EventLoop(self.session)
        if not event_loop:
            self.loop.start()
        self.events = events or defaultdict(Event)

        self.session.on(SessionEvent.CONNECTION_STATE_UPDATED, self.on_connection_state_updated)
        self.session.on(SessionEvent.END_OF_TRACK, self.on_end_of_track)

        self.session.login(username, password)
        self.audio = AlsaSink(self.session)

        if track_id:
            self.play_track_id(track_id)
        elif track_uri:
            self.play_track_uri(track_uri)

    def on_connection_state_updated(self, session):
        if self.session.connection.state is ConnectionState.LOGGED_IN:
            self.events['logged in'].set()

    def on_end_of_track(self, session):
        self.events['end of track'].set()

    def new_playlist_from_track_ids(self, track_ids, name=None):
        name = name or str(time())
        self.events['logged in'].wait()#blocks!
        self.session.playlist_container.load()#blocks!
        self.session.playlist_container.append(name)
        playlist = self.session.playlist_container[-1]
        playlist.add_tracks([self.session.get_track('spotify:track:' + t_id) for t_id in track_ids])
        return playlist

    def block_until_end_of_track(self):
        with suppress(KeyboardInterrupt):
            while not self.events['end of track'].wait(0.1):
                pass

    def play_track_uri(self, track_uri, block=False):
        self.events['logged in'].wait()
        track = self.session.get_track(track_uri).load()
        self.session.player.unload()
        self.session.player.load(track)
        self.session.player.play()
        if block:
            self.block_until_end_of_track()

    def play_track_id(self, track_id, block=False):
        self.play_track_uri('spotify:track:' + track_id, block)

    def pause(self):
        self.session.player.play(session.player.state != PlayerState.PLAYING)


if __name__ == '__main__':
    sp = SpotifyPlayer()
    sp.new_playlist_from_track_ids(
        ['1BJlYS8PLaj6zn5vEEupEV',
        '0wx5YZO0R5uyyabUmRZ2Vx',
        '4QBBggvmhsn1Kq46iAFon5',
        '1de9Os1k1mxT4wsH30GIIb',
        '77h8uh8VgoTU8xdXG8GHq4',
        '0DCLQZwpBadfCzTeqrMTCz',
        '3curAxvuKB5aTOVRo96TKC',
        '0dZ6fD6ZRR1JXgU5CLIARH',
        '4bKX2IrOpRVol9wTtAkcCR',
        '7p6ZeiNtEHJKmc4YWBZELG',
        '3QpLBTVFMncbv7QCG4ggTM',
        '07rC3IK3b1P7CcVpMTG9lk',
        '7HiekBFtD3tvKtJ7CSgMG8',
        '5ltQdnOKEYKbMHOjUIdYXI',
        '01yrRl8KDvaiIFIzeSkJeE',
        '2fUVvpijJHsHmRrNZeKjMm',
        '4aejSOKWJS0jvEg02eiRTn',
        '6uqpxbKd9weZNBN5dwVyFQ',
        '7dpxBp2RToVq7HUhg3pjoM',
        '37gcgx2keiiolP5uW3a4lI',
        '2aTd0JCTfCzgjDGeWRDxuN',
        '3Q5EpfXcZM3mnJ3vTWGNjC',
        '3M89DiryoIVBQDRmB4Owxn',
        '1HDpoq1lgBbFbjeEhtGyP4',
        '605ec1HR3tHdukWKBhl2P2',
        '19wpi7nMbTWEtrtmkWWY90',
        '1eZu9Rtj6vyb9mdVn9zAlw',
        '13BBPhltugT8vZ5NqCHr9S',
        '0tQ0QHsCOVNkmCXazfwHwS',
        '2ZiWStmhbBPoJ41ljEaTDp',
        '4Tdu8PriujHnDfSoHmA2jQ']
    )
@jodal jodal closed this in 66e7da1 Sep 4, 2015
@AndydeCleyre

Amazing, thank you!

@jodal
Member
jodal commented Sep 4, 2015

Thanks to you! Easy to fix bugs when you get both a stack trace and a script to reproduce :-)

@AndydeCleyre

So this now returns a Playlist which has a URI, but the playlist does not appear on my Spotify account, as checked on the Android app, Mopify, and the Spotify web player. I looked through the Playlist docs, but I haven't found any extra steps mentioned for creating a new playlist.

@jodal
Member
jodal commented Sep 5, 2015

You'll need to make sure the playlist and its changes are synced to the server before quitting your program. Since you have an EventLoop running, it should already call process_events() for you, so that is taken care of. Also, it is a good idea to logout properly and wait for the logged out event before quitting the process.

Relevant parts of the API:

Untested pseudo code:

def on_logged_out(session):
    sys.exit()

session.on(SessionEvent.LOGGED_OUT, on_logged_out)

while playlist.has_pending_changes:
    session.process_events()  # The event loop does this, so you can probably just sleep a bit instead.

session.logout()
@AndydeCleyre

Perfect, thanks

@jodal jodal added the bug label Sep 5, 2015
@jodal jodal self-assigned this Sep 5, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment