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.
Files changed (50) hide show
  1. {PyChromecast-14.0.4 → pychromecast-14.0.6}/PKG-INFO +7 -2
  2. {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/PKG-INFO +7 -2
  3. {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/SOURCES.txt +1 -0
  4. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/config.py +1 -0
  5. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/dial.py +30 -6
  6. pychromecast-14.0.6/pychromecast/py.typed +0 -0
  7. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/quick_play.py +1 -1
  8. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/socket_client.py +13 -1
  9. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pyproject.toml +4 -2
  10. pychromecast-14.0.6/requirements.txt +3 -0
  11. PyChromecast-14.0.4/requirements.txt +0 -3
  12. {PyChromecast-14.0.4 → pychromecast-14.0.6}/LICENSE +0 -0
  13. {PyChromecast-14.0.4 → pychromecast-14.0.6}/MANIFEST.in +0 -0
  14. {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/dependency_links.txt +0 -0
  15. {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/not-zip-safe +0 -0
  16. {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/requires.txt +0 -0
  17. {PyChromecast-14.0.4 → pychromecast-14.0.6}/PyChromecast.egg-info/top_level.txt +0 -0
  18. {PyChromecast-14.0.4 → pychromecast-14.0.6}/README.rst +0 -0
  19. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/__init__.py +0 -0
  20. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/const.py +0 -0
  21. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/__init__.py +0 -0
  22. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/bbciplayer.py +0 -0
  23. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/bbcsounds.py +0 -0
  24. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/bubbleupnp.py +0 -0
  25. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/dashcast.py +0 -0
  26. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/heartbeat.py +0 -0
  27. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/homeassistant.py +0 -0
  28. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/homeassistant_media.py +0 -0
  29. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/media.py +0 -0
  30. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/multizone.py +0 -0
  31. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/nrkradio.py +0 -0
  32. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/nrktv.py +0 -0
  33. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/plex.py +0 -0
  34. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/receiver.py +0 -0
  35. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/shaka.py +0 -0
  36. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/supla.py +0 -0
  37. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/yleareena.py +0 -0
  38. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/controllers/youtube.py +0 -0
  39. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/discovery.py +0 -0
  40. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/error.py +0 -0
  41. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/authority_keys_pb2.py +0 -0
  42. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/authority_keys_pb2.pyi +0 -0
  43. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/cast_channel_pb2.py +0 -0
  44. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/cast_channel_pb2.pyi +0 -0
  45. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/logging_pb2.py +0 -0
  46. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/logging_pb2.pyi +0 -0
  47. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/generated/readme.txt +0 -0
  48. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/models.py +0 -0
  49. {PyChromecast-14.0.4 → pychromecast-14.0.6}/pychromecast/response_handler.py +0 -0
  50. {PyChromecast-14.0.4 → pychromecast-14.0.6}/setup.cfg +0 -0
@@ -1,8 +1,9 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: PyChromecast
3
- Version: 14.0.4
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
1
+ Metadata-Version: 2.2
2
2
  Name: PyChromecast
3
- Version: 14.0.4
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
  ===========================
@@ -17,6 +17,7 @@ pychromecast/dial.py
17
17
  pychromecast/discovery.py
18
18
  pychromecast/error.py
19
19
  pychromecast/models.py
20
+ pychromecast/py.typed
20
21
  pychromecast/quick_play.py
21
22
  pychromecast/response_handler.py
22
23
  pychromecast/socket_client.py
@@ -22,6 +22,7 @@ APP_BBCIPLAYER = "5E81F6DB"
22
22
  APP_SHAKA = "07AEE832"
23
23
  APP_NRKTV = "3AEDF8D1"
24
24
  APP_NRKRADIO = "A49874B1"
25
+ APP_AUDIBLE = "25456794"
25
26
 
26
27
 
27
28
  def get_possible_app_ids() -> list[str]:
@@ -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
- req = urllib.request.Request(url, headers=headers)
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
@@ -1,4 +1,4 @@
1
- """ Choose a controller and quick play """
1
+ """Choose a controller and quick play"""
2
2
 
3
3
  from typing import Any
4
4
 
@@ -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) # type: ignore[unreachable]
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~=65.6", "wheel~=0.37.1"]
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.4"
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]
@@ -0,0 +1,3 @@
1
+ casttube==0.2.1
2
+ protobuf==5.29.3
3
+ zeroconf==0.146.1
@@ -1,3 +0,0 @@
1
- casttube==0.2.1
2
- protobuf==5.28.2
3
- zeroconf==0.135.0
File without changes
File without changes
File without changes
File without changes