Skip to content

Commit

Permalink
Doc
Browse files Browse the repository at this point in the history
  • Loading branch information
jacquev6 committed Jun 18, 2017
1 parent e8f49fc commit 8acb128
Show file tree
Hide file tree
Showing 22 changed files with 68 additions and 109 deletions.
35 changes: 14 additions & 21 deletions ActionTree/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
stderr = ctypes.c_void_p.in_dll(libc, "__stderrp")


# @todo Evaluate https://pypi.python.org/pypi/PyContracts


def execute(action, cpu_cores=None, keep_going=False, do_raise=True, hooks=None):
"""
Recursively execute an :class:`.Action`'s dependencies then the action.
Expand Down Expand Up @@ -82,21 +79,17 @@ class Action(object):

def __init__(self, label, dependencies=[], resources_required={}, accept_failed_dependencies=False):
"""
:param label:
@todo Insist on label being a str or None.
Add a note saying how it's used in GanttChart and DependencyGraph.
whatever you want to attach to the action.
``str(label)`` must succeed and return a string.
Can be retrieved by :attr:`label`.
:param label: A string used to represent the action in :class:`GanttChart` and
:class:`DependencyGraph`. Can be retrieved by :attr:`label`.
:type label: string or None
:param list(Action) dependencies:
see :meth:`~.Action.add_dependency`
:param resources_required:
see :meth:`~.Action.require_resource`
:type resources_required: dict(Resource, int)
:param bool accept_failed_dependencies:
it ``True``, then the action will execute even if some of its dependencies failed.
if ``True``, then the action will execute even after some of its dependencies failed.
"""
str(label)
self.__label = label
self.__dependencies = list(dependencies)
self.__resources_required = {CPU_CORE: 1}
Expand Down Expand Up @@ -293,7 +286,7 @@ def __init__(self):
super(DependencyCycleException, self).__init__("Dependency cycle")


class CompoundException(Exception): # Not doctested: @todo
class CompoundException(Exception): # Not doctested: @todoc
"""
Exception thrown by :func:`.execute` when dependencies raise exceptions.
"""
Expand Down Expand Up @@ -388,7 +381,7 @@ def pending_time(self):
:rtype: datetime.datetime
"""
return self.__pending_time # Not doctested: @todo
return self.__pending_time # Not doctested: @todoc

@property
def ready_time(self):
Expand Down Expand Up @@ -436,7 +429,7 @@ def return_value(self):
The value returned by this action
(``None`` if it failed or was never started).
"""
return self.__return_value # Not doctested: @todo
return self.__return_value # Not doctested: @todoc

@property
def failure_time(self):
Expand All @@ -454,7 +447,7 @@ def exception(self):
The exception raised by this action
(``None`` if it succeeded or was never started).
"""
return self.__exception # Not doctested: @todo
return self.__exception # Not doctested: @todoc

