diff piecrust/baking/baker.py @ 338:938be93215cb

bake: Improve render context and bake record, fix incremental bake bugs. * Used sources and taxonomies are now stored on a per-render-pass basis. This fixes bugs where sources/taxonomies were used for one pass, but that pass is skipped on a later bake because its result is cached. * Bake records are now created for all pages even when they're not baked. Record collapsing is gone except for taxonomy index pages. * Bake records now also have sub-entries in order to store information about each sub-page, since some sub-pages could use sources/taxonomies differently than others, or be missing from the output. This lets PieCrust handle clean/dirty states on a sub-page level.
author Ludovic Chabant <ludovic@chabant.com>
date Mon, 06 Apr 2015 19:59:54 -0700
parents b034f6f15e22
children dd25bd3ce1f9
line wrap: on
line diff
--- a/piecrust/baking/baker.py	Sat Apr 04 07:55:49 2015 -0700
+++ b/piecrust/baking/baker.py	Mon Apr 06 19:59:54 2015 -0700
@@ -103,7 +103,6 @@
         t = time.clock()
         record.current.bake_time = time.time()
         record.current.out_dir = self.out_dir
-        record.collapseRecords()
         record.saveCurrent(record_cache.getCachePath(record_name))
         logger.debug(format_timed(t, 'saved bake record', colored=False))
 
@@ -194,17 +193,6 @@
     def _bakeTaxonomies(self, record):
         logger.debug("Baking taxonomies")
 
-        class _TaxonomyTermsInfo(object):
-            def __init__(self):
-                self.dirty_terms = set()
-                self.all_terms = set()
-
-            def __str__(self):
-                return 'dirty:%s, all:%s' % (self.dirty_terms, self.all_terms)
-
-            def __repr__(self):
-                return 'dirty:%s, all:%s' % (self.dirty_terms, self.all_terms)
-
         # Let's see all the taxonomy terms for which we must bake a
         # listing page... first, pre-populate our big map of used terms.
         # For each source name, we have a list of taxonomies, and for each
@@ -222,62 +210,46 @@
         # Now see which ones are 'dirty' based on our bake record.
         logger.debug("Gathering dirty taxonomy terms")
         for prev_entry, cur_entry in record.transitions.values():
+            # Re-bake all taxonomy pages that include new or changed
+            # pages.
+            if cur_entry and cur_entry.was_any_sub_baked:
+                entries = [cur_entry]
+                if prev_entry:
+                    entries.append(prev_entry)
+
+                for tax in self.app.taxonomies:
+                    changed_terms = set()
+                    for e in entries:
+                        terms = e.config.get(tax.setting_name)
+                        if terms:
+                            if not tax.is_multiple:
+                                terms = [terms]
+                            changed_terms |= set(terms)
+
+                    if len(changed_terms) > 0:
+                        tt_info = buckets[cur_entry.source_name][tax.name]
+                        tt_info.dirty_terms |= changed_terms
+
+            # Remember all terms used.
             for tax in self.app.taxonomies:
-                # Re-bake all taxonomy pages that include new or changed
-                # pages.
-                if cur_entry and cur_entry.was_baked_successfully:
-                    if prev_entry and prev_entry.was_baked_successfully:
-                        # Entry was re-baked this time. Mark as dirty both the
-                        # old and new terms.
-                        changed_terms = []
-                        prev_terms = prev_entry.config.get(tax.setting_name)
-                        cur_terms = cur_entry.config.get(tax.setting_name)
-                        if tax.is_multiple:
-                            if prev_terms is not None:
-                                changed_terms += prev_terms
-                            if cur_terms is not None:
-                                changed_terms += cur_terms
-                        else:
-                            if prev_terms is not None:
-                                changed_terms.append(prev_terms)
-                            if cur_terms is not None:
-                                changed_terms.append(cur_terms)
-                    else:
-                        # Entry was not baked last time. Just mark as dirty
-                        # all the new terms.
-                        changed_terms = cur_entry.config.get(tax.setting_name)
-
-                    if changed_terms is not None:
-                        if not isinstance(changed_terms, list):
-                            changed_terms = [changed_terms]
-                        tt_info = buckets[cur_entry.source_name][tax.name]
-                        tt_info.dirty_terms |= set(changed_terms)
-
-                # Remember all terms used.
-                if cur_entry and cur_entry.was_baked_successfully:
+                if cur_entry and not cur_entry.was_overriden:
                     cur_terms = cur_entry.config.get(tax.setting_name)
