add the "list options" feature

closes #83
old options will be removed in #99
This commit is contained in:
lilydjwg 2019-03-06 21:51:04 +08:00
parent 58a68957e9
commit 7897317294
7 changed files with 64 additions and 22 deletions

View file

@ -197,16 +197,18 @@ The following options apply to sources that return a list. See individual
source sections to determine whether they are supported. source sections to determine whether they are supported.
include_regex include_regex
Only consider version strings that match the given regex. Only consider version strings that match the given regex. The whole string
should match the regex.
sort_version_key sort_version_key
Sort the version string using this key function. Choose between ``parse_version`` and Sort the version string using this key function. Choose between
``vercmp``. Default value is ``parse_version``. ``parse_version`` use ``parse_version`` and ``vercmp``. Default value is ``parse_version``.
``pkg_resources.parse_version``. ``vercmp`` use ``pyalpm.vercmp``. ``parse_version`` use ``pkg_resources.parse_version``. ``vercmp`` use
``pyalpm.vercmp``.
ignored ignored
Version strings that are explicitly ignored, separated by whitespace. This can Version strings that are explicitly ignored, separated by whitespace. This
be useful to avoid some known mis-named versions, so newer ones won't be can be useful to avoid some known mis-named versions, so newer ones won't be
"overridden" by the old broken ones. "overridden" by the old broken ones.
Search in a Webpage Search in a Webpage

View file

