Files

157 lines
3.3 KiB
Python
Raw Permalink Normal View History

import os
class DependencyResolutionError(Exception):
pass
class DependencyItem:
def __init__(self):
self.__target = None
self.__dep_list = None
def name(self):
return None
def target(self):
return self.__target
def dependencies(self):
return None
def dependency_list(self):
return self.__dep_list
def publish(self):
return None
def reset_resolution(self):
self.__dep_list = None
def resolve(self, **kwargs):
if self.__dep_list is not None:
return self.__dep_list
ctx = None
dep_list = None
if 'ctx' in kwargs:
ctx = kwargs['ctx']
else:
ctx = {}
if 'dep_list' in kwargs:
dep_list = kwargs['dep_list']
else:
dep_list = []
if self.name() in ctx:
return
ctx[self.name()] = self
deps = self.dependencies()
if deps is None:
return
for d in deps.values():
d_value = d.resolve_self()
if d_value is not None:
d_value.resolve(ctx=ctx, dep_list=dep_list)
dep_list.append(self)
return dep_list
class Dependency:
def __init__(self, parent):
self.__parent = parent
def name(self, parent):
return None
def parent_name(self):
return self.__parent
def resolve_self(self):
return None
def is_resolved(self):
return False
class SeedDependency(Dependency):
def __init__(self, **kwargs):
self.__target_seed = None
if 'name' in kwargs:
self.__name = kwargs['name']
if 'parent' in kwargs:
super().__init__(kwargs['parent'])
def name(self):
return self.__name
def target(self):
return self.__target_seed
def resolve_self(self):
from seed import Seed
if self.__target_seed is not None:
return self.__target_seed
target = Seed.get(self.__name)
if target is None:
raise DependencyResolutionError(
'{} depends on seed "{}", but the required seed cannot be found'.format(self.parent_name(), self.__name))
self.__target_seed = target
return self.__target_seed
def is_resolved(self):
return self.__target_seed is not None
class ProgramDependency(Dependency):
def __init__(self, **kwargs):
if 'name' in kwargs:
self.__name = kwargs['name']
if 'parent' in kwargs:
super().__init__(kwargs['parent'])
def __is_exe(self, fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
def name(self):
return self.__name
def resolve_self(self):
if self.__is_exe(self.__name):
return None
path_string = os.environ['PATH']
path_list = path_string.split(':')
for d in path_list:
exe_path = os.path.join(d, self.__name)
if self.__is_exe(exe_path):
return None
raise DependencyResolutionError(f'{self.parent_name()} depends on command `{self.__name}`, but the command cannot be found. Make sure that the named command exists, the containing directory is in $PATH if necessary, and the executable file has the correct permissions.')