-
Notifications
You must be signed in to change notification settings - Fork 3
/
remove_old_wheels.py
66 lines (55 loc) · 2.24 KB
/
remove_old_wheels.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
# Remove all but the latest N versions from wheels on Anaconda.org
from datetime import datetime, timezone, timedelta
import click
from binstar_client.utils import get_server_api
UPLOAD_TIME_FMT_V1 = r"%Y-%m-%d %H:%M:%S.%f%z" # e.g., 2018-10-19 19:03:58.717000+00:00
UPLOAD_TIME_FMT_V2 = r"%Y-%m-%d %H:%M:%S%z" # e.g., 2018-10-19 19:03:58+00:00
MIN_DATETIME = datetime.min.replace(tzinfo=timezone(timedelta(hours=0)))
def _parse_upload_time(upload_time: str) -> datetime:
for fmt in (UPLOAD_TIME_FMT_V1, UPLOAD_TIME_FMT_V2):
try:
return datetime.strptime(upload_time, fmt)
except ValueError:
continue
raise ValueError(
f"Failed to parse upload time {upload_time!r} "
"(didn't match any known format)"
)
@click.command()
@click.option("--user")
@click.option("--package")
@click.option("--keep", default=-1)
@click.option("--token")
@click.option("--dry", default=False)
def remove(user, package, keep, token, dry):
if keep < 0:
return
api = get_server_api(token=token)
pkg = api.package(user, package)
# Find versions for which wheels are available
pypi_versions = {}
for file_info in pkg["files"]:
if file_info["type"] == "pypi":
version = file_info["version"]
upload_time = _parse_upload_time(file_info["upload_time"])
# Keep date of version's most recent upload
pypi_versions[version] = max(
pypi_versions.get(version, MIN_DATETIME),
upload_time,
)
pypi_versions = [(upload_time, version) for version, upload_time in pypi_versions.items()]
pypi_versions = sorted(pypi_versions) # sort by upload time (then version)
# Determine versions to remove
versions_to_remove = [version[1] for version in pypi_versions[:-keep]]
# Remove the files
for file_info in pkg["files"]:
if file_info["version"] in versions_to_remove:
print(f"Removing {file_info['basename']}")
if not dry:
api.remove_dist(
user, package, file_info["version"], basename=file_info["basename"]
)
else:
print(f"Keeping {file_info['basename']}")
if __name__ == "__main__":
remove()