Hello community,

here is the log from the commit of package python-PyChromecast for 
openSUSE:Factory checked in at 2019-03-06 15:50:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-PyChromecast (Old)
 and      /work/SRC/openSUSE:Factory/.python-PyChromecast.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-PyChromecast"

Wed Mar  6 15:50:06 2019 rev:4 rq:681900 version:2.5.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-PyChromecast/python-PyChromecast.changes  
2019-01-24 14:03:38.904035507 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-PyChromecast.new.28833/python-PyChromecast.changes
       2019-03-06 15:50:09.128433168 +0100
@@ -1,0 +2,9 @@
+Tue Mar  5 20:03:56 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 2.5.2:
+  * YouTube controller version update (#258) @ur1katz
+  * Add support for connecting to named service (#267) @emontnemery
+  * Exponential backoff of mdns service resolution retries (#268) @emontnemery
+  * Improve exponential backoff of mdns service resolution retries (#269) 
@emontnemery
+
+-------------------------------------------------------------------

Old:
----
  PyChromecast-2.3.0.tar.gz

New:
----
  PyChromecast-2.5.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-PyChromecast.spec ++++++
--- /var/tmp/diff_new_pack.yAhYcP/_old  2019-03-06 15:50:10.384433340 +0100
+++ /var/tmp/diff_new_pack.yAhYcP/_new  2019-03-06 15:50:10.392433341 +0100
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-PyChromecast
-Version:        2.3.0
+Version:        2.5.2
 Release:        0
 Summary:        Python module to talk to Google Chromecast
 License:        MIT

++++++ PyChromecast-2.3.0.tar.gz -> PyChromecast-2.5.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyChromecast-2.3.0/PKG-INFO 
new/PyChromecast-2.5.2/PKG-INFO
--- old/PyChromecast-2.3.0/PKG-INFO     2018-09-05 15:02:22.000000000 +0200
+++ new/PyChromecast-2.5.2/PKG-INFO     2019-02-16 20:45:19.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: PyChromecast
-Version: 2.3.0
+Version: 2.5.2
 Summary: Python module to talk to Google Chromecast.
 Home-page: https://github.com/balloob/pychromecast
 Author: Paulus Schoutsen
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyChromecast-2.3.0/PyChromecast.egg-info/PKG-INFO 
new/PyChromecast-2.5.2/PyChromecast.egg-info/PKG-INFO
--- old/PyChromecast-2.3.0/PyChromecast.egg-info/PKG-INFO       2018-09-05 
15:02:22.000000000 +0200
+++ new/PyChromecast-2.5.2/PyChromecast.egg-info/PKG-INFO       2019-02-16 
20:45:19.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: PyChromecast
-Version: 2.3.0
+Version: 2.5.2
 Summary: Python module to talk to Google Chromecast.
 Home-page: https://github.com/balloob/pychromecast
 Author: Paulus Schoutsen
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/PyChromecast-2.3.0/PyChromecast.egg-info/requires.txt 
new/PyChromecast-2.5.2/PyChromecast.egg-info/requires.txt
--- old/PyChromecast-2.3.0/PyChromecast.egg-info/requires.txt   2018-09-05 
15:02:22.000000000 +0200
+++ new/PyChromecast-2.5.2/PyChromecast.egg-info/requires.txt   2019-02-16 
20:45:19.000000000 +0100
@@ -1,4 +1,4 @@
 requests>=2.0
 protobuf>=3.0.0
 zeroconf>=0.17.7
-casttube>=0.1.0
+casttube>=0.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyChromecast-2.3.0/pychromecast/__init__.py 
new/PyChromecast-2.5.2/pychromecast/__init__.py
--- old/PyChromecast-2.3.0/pychromecast/__init__.py     2018-07-10 
10:42:56.000000000 +0200
+++ new/PyChromecast-2.5.2/pychromecast/__init__.py     2019-02-12 
20:29:47.000000000 +0100
@@ -23,6 +23,8 @@
 IDLE_APP_ID = 'E8C28D3C'
 IGNORE_CEC = []
 
+_LOGGER = logging.getLogger(__name__)
+
 
 def _get_chromecast_from_host(host, tries=None, retry_wait=None, timeout=None,
                               blocking=True):
@@ -31,6 +33,7 @@
     # the primary source and the remaining will be fetched
     # later on.
     ip_address, port, uuid, model_name, friendly_name = host
+    _LOGGER.debug("_get_chromecast_from_host %s", host)
     cast_type = CAST_TYPES.get(model_name.lower(),
                                CAST_TYPE_CHROMECAST)
     device = DeviceStatus(
@@ -42,6 +45,25 @@
                       blocking=blocking)
 
 
+def _get_chromecast_from_service(services, tries=None, retry_wait=None,
+                                 timeout=None, blocking=True):
+    """Creates a Chromecast object from a zeroconf service."""
+    # Build device status from the mDNS service name info, this
+    # information is the primary source and the remaining will be
+    # fetched later on.
+    services, zconf, uuid, model_name, friendly_name = services
+    _LOGGER.debug("_get_chromecast_from_service %s", services)
+    cast_type = CAST_TYPES.get(model_name.lower(),
+                               CAST_TYPE_CHROMECAST)
+    device = DeviceStatus(
+        friendly_name=friendly_name, model_name=model_name,
+        manufacturer=None, uuid=uuid, cast_type=cast_type,
+    )
+    return Chromecast(host=None, device=device, tries=tries, timeout=timeout,
+                      retry_wait=retry_wait, blocking=blocking,
+                      services=services, zconf=zconf)
+
+
 # pylint: disable=too-many-locals
 def get_chromecasts(tries=None, retry_wait=None, timeout=None,
                     blocking=True, callback=None):
@@ -123,17 +145,20 @@
         timeout = kwargs.pop('timeout', None)
         retry_wait = kwargs.pop('retry_wait', None)
         blocking = kwargs.pop('blocking', True)
+        services = kwargs.pop('services', None)
+        zconf = kwargs.pop('zconf', True)
 
         self.logger = logging.getLogger(__name__)
 
         # Resolve host to IP address
+        self._services = services
         self.host = host
         self.port = port or 8009
 
         self.logger.info("Querying device status")
         self.device = device
         if device:
-            dev_status = get_device_status(self.host)
+            dev_status = get_device_status(self.host, services, zconf)
             if dev_status:
                 # Values from `device` have priority over `dev_status`
                 # as they come from the dial information.
@@ -154,7 +179,7 @@
             else:
                 self.device = device
         else:
-            self.device = get_device_status(self.host)
+            self.device = get_device_status(self.host, services, zconf)
 
         if not self.device:
             raise ChromecastConnectionError(  # noqa
@@ -166,7 +191,7 @@
         self.socket_client = socket_client.SocketClient(
             host, port=port, cast_type=self.device.cast_type,
             tries=tries, timeout=timeout, retry_wait=retry_wait,
-            blocking=blocking)
+            blocking=blocking, services=services, zconf=zconf)
 
         receiver_controller = self.socket_client.receiver_controller
         receiver_controller.register_status_listener(self)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/PyChromecast-2.3.0/pychromecast/controllers/youtube.py 
new/PyChromecast-2.5.2/pychromecast/controllers/youtube.py
--- old/PyChromecast-2.3.0/pychromecast/controllers/youtube.py  2018-07-10 
10:42:56.000000000 +0200
+++ new/PyChromecast-2.5.2/pychromecast/controllers/youtube.py  2019-01-17 
19:45:56.000000000 +0100
@@ -34,13 +34,14 @@
             self.update_screen_id()
             self._session = YouTubeSession(screen_id=self._screen_id)
 
-    def play_video(self, video_id):
+    def play_video(self, video_id, playlist_id=None):
         """
         Play video(video_id) now. This ignores the current play queue order.
         :param video_id: YouTube video id(http://youtube.com/watch?v=video_id)
+        :param playlist_id: youtube.com/watch?v=video_id&list=playlist_id
         """
         self.start_session_if_none()
-        self._session.play_video(video_id)
+        self._session.play_video(video_id, playlist_id)
 
     def add_to_queue(self, video_id):
         """
@@ -66,6 +67,13 @@
         self.start_session_if_none()
         self._session.remove_video(video_id)
 
+    def clear_playlist(self):
+        """
+        Clear the entire video queue
+        """
+        self.start_session_if_none()
+        self._session.clear_playlist()
+
     def update_screen_id(self):
         """
         Sends a getMdxSessionStatus to get the screenId and waits for response.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyChromecast-2.3.0/pychromecast/dial.py 
new/PyChromecast-2.5.2/pychromecast/dial.py
--- old/PyChromecast-2.3.0/pychromecast/dial.py 2018-07-10 10:42:56.000000000 
+0200
+++ new/PyChromecast-2.5.2/pychromecast/dial.py 2019-02-15 18:43:54.000000000 
+0100
@@ -4,8 +4,11 @@
 from collections import namedtuple
 from uuid import UUID
 
+import logging
 import requests
 
+from .discovery import get_info_from_service, get_host_from_service_info
+
 XML_NS_UPNP_DEVICE = "{urn:schemas-upnp-org:device-1-0}"
 
 FORMAT_BASE_URL = "http://{}:8008";
@@ -28,6 +31,8 @@
     'google cast group': CAST_TYPE_GROUP,
 }
 
+_LOGGER = logging.getLogger(__name__)
+
 
 def reboot(host):
     """ Reboots the chromecast. """
@@ -35,7 +40,7 @@
                     data='{"params":"now"}', timeout=10)
 
 
-def get_device_status(host):
+def get_device_status(host, services=None, zconf=None):
     """
     :param host: Hostname or ip to fetch status from
     :type host: str
@@ -44,6 +49,14 @@
     """
 
     try:
+        if not host:
+            for service in services.copy():
+                service_info = get_info_from_service(service, zconf)
+                host, _ = get_host_from_service_info(service_info)
+                if host:
+                    _LOGGER.debug("Resolved service %s to %s", service, host)
+                    break
+
         req = CC_SESSION.get(
             FORMAT_BASE_URL.format(host) + "/setup/eureka_info?options=detail",
             timeout=10)
@@ -80,7 +93,7 @@
         return DeviceStatus(friendly_name, model_name, manufacturer,
                             uuid, cast_type)
 
-    except (requests.exceptions.RequestException, ValueError):
+    except (requests.exceptions.RequestException, OSError, ValueError):
         return None
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyChromecast-2.3.0/pychromecast/discovery.py 
new/PyChromecast-2.5.2/pychromecast/discovery.py
--- old/PyChromecast-2.3.0/pychromecast/discovery.py    2018-07-10 
10:42:56.000000000 +0200
+++ new/PyChromecast-2.5.2/pychromecast/discovery.py    2019-02-16 
20:43:30.000000000 +0100
@@ -1,4 +1,5 @@
 """Discovers Chromecasts on the network using mDNS/zeroconf."""
+import logging
 import socket
 from uuid import UUID
 
@@ -6,13 +7,16 @@
 
 DISCOVER_TIMEOUT = 5
 
+_LOGGER = logging.getLogger(__name__)
+
 
 class CastListener(object):
     """Zeroconf Cast Services collection."""
 
-    def __init__(self, callback=None):
+    def __init__(self, add_callback=None, remove_callback=None):
         self.services = {}
-        self.callback = callback
+        self.add_callback = add_callback
+        self.remove_callback = remove_callback
 
     @property
     def count(self):
@@ -27,22 +31,32 @@
     # pylint: disable=unused-argument
     def remove_service(self, zconf, typ, name):
         """ Remove a service from the collection. """
-        self.services.pop(name, None)
+        _LOGGER.debug("remove_service %s, %s", typ, name)
+        service = self.services.pop(name, None)
+
+        if not service:
+            _LOGGER.debug("remove_service unknown %s, %s", typ, name)
+            return
+
+        if self.remove_callback:
+            self.remove_callback(name, service)
 
     def add_service(self, zconf, typ, name):
         """ Add a service to the collection. """
         service = None
         tries = 0
+        _LOGGER.debug("add_service %s, %s", typ, name)
         while service is None and tries < 4:
             try:
                 service = zconf.get_service_info(typ, name)
             except IOError:
-                # If the zerconf fails to receive the necesarry data we abort
+                # If the zeroconf fails to receive the necessary data we abort
                 # adding the service
                 break
             tries += 1
 
         if not service:
+            _LOGGER.debug("add_service failed to add %s, %s", typ, name)
             return
 
         def get_value(key):
@@ -66,11 +80,11 @@
         self.services[name] = (host, service.port, uuid, model_name,
                                friendly_name)
 
-        if self.callback:
-            self.callback(name)
+        if self.add_callback:
+            self.add_callback(name)
 
 
-def start_discovery(callback=None):
+def start_discovery(add_callback=None, remove_callback=None):
     """
     Start discovering chromecasts on the network.
 
@@ -84,7 +98,7 @@
     chromecasts. To stop discovery, call the stop_discovery method with the
     ServiceBrowser object.
     """
-    listener = CastListener(callback)
+    listener = CastListener(add_callback, remove_callback)
     service_browser = False
     try:
         service_browser = zeroconf.ServiceBrowser(zeroconf.Zeroconf(),
@@ -128,3 +142,32 @@
     finally:
         if browser is not False:
             stop_discovery(browser)
+
+
+def get_info_from_service(service, zconf):
+    """ Resolve service_info from service. """
+    service_info = None
+    try:
+        service_info = zconf.get_service_info('_googlecast._tcp.local.',
+                                              service)
+        if service_info:
+            _LOGGER.debug(
+                "get_info_from_service resolved service %s to service_info %s",
+                service, service_info)
+    except IOError:
+        pass
+    return service_info
+
+
+def get_host_from_service_info(service_info):
+    """ Get hostname or IP from service_info. """
+    host = None
+    port = None
+    if (service_info and service_info.port and
+            (service_info.server or service_info.address)):
+        if service_info.address:
+            host = socket.inet_ntoa(service_info.address)
+        else:
+            host = service_info.server.lower()
+        port = service_info.port
+    return (host, port)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyChromecast-2.3.0/pychromecast/socket_client.py 
new/PyChromecast-2.5.2/pychromecast/socket_client.py
--- old/PyChromecast-2.3.0/pychromecast/socket_client.py        2018-07-10 
10:42:56.000000000 +0200
+++ new/PyChromecast-2.5.2/pychromecast/socket_client.py        2019-02-16 
20:43:30.000000000 +0100
@@ -6,7 +6,7 @@
 Without him this would not have been possible.
 """
 # Pylint does not understand the protobuf objects correctly
-# pylint: disable=no-member
+# pylint: disable=no-member, too-many-lines
 
 import errno
 import json
@@ -24,6 +24,7 @@
 from .controllers import BaseController
 from .controllers.media import MediaController
 from .dial import CAST_TYPE_CHROMECAST, CAST_TYPE_AUDIO, CAST_TYPE_GROUP
+from .discovery import get_info_from_service, get_host_from_service_info
 from .error import (
     ChromecastConnectionError,
     UnsupportedNamespace,
@@ -57,6 +58,8 @@
 CONNECTION_STATUS_DISCONNECTED = "DISCONNECTED"
 # Connecting to socket failed (after a CONNECTION_STATUS_CONNECTING)
 CONNECTION_STATUS_FAILED = "FAILED"
+# Failed to resolve service name
+CONNECTION_STATUS_FAILED_RESOLVE = "FAILED_RESOLVE"
 # The socket connection was lost and needs to be retried
 CONNECTION_STATUS_LOST = "LOST"
 
@@ -154,6 +157,8 @@
         timeout = kwargs.pop('timeout', None)
         retry_wait = kwargs.pop('retry_wait', None)
         self.blocking = kwargs.pop('blocking', True)
+        services = kwargs.pop('services', None)
+        zconf = kwargs.pop('zconf', None)
 
         if self.blocking:
             self.polltime = POLL_TIME_BLOCKING
@@ -169,10 +174,13 @@
         self._force_recon = False
 
         self.cast_type = cast_type
+        self.fn = None  # pylint:disable=invalid-name
         self.tries = tries
         self.timeout = timeout or TIMEOUT_TIME
         self.retry_wait = retry_wait or RETRY_TIME
         self.host = host
+        self.services = services or [None]
+        self.zconf = zconf
         self.port = port or 8009
 
         self.source_id = "sender-0"
@@ -212,7 +220,7 @@
                                  NetworkAddress(self.host, self.port)))
             raise
 
-    def initialize_connection(self):
+    def initialize_connection(self):  # noqa: E501 
pylint:disable=too-many-statements, too-many-branches
         """Initialize a socket to a Chromecast, retrying as necessary."""
         tries = self.tries
 
@@ -234,51 +242,124 @@
         self.connecting = True
         retry_log_fun = self.logger.error
 
-        while not self.stop.is_set() and (tries is None or tries > 0):
-            try:
-                self.socket = new_socket()
-                self.socket.settimeout(self.timeout)
-                self._report_connection_status(
-                    ConnectionStatus(CONNECTION_STATUS_CONNECTING,
-                                     NetworkAddress(self.host, self.port)))
-                self.socket.connect((self.host, self.port))
-                self.socket = ssl.wrap_socket(self.socket)
-                self.connecting = False
-                self._force_recon = False
-                self._report_connection_status(
-                    ConnectionStatus(CONNECTION_STATUS_CONNECTED,
-                                     NetworkAddress(self.host, self.port)))
-                self.receiver_controller.update_status()
-                self.heartbeat_controller.ping()
-                self.heartbeat_controller.reset()
+        # Dict keeping track of individual retry delay for each named service
+        retries = {}
 
-                self.logger.debug("Connected!")
-                break
-            except OSError as err:
-                self.connecting = True
-                if self.stop.is_set():
-                    self.logger.error(
-                        "Failed to connect: %s. aborting due to stop signal.",
-                        err)
-                    raise ChromecastConnectionError("Failed to connect")
-
-                self._report_connection_status(
-                    ConnectionStatus(CONNECTION_STATUS_FAILED,
-                                     NetworkAddress(self.host, self.port)))
-
-                # Only sleep if we have another retry remaining
-                if tries is None or tries > 1:
-                    retry_log_fun("Failed to connect, retrying in %.1fs",
-                                  self.retry_wait)
+        def mdns_backoff(service, retry):
+            """Exponentional backoff for service name mdns lookups."""
+            now = time.time()
+            retry['next_retry'] = now + retry['delay']
+            retry['delay'] = min(retry['delay']*2, 300)
+            retries[service] = retry
+
+        while not self.stop.is_set() and (tries is None or tries > 0):  # 
noqa: E501 pylint:disable=too-many-nested-blocks
+            # Prune retries dict
+            retries = {key: retries[key] for key in self.services if (
+                key is not None and key in retries)}
+
+            for service in self.services.copy():
+                now = time.time()
+                retry = retries.get(
+                    service, {'delay': self.retry_wait, 'next_retry': now})
+                # If we're connecting to a named service, check if it's time
+                if service and now < retry['next_retry']:
+                    continue
+                try:
+                    self.socket = new_socket()
+                    self.socket.settimeout(self.timeout)
+                    self._report_connection_status(
+                        ConnectionStatus(CONNECTION_STATUS_CONNECTING,
+                                         NetworkAddress(self.host, self.port)))
+                    # Resolve the service name. If service is None, we're
+                    # connecting directly to a host name or IP-address
+                    if service:
+                        host = None
+                        port = None
+                        service_info = get_info_from_service(service,
+                                                             self.zconf)
+                        host, port = get_host_from_service_info(service_info)
+                        if host and port:
+                            try:
+                                self.fn = service_info.properties[b'fn']\
+                                    .decode('utf-8')
+                            except (AttributeError, KeyError, UnicodeError):
+                                pass
+                            self.logger.debug(
+                                "[%s:%s] Resolved service %s to %s:%s",
+                                self.fn or self.host, self.port, service, host,
+                                port)
+                            self.host = host
+                            self.port = port
+                        else:
+                            self.logger.debug(
+                                "[%s:%s] Failed to resolve service %s",
+                                self.fn or self.host, self.port, service)
+                            self._report_connection_status(
+                                ConnectionStatus(
+                                    CONNECTION_STATUS_FAILED_RESOLVE,
+                                    NetworkAddress(service, None)))
+                            mdns_backoff(service, retry)
+                            # If zeroconf fails to receive the necessary data,
+                            # try next service
+                            continue
+
+                    self.logger.debug("[%s:%s] Connecting to %s:%s",
+                                      self.fn or self.host, self.port,
+                                      self.host, self.port)
+                    self.socket.connect((self.host, self.port))
+                    self.socket = ssl.wrap_socket(self.socket)
+                    self.connecting = False
+                    self._force_recon = False
+                    self._report_connection_status(
+                        ConnectionStatus(CONNECTION_STATUS_CONNECTED,
+                                         NetworkAddress(self.host, self.port)))
+                    self.receiver_controller.update_status()
+                    self.heartbeat_controller.ping()
+                    self.heartbeat_controller.reset()
+
+                    self.logger.debug("[%s:%s] Connected!",
+                                      self.fn or self.host, self.port)
+                    return
+                except OSError as err:
+                    self.connecting = True
+                    if self.stop.is_set():
+                        self.logger.error(
+                            "[%s:%s] Failed to connect: %s. "
+                            "aborting due to stop signal.",
+                            self.fn or self.host, self.port, err)
+                        raise ChromecastConnectionError("Failed to connect")
+
+                    self._report_connection_status(
+                        ConnectionStatus(CONNECTION_STATUS_FAILED,
+                                         NetworkAddress(self.host, self.port)))
+                    if service is not None:
+                        retry_log_fun(
+                            "[%s:%s] Failed to connect to service %s"
+                            ", retrying in %.1fs",
+                            self.fn or self.host, self.port,
+                            service, retry['delay'])
+                        mdns_backoff(service, retry)
+                    else:
+                        retry_log_fun(
+                            "[%s:%s] Failed to connect, retrying in %.1fs",
+                            self.fn or self.host, self.port, self.retry_wait)
                     retry_log_fun = self.logger.debug
-                    time.sleep(self.retry_wait)
 
-                if tries:
-                    tries -= 1
-        else:
-            self.stop.set()
-            self.logger.error("Failed to connect. No retries.")
-            raise ChromecastConnectionError("Failed to connect")
+            # Only sleep if we have another retry remaining
+            if tries is None or tries > 1:
+                self.logger.debug(
+                    "[%s:%s] Not connected, sleeping for %.1fs. Services: %s",
+                    self.fn or self.host, self.port,
+                    self.retry_wait, self.services)
+                time.sleep(self.retry_wait)
+
+            if tries:
+                tries -= 1
+
+        self.stop.set()
+        self.logger.error("[%s:%s] Failed to connect. No retries.",
+                          self.fn or self.host, self.port)
+        raise ChromecastConnectionError("Failed to connect")
 
     def disconnect(self):
         """ Disconnect socket connection to Chromecast device """
@@ -368,11 +449,14 @@
             except InterruptLoop as exc:
                 if self.stop.is_set():
                     self.logger.info(
-                        "Stopped while reading message, disconnecting.")
+                        "[%s:%s] Stopped while reading message, "
+                        "disconnecting.",
+                        self.fn or self.host, self.port)
                 else:
                     self.logger.error(
-                        "Interruption caught without being stopped: %s",
-                        exc)
+                        "[%s:%s] Interruption caught without being stopped: "
+                        "%s",
+                        self.fn or self.host, self.port, exc)
                 return 1
             except ssl.SSLError as exc:
                 if exc.errno == ssl.SSL_ERROR_EOF:
@@ -381,7 +465,8 @@
                 raise
             except socket.error:
                 self._force_recon = True
-                self.logger.error('Error reading from socket.')
+                self.logger.error('[%s:%s] Error reading from socket.',
+                                  self.fn or self.host, self.port)
             else:
                 data = _json_from_message(message)
         if not message:
@@ -425,11 +510,15 @@
         reset = False
         if self._force_recon:
             self.logger.warning(
-                "Error communicating with socket, resetting connection")
+                "[%s:%s] Error communicating with socket, resetting "
+                "connection",
+                self.fn or self.host, self.port)
             reset = True
 
         elif self.heartbeat_controller.is_expired():
-            self.logger.warning("Heartbeat timeout, resetting connection")
+            self.logger.warning(
+                "[%s:%s] Heartbeat timeout, resetting connection",
+                self.fn or self.host, self.port)
             reset = True
 
         if reset:
@@ -451,7 +540,8 @@
             # debug messages
             if message.namespace != NS_HEARTBEAT:
                 self.logger.debug(
-                    "Received: %s", _message_to_string(message, data))
+                    "[%s:%s] Received: %s", self.fn or self.host, self.port,
+                    _message_to_string(message, data))
 
             # message handlers
             try:
@@ -462,18 +552,20 @@
                 if not handled:
                     if data.get(REQUEST_ID) not in self._request_callbacks:
                         self.logger.debug(
-                            "Message unhandled: %s",
+                            "[%s:%s] Message unhandled: %s",
+                            self.fn or self.host, self.port,
                             _message_to_string(message, data))
             except Exception:  # pylint: disable=broad-except
                 self.logger.exception(
-                    ("Exception caught while sending message to "
-                     "controller %s: %s"),
+                    ("[%s:%s] Exception caught while sending message to "
+                     "controller %s: %s"), self.fn or self.host, self.port,
                     type(self._handlers[message.namespace]).__name__,
                     _message_to_string(message, data))
 
         else:
             self.logger.debug(
-                "Received unknown namespace: %s",
+                "[%s:%s] Received unknown namespace: %s",
+                self.fn or self.host, self.port,
                 _message_to_string(message, data))
 
     def _cleanup(self):
@@ -490,7 +582,11 @@
             except Exception:  # pylint: disable=broad-except
                 pass
 
-        self.socket.close()
+        try:
+            self.socket.close()
+        except Exception:  # pylint: disable=broad-except
+            self.logger.exception(
+                "[%s:%s] _cleanup", self.fn or self.host, self.port)
         self._report_connection_status(
             ConnectionStatus(CONNECTION_STATUS_DISCONNECTED,
                              NetworkAddress(self.host, self.port)))
@@ -500,7 +596,8 @@
         """ Report a change in the connection status to any listeners """
         for listener in self._connection_listeners:
             try:
-                self.logger.debug("connection listener: %x (%s)",
+                self.logger.debug("[%s:%s] connection listener: %x (%s)",
+                                  self.fn or self.host, self.port,
                                   id(listener), type(listener).__name__)
                 listener.new_connection_status(status)
             except Exception:  # pylint: disable=broad-except
@@ -580,7 +677,9 @@
 
         # Log all messages except heartbeat
         if msg.namespace != NS_HEARTBEAT:
-            self.logger.debug("Sending: %s", _message_to_string(msg, data))
+            self.logger.debug("[%s:%s] Sending: %s",
+                              self.fn or self.host, self.port,
+                              _message_to_string(msg, data))
 
         if not force and self.stop.is_set():
             raise PyChromecastStopped("Socket client's thread is stopped.")
@@ -596,9 +695,11 @@
             except socket.error:
                 self._request_callbacks.pop(request_id, None)
                 self._force_recon = True
-                self.logger.info('Error writing to socket.')
+                self.logger.info('[%s:%s] Error writing to socket.',
+                                 self.fn or self.host, self.port)
         else:
-            raise NotConnected("Chromecast is connecting...")
+            raise NotConnected("Chromecast " + self.host + ":" + self.port +
+                               " is connecting...")
 
     def send_platform_message(self, namespace, message, inc_session_id=False,
                               callback_function_param=False):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyChromecast-2.3.0/requirements.txt 
new/PyChromecast-2.5.2/requirements.txt
--- old/PyChromecast-2.3.0/requirements.txt     2018-07-10 10:42:56.000000000 
+0200
+++ new/PyChromecast-2.5.2/requirements.txt     2019-01-17 19:45:56.000000000 
+0100
@@ -1,4 +1,4 @@
 requests>=2.0
 protobuf>=3.0.0
 zeroconf>=0.17.7
-casttube>=0.1.0
+casttube>=0.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyChromecast-2.3.0/setup.py 
new/PyChromecast-2.5.2/setup.py
--- old/PyChromecast-2.3.0/setup.py     2018-09-05 15:00:24.000000000 +0200
+++ new/PyChromecast-2.5.2/setup.py     2019-02-16 20:43:34.000000000 +0100
@@ -5,7 +5,7 @@
 
 setup(
     name='PyChromecast',
-    version='2.3.0',
+    version='2.5.2',
     license='MIT',
     url='https://github.com/balloob/pychromecast',
     author='Paulus Schoutsen',


Reply via email to