diff piecrust/pipelines/records.py @ 854:08e02c2a2a1a

core: Keep refactoring, this time to prepare for generator sources. - Make a few APIs simpler. - Content pipelines create their own jobs, so that generator sources can keep aborting in `getContents`, but rely on their pipeline to generate pages for baking.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 04 Jun 2017 23:34:28 -0700
parents f070a4fc033c
children 448710d84121
line wrap: on
line diff
--- a/piecrust/pipelines/records.py	Sun May 21 00:06:59 2017 -0700
+++ b/piecrust/pipelines/records.py	Sun Jun 04 23:34:28 2017 -0700
@@ -9,8 +9,53 @@
 logger = logging.getLogger(__name__)
 
 
+class RecordEntry:
+    """ An entry in a record, for a specific content item.
+    """
+    def __init__(self):
+        self.item_spec = None
+        self.errors = []
+
+    @property
+    def success(self):
+        return len(self.errors) == 0
+
+    def describe(self):
+        return {}
+
+    def getAllOutputPaths(self):
+        return None
+
+    def getAllErrors(self):
+        return self.errors
+
+
+class Record:
+    """ A class that represents a 'record' of a bake operation on a
+        content source.
+    """
+    def __init__(self, name):
+        self.name = name
+        self.deleted_out_paths = []
+        self.success = True
+        self._entries = {}
+
+    def addEntry(self, entry):
+        if entry.item_spec in self._entries:
+            raise ValueError("Entry '%s' is already in the record." %
+                             entry.item_spec)
+        self._entries[entry.item_spec] = entry
+
+    def getEntries(self):
+        return self._entries.values()
+
+    def getEntry(self, item_spec):
+        return self._entries[item_spec]
+
+
 class MultiRecord:
-    """ A container that includes multiple `Record` instances.
+    """ A container that includes multiple `Record` instances -- one for
+        each content source that was baked.
     """
     RECORD_VERSION = 12
 
@@ -49,31 +94,14 @@
             return pickle.load(fp)
 
 
-class Record:
-    """ A basic class that represents a 'record' of a bake operation on a
-        content source.
-    """
-    def __init__(self, name):
-        self.name = name
-        self.entries = []
-        self.deleted_out_paths = []
-        self.success = True
-
-
-class RecordEntry:
-    """ An entry in a record, for a specific content item.
-    """
-    def __init__(self):
-        self.item_spec = None
-        self.out_paths = []
-        self.errors = []
-
-    @property
-    def success(self):
-        return len(self.errors) == 0
-
-    def describe(self):
-        return {}
+def get_flag_descriptions(flags, flag_descriptions):
+    res = []
+    for k, v in flag_descriptions.items():
+        if flags & k:
+            res.append(v)
+    if res:
+        return ', '.join(res)
+    return 'none'
 
 
 def _are_records_valid(multi_record):
@@ -106,58 +134,6 @@
     return multi_record
 
 
-def _build_diff_key(item_spec):
-    return hashlib.md5(item_spec.encode('utf8')).hexdigest()
-
-
-class MultiRecordHistory:
-    """ Tracks the differences between an 'old' and a 'new' record
-        container.
-    """
-    def __init__(self, previous, current):
-        if previous is None or current is None:
-            raise ValueError()
-
-        self.previous = previous
-        self.current = current
-        self.histories = []
-        self._buildHistories(previous, current)
-
-    def getHistory(self, record_name):
-        for h in self.histories:
-            if h.name == record_name:
-                return h
-        rh = RecordHistory(
-            Record(record_name),
-            Record(record_name))
-        self.histories.append(rh)
-        self.previous.records.append(rh.previous)
-        self.current.records.append(rh.current)
-        return rh
-
-    def _buildHistories(self, previous, current):
-        pairs = {}
-        if previous:
-            for r in previous.records:
-                pairs[r.name] = (r, None)
-        if current:
-            for r in current.records:
-                p = pairs.get(r.name, (None, None))
-                if p[1] is not None:
-                    raise Exception("Got several records named: %s" % r.name)
-                pairs[r.name] = (p[0], r)
-
-        for name, pair in pairs.items():
-            p, c = pair
-            if p is None:
-                p = Record(name)
-                previous.records.append(p)
-            if c is None:
-                c = Record(name)
-                current.records.append(c)
-            self.histories.append(RecordHistory(p, c))
-
-
 class RecordHistory:
     def __init__(self, previous, current):
         if previous is None or current is None:
@@ -190,18 +166,26 @@
             raise Exception("This record history hasn't been built yet.")
         return self._diffs.values()
 
+    def getPreviousEntry(self, item_spec):
+        key = _build_diff_key(item_spec)
+        return self._diffs[key][0]
+
+    def getCurrentEntry(self, item_spec):
+        key = _build_diff_key(item_spec)
+        return self._diffs[key][1]
+
     def build(self):
         if self._diffs is not None:
             raise Exception("This record history has already been built.")
 
         self._diffs = {}
         if self._previous is not None:
-            for e in self._previous.entries:
+            for e in self._previous.getEntries():
                 key = _build_diff_key(e.item_spec)
                 self._diffs[key] = (e, None)
 
         if self._current is not None:
-            for e in self._current.entries:
+            for e in self._current.getEntries():
                 key = _build_diff_key(e.item_spec)
                 diff = self._diffs.get(key)
                 if diff is None:
@@ -210,5 +194,65 @@
                     self._diffs[key] = (diff[0], e)
                 else:
                     raise Exception(
-                        "A current record entry already exists for: %s" % key)
+                        "A current record entry already exists for '%s' "
+                        "(%s)" % (key, diff[1].item_spec))
+
+
+class MultiRecordHistory:
+    """ Tracks the differences between an 'old' and a 'new' record
+        container.
+    """
+    def __init__(self, previous, current):
+        if previous is None or current is None:
+            raise ValueError()
+
+        self.previous = previous
+        self.current = current
+        self.histories = []
+        self._linkHistories(previous, current)
+
+    def getPreviousRecord(self, record_name, auto_create=True):
+        return self.previous.getRecord(record_name, auto_create=auto_create)
+
+    def getCurrentRecord(self, record_name):
+        return self.current.getRecord(record_name)
+
+    def getHistory(self, record_name):
+        for h in self.histories:
+            if h.name == record_name:
+                return h
 
+        rh = RecordHistory(
+            Record(record_name),
+            Record(record_name))
+        self.histories.append(rh)
+        self.previous.records.append(rh.previous)
+        self.current.records.append(rh.current)
+        return rh
+
+    def _linkHistories(self, previous, current):
+        pairs = {}
+        if previous:
+            for r in previous.records:
+                pairs[r.name] = (r, None)
+        if current:
+            for r in current.records:
+                p = pairs.get(r.name, (None, None))
+                if p[1] is not None:
+                    raise Exception("Got several records named: %s" % r.name)
+                pairs[r.name] = (p[0], r)
+
+        for name, pair in pairs.items():
+            p, c = pair
+            if p is None:
+                p = Record(name)
+                previous.records.append(p)
+            if c is None:
+                c = Record(name)
+                current.records.append(c)
+            self.histories.append(RecordHistory(p, c))
+
+
+def _build_diff_key(item_spec):
+    return hashlib.md5(item_spec.encode('utf8')).hexdigest()
+