-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpackage.py
More file actions
68 lines (59 loc) · 2.61 KB
/
Copy pathpackage.py
File metadata and controls
68 lines (59 loc) · 2.61 KB
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
from dataclasses import dataclass
from packaging.version import InvalidVersion, parse
@dataclass
class Package:
json: dict
def __post_init__(self):
self.name = self.json["info"]["name"]
self.version = self.json["info"]["version"]
self.releases = self.json["releases"]
@property
def current_version(self):
return self.version
@property
def latest_version(self):
version_str = self.parse_versions_for_latest().__str__()
return version_str
@property
def repository_url(self):
"""
Returns the repository URL from project_urls in order of preference:
Changelog, Changes, Release log, Repository, then Source. Returns the first one found or None.
"""
project_urls = self.json["info"].get("project_urls", {})
if isinstance(project_urls, dict):
# Check in order of preference
for key in ["Changelog", "Changes", "Release log", "Repository", "Source"]:
if key in project_urls:
return project_urls[key]
return None
def parse_versions_for_latest(self):
"""
Parse the versions and return the latest version
using the packaging library now, previously parsed upload dates
but found that it was not reliable because if an earlier version
gets a new patch it's upload date could be the latest.
It only happened for the Django package but it's better to be safe
"""
latest_version = tuple()
for version, releases in self.releases.items():
for release in releases:
try:
parsed_version = parse(version)
except InvalidVersion:
# except InvalidVersion:
# # e.g. paramiko has a release with a version of '0.1-bulbasaur'
# # which isn't a version we are interested in and is likely a pre-release
# # without it bee declared as such
# pass
continue
# # This doesn't seen to be required but keep it here for now
# # until it's been tested a little more.
if parsed_version.is_prerelease or parsed_version.is_postrelease:
continue
if not len(latest_version):
latest_version = (parsed_version, release)
else:
if parsed_version > latest_version[0]:
latest_version = (parsed_version, release)
return latest_version[0] if len(latest_version) else None