-                    if cur_terms is not None:
-                        if not isinstance(cur_terms, list):
+                    if cur_terms:
+                        if not tax.is_multiple:
                             cur_terms = [cur_terms]
                         tt_info = buckets[cur_entry.source_name][tax.name]
                         tt_info.all_terms |= set(cur_terms)
-                elif (prev_entry and prev_entry.was_baked_successfully and
-                        cur_entry and not cur_entry.was_baked):
-                    prev_terms = prev_entry.config.get(tax.setting_name)
-                    if prev_terms is not None:
-                        if not isinstance(prev_terms, list):
-                            prev_terms = [prev_terms]
-                        tt_info = buckets[prev_entry.source_name][tax.name]
-                        tt_info.all_terms |= set(prev_terms)
 
         # Re-bake the combination pages for terms that are 'dirty'.
         known_combinations = set()
         logger.debug("Gathering dirty term combinations")
         for prev_entry, cur_entry in record.transitions.values():
-            if cur_entry and cur_entry.was_baked_successfully:
-                known_combinations |= cur_entry.used_taxonomy_terms
-            elif prev_entry:
-                known_combinations |= prev_entry.used_taxonomy_terms
+            if not cur_entry:
+                continue
+            used_taxonomy_terms = cur_entry.getAllUsedTaxonomyTerms()
+            for sn, tn, terms in used_taxonomy_terms:
+                if isinstance(terms, tuple):
+                    known_combinations.add((sn, tn, terms))
         for sn, tn, terms in known_combinations:
             tt_info = buckets[sn][tn]
             tt_info.all_terms.add(terms)
@@ -341,10 +313,7 @@
                 if tt in tt_info.all_terms:
                     logger.debug("Creating unbaked entry for taxonomy "
                                  "term '%s:%s'." % (tn, tt))
-                    entry = BakeRecordPageEntry(
-                            prev_entry.source_name, prev_entry.rel_path,
-                            prev_entry.path, prev_entry.taxonomy_info)
-                    record.addEntry(entry)
+                    record.collapseEntry(prev_entry)
                 else:
                     logger.debug("Taxonomy term '%s:%s' isn't used anymore." %
                                  (tn, tt))
@@ -471,14 +440,20 @@
                 entry.errors.append(str(ex))
                 ex = ex.__cause__
 
-        if entry.errors:
-            for e in entry.errors:
-                logger.error(e)
+        has_error = False
+        for e in entry.getAllErrors():
+            has_error = True
+            logger.error(e)
+        if has_error:
             return False
 
-        if entry.was_baked_successfully:
-            uri = entry.out_uris[0]
-            friendly_uri = uri if uri != '' else '[main page]'
+        if entry.was_any_sub_baked:
+            first_sub = entry.subs[0]
+
+            friendly_uri = first_sub.out_uri
+            if friendly_uri == '':
+                friendly_uri = '[main page]'
+
             friendly_count = ''
             if entry.num_subs > 1:
                 friendly_count = ' (%d pages)' % entry.num_subs
@@ -488,3 +463,14 @@
 
         return True
 
+
+class _TaxonomyTermsInfo(object):
+    def __init__(self):
+        self.dirty_terms = set()
+        self.all_terms = set()
+
+    def __str__(self):
+        return 'dirty:%s, all:%s' % (self.dirty_terms, self.all_terms)
+
+    def __repr__(self):
+        return 'dirty:%s, all:%s' % (self.dirty_terms, self.all_terms)