def load(obj, timeout=None): """Block until the object's data is loaded. The ``obj`` must at least have the :attr:`is_loaded` attribute. If it also has an :meth:`error` method, it will be checked for errors to raise. After ``timeout`` seconds with no results :exc:`~spotify.Timeout` is raised. If unspecified, the ``timeout`` defaults to 10s. Any timeout is better than no timeout, since no timeout would cause programs to potentially hang forever without any information to help debug the issue. The method returns ``self`` to allow for chaining of calls. """ if spotify.session_instance is None: raise RuntimeError('Session must be initialized to load objects') if spotify.session_instance.user is None: raise RuntimeError('Session must be logged in to load objects') if timeout is None: timeout = 10 deadline = time.time() + timeout while not obj.is_loaded: # TODO Consider sleeping for the time returned by process_events() # instead of making a tight loop. spotify.session_instance.process_events() spotify.Error.maybe_raise(getattr(obj, 'error', 0), ignores=[spotify.ErrorType.IS_LOADING]) if time.time() > deadline: raise spotify.Timeout(timeout) time.sleep(0.001) spotify.Error.maybe_raise(getattr(obj, 'error', 0), ignores=[spotify.ErrorType.IS_LOADING]) return obj
def load(session, obj, timeout=None): """Block until the object's data is loaded. If the session isn't logged in, a :exc:`spotify.Error` is raised as Spotify objects cannot be loaded without being online and logged in. The ``obj`` must at least have the :attr:`is_loaded` attribute. If it also has an :meth:`error` method, it will be checked for errors to raise. After ``timeout`` seconds with no results :exc:`~spotify.Timeout` is raised. If unspecified, the ``timeout`` defaults to 10s. Any timeout is better than no timeout, since no timeout would cause programs to potentially hang forever without any information to help debug the issue. The method returns ``self`` to allow for chaining of calls. """ _check_error(obj) if obj.is_loaded: return obj if session.connection.state is not spotify.ConnectionState.LOGGED_IN: raise spotify.Error( 'Session must be logged in and online to load objects: %r' % session.connection.state) if timeout is None: timeout = 10 deadline = time.time() + timeout while not obj.is_loaded: session.process_events() _check_error(obj) if obj.is_loaded: return obj if time.time() > deadline: raise spotify.Timeout(timeout) # Instead of sleeping for a very short time and making a tight loop # here, one might be tempted to sleep for the time returned by the # session.process_events() call above. If no event loop is running, # that could lead to very long waits (up to a minute or so) since no # one is doing anything on "notify_main_thread" session callbacks, # which is intended to interrupt the sleep interval prescribed by # session.process_events(). Thus, it is better to make this loop tight. time.sleep(0.001) _check_error(obj) return obj
def test_has_useful_repr(self): error = spotify.Timeout(0.5) self.assertIn('Operation did not complete in 0.500s', repr(error))
def test_has_useful_string_representation(self): error = spotify.Timeout(0.5) self.assertEqual('%s' % error, 'Operation did not complete in 0.500s') self.assertIsInstance('%s' % error, utils.text_type)
def test_is_an_error(self): error = spotify.Timeout(0.5) self.assertIsInstance(error, spotify.Error)