@ -6,6 +6,8 @@ from importlib import import_module
import structlog import structlog
from .sortversion import sort_version_keys
logger = structlog.get_logger(logger_name=__name__) logger = structlog.get_logger(logger_name=__name__)
handler_precedence = ( handler_precedence = (
@ -38,6 +40,26 @@ def substitute_version(version, name, conf):
# No substitution rules found. Just return the original version string. # No substitution rules found. Just return the original version string.
return version return version
def apply_list_options(versions, conf):
pattern = conf.get('include_regex')
if pattern:
pattern = re.compile(pattern)
versions = [x for x in versions
if pattern.fullmatch(x)]
ignored = set(conf.get('ignored', '').split())
if ignored:
versions = [x for x in versions if x not in ignored]
if not versions:
return
sort_version_key = sort_version_keys[
conf.get("sort_version_key", "parse_version")]
versions.sort(key=sort_version_key)
return versions[-1]
_cache = {} _cache = {}
async def get_version(name, conf, **kwargs): async def get_version(name, conf, **kwargs):
@ -60,6 +82,10 @@ async def get_version(name, conf, **kwargs):
return version return version
version = await func(name, conf, **kwargs) version = await func(name, conf, **kwargs)
if isinstance(version, list):
version = apply_list_options(version, conf)
if version: if version:
version = version.replace('\n', ' ') version = version.replace('\n', ' ')
try: try:
@ -69,4 +95,5 @@ async def get_version(name, conf, **kwargs):
if version is not None: if version is not None:
_cache[cache_key] = version _cache[cache_key] = version
return version return version

View file

@ -10,7 +10,6 @@ from functools import partial
import structlog import structlog
from . import session, HTTPError from . import session, HTTPError
from ..sortversion import sort_version_keys
logger = structlog.get_logger(logger_name=__name__) logger = structlog.get_logger(logger_name=__name__)
@ -32,7 +31,6 @@ async def get_version_real(name, conf, **kwargs):
use_max_tag = conf.getboolean('use_max_tag', False) use_max_tag = conf.getboolean('use_max_tag', False)
include_tags_pattern = conf.get("include_tags_pattern", "") include_tags_pattern = conf.get("include_tags_pattern", "")
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:
@ -64,7 +62,6 @@ async def get_version_real(name, conf, **kwargs):
return await max_tag(partial( return await max_tag(partial(
session.get, headers=headers, **kwargs), session.get, headers=headers, **kwargs),
url, name, ignored_tags, include_tags_pattern, url, name, ignored_tags, include_tags_pattern,
sort_version_key,
) )
async with session.get(url, headers=headers, **kwargs) as res: async with session.get(url, headers=headers, **kwargs) as res:
@ -87,8 +84,7 @@ async def get_version_real(name, conf, **kwargs):
return version return version
async def max_tag( async def max_tag(
getter, url, name, getter, url, name, ignored_tags, include_tags_pattern,
ignored_tags, include_tags_pattern, sort_version_key,
): ):
# paging is needed # paging is needed
@ -104,8 +100,7 @@ async def max_tag(
data = [x for x in data data = [x for x in data
if re.search(include_tags_pattern, x)] if re.search(include_tags_pattern, x)]
if data: if data:
data.sort(key=sort_version_key) return data
return data[-1]
else: else:
next_page_url = get_next_page_url(links) next_page_url = get_next_page_url(links)
if not next_page_url: if not next_page_url:

View file

@ -7,7 +7,6 @@ import urllib.parse
import structlog import structlog
from . import session, HTTPError from . import session, HTTPError
from ..sortversion import sort_version_keys
logger = structlog.get_logger(logger_name=__name__) logger = structlog.get_logger(logger_name=__name__)
@ -26,7 +25,6 @@ async def get_version_real(name, conf, **kwargs):
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")]
if use_max_tag: if use_max_tag:
url = GITLAB_MAX_TAG % (host, repo) url = GITLAB_MAX_TAG % (host, repo)
@ -52,9 +50,7 @@ async def get_version_real(name, conf, **kwargs):
async with session.get(url, headers=headers) as res: async with session.get(url, headers=headers) as res:
data = await res.json() data = await res.json()
if use_max_tag: if use_max_tag:
data = [tag["name"] for tag in data if tag["name"] not in ignored_tags] version = [tag["name"] for tag in data if tag["name"] not in ignored_tags]
data.sort(key=sort_version_key)
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('-', '')
return version return version

View file

@ -7,7 +7,6 @@ import sre_constants
import structlog import structlog
from . import session from . import session
from ..sortversion import sort_version_keys
logger = structlog.get_logger(logger_name=__name__) logger = structlog.get_logger(logger_name=__name__)
@ -26,12 +25,11 @@ async def get_version(name, conf, **kwargs):
kwargs["proxy"] = conf.get("proxy") kwargs["proxy"] = conf.get("proxy")
if conf.get('user_agent'): if conf.get('user_agent'):
headers['User-Agent'] = conf['user_agent'] headers['User-Agent'] = conf['user_agent']
sort_version_key = sort_version_keys[conf.get("sort_version_key", "parse_version")]
async with session.get(conf['url'], headers=headers, **kwargs) as res: async with session.get(conf['url'], headers=headers, **kwargs) as res:
body = (await res.read()).decode(encoding) body = (await res.read()).decode(encoding)
try: try:
version = max(regex.findall(body), key=sort_version_key) version = regex.findall(body)
except ValueError: except ValueError:
version = None version = None
if not conf.getboolean('missing_ok', False): if not conf.getboolean('missing_ok', False):

View file

@ -23,16 +23,27 @@ async def test_github_max_tag(get_version):
async def test_github_max_tag_with_ignored_tags(get_version): async def test_github_max_tag_with_ignored_tags(get_version):
assert await get_version("example", {"github": "harry-sanabria/ReleaseTestRepo", "use_max_tag": 1, "ignored_tags": "second_release release3"}) == "first_release" assert await get_version("example", {"github": "harry-sanabria/ReleaseTestRepo", "use_max_tag": 1, "ignored_tags": "second_release release3"}) == "first_release"
async def test_github_max_tag_with_ignored(get_version):
assert await get_version("example", {"github": "harry-sanabria/ReleaseTestRepo", "use_max_tag": 1, "ignored": "second_release release3"}) == "first_release"
async def test_github_with_path(get_version): async def test_github_with_path(get_version):
assert await get_version("example", {"github": "petronny/ReleaseTestRepo", "path": "test_directory"}) == "20140122.012101" assert await get_version("example", {"github": "petronny/ReleaseTestRepo", "path": "test_directory"}) == "20140122.012101"
async def test_github_with_path_and_branch(get_version): async def test_github_with_path_and_branch(get_version):
assert await get_version("example", {"github": "petronny/ReleaseTestRepo", "branch": "test", "path": "test_directory/test_directory"}) == "20190128.113201" assert await get_version("example", {"github": "petronny/ReleaseTestRepo", "branch": "test", "path": "test_directory/test_directory"}) == "20190128.113201"
async def test_github_max_tag_with_include(get_version): async def test_github_max_tag_with_include_old(get_version):
version = await get_version("example", { version = await get_version("example", {
"github": "EFForg/https-everywhere", "github": "EFForg/https-everywhere",
"use_max_tag": 1, "use_max_tag": 1,
"include_tags_pattern": r"^\d", "include_tags_pattern": r"^\d",
}) })
assert re.match(r'[\d.]+', version) assert re.match(r'[\d.]+', version)
async def test_github_max_tag_with_include(get_version):
version = await get_version("example", {
"github": "EFForg/https-everywhere",
"use_max_tag": 1,
"include_regex": r"^\d",
})
assert re.match(r'[\d.]+', version)

View file

@ -18,3 +18,16 @@ async def test_gitlab_max_tag(get_version):
async def test_gitlab_max_tag_with_ignored_tags(get_version): async def test_gitlab_max_tag_with_ignored_tags(get_version):
assert await get_version("example", {"gitlab": "gitlab-org/gitlab-test", "use_max_tag": 1, "ignored_tags": "v1.1.0"}) == "v1.0.0" assert await get_version("example", {"gitlab": "gitlab-org/gitlab-test", "use_max_tag": 1, "ignored_tags": "v1.1.0"}) == "v1.0.0"
async def test_gitlab_max_tag_with_include(get_version):
assert await get_version("example", {
"gitlab": "gitlab-org/gitlab-test", "use_max_tag": 1,
"include": r'v1\.0.*',
}) == "v1.0.0"
async def test_gitlab_max_tag_with_ignored(get_version):
assert await get_version("example", {
"gitlab": "gitlab-org/gitlab-test", "use_max_tag": 1,
"ignored": "v1.1.0",
}) == "v1.0.0"