Skip to content

Commit 3c20298

Browse files
authored
feat(scripts.downloads): add scripts/downloads.py (#735)
* add scripts/downloads.py * add total cumulative downloads to title * add module docstring * pagination * add datetime * accumulate by release_date * black/flake8
1 parent 6a62078 commit 3c20298

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

scripts/downloads.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""Plot downloads over time."""
2+
3+
import requests
4+
import matplotlib.pyplot as plt
5+
from datetime import datetime
6+
from pprint import pformat
7+
8+
import numpy as np
9+
10+
11+
def fetch_download_data(api_url: str) -> dict:
12+
"""Fetches download data from GitHub API and returns it as a dictionary.
13+
14+
Supports pagination.
15+
16+
Args:
17+
api_url (str): The URL of the GitHub API endpoint for releases.
18+
19+
Returns:
20+
dict: A dictionary with dates as keys and download counts as values.
21+
"""
22+
download_data = {}
23+
ignored_names = set()
24+
page = 1
25+
while True:
26+
response = requests.get(f"{api_url}?per_page=30&page={page}")
27+
releases = response.json()
28+
if not releases: # Break the loop if no more releases are returned
29+
break
30+
for release in releases:
31+
release_date = release["published_at"][:10]
32+
print(
33+
release["name"],
34+
list(
35+
(asset["name"], asset["download_count"])
36+
for asset in release["assets"]
37+
),
38+
)
39+
ignored_names |= set(
40+
[
41+
asset["name"]
42+
for asset in release["assets"]
43+
if not asset["name"].endswith(".zip")
44+
]
45+
)
46+
total_downloads = sum(
47+
asset["download_count"]
48+
for asset in release["assets"]
49+
if asset["name"].endswith(".zip")
50+
)
51+
download_data.setdefault(release_date, 0)
52+
download_data[release_date] += total_downloads
53+
page += 1 # Increment page number for the next API request
54+
print(f"ignored_names=\n{pformat(ignored_names)}")
55+
return download_data
56+
57+
58+
def plot_downloads(data: dict) -> None:
59+
"""Plots number of downloads and cumulative downloads over time using matplotlib.
60+
61+
Includes total cumulative in the title.
62+
63+
Args:
64+
data (dict): A dictionary with dates as keys and download counts as values.
65+
"""
66+
dates = [datetime.strptime(date, "%Y-%m-%d") for date in sorted(data.keys())]
67+
downloads = [data[date.strftime("%Y-%m-%d")] for date in dates]
68+
cumulative_downloads = np.cumsum(downloads)
69+
total_cumulative_downloads = (
70+
cumulative_downloads[-1] if cumulative_downloads.size > 0 else 0
71+
)
72+
73+
plt.figure(figsize=(12, 6))
74+
plt.plot(
75+
dates, downloads, marker="o", linestyle="-", color="b", label="Daily Downloads"
76+
)
77+
plt.plot(
78+
dates,
79+
cumulative_downloads,
80+
marker=None,
81+
linestyle="--",
82+
color="r",
83+
label="Cumulative Downloads",
84+
)
85+
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
86+
plt.title(
87+
"Downloads Over Time"
88+
f"\n(Total Cumulative: {total_cumulative_downloads}) "
89+
f"\n{current_time}"
90+
)
91+
plt.xlabel("Date")
92+
plt.ylabel("Number of Downloads")
93+
plt.grid(True)
94+
plt.xticks(rotation=45)
95+
plt.legend()
96+
plt.tight_layout()
97+
plt.show()
98+
99+
100+
if __name__ == "__main__":
101+
api_url = "https://api.github.com/repos/OpenAdaptAI/OpenAdapt/releases"
102+
download_data = fetch_download_data(api_url)
103+
plot_downloads(download_data)

0 commit comments

Comments
 (0)