class Executor(list): Dependence = namedtuple('Dependence', ['executable', 'path']) def run(self): "Исполнение последовательности команд" self.check_depends() # тут запуск последовательности команд @classmethod def depend_on(cls, executable, path=None): "Добавляет зависимость в список в атрибуте функции __depend_on__" def wrapper(f): dependence = cls.Dependence(executable, path) if hasattr(f, '__depend_on__'): f.__depend_on__.append(dependence) else: f.__depend_on__ = [dependence] return f return wrapper def check_depends(self): "Проверка наличия зависимостей для последовательности команд" def check(dependence): "Проверка зависимости" for x in chain(*(getattr(x.func, '__depend_on__', ()) for x in self)): check(x)
Вот так объявляются команды
@Executor.depend_on('hg.exe') def load_sources(revision): pass def build_executive(): pass @Executor.depend_on('hhc.exe') def build_help(): pass @Executor.depend_on('candle.exe', WIX_PATH) @Executor.depend_on('light.exe', WIX_PATH) def build_installer(): pass
А вот так они используются
executor = Executor() executor.append(build_executive) executor.append(build_help) executor.run()
Все хорошо, до тех пор пока не используем декорированную функцию
executor.append(partial(load_sources, options.revision))