@property
def output(self):
Expand All @@ -464,7 +457,7 @@ def output(self):
:rtype: str or None
"""
return self.__output # Not doctested: @todo
return self.__output # Not doctested: @todoc

def __init__(self, root_action, actions, now):
self._root_action = root_action
Expand Down Expand Up @@ -529,7 +522,7 @@ def __init__(self, action):
if action.label is None: # Not doctested: implementation detail
self.__graphviz_graph.node(node, shape="point")
else:
self.__graphviz_graph.node(node, str(action.label))
self.__graphviz_graph.node(node, action.label)
for dependency in action.dependencies:
assert dependency in nodes # Because we are iterating a possible execution order
self.__graphviz_graph.edge(node, nodes[dependency])
Expand Down Expand Up @@ -623,7 +616,7 @@ def draw(self, ax, ordinates, actions):
# @todo Make sure the text is not outside the plot on the right
if self.__label is not None:
ax.annotate(
str(self.__label),
self.__label,
xy=(self.__start_time, ordinate), xytext=(0, 3), textcoords="offset points",
)
for d in self.__dependencies:
Expand Down Expand Up @@ -655,7 +648,7 @@ def draw(self, ax, ordinates, actions):
)
if self.__label is not None:
ax.annotate(
str(self.__label),
self.__label,
xy=(self.__start_time, ordinate), xytext=(0, 3), textcoords="offset points",
)
for d in self.__dependencies:
Expand Down Expand Up @@ -683,7 +676,7 @@ def draw(self, ax, ordinates, actions):
ax.plot([self.__ready_time, self.__cancel_time], [ordinate, ordinate], color="grey", lw=1)
if self.__label is not None:
ax.annotate(
str(self.__label),
self.__label,
xy=(self.__cancel_time, ordinate), xytext=(0, 3), textcoords="offset points",
color="grey",
)
Expand Down Expand Up @@ -826,7 +819,7 @@ def run(self, root_action):
for w in multiprocessing.active_children():
w.join()

if self.do_raise and self.exceptions: # Not doctested: @todo
if self.do_raise and self.exceptions: # Not doctested: @todoc
raise CompoundException(self.exceptions, self.report)
else:
return self.report
Expand Down
14 changes: 0 additions & 14 deletions ActionTree/tests/dependency_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,6 @@ def test_diamond(self):
]
)

def test_typed_label(self):
a = Action(("a", "curious", "label", 42))

self.assertEqual(
DependencyGraph(a).get_graphviz_graph().source,
textwrap.dedent(
"""\
digraph action {
\tnode [shape=box]
\t0 [label="('a', 'curious', 'label', 42)"]
}"""
)
)

def test_weird_string_label(self):
a = Action("spaces and; semi=columns")

Expand Down
13 changes: 8 additions & 5 deletions ActionTree/tests/picklability.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@

import pickle
import unittest
import sys
import tempfile

from ActionTree import *
from . import *


class Unpicklable(object):
Expand All @@ -21,6 +18,12 @@ def __reduce__(self):
unpicklable = Unpicklable()


class UnpicklableAction(Action):
def __init__(self, *args, **kwds):
super(UnpicklableAction, self).__init__(*args, **kwds)
self.attribute = unpicklable


class UnpicklableReturnValue(Action):
def do_execute(self, dependency_statuses):
return unpicklable
Expand All @@ -31,10 +34,10 @@ def do_execute(self, dependency_statuses):
raise Exception(unpicklable)


class PicklabilityTestCase(ActionTreeTestCase):
class PicklabilityTestCase(unittest.TestCase):
def test_action(self):
with self.assertRaises(pickle.PicklingError):
execute(self._action(unpicklable))
execute(UnpicklableAction("x"))

def test_return_value(self):
with self.assertRaises(pickle.PicklingError):
Expand Down
10 changes: 0 additions & 10 deletions ActionTree/tests/possible_execution_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,6 @@


class PreviewTestCase(unittest.TestCase):
def test_dependencies_and_labels_are_not_only_equal_but_same(self):
bLabel = ("b",)
a = Action("a")
b = Action(bLabel)
a.add_dependency(b)

(otherB,) = a.dependencies
self.assertIs(otherB, b)
self.assertIs(otherB.label, bLabel)

def test_simple_preview(self):
a = Action("a")
self.assertEqual(a.get_possible_execution_order(), [a])
Expand Down
6 changes: 3 additions & 3 deletions ActionTree/tests/timing.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def test_leaves_have_same_ready_time(self):
def test_many_dependencies_with_unlimited_cpu_cores(self):
MANY = 20
a = self._action("a")
deps = [self._action(i) for i in range(MANY)]
deps = [self._action(str(i)) for i in range(MANY)]
for dep in deps:
a.add_dependency(dep)

Expand All @@ -96,7 +96,7 @@ def test_many_dependencies_with_unlimited_cpu_cores(self):
def test_many_dependencies_with_one_cpu_cores(self):
MANY = 20
a = self._action("a")
deps = [self._action(i) for i in range(MANY)]
deps = [self._action(str(i)) for i in range(MANY)]
for dep in deps:
a.add_dependency(dep)

Expand All @@ -109,7 +109,7 @@ def test_many_dependencies_with_one_cpu_cores(self):
def test_many_dependencies_with_limited_cpu_cores(self):
MANY = 20
a = self._action("a")
deps = [self._action(i) for i in range(MANY)]
deps = [self._action(str(i)) for i in range(MANY)]
for dep in deps:
a.add_dependency(dep)

Expand Down
4 changes: 2 additions & 2 deletions doc/user_guide/drawings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ Actions are linked to their dependencies using thin doted lines.

Actions that failed are in red, and actions that were canceled due to a failure in their dependencies are in grey:

>>> compile_unexisting = CallSubprocess(["g++", "-c", "unexisting.cpp", "-o", "_build/unexisting.o"])
>>> compile_unexisting = CallSubprocess(["g++", "-c", "unexisting.cpp", "-o", "_build/unexisting.o"], label="g++ -c unexisting.cpp")
>>> compile_unexisting.add_dependency(make_build_dir)
>>> link.add_dependency(compile_unexisting)

>>> failed_link_report = execute(link, keep_going=True, do_raise=False)
>>> failed_link_report = execute(link, cpu_cores=1, keep_going=True, do_raise=False)
>>> failed_link_report.is_success
False
>>> chart = GanttChart(failed_link_report)
Expand Down
6 changes: 3 additions & 3 deletions doc/user_guide/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,13 @@ Say you want to compile :ref:`two C++ files <source_files>` and link them:

>>> make_build_dir = CreateDirectory("_build")

>>> compile_a = CallSubprocess(["g++", "-c", "a.cpp", "-o", "_build/a.o"])
>>> 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"])
>>> 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"])
>>> 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)

Expand Down
20 changes: 8 additions & 12 deletions doc/user_guide/resources.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
Resources
=========

.. @todo Add labels to stock Actions (in ActionTree.stock, AND in the doc)
.. testsetup::

import shutil
Expand All @@ -29,11 +27,11 @@ You can tell *ActionTree* that your :class:`.Action` uses more cores with :meth:

>>> from ActionTree import CPU_CORE

>>> compile_others = CallSubprocess(["make", "-j", "4", "_build/c.o", "_build/d.o", "_build/e.o", "_build/f.o", "_build/g.o", "_build/h.o"])
>>> compile_others = CallSubprocess(["make", "-j", "4", "_build/c.o", "_build/d.o", "_build/e.o", "_build/f.o", "_build/g.o", "_build/h.o"], label="make -j 4")
>>> compile_others.add_dependency(make_build_dir)
>>> compile_others.require_resource(CPU_CORE, 4)

>>> link_with_others = CallSubprocess(["g++", "-o", "_build/test", "_build/a.o", "_build/b.o", "_build/c.o", "_build/d.o", "_build/e.o", "_build/f.o", "_build/g.o", "_build/h.o"])
>>> link_with_others = CallSubprocess(["g++", "-o", "_build/test", "_build/a.o", "_build/b.o", "_build/c.o", "_build/d.o", "_build/e.o", "_build/f.o", "_build/g.o", "_build/h.o"], label="g++ -o test")
>>> link_with_others.add_dependency(compile_a)
>>> link_with_others.add_dependency(compile_b)
>>> link_with_others.add_dependency(compile_others)
Expand All @@ -60,22 +58,20 @@ while allowing other actions to run, just create a resource:
>>> semaphore = Resource(2)
>>> dependencies = []
>>> for i in range(6):
... d = Sleep(0.3)
... d = Sleep(0.3, label="limited")
... d.require_resource(semaphore)
... dependencies.append(d)
>>> for i in range(5):
... d = Sleep(0.4)
... d = Sleep(0.4, label="free")
... dependencies.append(d)
>>> arbitrary_resource = NullAction()
>>> for d in dependencies:
... arbitrary_resource.add_dependency(d)
>>> with_resource = NullAction(dependencies=dependencies)

>>> GanttChart(execute(arbitrary_resource, cpu_cores=5)).write_to_png("arbitrary_resource_gantt_chart.png")
>>> GanttChart(execute(with_resource, cpu_cores=5)).write_to_png("with_resource_gantt_chart.png")

.. figure:: artifacts/arbitrary_resource_gantt_chart.png
.. figure:: artifacts/with_resource_gantt_chart.png
:align: center

``arbitrary_resource_gantt_chart.png``
``with_resource_gantt_chart.png``

As expected again, there was never more than two ``sleep 0.3`` actions running at the same time,
but ``sleep 0.4`` actions were free to execute.
Expand Down
Binary file removed docs/_images/arbitrary_resource_gantt_chart.png
Binary file not shown.
Binary file modified docs/_images/failed_link_gantt_chart.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_images/link_dependency_graph.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_images/link_gantt_chart.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_images/link_with_others_gantt_chart.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/_images/with_resource_gantt_chart.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/_sources/user_guide/drawings.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ Actions are linked to their dependencies using thin doted lines.

Actions that failed are in red, and actions that were canceled due to a failure in their dependencies are in grey:

>>> compile_unexisting = CallSubprocess(["g++", "-c", "unexisting.cpp", "-o", "_build/unexisting.o"])
>>> compile_unexisting = CallSubprocess(["g++", "-c", "unexisting.cpp", "-o", "_build/unexisting.o"], label="g++ -c unexisting.cpp")
>>> compile_unexisting.add_dependency(make_build_dir)
>>> link.add_dependency(compile_unexisting)

>>> failed_link_report = execute(link, keep_going=True, do_raise=False)
>>> failed_link_report = execute(link, cpu_cores=1, keep_going=True, do_raise=False)
>>> failed_link_report.is_success
False
>>> chart = GanttChart(failed_link_report)
Expand Down
6 changes: 3 additions & 3 deletions docs/_sources/user_guide/introduction.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,13 @@ Say you want to compile :ref:`two C++ files <source_files>` and link them:

>>> make_build_dir = CreateDirectory("_build")

>>> compile_a = CallSubprocess(["g++", "-c", "a.cpp", "-o", "_build/a.o"])
>>> 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"])
>>> 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"])
>>> 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)

Expand Down
20 changes: 8 additions & 12 deletions docs/_sources/user_guide/resources.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
Resources
=========

.. @todo Add labels to stock Actions (in ActionTree.stock, AND in the doc)
.. testsetup::

import shutil
Expand All @@ -29,11 +27,11 @@ You can tell *ActionTree* that your :class:`.Action` uses more cores with :meth:

>>> from ActionTree import CPU_CORE

>>> compile_others = CallSubprocess(["make", "-j", "4", "_build/c.o", "_build/d.o", "_build/e.o", "_build/f.o", "_build/g.o", "_build/h.o"])
>>> compile_others = CallSubprocess(["make", "-j", "4", "_build/c.o", "_build/d.o", "_build/e.o", "_build/f.o", "_build/g.o", "_build/h.o"], label="make -j 4")
>>> compile_others.add_dependency(make_build_dir)
>>> compile_others.require_resource(CPU_CORE, 4)

>>> link_with_others = CallSubprocess(["g++", "-o", "_build/test", "_build/a.o", "_build/b.o", "_build/c.o", "_build/d.o", "_build/e.o", "_build/f.o", "_build/g.o", "_build/h.o"])
>>> link_with_others = CallSubprocess(["g++", "-o", "_build/test", "_build/a.o", "_build/b.o", "_build/c.o", "_build/d.o", "_build/e.o", "_build/f.o", "_build/g.o", "_build/h.o"], label="g++ -o test")
>>> link_with_others.add_dependency(compile_a)
>>> link_with_others.add_dependency(compile_b)
>>> link_with_others.add_dependency(compile_others)
Expand All @@ -60,22 +58,20 @@ while allowing other actions to run, just create a resource:
>>> semaphore = Resource(2)
>>> dependencies = []
>>> for i in range(6):
... d = Sleep(0.3)
... d = Sleep(0.3, label="limited")
... d.require_resource(semaphore)
... dependencies.append(d)
>>> for i in range(5):
... d = Sleep(0.4)
... d = Sleep(0.4, label="free")
... dependencies.append(d)
>>> arbitrary_resource = NullAction()
>>> for d in dependencies:
... arbitrary_resource.add_dependency(d)
>>> with_resource = NullAction(dependencies=dependencies)

>>> GanttChart(execute(arbitrary_resource, cpu_cores=5)).write_to_png("arbitrary_resource_gantt_chart.png")
>>> GanttChart(execute(with_resource, cpu_cores=5)).write_to_png("with_resource_gantt_chart.png")

.. figure:: artifacts/arbitrary_resource_gantt_chart.png
.. figure:: artifacts/with_resource_gantt_chart.png
:align: center

``arbitrary_resource_gantt_chart.png``
``with_resource_gantt_chart.png``

As expected again, there was never more than two ``sleep 0.3`` actions running at the same time,
but ``sleep 0.4`` actions were free to execute.
Expand Down

0 comments on commit 8acb128

Please sign in to comment.