-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck_release_version.py
More file actions
62 lines (49 loc) · 2.1 KB
/
Copy pathcheck_release_version.py
File metadata and controls
62 lines (49 loc) · 2.1 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
"""Query Github to check if current version is latest."""
import re
import urllib.error
import urllib.request
import warnings
import packaging.version
REPO_URL = "https://github.com/jmball/data_analysis"
RELEASES_URL = f"{REPO_URL}/releases"
def get_latest_release_version():
"""Scrape Github for the latest release version tag.
Release version tags are formatted as "v[semantic version]", e.g. "v1.0.0".
"""
# get html of releases webpage
# suppress linter warning about urllib as url is hard coded
try:
page = urllib.request.urlopen(RELEASES_URL) # nosec
except urllib.error.URLError:
warnings.warn("Cannot access URL. Check internet connection.")
return None
html = page.read().decode("utf-8")
# official regex for a semantic version string
# from https://semver.org#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
sem_ver_re = r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"
# remove limitations of single line (i.e. remove ^ and $) from official string to
# allow searching for a semantic version string as a substring, and prepend "v" to
# match release tags
tag_re = f"(v){sem_ver_re[1:-1]}"
# search html to get all version tags on the releases page
pattern = re.compile(tag_re)
pos = 0
version_tags = []
while True:
match = pattern.search(html, pos)
if match is None:
break
version_tags.append(match.group())
pos = match.start() + 1
# get all unique semantic versions from the release tags
versions = [tag[1:] for tag in set(version_tags)]
# get latest version
latest_version = None
for version in versions:
if latest_version is None:
latest_version = version
elif packaging.version.parse(version) > packaging.version.parse(latest_version):
latest_version = version
return latest_version
if __name__ == "__main__":
print(get_latest_release_version())