simplepush 3.7.0__tar.gz → 3.7.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: simplepush
3
- Version: 3.7.0
3
+ Version: 3.7.1
4
4
  Summary: Python client for Simplepush (tasks, notifications, events, end-to-end encryption).
5
5
  Project-URL: Homepage, https://simplepu.sh
6
6
  Project-URL: Documentation, https://simplepu.sh/guide/python-sdk
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "simplepush"
7
- version = "3.7.0"
7
+ version = "3.7.1"
8
8
  description = "Python client for Simplepush (tasks, notifications, events, end-to-end encryption)."
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -56,7 +56,7 @@ from .client import (
56
56
  Event, GroupCancelResult, InputEvent, Notification, NotificationGroup,
57
57
  NotificationGroupRecipient, RawEvents, Reply, Subtask, Submissions, Task,
58
58
  TaskGroup, TaskGroupRecipient,
59
- _DownloadTransport, _FileBinder, _Hub,
59
+ _HTTP_TIMEOUT, _DownloadTransport, _FileBinder, _Hub,
60
60
  )
61
61
 
62
62
 
@@ -568,7 +568,7 @@ class _BaseClient:
568
568
  method="GET",
569
569
  )
570
570
  try:
571
- with urllib.request.urlopen(req) as resp:
571
+ with urllib.request.urlopen(req, timeout=_HTTP_TIMEOUT) as resp:
572
572
  info = json.loads(resp.read().decode("utf-8"))
573
573
  except urllib.error.HTTPError as e:
574
574
  raise ApiError(e.code, e.read().decode("utf-8")) from e
@@ -1524,7 +1524,7 @@ class _BaseClient:
1524
1524
  attempt += 1
1525
1525
  req = urllib.request.Request(url, data=data, headers=req_headers, method="POST")
1526
1526
  try:
1527
- with urllib.request.urlopen(req) as resp:
1527
+ with urllib.request.urlopen(req, timeout=_HTTP_TIMEOUT) as resp:
1528
1528
  resp_body = resp.read().decode("utf-8")
1529
1529
  if resp_body:
1530
1530
  return json.loads(resp_body)
@@ -1535,8 +1535,9 @@ class _BaseClient:
1535
1535
  if not (retry and retryable) or attempt >= self._RETRY_MAX_ATTEMPTS:
1536
1536
  raise ApiError(e.code, payload) from e
1537
1537
  time.sleep(self._retry_delay(attempt, e.headers.get("Retry-After")))
1538
- except urllib.error.URLError as e:
1539
- # Network-level failure (connection refused/reset, DNS).
1538
+ except (urllib.error.URLError, TimeoutError) as e:
1539
+ # Network-level failure (connection refused/reset, DNS, or no
1540
+ # response within the timeout).
1540
1541
  if not retry or attempt >= self._RETRY_MAX_ATTEMPTS:
1541
1542
  raise
1542
1543
  time.sleep(self._retry_delay(attempt, None))
@@ -1548,7 +1549,7 @@ class _BaseClient:
1548
1549
  url = f"{self._base}{path}"
1549
1550
  req = urllib.request.Request(url, data=b"", headers=dict(headers or {}), method="POST")
1550
1551
  try:
1551
- with urllib.request.urlopen(req) as resp:
1552
+ with urllib.request.urlopen(req, timeout=_HTTP_TIMEOUT) as resp:
1552
1553
  resp_body = resp.read().decode("utf-8")
1553
1554
  return json.loads(resp_body) if resp_body else None
1554
1555
  except urllib.error.HTTPError as e:
@@ -1561,7 +1562,7 @@ class _BaseClient:
1561
1562
  req = urllib.request.Request(url, data=data, method="PUT")
1562
1563
  req.add_header("Content-Type", "application/octet-stream")
1563
1564
  try:
1564
- with urllib.request.urlopen(req) as resp:
1565
+ with urllib.request.urlopen(req, timeout=_HTTP_TIMEOUT) as resp:
1565
1566
  resp.read()
1566
1567
  except urllib.error.HTTPError as e:
1567
1568
  raise ApiError(e.code, e.read().decode("utf-8")) from e
@@ -49,6 +49,10 @@ from urllib.parse import quote
49
49
  import websockets
50
50
  import websockets.exceptions
51
51
 
52
+ # Seconds an HTTP request waits for the connection or the next data before it
53
+ # fails. It bounds each wait, not a whole upload or download.
54
+ _HTTP_TIMEOUT = 30
55
+
52
56
  if TYPE_CHECKING:
53
57
  # Type-only: api.py imports from this module at runtime, so a real import
54
58
  # here would be circular. The enum-or-Literal unions below give static
@@ -276,7 +280,7 @@ class _DownloadTransport:
276
280
  url = f"{self._base}/{scope}/{quote(str(scope_id))}/{kind}/{quote(str(file_id))}/download-url"
277
281
  req = urllib.request.Request(url, data=b"", headers=self._headers, method="POST")
278
282
  try:
279
- with urllib.request.urlopen(req) as resp:
283
+ with urllib.request.urlopen(req, timeout=_HTTP_TIMEOUT) as resp:
280
284
  body = resp.read().decode("utf-8")
281
285
  except urllib.error.HTTPError as e:
282
286
  detail = e.read().decode("utf-8", "replace")
@@ -286,7 +290,7 @@ class _DownloadTransport:
286
290
 
287
291
  def get(self, url: str) -> bytes:
288
292
  try:
289
- with urllib.request.urlopen(url) as resp:
293
+ with urllib.request.urlopen(url, timeout=_HTTP_TIMEOUT) as resp:
290
294
  return resp.read()
291
295
  except urllib.error.HTTPError as e:
292
296
  raise DownloadError(f"file fetch failed: HTTP {e.code}", status_code=e.code) from e
File without changes
File without changes
File without changes