import logging import pip from pkg_resources import working_set, WorkingSet from collections import namedtuple LOG = logging.getLogger(__name__) MM_NODES_ENTRYPOINT = 'minemeld_nodes' MM_NODES_GCS_ENTRYPOINT = 'minemeld_nodes_gcs' MM_NODES_VALIDATORS_ENTRYPOINT = 'minemeld_nodes_validators' MM_PROTOTYPES_ENTRYPOINT = 'minemeld_prototypes' MM_API_ENTRYPOINT = 'minemeld_api' MM_WEBUI_ENTRYPOINT = 'minemeld_webui' MMEntryPoint = namedtuple( 'MMEntryPoint', ['ep', 'name', 'loadable', 'conflicts'] ) _ENTRYPOINT_GROUPS = {} _WS = None def _conflicts(requirements, installed): result = [] for r in requirements: installed_dist = installed.get(r.project_name, None) if installed_dist is None: result.append('{} not installed'.format(r.project_name)) continue if installed_dist.version not in r: result.append('{}=={} not compatible with {}'.format( installed_dist.project_name, installed_dist.version, str(r) )) return result def _initialize_entry_point_group(entrypoint_group): global _WS installed = {d.project_name: d for d in working_set} if _WS is None: _WS = WorkingSet() cache = {} result = {} for ep in _WS.iter_entry_points(entrypoint_group): egg_name = ep.dist.egg_name() conflicts = cache.get(egg_name, None) if conflicts is None: conflicts = _conflicts( ep.dist.requires(), installed ) cache[egg_name] = conflicts if len(conflicts) != 0: LOG.error('{} not loadable: {}'.format( ep.name, ', '.join(conflicts) )) result[ep.name] = MMEntryPoint( ep=ep, name=ep.name, conflicts=conflicts, loadable=(len(conflicts) == 0) ) _ENTRYPOINT_GROUPS[entrypoint_group] = result def bump_workingset(): global _WS, _ENTRYPOINT_GROUPS _WS = None _ENTRYPOINT_GROUPS = {} def list(entrypoint_group): if entrypoint_group not in _ENTRYPOINT_GROUPS: _initialize_entry_point_group(entrypoint_group) eg = _ENTRYPOINT_GROUPS[entrypoint_group] return eg.keys() def map(entrypoint_group): if entrypoint_group not in _ENTRYPOINT_GROUPS: _initialize_entry_point_group(entrypoint_group) eg = _ENTRYPOINT_GROUPS[entrypoint_group] return eg def load(entrypoint_group, entrypoint_name): LOG.info('Loading %s:%s', entrypoint_group, entrypoint_name) if entrypoint_group not in _ENTRYPOINT_GROUPS: _initialize_entry_point_group(entrypoint_group) eg = _ENTRYPOINT_GROUPS[entrypoint_group] mmep = eg.get(entrypoint_name, None) if mmep is None: raise RuntimeError('Unknown entry point: {}:{}'.format(entrypoint_group, entrypoint_name)) if not mmep.loadable: raise RuntimeError('Entry point {}:{} not loadable: {}'.format( entrypoint_group, entrypoint_name, ', '.join(mmep.conflicts) )) return mmep.ep.load()