Mercurial > piecrust2
diff piecrust/processing/records.py @ 120:133845647083
Better error management and removal support in baking/processing.
* Baker and processor pipeline now store errors in their records.
* They also support deleting output files that are no longer valid.
* The basic transitional record class implements more boilerplate code.
* The processor pipeline is run from the `bake` command directly.
* New unit tests.
* Unit test mocking now mocks `os.remove` too.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 09 Nov 2014 14:46:23 -0800 |
parents | |
children | 9e4c2e68a129 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piecrust/processing/records.py Sun Nov 09 14:46:23 2014 -0800 @@ -0,0 +1,86 @@ +import os.path +from piecrust.records import Record, TransitionalRecord + + +class ProcessorPipelineRecord(Record): + RECORD_VERSION = 2 + + def __init__(self): + super(ProcessorPipelineRecord, self).__init__() + self.out_dir = None + self.process_time = None + + def hasOverrideEntry(self, rel_path): + return self.findEntry(rel_path) is not None + + def findEntry(self, rel_path): + rel_path = rel_path.lower() + for entry in self.entries: + for out_path in entry.rel_outputs: + if out_path.lower() == rel_path: + return entry + return None + + +FLAG_NONE = 0 +FLAG_PROCESSED = 2**0 +FLAG_OVERRIDEN = 2**1 + + +class ProcessorPipelineRecordEntry(object): + def __init__(self, base_dir, rel_input): + self.base_dir = base_dir + self.rel_input = rel_input + + self.flags = FLAG_NONE + self.rel_outputs = [] + self.errors = [] + + @property + def path(self): + return os.path.join(self.base_dir, self.rel_input) + + @property + def was_processed(self): + return bool(self.flags & FLAG_PROCESSED) + + @property + def was_processed_successfully(self): + return self.was_processed and not self.errors + + +class TransitionalProcessorPipelineRecord(TransitionalRecord): + def __init__(self, previous_path=None): + super(TransitionalProcessorPipelineRecord, self).__init__( + ProcessorPipelineRecord, previous_path) + + def getTransitionKey(self, entry): + return entry.rel_input + + def getPreviousEntry(self, rel_path): + pair = self.transitions.get(rel_path) + if pair is not None: + return pair[0] + return None + + def collapseRecords(self): + for prev, cur in self.transitions.values(): + if prev and cur and not cur.was_processed: + # This asset wasn't processed, so the information from + # last time is still valid. + cur.flags = prev.flags + cur.rel_outputs = list(prev.rel_outputs) + cur.errors = list(prev.errors) + + def getDeletions(self): + for prev, cur in self.transitions.values(): + if prev and not cur: + for p in prev.rel_outputs: + abs_p = os.path.join(self.previous.out_dir, p) + yield (abs_p, 'previous asset was removed') + elif prev and cur and cur.was_processed_successfully: + diff = set(prev.rel_outputs) - set(cur.rel_outputs) + for p in diff: + abs_p = os.path.join(self.previous.out_dir, p) + yield (abs_p, 'asset changed outputs') +