Mercurial > piecrust2
comparison 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 |
comparison
equal
deleted
inserted
replaced
119:0811f92cbdc7 | 120:133845647083 |
---|---|
1 import os.path | |
2 from piecrust.records import Record, TransitionalRecord | |
3 | |
4 | |
5 class ProcessorPipelineRecord(Record): | |
6 RECORD_VERSION = 2 | |
7 | |
8 def __init__(self): | |
9 super(ProcessorPipelineRecord, self).__init__() | |
10 self.out_dir = None | |
11 self.process_time = None | |
12 | |
13 def hasOverrideEntry(self, rel_path): | |
14 return self.findEntry(rel_path) is not None | |
15 | |
16 def findEntry(self, rel_path): | |
17 rel_path = rel_path.lower() | |
18 for entry in self.entries: | |
19 for out_path in entry.rel_outputs: | |
20 if out_path.lower() == rel_path: | |
21 return entry | |
22 return None | |
23 | |
24 | |
25 FLAG_NONE = 0 | |
26 FLAG_PROCESSED = 2**0 | |
27 FLAG_OVERRIDEN = 2**1 | |
28 | |
29 | |
30 class ProcessorPipelineRecordEntry(object): | |
31 def __init__(self, base_dir, rel_input): | |
32 self.base_dir = base_dir | |
33 self.rel_input = rel_input | |
34 | |
35 self.flags = FLAG_NONE | |
36 self.rel_outputs = [] | |
37 self.errors = [] | |
38 | |
39 @property | |
40 def path(self): | |
41 return os.path.join(self.base_dir, self.rel_input) | |
42 | |
43 @property | |
44 def was_processed(self): | |
45 return bool(self.flags & FLAG_PROCESSED) | |
46 | |
47 @property | |
48 def was_processed_successfully(self): | |
49 return self.was_processed and not self.errors | |
50 | |
51 | |
52 class TransitionalProcessorPipelineRecord(TransitionalRecord): | |
53 def __init__(self, previous_path=None): | |
54 super(TransitionalProcessorPipelineRecord, self).__init__( | |
55 ProcessorPipelineRecord, previous_path) | |
56 | |
57 def getTransitionKey(self, entry): | |
58 return entry.rel_input | |
59 | |
60 def getPreviousEntry(self, rel_path): | |
61 pair = self.transitions.get(rel_path) | |
62 if pair is not None: | |
63 return pair[0] | |
64 return None | |
65 | |
66 def collapseRecords(self): | |
67 for prev, cur in self.transitions.values(): | |
68 if prev and cur and not cur.was_processed: | |
69 # This asset wasn't processed, so the information from | |
70 # last time is still valid. | |
71 cur.flags = prev.flags | |
72 cur.rel_outputs = list(prev.rel_outputs) | |
73 cur.errors = list(prev.errors) | |
74 | |
75 def getDeletions(self): | |
76 for prev, cur in self.transitions.values(): | |
77 if prev and not cur: | |
78 for p in prev.rel_outputs: | |
79 abs_p = os.path.join(self.previous.out_dir, p) | |
80 yield (abs_p, 'previous asset was removed') | |
81 elif prev and cur and cur.was_processed_successfully: | |
82 diff = set(prev.rel_outputs) - set(cur.rel_outputs) | |
83 for p in diff: | |
84 abs_p = os.path.join(self.previous.out_dir, p) | |
85 yield (abs_p, 'asset changed outputs') | |
86 |