Introduction¶
Actions and dependencies¶
In ActionTree, you create a dependency graph of actions to be executed and then call the execute()
function on its root.
For example, let’s say you want to generate three files, and then concatenate them into a fourth file.
First, import ActionTree
>>> from ActionTree import Action, execute
Then create your specialized Action
classes:
>>> class CreateFile(Action):
... def __init__(self, name):
... super(CreateFile, self).__init__("create {}".format(name))
... self.__name = name
...
... def do_execute(self, dependency_statuses):
... with open(self.__name, "w") as f:
... f.write("This is {}\n".format(self.__name))
>>> class ConcatFiles(Action):
... def __init__(self, files, name):
... super(ConcatFiles, self).__init__("concat")
... self.__files = files
... self.__name = name
...
... def do_execute(self, dependency_statuses):
... with open(self.__name, "w") as output:
... for file in self.__files:
... with open(file) as input:
... output.write(input.read())
Create an actions dependency graph:
>>> concat = ConcatFiles(["first", "second", "third"], "fourth")
>>> concat.add_dependency(CreateFile("first"))
>>> concat.add_dependency(CreateFile("second"))
>>> concat.add_dependency(CreateFile("third"))
And execute()
it:
>>> execute(concat).is_success
True
The actions have been executed successfully:
>>> def cat(name):
... with open(name) as f:
... print(f.read(), end="")
>>> cat("first")
This is first
>>> cat("second")
This is second
>>> cat("third")
This is third
>>> cat("fourth")
This is first
This is second
This is third
You have no guaranty about the order of execution of the CreateFile
actions,
but you are sure that they are all finished before the ConcatFiles
action starts.
If your system has several CPUs, the CreateFile
actions have been executed concurrently.
Preview¶
If you just want to know what would be done, you can use Action.get_possible_execution_order()
:
>>> [a.label for a in concat.get_possible_execution_order()]
['create first', 'create second', 'create third', 'concat']
As said earlier, you have no guaranty about the order of the first three actions,
so get_possible_execution_order()
returns one possible order.
Stock actions¶
ActionTree ships with some stock
actions for common tasks,
including running subprocesses and basic operations on files and directories.
Say you want to compile two C++ files and link them:
>>> from ActionTree import execute
>>> from ActionTree.stock import CreateDirectory, CallSubprocess
>>> make_build_dir = CreateDirectory("_build")
>>> compile_a = CallSubprocess(["g++", "-c", "a.cpp", "-o", "_build/a.o"], label="g++ -c a.cpp")
>>> compile_a.add_dependency(make_build_dir)
>>> compile_b = CallSubprocess(["g++", "-c", "b.cpp", "-o", "_build/b.o"], label="g++ -c b.cpp")
>>> compile_b.add_dependency(make_build_dir)
>>> link = CallSubprocess(["g++", "-o", "_build/test", "_build/a.o", "_build/b.o"], label="g++ -o test")
>>> link.add_dependency(compile_a)
>>> link.add_dependency(compile_b)
>>> link_report = execute(link)