github-dependents-info 2.0.1__tar.gz → 2.0.2__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.
- {github_dependents_info-2.0.1 → github_dependents_info-2.0.2}/PKG-INFO +2 -2
- {github_dependents_info-2.0.1 → github_dependents_info-2.0.2}/README.md +1 -1
- {github_dependents_info-2.0.1 → github_dependents_info-2.0.2}/github_dependents_info/gh_dependents_info.py +60 -5
- {github_dependents_info-2.0.1 → github_dependents_info-2.0.2}/pyproject.toml +1 -1
- {github_dependents_info-2.0.1 → github_dependents_info-2.0.2}/LICENSE +0 -0
- {github_dependents_info-2.0.1 → github_dependents_info-2.0.2}/github_dependents_info/__init__.py +0 -0
- {github_dependents_info-2.0.1 → github_dependents_info-2.0.2}/github_dependents_info/__main__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-dependents-info
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: Collect information about dependencies between a github repo and other repositories. Results available in JSON, markdown and badges.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -37,7 +37,7 @@ Description-Content-Type: text/markdown
|
|
|
37
37
|
[](https://github.com/nvuillam/github-dependents-info/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aapp%2Fdependabot)
|
|
38
38
|
|
|
39
39
|
[](https://github.com/nvuillam/github-dependents-info/graphs/contributors/)<!-- gh-dependents-info-used-by-start -->
|
|
40
|
-
[](https://github.com/nvuillam/github-dependents-info/blob/main/docs/github-dependents-info.md)<!-- gh-dependents-info-used-by-end -->
|
|
41
41
|
[](https://github.com/sponsors/nvuillam)
|
|
42
42
|
[](https://github.com/nvuillam/github-dependents-info/actions/workflows/mega-linter.yml)
|
|
43
43
|
[](https://github.com/nvuillam/github-dependents-info/blob/master/LICENSE)
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
[](https://github.com/nvuillam/github-dependents-info/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aapp%2Fdependabot)
|
|
11
11
|
|
|
12
12
|
[](https://github.com/nvuillam/github-dependents-info/graphs/contributors/)<!-- gh-dependents-info-used-by-start -->
|
|
13
|
-
[](https://github.com/nvuillam/github-dependents-info/blob/main/docs/github-dependents-info.md)<!-- gh-dependents-info-used-by-end -->
|
|
14
14
|
[](https://github.com/sponsors/nvuillam)
|
|
15
15
|
[](https://github.com/nvuillam/github-dependents-info/actions/workflows/mega-linter.yml)
|
|
16
16
|
[](https://github.com/nvuillam/github-dependents-info/blob/master/LICENSE)
|
|
@@ -50,6 +50,10 @@ class GithubDependentsInfo:
|
|
|
50
50
|
self.badges = {}
|
|
51
51
|
self.result = {}
|
|
52
52
|
self.time_delay = options["time_delay"] if "time_delay" in options else 0.1
|
|
53
|
+
self.http_retry_attempts = options.get("http_retry_attempts", 5)
|
|
54
|
+
self.http_retry_initial_delay = options.get("http_retry_initial_delay", max(self.time_delay, 1.0))
|
|
55
|
+
self.http_retry_backoff = options.get("http_retry_backoff", 2.0)
|
|
56
|
+
self.http_retry_max_delay = options.get("http_retry_max_delay", 60.0)
|
|
53
57
|
|
|
54
58
|
def collect(self):
|
|
55
59
|
"""Main entry point - synchronous wrapper for async collection."""
|
|
@@ -627,13 +631,64 @@ class GithubDependentsInfo:
|
|
|
627
631
|
follow_redirects=True,
|
|
628
632
|
)
|
|
629
633
|
|
|
634
|
+
def _compute_retry_delay(self, attempt: int, response: httpx.Response | None = None) -> float:
|
|
635
|
+
"""Calculate delay before next retry using headers or exponential backoff."""
|
|
636
|
+
if response is not None:
|
|
637
|
+
retry_after = response.headers.get("Retry-After")
|
|
638
|
+
if retry_after:
|
|
639
|
+
try:
|
|
640
|
+
wait_seconds = float(retry_after)
|
|
641
|
+
if wait_seconds > 0:
|
|
642
|
+
return min(wait_seconds, self.http_retry_max_delay)
|
|
643
|
+
except ValueError:
|
|
644
|
+
pass
|
|
645
|
+
delay = self.http_retry_initial_delay * (self.http_retry_backoff ** max(attempt - 1, 0))
|
|
646
|
+
return min(delay, self.http_retry_max_delay)
|
|
647
|
+
|
|
630
648
|
async def fetch_page(self, client, url, semaphore):
|
|
631
649
|
"""Fetch a single page with rate limiting."""
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
650
|
+
last_error = None
|
|
651
|
+
for attempt in range(1, self.http_retry_attempts + 1):
|
|
652
|
+
try:
|
|
653
|
+
async with semaphore:
|
|
654
|
+
await asyncio.sleep(self.time_delay)
|
|
655
|
+
response = await client.get(url)
|
|
656
|
+
response.raise_for_status()
|
|
657
|
+
return response.text
|
|
658
|
+
except httpx.HTTPStatusError as exc: # type: ignore[attr-defined]
|
|
659
|
+
last_error = exc
|
|
660
|
+
status_code = exc.response.status_code
|
|
661
|
+
should_retry = status_code == 429 or 500 <= status_code < 600
|
|
662
|
+
if not should_retry or attempt == self.http_retry_attempts:
|
|
663
|
+
raise
|
|
664
|
+
delay = self._compute_retry_delay(attempt, response=exc.response)
|
|
665
|
+
if self.debug:
|
|
666
|
+
logging.warning(
|
|
667
|
+
"HTTP %s while fetching %s (attempt %s/%s). Retrying in %.1fs",
|
|
668
|
+
status_code,
|
|
669
|
+
url,
|
|
670
|
+
attempt,
|
|
671
|
+
self.http_retry_attempts,
|
|
672
|
+
delay,
|
|
673
|
+
)
|
|
674
|
+
await asyncio.sleep(delay)
|
|
675
|
+
except (httpx.RequestError, httpx.TimeoutException) as exc: # type: ignore[attr-defined]
|
|
676
|
+
last_error = exc
|
|
677
|
+
if attempt == self.http_retry_attempts:
|
|
678
|
+
raise
|
|
679
|
+
delay = self._compute_retry_delay(attempt)
|
|
680
|
+
if self.debug:
|
|
681
|
+
logging.warning(
|
|
682
|
+
"Request error while fetching %s (attempt %s/%s): %s. Retrying in %.1fs",
|
|
683
|
+
url,
|
|
684
|
+
attempt,
|
|
685
|
+
self.http_retry_attempts,
|
|
686
|
+
exc,
|
|
687
|
+
delay,
|
|
688
|
+
)
|
|
689
|
+
await asyncio.sleep(delay)
|
|
690
|
+
if last_error is not None:
|
|
691
|
+
raise last_error
|
|
637
692
|
|
|
638
693
|
async def fetch_all_package_pages(self, client, package):
|
|
639
694
|
"""Fetch all pages for a package in parallel."""
|
|
@@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "github-dependents-info"
|
|
8
|
-
version = "2.0.
|
|
8
|
+
version = "2.0.2"
|
|
9
9
|
description = "Collect information about dependencies between a github repo and other repositories. Results available in JSON, markdown and badges."
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
license = "MIT"
|
|
File without changes
|
{github_dependents_info-2.0.1 → github_dependents_info-2.0.2}/github_dependents_info/__init__.py
RENAMED
|
File without changes
|
{github_dependents_info-2.0.1 → github_dependents_info-2.0.2}/github_dependents_info/__main__.py
RENAMED
|
File without changes
|