comparison piecrust/baking/records.py @ 91:e88e330eb8dc

Improvements to incremental baking and cache invalidating.
author Ludovic Chabant <ludovic@chabant.com>
date Fri, 05 Sep 2014 00:42:13 -0700
parents 3471ffa059b2
children 0445a2232de7
comparison
equal deleted inserted replaced
90:e293f08d954e 91:e88e330eb8dc
1 import os.path
1 import logging 2 import logging
3 from piecrust import APP_VERSION
2 from piecrust.sources.base import PageSource 4 from piecrust.sources.base import PageSource
3 from piecrust.records import Record 5 from piecrust.records import Record
4 6
5 7
6 logger = logging.getLogger(__name__) 8 logger = logging.getLogger(__name__)
9
10
11 RECORD_VERSION = 4
7 12
8 13
9 def _get_transition_key(source_name, rel_path, taxonomy_name=None, 14 def _get_transition_key(source_name, rel_path, taxonomy_name=None,
10 taxonomy_term=None): 15 taxonomy_term=None):
11 key = '%s:%s' % (source_name, rel_path) 16 key = '%s:%s' % (source_name, rel_path)
17 key += taxonomy_term 22 key += taxonomy_term
18 return key 23 return key
19 24
20 25
21 class BakeRecord(Record): 26 class BakeRecord(Record):
22 VERSION = 1
23
24 def __init__(self): 27 def __init__(self):
25 super(BakeRecord, self).__init__() 28 super(BakeRecord, self).__init__()
26 self.out_dir = None 29 self.out_dir = None
27 self.bake_time = None 30 self.bake_time = None
31 self.app_version = APP_VERSION
32 self.record_version = RECORD_VERSION
33
34 def hasLatestVersion(self):
35 return (self.app_version == APP_VERSION and
36 self.record_version == RECORD_VERSION)
37
38 def __setstate__(self, state):
39 state.setdefault('app_version', -1)
40 state.setdefault('record_version', -1)
41 super(BakeRecord, self).__setstate__(state)
42
43
44 FLAG_NONE = 0
45 FLAG_SOURCE_MODIFIED = 2**0
46 FLAG_OVERRIDEN = 2**1
28 47
29 48
30 class BakeRecordPageEntry(object): 49 class BakeRecordPageEntry(object):
31 def __init__(self, page=None): 50 def __init__(self, factory, taxonomy_name=None, taxonomy_term=None):
32 self.path = None 51 self.path = factory.path
33 self.rel_path = None 52 self.rel_path = factory.rel_path
34 self.source_name = None 53 self.source_name = factory.source.name
54 self.taxonomy_name = taxonomy_name
55 self.taxonomy_term = taxonomy_term
56 self.path_mtime = os.path.getmtime(factory.path)
57
58 self.flags = FLAG_NONE
35 self.config = None 59 self.config = None
36 self.taxonomy_name = None
37 self.taxonomy_term = None
38 self.was_overriden = False
39 self.out_uris = [] 60 self.out_uris = []
40 self.out_paths = [] 61 self.out_paths = []
41 self.used_source_names = set() 62 self.used_source_names = set()
42 self.used_taxonomy_terms = set() 63 self.used_taxonomy_terms = set()
43
44 if page:
45 self.path = page.path
46 self.rel_path = page.rel_path
47 self.source_name = page.source.name
48 self.config = page.config.get()
49 64
50 @property 65 @property
51 def was_baked(self): 66 def was_baked(self):
52 return len(self.out_paths) > 0 67 return len(self.out_paths) > 0
53 68
62 77
63 def addUsedSource(self, source): 78 def addUsedSource(self, source):
64 if isinstance(source, PageSource): 79 if isinstance(source, PageSource):
65 self.used_source_names.add(source.name) 80 self.used_source_names.add(source.name)
66 81
82 def __getstate__(self):
83 state = self.__dict__.copy()
84 del state['path_mtime']
85 return state
86
67 87
68 class TransitionalBakeRecord(object): 88 class TransitionalBakeRecord(object):
69 DELETION_MISSING = 1 89 DELETION_MISSING = 1
70 DELETION_CHANGED = 2 90 DELETION_CHANGED = 2
71 91
72 def __init__(self, previous_path=None): 92 def __init__(self, previous_path=None):
73 self.previous = BakeRecord() 93 self.previous = BakeRecord()
74 self.current = BakeRecord() 94 self.current = BakeRecord()
75 self.transitions = {} 95 self.transitions = {}
96 self.incremental_count = 0
76 if previous_path: 97 if previous_path:
77 self.loadPrevious(previous_path) 98 self.loadPrevious(previous_path)
78 self.current.entry_added += self._onCurrentEntryAdded 99 self.current.entry_added += self._onCurrentEntryAdded
79 100
80 def loadPrevious(self, previous_path): 101 def loadPrevious(self, previous_path):
91 112
92 def saveCurrent(self, current_path): 113 def saveCurrent(self, current_path):
93 self.current.save(current_path) 114 self.current.save(current_path)
94 115
95 def addEntry(self, entry): 116 def addEntry(self, entry):
117 if (self.previous.bake_time and
118 entry.path_mtime >= self.previous.bake_time):
119 entry.flags |= FLAG_SOURCE_MODIFIED
96 self.current.addEntry(entry) 120 self.current.addEntry(entry)
97 121
98 def getOverrideEntry(self, factory, uri): 122 def getOverrideEntry(self, factory, uri):
99 for pair in self.transitions.values(): 123 for pair in self.transitions.values():
100 prev = pair[0] 124 prev = pair[0]
118 pair = self.transitions.get(key) 142 pair = self.transitions.get(key)
119 if pair is not None: 143 if pair is not None:
120 return pair[0] 144 return pair[0]
121 return None 145 return None
122 146
147 def getCurrentEntries(self, source_name):
148 return [e for e in self.current.entries
149 if e.source_name == source_name]
150
123 def collapseRecords(self): 151 def collapseRecords(self):
124 for pair in self.transitions.values(): 152 for pair in self.transitions.values():
125 prev = pair[0] 153 prev = pair[0]
126 cur = pair[1] 154 cur = pair[1]
127 155
128 if prev and cur and not cur.was_baked: 156 if prev and cur and not cur.was_baked:
129 # This page wasn't baked, so the information from last 157 # This page wasn't baked, so the information from last
130 # time is still valid (we didn't get any information 158 # time is still valid (we didn't get any information
131 # since we didn't bake). 159 # since we didn't bake).
132 cur.was_overriden = prev.was_overriden 160 cur.flags = prev.flags
161 if prev.config:
162 cur.config = prev.config.copy()
133 cur.out_uris = list(prev.out_uris) 163 cur.out_uris = list(prev.out_uris)
134 cur.out_paths = list(prev.out_paths) 164 cur.out_paths = list(prev.out_paths)
135 cur.used_source_names = set(prev.used_source_names) 165 cur.used_source_names = set(prev.used_source_names)
136 cur.used_taxonomy_terms = set(prev.used_taxonomy_terms) 166 cur.used_taxonomy_terms = set(prev.used_taxonomy_terms)
137 167