diff piecrust/environment.py @ 3:f485ba500df3

Gigantic change to basically make PieCrust 2 vaguely functional. - Serving works, with debug window. - Baking works, multi-threading, with dependency handling. - Various things not implemented yet.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 10 Aug 2014 23:43:16 -0700
parents aaa8fb7c8918
children 30a42341cfa8
line wrap: on
line diff
--- a/piecrust/environment.py	Wed Dec 25 22:16:46 2013 -0800
+++ b/piecrust/environment.py	Sun Aug 10 23:43:16 2014 -0700
@@ -1,51 +1,77 @@
+import time
 import logging
-from decorators import lazy_property
+import threading
+import repoze.lru
 
 
 logger = logging.getLogger(__name__)
 
 
-class PageRepository(object):
-    pass
+class MemCache(object):
+    def __init__(self, size=2048):
+        self.cache = repoze.lru.LRUCache(size)
+        self.lock = threading.RLock()
+
+    def get(self, key, item_maker):
+        item = self.cache.get(key)
+        if item is None:
+            logger.debug("Acquiring lock for: %s" % key)
+            with self.lock:
+                item = self.cache.get(key)
+                if item is None:
+                    logger.debug("'%s' not found in cache, must build." % key)
+                    item = item_maker()
+                    self.cache.put(key, item)
+        return item
+
+
+PHASE_PAGE_PARSING = 0
+PHASE_PAGE_FORMATTING = 1
+PHASE_PAGE_RENDERING = 2
 
 
-class ExecutionContext(object):
-    pass
+class ExecutionInfo(object):
+    def __init__(self, page, phase, render_ctx):
+        self.page = page
+        self.phase = phase
+        self.render_ctx = render_ctx
+        self.was_cache_valid = False
+        self.start_time = time.clock()
+
+
+class ExecutionInfoStack(threading.local):
+    def __init__(self):
+        self._page_stack = []
+
+    @property
+    def current_page_info(self):
+        if len(self._page_stack) == 0:
+            return None
+        return self._page_stack[-1]
+
+    @property
+    def is_main_page(self):
+        return len(self._page_stack) == 1
+
+    def pushPage(self, page, phase, render_ctx):
+        self._page_stack.append(ExecutionInfo(page, phase, render_ctx))
+
+    def popPage(self):
+        del self._page_stack[-1]
 
 
 class Environment(object):
     def __init__(self):
-        self.page_repository = PageRepository()
-        self._execution_ctx = None
+        self.start_time = time.clock()
+        self.exec_info_stack = ExecutionInfoStack()
+        self.was_cache_cleaned = False
+        self.page_repository = MemCache()
+        self.rendered_segments_repository = MemCache()
+        self.base_asset_url_format = '%site_root%%uri%'
 
     def initialize(self, app):
         pass
 
-    @lazy_property
-    def pages(self):
-        logger.debug("Loading pages...")
-        return self._loadPages()
-
-    @lazy_property
-    def posts(self):
-        logger.debug("Loading posts...")
-        return self._loadPosts()
-
-    @lazy_property
-    def file_system(self):
-        return None
-
-    def get_execution_context(self, auto_create=False):
-        if auto_create and self._execution_ctx is None:
-            self._execution_ctx = ExecutionContext()
-        return self._execution_ctx
-
-    def _loadPages(self):
-        raise NotImplementedError()
-
-    def _loadPosts(self):
-        raise NotImplementedError()
-
 
 class StandardEnvironment(Environment):
     def __init__(self):