vxSDK/vxsdk/core/pkg/backend/core.py

135 lines
4.4 KiB
Python

"""
Vhex package core abstract class
"""
import abc
from core.logger import log
__all__ = [
'VxRemoteBackendCore'
]
class VxRemoteBackendCore(abc.ABC):
r"""Represent a remote backend 'core' class.
This class is a simple abstract class that should be used by all internal
'backend' wich should expose some common methods and property:
================================== =========================================
Property Description
================================== =========================================
name (str) Backend name (for debug)
url (str) Backend URL (for internal use)
================================== =========================================
================================== =========================================
Method Description
================================== =========================================
find() find packages
clone() clone a package
================================== =========================================
"""
def __init__(self, url):
self._url = url
self._pkg_list = []
@property
@abc.abstractmethod
def name(self):
"""<property> hold pacakge name"""
@property
@abc.abstractmethod
def url(self):
"""<property> hold pacakge URL (or path for local package)"""
@property
@abc.abstractmethod
def package_list(self):
"""<property> return the pacakge list (cached)"""
@abc.abstractmethod
def package_fetch_versions(self, pkg):
"""<method> pacakge version fetch (cache)"""
@abc.abstractmethod
def package_clone(self, pkg, prefix=None):
"""<method> package primtive """
def package_find(self, name, version=None):
r"""Try to find package
This method will try to find a particular package with a specific
version if the `version` argument is provided. Otherwise, the version
argument can holds special version requirement if the package use a
versionning sementic (more information in <vxsdk/core/pkg/version.py>)
If name is empty, all package will be returned
@args
> names (str) - package name
> versions (str) - version pattern
Return:
> A list of dictionary with (at least):
[
{
'name' (str) : package name
'full_name' (str) : full named package (author+name)
'description' (str) : package description
'versions' (list) : [
List of :obj:VxVersion that match the `version` argument
]
},
...
]
"""
# check if we need to return the complet list
if not name:
ret = []
for pkg in self.package_list:
if not self.package_fetch_versions(pkg):
continue
pkg_cpy = pkg.copy()
pkg_cpy['version'] = None
ret.append(pkg_cpy)
return ret
# handle package name and version verification
# @note
# - return on the first matched package
for pkg in self.package_list:
# check package name
if pkg['name'] != name:
continue
# fetch version information
if not self.package_fetch_versions(pkg):
log.warn("[pkg] '{pkg['name']}' unable to fetch versions")
continue
# if the version is None, we just need to fetch available
# versions then return
if not version:
pkg_cpy = pkg.copy()
pkg_cpy['version'] = None
return [pkg_cpy]
# perform version checking and select the best fit
ver_found = None
for ver in pkg['versions']:
if not ver.validate(version):
continue
if not ver_found or ver.compare(ver_found.name) < 0:
ver_found = ver
if not ver_found:
return []
# isolate the best version
pkg_cpy = pkg.copy()
pkg_cpy['version'] = ver_found
return [pkg_cpy]
# not requested package found, return
return None