Simplify update checker
Motivated by the distutils removal, this replaces version parsing by a "good enough" version comparison algorithm...
This commit is contained in:
parent
a392a41acb
commit
af20ca7478
4 changed files with 45 additions and 37 deletions
|
@ -1,7 +1,7 @@
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
# Copyright (C) 2004-2008 Tristan Seligmann and Jonathan Jacobs
|
# SPDX-FileCopyrightText: © 2004 Tristan Seligmann and Jonathan Jacobs
|
||||||
# Copyright (C) 2012-2014 Bastian Kleineidam
|
# SPDX-FileCopyrightText: © 2012 Bastian Kleineidam
|
||||||
# Copyright (C) 2015-2022 Tobias Gruetzmacher
|
# SPDX-FileCopyrightText: © 2015 Tobias Gruetzmacher
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
@ -124,8 +124,8 @@ def display_version(verbose):
|
||||||
if verbose:
|
if verbose:
|
||||||
# search for updates
|
# search for updates
|
||||||
from .updater import check_update
|
from .updater import check_update
|
||||||
result, value = check_update()
|
try:
|
||||||
if result:
|
value = check_update()
|
||||||
if value:
|
if value:
|
||||||
version, url = value
|
version, url = value
|
||||||
if url is None:
|
if url is None:
|
||||||
|
@ -139,13 +139,8 @@ def display_version(verbose):
|
||||||
attrs = {'version': version, 'app': AppName,
|
attrs = {'version': version, 'app': AppName,
|
||||||
'url': url, 'currentversion': __version__}
|
'url': url, 'currentversion': __version__}
|
||||||
print(text % attrs)
|
print(text % attrs)
|
||||||
else:
|
except (IOError, KeyError) as err:
|
||||||
if value is None:
|
print(f'An error occured while checking for an update of {AppName}: {err!r}')
|
||||||
value = 'invalid update file syntax'
|
|
||||||
text = ('An error occured while checking for an '
|
|
||||||
'update of %(app)s: %(error)s.')
|
|
||||||
attrs = {'error': value, 'app': AppName}
|
|
||||||
print(text % attrs)
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
# Copyright (C) 2004-2008 Tristan Seligmann and Jonathan Jacobs
|
# SPDX-FileCopyrightText: © 2004 Tristan Seligmann and Jonathan Jacobs
|
||||||
# Copyright (C) 2012-2014 Bastian Kleineidam
|
# SPDX-FileCopyrightText: © 2012 Bastian Kleineidam
|
||||||
# Copyright (C) 2015-2020 Tobias Gruetzmacher
|
# SPDX-FileCopyrightText: © 2015 Tobias Gruetzmacher
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
from distutils.version import LooseVersion
|
from typing import Any
|
||||||
|
|
||||||
import dosagelib
|
import dosagelib
|
||||||
from . import http
|
from . import http
|
||||||
|
@ -18,35 +18,34 @@ EXTPRIO = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def check_update():
|
def check_update() -> None | tuple[str, None | str]:
|
||||||
"""Return the following values:
|
"""Return the following values:
|
||||||
(False, errmsg) - online version could not be determined
|
throws exception - online version could not be determined
|
||||||
(True, None) - user has newest version
|
None - user has newest version
|
||||||
(True, (version, url string)) - update available
|
(version, url string) - update available
|
||||||
(True, (version, None)) - current version is newer than online version
|
(version, None) - current version is newer than online version
|
||||||
"""
|
"""
|
||||||
version, value = get_online_version()
|
version, value = get_online_version()
|
||||||
if version is None:
|
|
||||||
# value is an error message
|
|
||||||
return False, value
|
|
||||||
if version == dosagelib.__version__:
|
if version == dosagelib.__version__:
|
||||||
# user has newest version
|
# user has newest version
|
||||||
return True, None
|
return None
|
||||||
if is_newer_version(version):
|
if is_newer_version(version):
|
||||||
# value is an URL linking to the update package
|
# value is an URL linking to the update package
|
||||||
return True, (version, value)
|
return (version, value)
|
||||||
# user is running a local or development version
|
# user is running a local or development version
|
||||||
return True, (version, None)
|
return (version, None)
|
||||||
|
|
||||||
|
|
||||||
def asset_key(asset):
|
def asset_key(asset: dict[str, Any]) -> int:
|
||||||
return EXTPRIO.get(os.path.splitext(asset['browser_download_url'])[1], 99)
|
return EXTPRIO.get(os.path.splitext(asset['browser_download_url'])[1], 99)
|
||||||
|
|
||||||
|
|
||||||
def get_online_version():
|
def get_online_version() -> tuple[str, None | str]:
|
||||||
"""Download update info and parse it."""
|
"""Download update info and parse it."""
|
||||||
page = http.default_session.get(UPDATE_URL).json()
|
response = http.default_session.get(UPDATE_URL)
|
||||||
version = page.get('tag_name', None)
|
response.raise_for_status()
|
||||||
|
page = response.json()
|
||||||
|
version = page['tag_name']
|
||||||
|
|
||||||
url = None
|
url = None
|
||||||
try:
|
try:
|
||||||
|
@ -58,6 +57,12 @@ def get_online_version():
|
||||||
return version, url
|
return version, url
|
||||||
|
|
||||||
|
|
||||||
def is_newer_version(version):
|
def version_nums(ver: str) -> tuple[int, ...]:
|
||||||
|
"""Extract all numeric "sub-parts" of a version string. Not very exact, but
|
||||||
|
works for our use case."""
|
||||||
|
return tuple(int(s) for s in re.split(r'\D+', ver + '0'))
|
||||||
|
|
||||||
|
|
||||||
|
def is_newer_version(version) -> bool:
|
||||||
"""Check if given version is newer than current version."""
|
"""Check if given version is newer than current version."""
|
||||||
return LooseVersion(version) > LooseVersion(dosagelib.__version__)
|
return version_nums(version) > version_nums(dosagelib.__version__)
|
||||||
|
|
|
@ -52,16 +52,16 @@ dev = [
|
||||||
"pytest-cov",
|
"pytest-cov",
|
||||||
"pytest-xdist",
|
"pytest-xdist",
|
||||||
"responses",
|
"responses",
|
||||||
"setup-cfg-fmt",
|
|
||||||
]
|
]
|
||||||
lint = [
|
lint = [
|
||||||
"flake8<6",
|
"flake8~=6.0",
|
||||||
"flake8-2020",
|
"flake8-2020",
|
||||||
"flake8-breakpoint",
|
"flake8-breakpoint",
|
||||||
"flake8-bugbear",
|
"flake8-bugbear",
|
||||||
"flake8-coding",
|
"flake8-coding",
|
||||||
"flake8-commas",
|
"flake8-commas",
|
||||||
"flake8-comprehensions",
|
"flake8-comprehensions",
|
||||||
|
"flake8-deprecated",
|
||||||
"flake8-eradicate",
|
"flake8-eradicate",
|
||||||
"flake8-fixme",
|
"flake8-fixme",
|
||||||
"flake8-functions",
|
"flake8-functions",
|
||||||
|
|
|
@ -82,7 +82,15 @@ class TestDosage:
|
||||||
json={})
|
json={})
|
||||||
cmd_ok('--version', '-v')
|
cmd_ok('--version', '-v')
|
||||||
out = capfd.readouterr().out
|
out = capfd.readouterr().out
|
||||||
assert 'invalid update file' in out
|
assert 'KeyError' in out
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_update_rate_limit(self, capfd):
|
||||||
|
responses.add(responses.GET, re.compile(r'https://api\.github\.com/'),
|
||||||
|
status=403)
|
||||||
|
cmd_ok('--version', '-v')
|
||||||
|
out = capfd.readouterr().out
|
||||||
|
assert 'HTTPError' in out
|
||||||
|
|
||||||
def test_display_help(self):
|
def test_display_help(self):
|
||||||
for option in ("-h", "--help"):
|
for option in ("-h", "--help"):
|
||||||
|
|
Loading…
Reference in a new issue