If an iterator is currently in progress, all functions which fetch a
response (such as <cmd>() and fetch_<cmd>()) will be disabled, as well as
command lists. This makes iterators much more reliable by preventing code
from reading a response while an iterator is trying to read another
response. Previously this was allowed, and would corrupt the library state
by providing false responses to both the iterator and the code trying to
fetch a different response.
class PendingCommandError(MPDError):
pass
class PendingCommandError(MPDError):
pass
+class IteratingError(MPDError):
+ pass
+
class _NotConnected(object):
def __getattr__(self, attr):
class _NotConnected(object):
def __getattr__(self, attr):
if self._command_list is not None:
raise CommandListError("Cannot use fetch_%s in a command list" %
command)
if self._command_list is not None:
raise CommandListError("Cannot use fetch_%s in a command list" %
command)
+ if self._iterating:
+ raise IteratingError("Cannot use fetch_%s while iterating" %
+ command)
if not self._pending:
raise PendingCommandError("No pending commands to fetch")
if self._pending[0] != command:
if not self._pending:
raise PendingCommandError("No pending commands to fetch")
if self._pending[0] != command:
return retval()
def _execute(self, command, args):
return retval()
def _execute(self, command, args):
+ if self._iterating:
+ raise IteratingError("Cannot execute %s while iterating" % command)
if self._pending:
raise PendingCommandError("Cannot execute %s with "
"pending commands" % command)
if self._pending:
raise PendingCommandError("Cannot execute %s with "
"pending commands" % command)
self._command_list = None
self._fetch_nothing()
self._command_list = None
self._fetch_nothing()
+ def _iterator_wrapper(self, iterator):
+ self._iterating = True
+ for item in iterator:
+ yield item
+ self._iterating = False
+
def _wrap_iterator(self, iterator):
if not self.iterate:
return list(iterator)
def _wrap_iterator(self, iterator):
if not self.iterate:
return list(iterator)
+ return self._iterator_wrapper(iterator)
def _fetch_nothing(self):
line = self._read_line()
def _fetch_nothing(self):
line = self._read_line()
def _reset(self):
self.mpd_version = None
def _reset(self):
self.mpd_version = None
+ self._iterating = False
self._pending = []
self._command_list = None
self._sock = None
self._pending = []
self._command_list = None
self._sock = None
def command_list_ok_begin(self):
if self._command_list is not None:
raise CommandListError("Already in command list")
def command_list_ok_begin(self):
if self._command_list is not None:
raise CommandListError("Already in command list")
+ if self._iterating:
+ raise IteratingError("Cannot begin command list while iterating")
if self._pending:
raise PendingCommandError("Cannot begin command list "
"with pending commands")
if self._pending:
raise PendingCommandError("Cannot begin command list "
"with pending commands")