nvchecker/nvchecker_source/aur.py

106 lines
2.8 KiB
Python
Raw Normal View History

2020-08-11 09:43:03 +00:00
# MIT licensed
# Copyright (c) 2013-2020 lilydjwg <lilydjwg@gmail.com>, et al.
from datetime import datetime
import asyncio
from typing import Iterable, Dict, List, Tuple, Any, Optional
2020-08-11 09:43:03 +00:00
2020-08-14 12:04:05 +00:00
from nvchecker.api import (
session, GetVersionError, VersionResult,
Entry, BaseWorker, RawResult,
)
2020-08-11 09:43:03 +00:00
AUR_URL = 'https://aur.archlinux.org/rpc/'
2020-08-13 10:42:55 +00:00
class AurResults:
cache: Dict[str, Optional[Dict[str, Any]]]
2020-08-13 10:42:55 +00:00
def __init__(self) -> None:
self.cache = {}
async def get_multiple(
self,
aurnames: Iterable[str],
) -> Dict[str, Optional[Dict[str, Any]]]:
2020-08-13 10:42:55 +00:00
params = [('v', '5'), ('type', 'info')]
params.extend(('arg[]', name) for name in aurnames
if name not in self.cache)
2020-08-15 08:58:13 +00:00
res = await session.get(AUR_URL, params=params)
data = res.json()
2020-08-13 10:42:55 +00:00
new_results = {r['Name']: r for r in data['results']}
cache = self.cache
cache.update(new_results)
cache.update(
(name, None)
for name in set(aurnames) - new_results.keys()
)
return {name: cache[name] for name in aurnames
if name in cache}
2020-08-11 09:43:03 +00:00
class Worker(BaseWorker):
# https://wiki.archlinux.org/index.php/Aurweb_RPC_interface#Limitations
batch_size = 100
async def run(self) -> None:
tasks = self.tasks
n_batch, left = divmod(len(tasks), self.batch_size)
if left > 0:
n_batch += 1
2020-08-13 10:42:55 +00:00
aur_results = AurResults()
2020-08-11 09:43:03 +00:00
ret = []
for i in range(n_batch):
s = i * self.batch_size
batch = tasks[s : s+self.batch_size]
2020-08-13 10:42:55 +00:00
fu = self._run_batch(batch, aur_results)
2020-08-11 09:43:03 +00:00
ret.append(fu)
2021-06-06 04:26:53 +00:00
await asyncio.gather(*ret)
2020-08-11 09:43:03 +00:00
2020-08-13 10:42:55 +00:00
async def _run_batch(
self,
batch: List[Tuple[str, Entry]],
aur_results: AurResults,
) -> None:
2020-08-11 09:43:03 +00:00
task_by_name: Dict[str, Entry] = dict(self.tasks)
2020-08-13 10:42:55 +00:00
async with self.task_sem:
2020-08-13 10:42:55 +00:00
results = await _run_batch_impl(batch, aur_results)
2020-08-11 09:43:03 +00:00
for name, version in results.items():
r = RawResult(name, version, task_by_name[name])
await self.result_q.put(r)
2020-08-13 10:42:55 +00:00
async def _run_batch_impl(
batch: List[Tuple[str, Entry]],
aur_results: AurResults,
2020-08-14 12:04:05 +00:00
) -> Dict[str, VersionResult]:
2020-08-11 09:43:03 +00:00
aurnames = {conf.get('aur', name) for name, conf in batch}
2020-08-13 10:42:55 +00:00
results = await aur_results.get_multiple(aurnames)
2020-08-11 09:43:03 +00:00
2020-08-14 12:04:05 +00:00
ret: Dict[str, VersionResult] = {}
2020-08-11 09:43:03 +00:00
for name, conf in batch:
aurname = conf.get('aur', name)
use_last_modified = conf.get('use_last_modified', False)
2020-08-14 12:04:05 +00:00
strip_release = conf.get('strip_release', False)
2020-08-11 09:43:03 +00:00
result = results.get(aurname)
if result is None:
2020-08-14 12:04:05 +00:00
ret[name] = GetVersionError('AUR upstream not found')
2020-08-11 09:43:03 +00:00
continue
version = result['Version']
if use_last_modified:
version += '-' + datetime.utcfromtimestamp(result['LastModified']).strftime('%Y%m%d%H%M%S')
if strip_release and '-' in version:
version = version.rsplit('-', 1)[0]
ret[name] = version
return ret