build a graph of method dependencies

to allow individual subclasses of BaseDoctype to be able to implement as many
methods as they want to create document outputs, the BaseDoctype now
implements a graph of method dependencies.  The sequence of tasks is
determined by applying the @depends decorator to the methods in the
heavy-lifting classes which actually implement the document procsesing.

For example, the Linuxdoc class will probably have about 6 or 7 methods to
generate the outputs, whereas, the more complex DocbookSGML class will have at
least two or three more to handle the build-time index-generation (if
necessary for the document).
This commit is contained in:
Martin A. Brown 2016-02-26 00:30:37 -08:00
parent 2d052e443e
commit 85b2b15c3b
1 changed files with 37 additions and 4 deletions

View File

@ -5,13 +5,34 @@ from __future__ import absolute_import, division, print_function
import os
import stat
from tempfile import NamedTemporaryFile as ntf
import logging
logger = logging.getLogger(__name__)
from tempfile import NamedTemporaryFile as ntf
from functools import wraps
import networkx as nx
from tldp.utils import execute
logger = logging.getLogger(__name__)
preamble = '''#! /bin/bash
set -x
set -e
set -o pipefail
'''
def depends(graph, *predecessors):
'''decorator to be used for constructing build order graph'''
def anon(f):
for dep in predecessors:
graph.add_edge(dep.__name__, f.__name__)
@wraps(f)
def method(self, *args, **kwargs):
return f(self, *args, **kwargs)
return method
return anon
class SignatureChecker(object):
@ -51,7 +72,7 @@ class BaseDoctype(object):
assert validator(thing)
return True
def shellscript(self, script):
def shellscript(self, script, preamble=preamble):
source = self.source
output = self.output
config = self.config
@ -61,6 +82,8 @@ class BaseDoctype(object):
s = script.format(output=output, source=source, config=config)
tf = ntf(dir=logdir, prefix=prefix, suffix='.sh', delete=False)
if preamble:
tf.write(preamble)
tf.write(s)
tf.close()
@ -73,6 +96,16 @@ class BaseDoctype(object):
return False
return True
def buildall(self):
order = nx.dag.topological_sort(self.graph)
logger.debug("%s build order %r", self.source.stem, order)
for dep in order:
method = getattr(self, dep, None)
assert method is not None
if not method():
return False
return True
def generate(self):
# -- the output directory gets to prepare; must return True
#