From 254daf50788d3d8c7cd7fdec407560cdda633b35 Mon Sep 17 00:00:00 2001 From: kaliko Date: Sat, 9 Mar 2024 14:43:44 +0100 Subject: [PATCH] Add password (issue #4) and refactoring --- mpdaio/__init__.py | 14 +------------- mpdaio/client.py | 25 +++++++++++++++++++------ mpdaio/connection.py | 5 +++-- mpdaio/const.py | 17 +++++++++++++++++ 4 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 mpdaio/const.py diff --git a/mpdaio/__init__.py b/mpdaio/__init__.py index f075087..fd291fa 100644 --- a/mpdaio/__init__.py +++ b/mpdaio/__init__.py @@ -2,16 +2,4 @@ # SPDX-FileCopyrightText: 2012-2024 kaliko # SPDX-License-Identifier: LGPL-3.0-or-later -HELLO_PREFIX = 'OK MPD ' -ERROR_PREFIX = 'ACK ' -SUCCESS = 'OK' -NEXT = 'list_OK' -#: Module version -VERSION = '0.0.1b0' -#: Seconds before a connection attempt times out -#: (overriden by :envvar:`MPD_TIMEOUT` env. var.) -CONNECTION_TIMEOUT = 30 -#: Socket timeout in second > 0 (Default is :py:obj:`None` for no timeout) -SOCKET_TIMEOUT = None -#: Maximum concurrent connections -CONNECTION_MAX = 100 +from .client import MPDClient diff --git a/mpdaio/client.py b/mpdaio/client.py index 8a7e9af..48b37bd 100644 --- a/mpdaio/client.py +++ b/mpdaio/client.py @@ -10,8 +10,8 @@ from .connection import ConnectionPool, Connection from .exceptions import MPDConnectionError, MPDProtocolError, MPDCommandError from .utils import Range, escape -from . import CONNECTION_MAX, CONNECTION_TIMEOUT -from . import ERROR_PREFIX, SUCCESS, NEXT +from .const import CONNECTION_MAX, CONNECTION_TIMEOUT +from .const import ERROR_PREFIX, SUCCESS, NEXT log = logging.getLogger(__name__) @@ -24,7 +24,7 @@ class MPDClient: #: host used with the current connection (:py:obj:`str`) self.host = host or self.server_discovery[0] #: password detected in :envvar:`MPD_HOST` environment variable (:py:obj:`str`) - self.password = password or self.server_discovery[2] + self.pwd = 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] self.mpd_timeout = CONNECTION_TIMEOUT @@ -78,7 +78,7 @@ class MPDClient: def __getattr__(self, attr): command = attr - wrapper = CmdHandler(self._pool, self.host, self.port, self.password, self.mpd_timeout) + wrapper = CmdHandler(self._pool, self.host, self.port, self.pwd, self.mpd_timeout) if command not in wrapper._commands: command = command.replace("_", " ") if command not in wrapper._commands: @@ -116,7 +116,7 @@ class CmdHandler: "clearerror": self._fetch_nothing, "currentsong": self._fetch_object, "idle": self._fetch_list, - # "noidle": None, + "noidle": self._fetch_nothing, "status": self._fetch_object, "stats": self._fetch_object, # Playback Option Commands @@ -261,14 +261,27 @@ class CmdHandler: server, port = self.host self.command = command self.args = args or '' - self.connection = await self.pool.connect(server, port, timeout=self.timeout) + self.connection = await self.pool.connect(server, port, self.timeout) async with self.connection: + await self._init_connection() retval = self._commands[command] await self._write_command(command, args) if callable(retval): return await retval() return retval + async def _init_connection(self): + """Init connection if needed""" + if not self.connection.version: + # TODO: move hello here instead of connection? + # Need to consume hello + pass + if self.password and not self.connection.auth: + # Need to send password + await self._write_command('password', [self.password]) + await self._fetch_nothing() + self.connection.auth = True + async def _write_line(self, line): self.connection.write(f"{line!s}\n".encode()) await self.connection.drain() diff --git a/mpdaio/connection.py b/mpdaio/connection.py index 072fc3f..d00f85a 100644 --- a/mpdaio/connection.py +++ b/mpdaio/connection.py @@ -12,7 +12,7 @@ from collections import OrderedDict from types import TracebackType from typing import Any, List, Optional, Tuple, Type -from . import HELLO_PREFIX +from .const import HELLO_PREFIX from .exceptions import MPDProtocolError try: # Python 3.7 @@ -140,7 +140,9 @@ class Connection(base): self._reader = reader self._writer = writer self._closed = False + self.auth = False self.in_use = False + self.version: str | None = None def __repr__(self): host = f"{self._host[0]}:{self._host[1]}" @@ -176,7 +178,6 @@ class Connection(base): raise MPDProtocolError(f'Got invalid MPD hello: "{rcv}"') log.debug('consumed hello prefix: %r', rcv) 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""" diff --git a/mpdaio/const.py b/mpdaio/const.py new file mode 100644 index 0000000..6781184 --- /dev/null +++ b/mpdaio/const.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: 2012-2024 kaliko +# SPDX-License-Identifier: LGPL-3.0-or-later + +HELLO_PREFIX = 'OK MPD ' +ERROR_PREFIX = 'ACK ' +SUCCESS = 'OK' +NEXT = 'list_OK' +#: Module version +VERSION = '0.1.b0' +#: Seconds before a connection attempt times out +#: (overriden by :envvar:`MPD_TIMEOUT` env. var.) +CONNECTION_TIMEOUT = 30 +#: Socket timeout in second > 0 (Default is :py:obj:`None` for no timeout) +SOCKET_TIMEOUT = None +#: Maximum concurrent connections +CONNECTION_MAX = 100 -- 2.39.5