[Pkg-mpd-commits] [python-mpd] 51/91: asyncio: prepare `async for` iteration over commands
Simon McVittie
smcv at debian.org
Sat Feb 24 14:55:35 UTC 2018
This is an automated email from the git hooks/post-receive script.
smcv pushed a commit to branch debian/master
in repository python-mpd.
commit 01d991a22dbb8e0f03a5cd2fa907fdd64c9cb1c8
Author: chrysn <chrysn at fsfe.org>
Date: Fri Apr 7 08:11:28 2017 +0200
asyncio: prepare `async for` iteration over commands
This moves the line handling into the CommandResult, and makes the "full
set of lines" always contain the final None line
---
mpd/asyncio.py | 49 ++++++++++++++++++++++++++++++++++++-------------
1 file changed, 36 insertions(+), 13 deletions(-)
diff --git a/mpd/asyncio.py b/mpd/asyncio.py
index e5ac2cd..4eb42cf 100644
--- a/mpd/asyncio.py
+++ b/mpd/asyncio.py
@@ -1,11 +1,33 @@
import asyncio
+from functools import partial
from mpd.base import HELLO_PREFIX, ERROR_PREFIX, SUCCESS
from mpd.base import MPDClientBase
from mpd.base import MPDClient as SyncMPDClient
-from mpd.base import ProtocolError, ConnectionError
+from mpd.base import ProtocolError, ConnectionError, CommandError
from mpd.base import mpd_command_provider
+class CommandResult(asyncio.Future):
+ """A future that carries its command/args/callback with it for the
+ convenience of passing it around to the command queue."""
+
+ def __init__(self, command, args, callback):
+ super().__init__()
+ self._command = command
+ self._args = args
+ self.__callback = callback
+ self.__spooled_lines = []
+
+ def _feed_line(self, line):
+ """Put the given line into the callback machinery, and set the result on a None line."""
+ if line is None:
+ self.set_result(self.__callback(self.__spooled_lines))
+ else:
+ self.__spooled_lines.append(line)
+
+ async def __aiter__(self):
+ raise NotImplementedError("async for x in clientcommand() is work in progress")
+
@mpd_command_provider
class MPDClient(MPDClientBase):
__run_task = None # doubles as indicator for being connected
@@ -32,13 +54,17 @@ class MPDClient(MPDClientBase):
async def __run(self):
while True:
- command, args, callback, result = await self.__commandqueue.get()
- self._write_command(command, args)
- responselines = await self.__read_full_output()
+ result = await self.__commandqueue.get()
+ self._write_command(result._command, result._args)
try:
- result.set_result(callback(self, responselines))
+ responselines = await self.__read_full_output()
+ for l in responselines:
+ result._feed_line(l)
except Exception as e:
- result.set_error(e)
+ # may be CommandError flying out of __read_fulloutput or any kind of exception from the callback
+ result.set_exception(e)
+ finally:
+ assert result.done(), "Result %s not done after __read_full_output was processed"%(result,)
# helper methods
@@ -74,7 +100,7 @@ class MPDClient(MPDClientBase):
raise ProtocolError("Got invalid MPD hello: '{}'".format(line))
self.mpd_version = line[len(HELLO_PREFIX):].strip()
- # FIXME this is just a wrapper for the below
+ # this is just a wrapper for the below
def _write_line(self, text):
self.__write(text + "\n")
# FIXME this code should be sharable
@@ -100,10 +126,9 @@ class MPDClient(MPDClientBase):
result = []
while True:
line = await self.__read_output_line()
+ result.append(line)
if line is None:
return result
- else:
- result.append(line)
# command provider interface
@@ -114,10 +139,8 @@ class MPDClient(MPDClientBase):
# experience that'll make me take the same router at some point.
raise AttributeError("Refusing to override the %s command"%name)
def f(self, *args):
- result = asyncio.Future()
- self.__commandqueue.put_nowait(
- (name, args, callback, result)
- )
+ result = CommandResult(name, args, partial(callback, self))
+ self.__commandqueue.put_nowait(result)
return result
escaped_name = name.replace(" ", "_")
f.__name__ = escaped_name
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mpd/python-mpd.git
More information about the Pkg-mpd-commits
mailing list