PyChromecast 14.0.4__tar.gz → 14.0.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/PKG-INFO +7 -2
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/PKG-INFO +7 -2
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/SOURCES.txt +1 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/config.py +1 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/dial.py +30 -6
- pychromecast-14.0.6/pychromecast/py.typed +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/quick_play.py +1 -1
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/socket_client.py +13 -1
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pyproject.toml +4 -2
- pychromecast-14.0.6/requirements.txt +3 -0
- PyChromecast-14.0.4/requirements.txt +0 -3
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/LICENSE +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/MANIFEST.in +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/dependency_links.txt +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/not-zip-safe +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/requires.txt +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/top_level.txt +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/README.rst +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/__init__.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/const.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/__init__.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/bbciplayer.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/bbcsounds.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/bubbleupnp.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/dashcast.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/heartbeat.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/homeassistant.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/homeassistant_media.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/media.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/multizone.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/nrkradio.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/nrktv.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/plex.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/receiver.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/shaka.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/supla.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/yleareena.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/youtube.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/discovery.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/error.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/authority_keys_pb2.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/authority_keys_pb2.pyi +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/cast_channel_pb2.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/cast_channel_pb2.pyi +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/logging_pb2.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/logging_pb2.pyi +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/readme.txt +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/models.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/response_handler.py +0 -0
- {PyChromecast-14.0.4 → pychromecast-14.0.6}/setup.cfg +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: PyChromecast
|
|
3
|
-
Version: 14.0.
|
|
3
|
+
Version: 14.0.6
|
|
4
4
|
Summary: Python module to talk to Google Chromecast.
|
|
5
5
|
Author-email: Paulus Schoutsen <paulus@paulusschoutsen.nl>
|
|
6
|
+
License: MIT
|
|
6
7
|
Project-URL: Homepage, https://github.com/home-assistant-libs/pychromecast
|
|
7
8
|
Platform: any
|
|
8
9
|
Classifier: Intended Audience :: Developers
|
|
@@ -11,9 +12,13 @@ Classifier: Operating System :: OS Independent
|
|
|
11
12
|
Classifier: Programming Language :: Python
|
|
12
13
|
Classifier: Programming Language :: Python :: 3
|
|
13
14
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Classifier: Typing :: Typed
|
|
14
16
|
Requires-Python: >=3.11.0
|
|
15
17
|
Description-Content-Type: text/x-rst
|
|
16
18
|
License-File: LICENSE
|
|
19
|
+
Requires-Dist: protobuf>=4.25.1
|
|
20
|
+
Requires-Dist: zeroconf>=0.25.1
|
|
21
|
+
Requires-Dist: casttube>=0.2.0
|
|
17
22
|
|
|
18
23
|
pychromecast |Build Status|
|
|
19
24
|
===========================
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: PyChromecast
|
|
3
|
-
Version: 14.0.
|
|
3
|
+
Version: 14.0.6
|
|
4
4
|
Summary: Python module to talk to Google Chromecast.
|
|
5
5
|
Author-email: Paulus Schoutsen <paulus@paulusschoutsen.nl>
|
|
6
|
+
License: MIT
|
|
6
7
|
Project-URL: Homepage, https://github.com/home-assistant-libs/pychromecast
|
|
7
8
|
Platform: any
|
|
8
9
|
Classifier: Intended Audience :: Developers
|
|
@@ -11,9 +12,13 @@ Classifier: Operating System :: OS Independent
|
|
|
11
12
|
Classifier: Programming Language :: Python
|
|
12
13
|
Classifier: Programming Language :: Python :: 3
|
|
13
14
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Classifier: Typing :: Typed
|
|
14
16
|
Requires-Python: >=3.11.0
|
|
15
17
|
Description-Content-Type: text/x-rst
|
|
16
18
|
License-File: LICENSE
|
|
19
|
+
Requires-Dist: protobuf>=4.25.1
|
|
20
|
+
Requires-Dist: zeroconf>=0.25.1
|
|
21
|
+
Requires-Dist: casttube>=0.2.0
|
|
17
22
|
|
|
18
23
|
pychromecast |Build Status|
|
|
19
24
|
===========================
|
|
@@ -5,6 +5,7 @@ Implements the DIAL-protocol to communicate with the Chromecast
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
7
|
from dataclasses import dataclass
|
|
8
|
+
from http import HTTPStatus
|
|
8
9
|
import json
|
|
9
10
|
import logging
|
|
10
11
|
import socket
|
|
@@ -74,6 +75,28 @@ def _get_host_from_zc_service_info(
|
|
|
74
75
|
return (host, port)
|
|
75
76
|
|
|
76
77
|
|
|
78
|
+
def _urlopen(url: str, timeout: float, context: ssl.SSLContext | None) -> Any:
|
|
79
|
+
"""Help open an URL."""
|
|
80
|
+
headers = {"content-type": "application/json"}
|
|
81
|
+
try:
|
|
82
|
+
req = urllib.request.Request(url, headers=headers)
|
|
83
|
+
return urllib.request.urlopen(req, timeout=timeout, context=context)
|
|
84
|
+
except urllib.error.HTTPError as err:
|
|
85
|
+
if err.code != HTTPStatus.FORBIDDEN:
|
|
86
|
+
raise
|
|
87
|
+
# We may be blocked because we're connecting to a hostname specified directly
|
|
88
|
+
# instead of to an IP address resolved by mDNS, cast devices will reject the
|
|
89
|
+
# request when the address is set to the hostname. Do another attempt with an
|
|
90
|
+
# empty host header.
|
|
91
|
+
# Note: This is a simplified approach to not have to deal with name resolution
|
|
92
|
+
# in pychromecast. If devices reject the empty host header we need to do name
|
|
93
|
+
# resolution and instead set the host header to the string version of the IP.
|
|
94
|
+
_LOGGER.debug("Failed to fetch %s, retrying with empty host header", url)
|
|
95
|
+
headers["host"] = ""
|
|
96
|
+
req = urllib.request.Request(url, headers=headers)
|
|
97
|
+
return urllib.request.urlopen(req, timeout=timeout, context=context)
|
|
98
|
+
|
|
99
|
+
|
|
77
100
|
def _get_status(
|
|
78
101
|
services: set[HostServiceInfo | MDNSServiceInfo],
|
|
79
102
|
zconf: zeroconf.Zeroconf | None,
|
|
@@ -90,8 +113,6 @@ def _get_status(
|
|
|
90
113
|
_LOGGER.debug("Resolved service %s to %s", service, host)
|
|
91
114
|
break
|
|
92
115
|
|
|
93
|
-
headers = {"content-type": "application/json"}
|
|
94
|
-
|
|
95
116
|
if secure:
|
|
96
117
|
url = FORMAT_BASE_URL_HTTPS.format(host) + path
|
|
97
118
|
else:
|
|
@@ -101,8 +122,7 @@ def _get_status(
|
|
|
101
122
|
if secure and not has_context:
|
|
102
123
|
context = get_ssl_context()
|
|
103
124
|
|
|
104
|
-
|
|
105
|
-
with urllib.request.urlopen(req, timeout=timeout, context=context) as response:
|
|
125
|
+
with _urlopen(url, timeout, context) as response:
|
|
106
126
|
data = response.read()
|
|
107
127
|
return (host, json.loads(data.decode("utf-8")))
|
|
108
128
|
|
|
@@ -246,7 +266,8 @@ def get_device_info( # pylint: disable=too-many-locals
|
|
|
246
266
|
multizone_supported,
|
|
247
267
|
)
|
|
248
268
|
|
|
249
|
-
except (urllib.error.HTTPError, urllib.error.URLError, OSError, ValueError):
|
|
269
|
+
except (urllib.error.HTTPError, urllib.error.URLError, OSError, ValueError) as err:
|
|
270
|
+
_LOGGER.debug("Failed to get device info for %s: %s (%s)", host, err, type(err))
|
|
250
271
|
return None
|
|
251
272
|
|
|
252
273
|
|
|
@@ -305,7 +326,10 @@ def get_multizone_status(
|
|
|
305
326
|
|
|
306
327
|
return MultizoneStatus(dynamic_groups, groups)
|
|
307
328
|
|
|
308
|
-
except (urllib.error.HTTPError, urllib.error.URLError, OSError, ValueError):
|
|
329
|
+
except (urllib.error.HTTPError, urllib.error.URLError, OSError, ValueError) as err:
|
|
330
|
+
_LOGGER.debug(
|
|
331
|
+
"Failed to get multizone status for %s: %s (%s)", host, err, type(err)
|
|
332
|
+
)
|
|
309
333
|
return None
|
|
310
334
|
|
|
311
335
|
|
|
File without changes
|
|
@@ -24,6 +24,7 @@ from struct import pack, unpack
|
|
|
24
24
|
|
|
25
25
|
import zeroconf
|
|
26
26
|
|
|
27
|
+
from .config import APP_AUDIBLE
|
|
27
28
|
from .const import MESSAGE_TYPE, PLATFORM_DESTINATION_ID, REQUEST_ID, SESSION_ID
|
|
28
29
|
from .controllers import BaseController, CallbackType
|
|
29
30
|
from .controllers.heartbeat import NS_HEARTBEAT, HeartbeatController
|
|
@@ -286,7 +287,7 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
286
287
|
try:
|
|
287
288
|
if self.socket is not None:
|
|
288
289
|
# If we retry connecting, we need to clean up the socket again
|
|
289
|
-
self.selector.unregister(self.socket)
|
|
290
|
+
self.selector.unregister(self.socket)
|
|
290
291
|
self.socket.close()
|
|
291
292
|
self.socket = None
|
|
292
293
|
self.remote_selector_key = None
|
|
@@ -485,6 +486,17 @@ class SocketClient(threading.Thread, CastStatusListener):
|
|
|
485
486
|
self.session_id = status.session_id
|
|
486
487
|
|
|
487
488
|
if new_channel and self.destination_id is not None:
|
|
489
|
+
# App quirk: If the Audible app is running, wait 1s after receiving cast status
|
|
490
|
+
# before connecting to the media player channel. This is a workaround for
|
|
491
|
+
# https://github.com/home-assistant-libs/pychromecast/issues/738
|
|
492
|
+
if (
|
|
493
|
+
any(namespace in self._handlers for namespace in self.app_namespaces)
|
|
494
|
+
and self.destination_id not in self._open_channels
|
|
495
|
+
and status.app_id == APP_AUDIBLE
|
|
496
|
+
):
|
|
497
|
+
self.logger.debug("Detected Audible connection. Sleeping for 1s")
|
|
498
|
+
time.sleep(1)
|
|
499
|
+
|
|
488
500
|
# If any of the namespaces of the new app are supported
|
|
489
501
|
# we will automatically connect to it to receive updates
|
|
490
502
|
for namespace in self.app_namespaces:
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["setuptools
|
|
2
|
+
requires = ["setuptools>=65.6,<77.0", "wheel>=0.37.1,<0.46.0"]
|
|
3
3
|
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "PyChromecast"
|
|
7
|
-
version = "14.0.
|
|
7
|
+
version = "14.0.6"
|
|
8
|
+
license = {text = "MIT"}
|
|
8
9
|
description = "Python module to talk to Google Chromecast."
|
|
9
10
|
readme = "README.rst"
|
|
10
11
|
authors = [
|
|
@@ -23,6 +24,7 @@ classifiers=[
|
|
|
23
24
|
"Programming Language :: Python",
|
|
24
25
|
"Programming Language :: Python :: 3",
|
|
25
26
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
|
+
"Typing :: Typed",
|
|
26
28
|
]
|
|
27
29
|
|
|
28
30
|
[project.urls]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|