Source code for smac.utils.dependencies

from typing import List, Union

import importlib
import re

import pkg_resources  # type: ignore
from packaging.version import Version

__copyright__ = "Copyright 2021, AutoML.org Freiburg-Hannover"
__license__ = "3-clause BSD"


SUBPATTERN = r"((?P<operation%d>==|>=|>|<)(?P<version%d>(\d+)?(\.[a-zA-Z0-9]+)?(\.\d+)?))"
RE_PATTERN = re.compile(r"^(?P<name>[\w\-]+)%s?(,%s)?$" % (SUBPATTERN % (1, 1), SUBPATTERN % (2, 2)))


[docs]def verify_packages(packages: Union[List[str], str]) -> None: """Verifies packages. Calls `_verify_packages` as subroutine. Parameters ---------- packages : Union[List[str], str] Packages to verify. Raises ------ ValueError If requirements can not be read. """ if not packages: return if isinstance(packages, str): packages = packages.splitlines() for package in packages: if not package: continue match = RE_PATTERN.match(package) if match: name = match.group("name") for group_id in range(1, 3): if "operation%d" % group_id in match.groupdict(): operation = match.group("operation%d" % group_id) version = match.group("version%d" % group_id) _verify_package(name, operation, version) else: raise ValueError("Unable to read requirement: %s" % package)
def _verify_package(name: str, operation: str, version: str) -> None: """Verifies a package. Parameters ---------- name : str Name of the package. operation : str Operation of the package. version : str Version of the package. Raises ------ MissingPackageError If package is missing. NotImplementedError If operation is not implemented. IncorrectPackageVersionError If package version is incorrect. """ try: distribution = pkg_resources.get_distribution(name) installed_version = Version(distribution.version) except pkg_resources.DistributionNotFound: try: module = importlib.import_module(name) installed_version = Version(module.__version__) # type: ignore[attr-defined] # noqa F821 except ImportError: raise MissingPackageError(name) if not operation: return # pkg_resources.get_distribution can (not) find a version depending on how the package was built # if we get version 0.0.0 we fallback to the module's version if installed_version == Version("0.0.0"): module = importlib.import_module(name) installed_version = Version(module.__version__) required_version = Version(version) if operation == "==": check = required_version == installed_version elif operation == ">": check = installed_version > required_version elif operation == "<": check = installed_version < required_version elif operation == ">=": check = installed_version > required_version or installed_version == required_version elif operation == "<=": check = installed_version < required_version or installed_version == required_version else: raise NotImplementedError("operation '%s' is not supported" % operation) if not check: raise IncorrectPackageVersionError(name, installed_version, operation, required_version)
[docs]class MissingPackageError(Exception): error_message = "Mandatory package '{name}' not found!" def __init__(self, package_name: str) -> None: self.package_name = package_name super(MissingPackageError, self).__init__(self.error_message.format(name=package_name))
[docs]class IncorrectPackageVersionError(Exception): error_message = "'{name} {installed_version}' version mismatch ({operation}{required_version})" def __init__( self, package_name: str, installed_version: Version, operation: str, required_version: Version, ) -> None: self.package_name = package_name self.installed_version = installed_version self.operation = operation self.required_version = required_version message = self.error_message.format( name=package_name, installed_version=installed_version, operation=operation, required_version=required_version, ) super(IncorrectPackageVersionError, self).__init__(message)