From: kaliko Date: Sun, 3 Mar 2024 20:33:06 +0000 (+0100) Subject: Add binary read for albumart/readpicture and protocol version X-Git-Url: https://git.kaliko.me/?a=commitdiff_plain;h=67af350e8543fa42463a7926e4c5987fd182c271;p=python-musicpdaio.git Add binary read for albumart/readpicture and protocol version --- diff --git a/mpdaio/client.py b/mpdaio/client.py index a8ae0cd..bde752f 100644 --- a/mpdaio/client.py +++ b/mpdaio/client.py @@ -26,10 +26,8 @@ class MPDClient: self.password = password or self.server_discovery[2] #: port used with the current connection (:py:obj:`int`, :py:obj:`str`) self.port = port or self.server_discovery[1] - log.info('logger : "%s"', __name__) - #: Protocol version - self.version: [None, str] = None self.mpd_timeout = CONNECTION_TIMEOUT + log.info('Using %s:%s to connect', self.host, self.port) def _get_envvars(self): """ @@ -87,13 +85,23 @@ class MPDClient: f"'CmdHandler' object has no attribute '{attr}'") return lambda *args: wrapper(command, args) + @property + def version(self): + """MPD protocol version""" + host = (self.host, self.port) + version = {_.version for _ in self._pool._connections.get(host, [])} + if not version: + log.warning('No connections yet in the connections pool for %s', host) + return '' + if len(version) > 1: + log.warning('More than one version in the connections pool for %s', host) + return version.pop() + async def close(self): await self._pool.close() class CmdHandler: - #TODO: CmdHandler to intanciate in place of MPDClient._execute - # The MPDClient.__getattr__ wrapper should instanciate an CmdHandler object def __init__(self, pool, server, port, password, timeout): self._commands = { @@ -272,12 +280,12 @@ class CmdHandler: log.debug(' '.join(parts)) await self._write_line(' '.join(parts)) - def _read_binary(self, amount): + async def _read_binary(self, amount): chunk = bytearray() while amount > 0: - result = self._rbfile.read(amount) + result = await self.connection.read(amount) if len(result) == 0: - self.disconnect() + await self.connection.close() raise ConnectionError( "Connection lost while reading binary content") chunk.extend(result) @@ -285,13 +293,10 @@ class CmdHandler: return bytes(chunk) async def _read_line(self, binary=False): - if binary: - line = self._rbfile.readline().decode('utf-8') - else: - line = await self.connection.readline() + line = await self.connection.readline() line = line.decode('utf-8') if not line.endswith('\n'): - await self.close() + await self.connection.close() raise MPDConnectionError("Connection lost while reading line") line = line.rstrip('\n') if line.startswith(ERROR_PREFIX): @@ -316,7 +321,6 @@ class CmdHandler: return pair async def _read_pairs(self, separator=": ", binary=False): - """OK""" pair = await self._read_pair(separator, binary=binary) while pair: yield pair @@ -419,7 +423,7 @@ class CmdHandler: async def _fetch_composite(self): obj = {} - for key, value in self._read_pairs(binary=True): + async for key, value in self._read_pairs(binary=True): key = key.lower() obj[key] = value if key == 'binary': @@ -430,7 +434,7 @@ class CmdHandler: return obj amount = int(obj['binary']) try: - obj['data'] = self._read_binary(amount) + obj['data'] = await self._read_binary(amount) except IOError as err: raise ConnectionError( f'Error reading binary content: {err}') from err @@ -440,8 +444,10 @@ class CmdHandler: f'Expects {amount}B, got {data_bytes}') # Fetches trailing new line await self._read_line(binary=True) + #ALT: await self.connection.readuntil(b'\n') # Fetches SUCCESS code await self._read_line(binary=True) + #ALT: await self.connection.readuntil(b'OK\n') return obj async def _fetch_command_list(self): diff --git a/mpdaio/connection.py b/mpdaio/connection.py index f4a97de..5da292c 100644 --- a/mpdaio/connection.py +++ b/mpdaio/connection.py @@ -172,7 +172,6 @@ class Connection(base): self.version = rcv.split('\n')[0][len(HELLO_PREFIX):] log.info('protocol version: %s', self.version) - def __getattr__(self, name: str) -> Any: """All unknown attributes are delegated to the reader and writer""" if self._closed or not self.in_use: