mirror of
https://github.com/lilydjwg/nvchecker.git
synced 2025-03-10 06:14:02 +00:00
add pyalpm.vercmp as an alternative to parse_version
`pkg_resources.parse_version` has different results from `pyalpm.vercmp`. This allows to use `pyalpm.vercmp` as the sorting key. This closes #40.
This commit is contained in:
parent
8850babe71
commit
b9f5a1e476
7 changed files with 79 additions and 18 deletions
26
README.rst
26
README.rst
|
@ -114,6 +114,12 @@ oldver
|
||||||
newver
|
newver
|
||||||
Specify a version record file to store the new version info.
|
Specify a version record file to store the new version info.
|
||||||
|
|
||||||
|
sort_version_key
|
||||||
|
Sort the version string using this key function. Choose between ``parse_version`` and
|
||||||
|
``vercmp``. Default value is ``parse_version``. ``parse_version`` use
|
||||||
|
``pkg_resources.parse_version``. ``vercmp`` use ``pyalpm.vercmp``.
|
||||||
|
|
||||||
|
|
||||||
Search in a Webpage
|
Search in a Webpage
|
||||||
-------------------
|
-------------------
|
||||||
Search through a specific webpage for the version string. This type of version finding has these fields:
|
Search through a specific webpage for the version string. This type of version finding has these fields:
|
||||||
|
@ -137,6 +143,11 @@ proxy
|
||||||
user_agent
|
user_agent
|
||||||
The ``User-Agent`` header value to use. Use something more like a tool (e.g. ``curl/7.40.0``) in Europe or the real web page won't get through because cookie policies (SourceForge has this issue).
|
The ``User-Agent`` header value to use. Use something more like a tool (e.g. ``curl/7.40.0``) in Europe or the real web page won't get through because cookie policies (SourceForge has this issue).
|
||||||
|
|
||||||
|
sort_version_key
|
||||||
|
Sort the version string using this key function. Choose between ``parse_version`` and
|
||||||
|
``vercmp``. Default value is ``parse_version``. ``parse_version`` use
|
||||||
|
``pkg_resources.parse_version``. ``vercmp`` use ``pyalpm.vercmp``.
|
||||||
|
|
||||||
Find with a Command
|
Find with a Command
|
||||||
-------------------
|
-------------------
|
||||||
Use a shell command line to get the version. The output is striped first, so trailing newlines do not bother.
|
Use a shell command line to get the version. The output is striped first, so trailing newlines do not bother.
|
||||||
|
@ -180,6 +191,11 @@ ignored_tags
|
||||||
be useful to avoid some known badly versioned tags, so the newer tags won't
|
be useful to avoid some known badly versioned tags, so the newer tags won't
|
||||||
be "overridden" by the old broken ones.
|
be "overridden" by the old broken ones.
|
||||||
|
|
||||||
|
sort_version_key
|
||||||
|
Sort the version string using this key function. Choose between ``parse_version`` and
|
||||||
|
``vercmp``. Default value is ``parse_version``. ``parse_version`` use
|
||||||
|
``pkg_resources.parse_version``. ``vercmp`` use ``pyalpm.vercmp``.
|
||||||
|
|
||||||
An environment variable ``NVCHECKER_GITHUB_TOKEN`` can be set to a GitHub OAuth token in order to request more frequently than anonymously.
|
An environment variable ``NVCHECKER_GITHUB_TOKEN`` can be set to a GitHub OAuth token in order to request more frequently than anonymously.
|
||||||
|
|
||||||
Check BitBucket
|
Check BitBucket
|
||||||
|
@ -202,6 +218,11 @@ ignored_tags
|
||||||
be useful to avoid some known badly versioned tags, so the newer tags won't
|
be useful to avoid some known badly versioned tags, so the newer tags won't
|
||||||
be "overridden" by the old broken ones.
|
be "overridden" by the old broken ones.
|
||||||
|
|
||||||
|
sort_version_key
|
||||||
|
Sort the version string using this key function. Choose between ``parse_version`` and
|
||||||
|
``vercmp``. Default value is ``parse_version``. ``parse_version`` use
|
||||||
|
``pkg_resources.parse_version``. ``vercmp`` use ``pyalpm.vercmp``.
|
||||||
|
|
||||||
Check GitCafe
|
Check GitCafe
|
||||||
-------------
|
-------------
|
||||||
Check `GitCafe <https://gitcafe.com/>`_ for updates. The version returned is in date format ``%Y%m%d``, e.g. ``20130701``.
|
Check `GitCafe <https://gitcafe.com/>`_ for updates. The version returned is in date format ``%Y%m%d``, e.g. ``20130701``.
|
||||||
|
@ -234,6 +255,11 @@ ignored_tags
|
||||||
be useful to avoid some known badly versioned tags, so the newer tags won't
|
be useful to avoid some known badly versioned tags, so the newer tags won't
|
||||||
be "overridden" by the old broken ones.
|
be "overridden" by the old broken ones.
|
||||||
|
|
||||||
|
sort_version_key
|
||||||
|
Sort the version string using this key function. Choose between ``parse_version`` and
|
||||||
|
``vercmp``. Default value is ``parse_version``. ``parse_version`` use
|
||||||
|
``pkg_resources.parse_version``. ``vercmp`` use ``pyalpm.vercmp``.
|
||||||
|
|
||||||
host
|
host
|
||||||
Hostname for self-hosted GitLab instance.
|
Hostname for self-hosted GitLab instance.
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@ import sys
|
||||||
import logging
|
import logging
|
||||||
import configparser
|
import configparser
|
||||||
|
|
||||||
from pkg_resources import parse_version
|
|
||||||
from tornado.stack_context import ExceptionStackContext
|
from tornado.stack_context import ExceptionStackContext
|
||||||
|
|
||||||
from .lib import nicelogger
|
from .lib import nicelogger
|
||||||
from .get_version import get_version
|
from .get_version import get_version
|
||||||
|
from .sortversion import sort_version_keys
|
||||||
|
|
||||||
from . import __version__
|
from . import __version__
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ class Source:
|
||||||
started = False
|
started = False
|
||||||
tasks = 0
|
tasks = 0
|
||||||
oldver = newver = None
|
oldver = newver = None
|
||||||
|
sort_version_key = None
|
||||||
def __init__(self, file):
|
def __init__(self, file):
|
||||||
self.config = config = configparser.ConfigParser(
|
self.config = config = configparser.ConfigParser(
|
||||||
dict_type=dict, allow_no_value=True
|
dict_type=dict, allow_no_value=True
|
||||||
|
@ -73,6 +74,7 @@ class Source:
|
||||||
d = os.path.dirname(file.name)
|
d = os.path.dirname(file.name)
|
||||||
self.oldver = os.path.expandvars(os.path.expanduser(os.path.join(d, c.get('oldver'))))
|
self.oldver = os.path.expandvars(os.path.expanduser(os.path.join(d, c.get('oldver'))))
|
||||||
self.newver = os.path.expandvars(os.path.expanduser(os.path.join(d, c.get('newver'))))
|
self.newver = os.path.expandvars(os.path.expanduser(os.path.join(d, c.get('newver'))))
|
||||||
|
self.sort_version_key = sort_version_keys[c.get("sort_version_key", "parse_version")]
|
||||||
|
|
||||||
def check(self):
|
def check(self):
|
||||||
self.started = True
|
self.started = True
|
||||||
|
@ -113,7 +115,7 @@ class Source:
|
||||||
return
|
return
|
||||||
|
|
||||||
oldver = self.oldvers.get(name, None)
|
oldver = self.oldvers.get(name, None)
|
||||||
if not oldver or parse_version(oldver) < parse_version(version):
|
if not oldver or self.sort_version_key(oldver) < self.sort_version_key(version):
|
||||||
logger.info('%s updated version %s', name, version)
|
logger.info('%s updated version %s', name, version)
|
||||||
self.curvers[name] = version
|
self.curvers[name] = version
|
||||||
self.on_update(name, version, oldver)
|
self.on_update(name, version, oldver)
|
||||||
|
|
26
nvchecker/sortversion.py
Normal file
26
nvchecker/sortversion.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
'''
|
||||||
|
Sort versions using pkg_resource.parse_version or pyalpm.vercmp
|
||||||
|
'''
|
||||||
|
|
||||||
|
__all__ = ["sort_version_keys"]
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from functools import cmp_to_key
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
from pkg_resources import parse_version
|
||||||
|
try:
|
||||||
|
import pyalpm
|
||||||
|
vercmp = cmp_to_key(pyalpm.vercmp)
|
||||||
|
except ImportError:
|
||||||
|
def vercmp(k):
|
||||||
|
raise NotImplementedError("Using vercmp but pyalpm can not be imported!")
|
||||||
|
|
||||||
|
sort_version_keys = {"parse_version": parse_version, "vercmp": vercmp}
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
assert(parse_version("v6.0") < parse_version("6.1"))
|
||||||
|
assert(parse_version("v6.0") > parse_version("v6.1-stable"))
|
||||||
|
assert(vercmp("v6.0") < vercmp("v6.1-stable"))
|
|
@ -2,9 +2,10 @@ import os
|
||||||
import json
|
import json
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from pkg_resources import parse_version
|
|
||||||
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
|
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
|
||||||
|
|
||||||
|
from ..sortversion import sort_version_keys
|
||||||
|
|
||||||
# doc: https://confluence.atlassian.com/display/BITBUCKET/commits+or+commit+Resource
|
# doc: https://confluence.atlassian.com/display/BITBUCKET/commits+or+commit+Resource
|
||||||
BITBUCKET_URL = 'https://bitbucket.org/api/2.0/repositories/%s/commits/%s'
|
BITBUCKET_URL = 'https://bitbucket.org/api/2.0/repositories/%s/commits/%s'
|
||||||
BITBUCKET_MAX_TAG = 'https://bitbucket.org/api/1.0/repositories/%s/tags'
|
BITBUCKET_MAX_TAG = 'https://bitbucket.org/api/1.0/repositories/%s/tags'
|
||||||
|
@ -14,19 +15,20 @@ def get_version(name, conf, callback):
|
||||||
br = conf.get('branch', '')
|
br = conf.get('branch', '')
|
||||||
use_max_tag = conf.getboolean('use_max_tag', False)
|
use_max_tag = conf.getboolean('use_max_tag', False)
|
||||||
ignored_tags = conf.get("ignored_tags", "").split()
|
ignored_tags = conf.get("ignored_tags", "").split()
|
||||||
|
sort_version_key = sort_version_keys[conf.get("sort_version_key", "parse_version")]
|
||||||
if use_max_tag:
|
if use_max_tag:
|
||||||
url = BITBUCKET_MAX_TAG % repo
|
url = BITBUCKET_MAX_TAG % repo
|
||||||
else:
|
else:
|
||||||
url = BITBUCKET_URL % (repo, br)
|
url = BITBUCKET_URL % (repo, br)
|
||||||
request = HTTPRequest(url, user_agent='lilydjwg/nvchecker')
|
request = HTTPRequest(url, user_agent='lilydjwg/nvchecker')
|
||||||
AsyncHTTPClient().fetch(request,
|
AsyncHTTPClient().fetch(request,
|
||||||
callback=partial(_bitbucket_done, name, use_max_tag, ignored_tags, callback))
|
callback=partial(_bitbucket_done, name, use_max_tag, ignored_tags, sort_version_key, callback))
|
||||||
|
|
||||||
def _bitbucket_done(name, use_max_tag, ignored_tags, callback, res):
|
def _bitbucket_done(name, use_max_tag, ignored_tags, sort_version_key, callback, res):
|
||||||
data = json.loads(res.body.decode('utf-8'))
|
data = json.loads(res.body.decode('utf-8'))
|
||||||
if use_max_tag:
|
if use_max_tag:
|
||||||
data = [tag for tag in data if tag not in ignored_tags]
|
data = [tag for tag in data if tag not in ignored_tags]
|
||||||
data.sort(key=parse_version)
|
data.sort(key=sort_version_key)
|
||||||
version = data[-1]
|
version = data[-1]
|
||||||
else:
|
else:
|
||||||
version = data['values'][0]['date'].split('T', 1)[0].replace('-', '')
|
version = data['values'][0]['date'].split('T', 1)[0].replace('-', '')
|
||||||
|
|
|
@ -2,9 +2,10 @@ import os
|
||||||
import json
|
import json
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from pkg_resources import parse_version
|
|
||||||
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
|
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
|
||||||
|
|
||||||
|
from ..sortversion import sort_version_keys
|
||||||
|
|
||||||
GITHUB_URL = 'https://api.github.com/repos/%s/commits?sha=%s'
|
GITHUB_URL = 'https://api.github.com/repos/%s/commits?sha=%s'
|
||||||
GITHUB_LATEST_RELEASE = 'https://api.github.com/repos/%s/releases/latest'
|
GITHUB_LATEST_RELEASE = 'https://api.github.com/repos/%s/releases/latest'
|
||||||
GITHUB_MAX_TAG = 'https://api.github.com/repos/%s/tags'
|
GITHUB_MAX_TAG = 'https://api.github.com/repos/%s/tags'
|
||||||
|
@ -15,6 +16,7 @@ def get_version(name, conf, callback):
|
||||||
use_latest_release = conf.getboolean('use_latest_release', False)
|
use_latest_release = conf.getboolean('use_latest_release', False)
|
||||||
use_max_tag = conf.getboolean('use_max_tag', False)
|
use_max_tag = conf.getboolean('use_max_tag', False)
|
||||||
ignored_tags = conf.get("ignored_tags", "").split()
|
ignored_tags = conf.get("ignored_tags", "").split()
|
||||||
|
sort_version_key = sort_version_keys[conf.get("sort_version_key", "parse_version")]
|
||||||
if use_latest_release:
|
if use_latest_release:
|
||||||
url = GITHUB_LATEST_RELEASE % repo
|
url = GITHUB_LATEST_RELEASE % repo
|
||||||
elif use_max_tag:
|
elif use_max_tag:
|
||||||
|
@ -26,15 +28,15 @@ def get_version(name, conf, callback):
|
||||||
headers['Authorization'] = 'token %s' % os.environ['NVCHECKER_GITHUB_TOKEN']
|
headers['Authorization'] = 'token %s' % os.environ['NVCHECKER_GITHUB_TOKEN']
|
||||||
request = HTTPRequest(url, headers=headers, user_agent='lilydjwg/nvchecker')
|
request = HTTPRequest(url, headers=headers, user_agent='lilydjwg/nvchecker')
|
||||||
AsyncHTTPClient().fetch(request,
|
AsyncHTTPClient().fetch(request,
|
||||||
callback=partial(_github_done, name, use_latest_release, use_max_tag, ignored_tags, callback))
|
callback=partial(_github_done, name, use_latest_release, use_max_tag, ignored_tags, sort_version_key, callback))
|
||||||
|
|
||||||
def _github_done(name, use_latest_release, use_max_tag, ignored_tags, callback, res):
|
def _github_done(name, use_latest_release, use_max_tag, ignored_tags, sort_version_key, callback, res):
|
||||||
data = json.loads(res.body.decode('utf-8'))
|
data = json.loads(res.body.decode('utf-8'))
|
||||||
if use_latest_release:
|
if use_latest_release:
|
||||||
version = data['tag_name']
|
version = data['tag_name']
|
||||||
elif use_max_tag:
|
elif use_max_tag:
|
||||||
data = [tag["name"] for tag in data if tag["name"] not in ignored_tags]
|
data = [tag["name"] for tag in data if tag["name"] not in ignored_tags]
|
||||||
data.sort(key=parse_version)
|
data.sort(key=sort_version_key)
|
||||||
version = data[-1]
|
version = data[-1]
|
||||||
else:
|
else:
|
||||||
# YYYYMMDD.HHMMSS
|
# YYYYMMDD.HHMMSS
|
||||||
|
|
|
@ -4,9 +4,10 @@ from functools import partial
|
||||||
import logging
|
import logging
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from pkg_resources import parse_version
|
|
||||||
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
|
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
|
||||||
|
|
||||||
|
from ..sortversion import sort_version_keys
|
||||||
|
|
||||||
GITLAB_URL = 'https://%s/api/v3/projects/%s/repository/commits?ref_name=%s'
|
GITLAB_URL = 'https://%s/api/v3/projects/%s/repository/commits?ref_name=%s'
|
||||||
GITLAB_MAX_TAG = 'https://%s/api/v3/projects/%s/repository/tags'
|
GITLAB_MAX_TAG = 'https://%s/api/v3/projects/%s/repository/tags'
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@ def get_version(name, conf, callback):
|
||||||
host = conf.get('host', "gitlab.com")
|
host = conf.get('host', "gitlab.com")
|
||||||
use_max_tag = conf.getboolean('use_max_tag', False)
|
use_max_tag = conf.getboolean('use_max_tag', False)
|
||||||
ignored_tags = conf.get("ignored_tags", "").split()
|
ignored_tags = conf.get("ignored_tags", "").split()
|
||||||
|
sort_version_key = sort_version_keys[conf.get("sort_version_key", "parse_version")]
|
||||||
|
|
||||||
env_name = "NVCHECKER_GITLAB_TOKEN_" + host.upper().replace(".", "_").replace("/", "_")
|
env_name = "NVCHECKER_GITLAB_TOKEN_" + host.upper().replace(".", "_").replace("/", "_")
|
||||||
token = conf.get('token', os.environ.get(env_name, None))
|
token = conf.get('token', os.environ.get(env_name, None))
|
||||||
|
@ -34,13 +36,13 @@ def get_version(name, conf, callback):
|
||||||
headers = {"PRIVATE-TOKEN": token}
|
headers = {"PRIVATE-TOKEN": token}
|
||||||
request = HTTPRequest(url, headers=headers, user_agent='lilydjwg/nvchecker')
|
request = HTTPRequest(url, headers=headers, user_agent='lilydjwg/nvchecker')
|
||||||
AsyncHTTPClient().fetch(request,
|
AsyncHTTPClient().fetch(request,
|
||||||
callback=partial(_gitlab_done, name, use_max_tag, ignored_tags, callback))
|
callback=partial(_gitlab_done, name, use_max_tag, ignored_tags, sort_version_key, callback))
|
||||||
|
|
||||||
def _gitlab_done(name, use_max_tag, ignored_tags, callback, res):
|
def _gitlab_done(name, use_max_tag, ignored_tags, sort_version_key, callback, res):
|
||||||
data = json.loads(res.body.decode('utf-8'))
|
data = json.loads(res.body.decode('utf-8'))
|
||||||
if use_max_tag:
|
if use_max_tag:
|
||||||
data = [tag["name"] for tag in data if tag["name"] not in ignored_tags]
|
data = [tag["name"] for tag in data if tag["name"] not in ignored_tags]
|
||||||
data.sort(key=parse_version)
|
data.sort(key=sort_version_key)
|
||||||
version = data[-1]
|
version = data[-1]
|
||||||
else:
|
else:
|
||||||
version = data[0]['created_at'].split('T', 1)[0].replace('-', '')
|
version = data[0]['created_at'].split('T', 1)[0].replace('-', '')
|
||||||
|
|
|
@ -4,10 +4,10 @@ import logging
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from pkg_resources import parse_version
|
|
||||||
from tornado.httpclient import AsyncHTTPClient
|
from tornado.httpclient import AsyncHTTPClient
|
||||||
|
|
||||||
from .base import pycurl
|
from .base import pycurl
|
||||||
|
from ..sortversion import sort_version_keys
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -32,17 +32,18 @@ def get_version(name, conf, callback):
|
||||||
logger.warn('%s: proxy set but not used because pycurl is unavailable.', name)
|
logger.warn('%s: proxy set but not used because pycurl is unavailable.', name)
|
||||||
if conf.get('user_agent'):
|
if conf.get('user_agent'):
|
||||||
kwargs['user_agent'] = conf['user_agent']
|
kwargs['user_agent'] = conf['user_agent']
|
||||||
|
sort_version_key = sort_version_keys[conf.get("sort_version_key", "parse_version")]
|
||||||
|
|
||||||
httpclient.fetch(conf['url'], partial(
|
httpclient.fetch(conf['url'], partial(
|
||||||
_got_version, name, r, encoding, callback
|
_got_version, name, r, encoding, sort_version_key, callback
|
||||||
), **kwargs)
|
), **kwargs)
|
||||||
|
|
||||||
def _got_version(name, regex, encoding, callback, res):
|
def _got_version(name, regex, encoding, sort_version_key, callback, res):
|
||||||
version = None
|
version = None
|
||||||
try:
|
try:
|
||||||
body = res.body.decode(encoding)
|
body = res.body.decode(encoding)
|
||||||
try:
|
try:
|
||||||
version = max(regex.findall(body), key=parse_version)
|
version = max(regex.findall(body), key=sort_version_key)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.error('%s: version string not found.', name)
|
logger.error('%s: version string not found.', name)
|
||||||
finally:
|
finally:
|
||||||
|
|
Loading…
Add table
Reference in a new issue