pierre-sdk 0.1.0.dev4__py3-none-any.whl
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.
- pierre/__init__.py +59 -0
- pierre/_client.py +544 -0
- pierre/_compat.py +14 -0
- pierre/_content.py +168 -0
- pierre/_credentials.py +321 -0
- pierre/_errors.py +205 -0
- pierre/_generated/__init__.py +2 -0
- pierre/_generated/client.py +54 -0
- pierre/_generated/headers.py +69 -0
- pierre/_generated/namespaces/__init__.py +2 -0
- pierre/_generated/namespaces/meta.py +125 -0
- pierre/_generated/namespaces/repos.py +5658 -0
- pierre/_generated/schemas.py +1437 -0
- pierre/_generated/scopes.py +12 -0
- pierre/_generated/webhooks.py +30 -0
- pierre/_helpers/__init__.py +1 -0
- pierre/_helpers/commits.py +220 -0
- pierre/_helpers/repos.py +58 -0
- pierre/_operation.py +66 -0
- pierre/_page.py +154 -0
- pierre/_response.py +92 -0
- pierre/_retry.py +65 -0
- pierre/_runtime.py +763 -0
- pierre/_types.py +73 -0
- pierre/_version.py +3 -0
- pierre/auth.py +84 -0
- pierre/git.py +161 -0
- pierre/py.typed +0 -0
- pierre/types.py +14 -0
- pierre/webhooks.py +145 -0
- pierre_sdk-0.1.0.dev4.dist-info/METADATA +153 -0
- pierre_sdk-0.1.0.dev4.dist-info/RECORD +34 -0
- pierre_sdk-0.1.0.dev4.dist-info/WHEEL +4 -0
- pierre_sdk-0.1.0.dev4.dist-info/licenses/LICENSE +189 -0
pierre/_retry.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""The retry rules: which results are transient, and how long to wait."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import random
|
|
5
|
+
import re
|
|
6
|
+
import time
|
|
7
|
+
from email.utils import parsedate_to_datetime
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
# The 409 codes of a condition that ends by itself.
|
|
11
|
+
_RETRYABLE_CONFLICT_CODES = frozenset({"repository_thawing", "sync_in_progress"})
|
|
12
|
+
|
|
13
|
+
# The first backoff delay, in seconds.
|
|
14
|
+
_INITIAL_DELAY = 0.5
|
|
15
|
+
# The longest backoff delay.
|
|
16
|
+
_MAX_BACKOFF = 8.0
|
|
17
|
+
# The longest `Retry-After` that the SDK waits. A longer value falls back to the backoff.
|
|
18
|
+
_MAX_RETRY_AFTER = 60.0
|
|
19
|
+
|
|
20
|
+
# The HTTP date form that servers send (IMF-fixdate, RFC 9110), for example
|
|
21
|
+
# `Sun, 06 Nov 1994 08:49:37 GMT`.
|
|
22
|
+
_HTTP_DATE = re.compile(
|
|
23
|
+
r"[A-Z][a-z]{2}, [0-9]{2} [A-Z][a-z]{2} [0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} GMT", re.ASCII
|
|
24
|
+
)
|
|
25
|
+
_SECONDS = re.compile(r"[0-9]+(\.[0-9]+)?")
|
|
26
|
+
|
|
27
|
+
# The wait between two attempts. Tests replace them to record the delays.
|
|
28
|
+
sleep = time.sleep
|
|
29
|
+
async_sleep = asyncio.sleep
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def transient_status(status: int, code: Optional[str]) -> bool:
|
|
33
|
+
"""Whether an error status can succeed on a repeat."""
|
|
34
|
+
return (
|
|
35
|
+
status in (408, 429)
|
|
36
|
+
or status >= 500
|
|
37
|
+
or (status == 409 and code is not None and code in _RETRYABLE_CONFLICT_CODES)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def retry_delay(retry_after: Optional[str], attempt: int, now: Optional[float] = None) -> float:
|
|
42
|
+
"""The wait in seconds before retry number `attempt + 1`: the `Retry-After` value when it is
|
|
43
|
+
60 seconds or less, or else an exponential backoff from 0.5 seconds, up to 8 seconds, less up
|
|
44
|
+
to 25% jitter."""
|
|
45
|
+
after = _retry_after_seconds(retry_after, time.time() if now is None else now)
|
|
46
|
+
if after is not None and after <= _MAX_RETRY_AFTER:
|
|
47
|
+
return after
|
|
48
|
+
backoff: float = min(_INITIAL_DELAY * 2**attempt, _MAX_BACKOFF)
|
|
49
|
+
return backoff * (1 - random.random() * 0.25)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _retry_after_seconds(value: Optional[str], now: float) -> Optional[float]:
|
|
53
|
+
"""A `Retry-After` value in seconds or as an HTTP date, in seconds from `now`."""
|
|
54
|
+
if value is None:
|
|
55
|
+
return None
|
|
56
|
+
text = value.strip()
|
|
57
|
+
if _SECONDS.fullmatch(text):
|
|
58
|
+
return float(text)
|
|
59
|
+
if not _HTTP_DATE.fullmatch(text):
|
|
60
|
+
return None
|
|
61
|
+
try:
|
|
62
|
+
date = parsedate_to_datetime(text)
|
|
63
|
+
except (TypeError, ValueError):
|
|
64
|
+
return None
|
|
65
|
+
return max(0.0, date.timestamp() - now)
|