PageRenderTime 36ms CodeModel.GetById 23ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/lib/galaxy/tools/deps/__init__.py

https://bitbucket.org/cistrome/cistrome-harvard/
Python | 133 lines | 109 code | 14 blank | 10 comment | 1 complexity | fda4669f84a6ce67427db1f79ac5c835 MD5 | raw file
  1"""
  2Dependency management for tools.
  3"""
  4
  5import os.path
  6
  7import logging
  8log = logging.getLogger( __name__ )
  9
 10from xml.etree import ElementTree
 11
 12from .resolvers import INDETERMINATE_DEPENDENCY
 13from .resolvers.galaxy_packages import GalaxyPackageDependencyResolver
 14from .resolvers.tool_shed_packages import ToolShedPackageDependencyResolver
 15from galaxy.util.submodules import submodules
 16
 17
 18def build_dependency_manager( config ):
 19    if config.use_tool_dependencies:
 20        dependency_manager_kwds = {
 21            'default_base_path': config.tool_dependency_dir,
 22            'conf_file': config.dependency_resolvers_config_file,
 23        }
 24        dependency_manager = DependencyManager( **dependency_manager_kwds )
 25    else:
 26        dependency_manager = NullDependencyManager()
 27
 28    return dependency_manager
 29
 30
 31class NullDependencyManager( object ):
 32
 33    def uses_tool_shed_dependencies(self):
 34        return False
 35
 36    def dependency_shell_commands( self, requirements, **kwds ):
 37        return []
 38
 39    def find_dep( self, name, version=None, type='package', **kwds ):
 40        return INDETERMINATE_DEPENDENCY
 41
 42
 43class DependencyManager( object ):
 44    """
 45    A DependencyManager attempts to resolve named and versioned dependencies by
 46    searching for them under a list of directories. Directories should be
 47    of the form:
 48
 49        $BASE/name/version/...
 50
 51    and should each contain a file 'env.sh' which can be sourced to make the
 52    dependency available in the current shell environment.
 53    """
 54    def __init__( self, default_base_path, conf_file=None ):
 55        """
 56        Create a new dependency manager looking for packages under the paths listed
 57        in `base_paths`.  The default base path is app.config.tool_dependency_dir.
 58        """
 59        if not os.path.exists( default_base_path ):
 60            log.warn( "Path '%s' does not exist, ignoring", default_base_path )
 61        if not os.path.isdir( default_base_path ):
 62            log.warn( "Path '%s' is not directory, ignoring", default_base_path )
 63        self.default_base_path = os.path.abspath( default_base_path )
 64        self.resolver_classes = self.__resolvers_dict()
 65        self.dependency_resolvers = self.__build_dependency_resolvers( conf_file )
 66
 67    def dependency_shell_commands( self, requirements, **kwds ):
 68        commands = []
 69        for requirement in requirements:
 70            log.debug( "Building dependency shell command for dependency '%s'", requirement.name )
 71            dependency = INDETERMINATE_DEPENDENCY
 72            if requirement.type in [ 'package', 'set_environment' ]:
 73                dependency = self.find_dep( name=requirement.name,
 74                                            version=requirement.version,
 75                                            type=requirement.type,
 76                                            **kwds )
 77            dependency_commands = dependency.shell_commands( requirement )
 78            if not dependency_commands:
 79                log.warn( "Failed to resolve dependency on '%s', ignoring", requirement.name )
 80            else:
 81                commands.append( dependency_commands )
 82        return commands
 83
 84    def uses_tool_shed_dependencies(self):
 85        return any( map( lambda r: isinstance( r, ToolShedPackageDependencyResolver ), self.dependency_resolvers ) )
 86
 87    def find_dep( self, name, version=None, type='package', **kwds ):
 88        for resolver in self.dependency_resolvers:
 89            dependency = resolver.resolve( name, version, type, **kwds )
 90            if dependency != INDETERMINATE_DEPENDENCY:
 91                return dependency
 92        return INDETERMINATE_DEPENDENCY
 93
 94    def __build_dependency_resolvers( self, conf_file ):
 95        if not conf_file or not os.path.exists( conf_file ):
 96            return self.__default_dependency_resolvers()
 97        root = ElementTree.parse( conf_file ).getroot()
 98        return self.__parse_resolver_conf_xml( root )
 99
100    def __default_dependency_resolvers( self ):
101        return [
102            ToolShedPackageDependencyResolver(self),
103            GalaxyPackageDependencyResolver(self),
104            GalaxyPackageDependencyResolver(self, versionless=True),
105        ]
106
107    def __parse_resolver_conf_xml(self, root):
108        """
109
110        :param root: Object representing the root ``<dependency_resolvers>`` object in the file.
111        :type root: ``xml.etree.ElementTree.Element``
112        """
113        resolvers = []
114        resolvers_element = root
115        for resolver_element in resolvers_element.getchildren():
116            resolver_type = resolver_element.tag
117            resolver_kwds = dict(resolver_element.items())
118            resolver = self.resolver_classes[resolver_type](self, **resolver_kwds)
119            resolvers.append(resolver)
120        return resolvers
121
122    def __resolvers_dict( self ):
123        resolver_dict = {}
124        for resolver_module in self.__resolver_modules():
125            for clazz in resolver_module.__all__:
126                resolver_type = getattr(clazz, 'resolver_type', None)
127                if resolver_type:
128                    resolver_dict[resolver_type] = clazz
129        return resolver_dict
130
131    def __resolver_modules( self ):
132        import galaxy.tools.deps.resolvers
133        return submodules( galaxy.tools.deps.resolvers )