# -*- coding: utf-8 -*-
-# SPDX-FileCopyrightText: 2012-2023 kaliko <kaliko@azylum.org>
+# SPDX-FileCopyrightText: 2012-2024 kaliko <kaliko@azylum.org>
# SPDX-FileCopyrightText: 2021 Wonko der Verständige <wonko@hanstool.org>
# SPDX-FileCopyrightText: 2019 Naglis Jonaitis <naglis@mailbox.org>
# SPDX-FileCopyrightText: 2019 Bart Van Loon <bbb@bbbart.be>
SUCCESS = "OK"
NEXT = "list_OK"
#: Module version
-VERSION = '0.9.0b1'
+VERSION = '0.9.0b2'
#: Seconds before a connection attempt times out
#: (overriden by :envvar:`MPD_TIMEOUT` env. var.)
CONNECTION_TIMEOUT = 30
-#: Socket timeout in second (Default is None for no timeout)
+#: Socket timeout in second > 0 (Default is :py:obj:`None` for no timeout)
SOCKET_TIMEOUT = None
log = logging.getLogger(__name__)
parts = [command]
for arg in args:
if isinstance(arg, tuple):
- parts.append('{0!s}'.format(Range(arg)))
+ parts.append(f'{Range(arg)!s}')
else:
- parts.append('"%s"' % escape(str(arg)))
+ parts.append(f'"{escape(str(arg))}"')
if '\n' in ' '.join(parts):
raise CommandError('new line found in the command!')
self._write_line(" ".join(parts))
# abstract socket
if path.startswith('@'):
path = '\0'+path[1:]
- sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- sock.settimeout(self.mpd_timeout)
- sock.connect(path)
- sock.settimeout(self.socket_timeout)
+ try:
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ sock.settimeout(self.mpd_timeout)
+ sock.connect(path)
+ sock.settimeout(self.socket_timeout)
+ except socket.error as socket_err:
+ raise ConnectionError(socket_err) from socket_err
return sock
def _connect_tcp(self, host, port):
except AttributeError:
flags = 0
err = None
- for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC,
- socket.SOCK_STREAM, socket.IPPROTO_TCP,
- flags):
+ try:
+ gai = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
+ socket.SOCK_STREAM, socket.IPPROTO_TCP,
+ flags)
+ except socket.error as gaierr:
+ raise ConnectionError(gaierr) from gaierr
+ for res in gai:
af, socktype, proto, _, sa = res
sock = None
try:
+ log.debug('opening socket %s', sa)
sock = socket.socket(af, socktype, proto)
sock.settimeout(self.mpd_timeout)
sock.connect(sa)
sock.settimeout(self.socket_timeout)
return sock
except socket.error as socket_err:
+ log.debug('opening socket %s failed: %s', sa, socket_err)
err = socket_err
if sock is not None:
sock.close()
if err is not None:
- raise ConnectionError(str(err))
+ raise ConnectionError(err)
raise ConnectionError("getaddrinfo returns an empty list")
def noidle(self):
@property
def socket_timeout(self):
"""Socket timeout in second (defaults to :py:obj:`SOCKET_TIMEOUT`).
- Use None to disable socket timout."""
+ Use :py:obj:`None` to disable socket timout.
+
+ :setter: Set the socket timeout
+ :type: int or None (integer > 0)
+ """
return self._socket_timeout
@socket_timeout.setter
def socket_timeout(self, timeout):
- self._socket_timeout = timeout
+ if timeout is not None:
+ if int(timeout) <= 0:
+ raise ValueError('socket_timeout expects a non zero positive integer')
+ self._socket_timeout = int(timeout)
+ else:
+ self._socket_timeout = timeout
if getattr(self._sock, 'settimeout', False):
self._sock.settimeout(self._socket_timeout)
+
def disconnect(self):
"""Closes the MPD connection.
The client closes the actual socket, it does not use the