-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmacos-versions.py
executable file
·148 lines (120 loc) · 4.39 KB
/
macos-versions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env -S uv run --script
"""
Sum totals for macOS major.minor versions.
First do something like:
$ pypinfo --limit 1000 --json --markdown pillow system distro-version > macos.json
Then:
$ python3 macos-versions.py
Or:
$ uv run macos-versions.py
This then takes the JSON output file of that, and sums up the downloads for
each macOS major.minor version, ignoring the patch number: x.y.z -> x.y
"""
# /// script
# dependencies = [
# "natsort",
# "prettytable",
# ]
# ///
from __future__ import annotations
import argparse
import csv
import glob
import json
import sys
from collections import OrderedDict
from natsort import natsorted # pip install natsort
from prettytable import PrettyTable, TableStyle # pip install prettytable
# from pprint import pprint
# from rich import print # pip install rich
# https://stackoverflow.com/a/5734564/724176
def month_year_iter(start_month, start_year, end_month, end_year):
ym_start = 12 * start_year + start_month - 1
ym_end = 12 * end_year + end_month - 1
for ym in range(ym_start, ym_end):
y, m = divmod(ym, 12)
yield y, m + 1
def main():
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument("-i", "--inspec", default="macos.json", help="Input file spec")
args = parser.parse_args()
new_rows = []
darwin_downloads = {}
files = glob.glob(args.inspec)
files = sorted(files)
if len(files) == 0:
sys.exit("No files matching " + args.inspec)
for f in files:
# print(f)
with open(f) as json_data:
d = json.load(json_data)
# pprint(d)
for row in d["rows"]:
# pprint(row)
# print(row["system_name"])
if row["system_name"] != "Darwin":
continue
distro_version = row["distro_version"]
download_count = row["download_count"]
if distro_version == "None":
darwin_downloads[distro_version] = download_count
continue
if isinstance(distro_version, int):
x, y = distro_version, 0
else:
x, y, *rest = str(distro_version).split(".")
if int(x) >= 11:
xy = f"{x}"
else:
xy = f"{x}.{y}"
if xy == "10.16":
xy = "11"
# print(f"{distro_version}\t{x} {y}\t{xy}")
# December 2024: macOS 16 isn't out yet, let's skip less useful data:
# 16.6.1, 20.04 etc. They account for ~0.11% of the total.
if int(x) >= 16:
continue
try:
darwin_downloads[xy] += download_count
except KeyError:
darwin_downloads[xy] = download_count
# pprint(darwin_downloads)
# Sort by version number
ordered_keys = natsorted(darwin_downloads)
darwin_downloads = OrderedDict((key, darwin_downloads[key]) for key in ordered_keys)
darwin_total = sum(darwin_downloads.values())
# print(darwin_total)
for version in darwin_downloads:
percent = darwin_downloads[version] / darwin_total * 100
row = {
"system_name": "Darwin",
"distro_version": version,
"download_count": darwin_downloads[version],
"percent": f"{round(percent, 2):.2f}%",
}
new_rows.append(row)
# pprint(new_rows)
fieldnames = ["system_name", "distro_version", "percent", "download_count"]
with open("macos.csv", "w+") as output_file:
dict_writer = csv.DictWriter(output_file, fieldnames=fieldnames)
dict_writer.writeheader()
dict_writer.writerows(new_rows)
summed_percent = 0
for row in new_rows[::-1]:
summed_percent += float(row["percent"].rstrip("%"))
row["summed_percent"] = f"{round(summed_percent, 2):.2f}%"
t = PrettyTable()
t.set_style(TableStyle.MARKDOWN)
t.field_names = new_rows[0].keys()
for row in new_rows:
t.add_row(row.values())
t.align["distro_version"] = "r"
t.align["download_count"] = "r"
t.align["percent"] = "r"
t.align["summed_percent"] = "r"
t.custom_format["download_count"] = lambda _, v: f"{v:,}"
print(t)
if __name__ == "__main__":
main()