feat: add jq source

This commit is contained in:
Rocka 2024-03-31 15:40:48 +08:00
parent 511922e6fb
commit 60cdb5a3c5
No known key found for this signature in database
GPG key ID: 28031158FFDD6853
4 changed files with 103 additions and 0 deletions

View file

@ -326,6 +326,31 @@ post_data_type
An additional dependency "lxml" is required.
You can use ``pip install 'nvchecker[htmlparser]'``.
Search with an JSON Parser (jq)
~~~~~~~~~~~~~~~~~~~~~~~~~~
::
source = "jq"
Send an HTTP request and search through the body with a specific ``jq`` filter.
url
The URL of the HTTP request.
filter
An ``jq`` filter used to find the version string.
post_data
(*Optional*) When present, a ``POST`` request (instead of a ``GET``) will be used. The value should be a string containing the full body of the request. The encoding of the string can be specified using the ``post_data_type`` option.
post_data_type
(*Optional*) Specifies the ``Content-Type`` of the request body (``post_data``). By default, this is ``application/json``.
This source supports :ref:`list options`.
.. note::
An additional dependency "jq.py" is required.
Find with a Command
~~~~~~~~~~~~~~~~~~~
::

43
nvchecker_source/jq.py Normal file
View file

@ -0,0 +1,43 @@
# MIT licensed
# Copyright (c) 2024 Rocket Aaron <i@rocka.me>, et al.
import json
import jq
from nvchecker.api import session, GetVersionError
async def get_version(name, conf, *, cache, **kwargs):
key = tuple(sorted(conf.items()))
return await cache.get(key, get_version_impl)
async def get_version_impl(info):
conf = dict(info)
try:
program = jq.compile(conf.get('filter', '.'))
except ValueError as e:
raise GetVersionError('bad jq filter', exc_info=e)
encoding = conf.get('encoding')
data = conf.get('post_data')
if data is None:
res = await session.get(conf['url'])
else:
res = await session.post(conf['url'], body = data, headers = {
'Content-Type': conf.get('post_data_type', 'application/json')
})
try:
obj = json.loads(res.body)
except json.decoder.JSONDecodeError as e:
raise GetVersionError('bad json string', exc_info=e)
try:
version = program.input(obj).all()
if version == [None] and not conf.get('missing_ok', False):
raise GetVersionError('version string not found.')
version = [str(v) for v in version]
except ValueError as e:
raise GetVersionError('failed to filter json', exc_info=e)
return version

View file

@ -63,6 +63,8 @@ pypi =
packaging
htmlparser =
lxml
jq =
jq
[options.entry_points]
console_scripts =

33
tests/test_jq.py Normal file
View file

@ -0,0 +1,33 @@
# MIT licensed
# Copyright (c) 2024 Rocket Aaron <i@rocka.me>, et al.
import pytest
jq_available = True
try:
import jq
except jq:
jq_available = False
pytestmark = [
pytest.mark.asyncio(scope="session"),
pytest.mark.needs_net,
pytest.mark.skipif(not jq_available, reason="needs jq"),
]
async def test_jq(get_version):
ver = await get_version("aur", {
"source": "jq",
"url": "https://aur.archlinux.org/rpc/v5/info?arg[]=nvchecker-git"
})
ver = ver.strip()
assert ver.startswith("{")
assert ver.endswith("}")
async def test_jq_filter(get_version):
ver = await get_version("aur", {
"source": "jq",
"url": "https://aur.archlinux.org/rpc/v5/info?arg[]=nvchecker-git",
"filter": '.results[0].PackageBase',
})
assert ver == "nvchecker-git"