changeset 850:370e74941d32

optimize: Only load some 3rd party packages when needed. This commit only optimizes the Markdown, SmartyPants, and Pystache wrappers.
author Ludovic Chabant <ludovic@chabant.com>
date Sat, 29 Apr 2017 21:27:33 -0700
parents 8f8bbb2e70e1
children 2c7e57d80bba
files piecrust/formatting/markdownformatter.py piecrust/formatting/smartypantsformatter.py piecrust/templating/pystacheengine.py
diffstat 3 files changed, 40 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/piecrust/formatting/markdownformatter.py	Thu Apr 27 20:55:07 2017 -0700
+++ b/piecrust/formatting/markdownformatter.py	Sat Apr 29 21:27:33 2017 -0700
@@ -1,4 +1,3 @@
-from markdown import Markdown
 from piecrust.formatting.base import Formatter
 
 
@@ -35,6 +34,6 @@
 
         extension_configs = config.get('extension_configs', {})
 
+        from markdown import Markdown
         self._formatter = Markdown(extensions=extensions,
                                    extension_configs=extension_configs)
-
--- a/piecrust/formatting/smartypantsformatter.py	Thu Apr 27 20:55:07 2017 -0700
+++ b/piecrust/formatting/smartypantsformatter.py	Sat Apr 29 21:27:33 2017 -0700
@@ -1,4 +1,3 @@
-import smartypants
 from piecrust.formatting.base import Formatter, PRIORITY_LAST
 
 
@@ -10,13 +9,15 @@
         super(SmartyPantsFormatter, self).__init__()
         self.priority = PRIORITY_LAST
 
+        import smartypants
+        self._sp = smartypants.smartypants
+
     def initialize(self, app):
         super(SmartyPantsFormatter, self).initialize(app)
         self.enabled = (
-                app.config.get('smartypants/enable') or
-                app.config.get('smartypants/enabled'))
+            app.config.get('smartypants/enable') or
+            app.config.get('smartypants/enabled'))
 
     def render(self, format_name, txt):
         assert format_name == 'html'
-        return smartypants.smartypants(txt)
-
+        return self._sp(txt)
--- a/piecrust/templating/pystacheengine.py	Thu Apr 27 20:55:07 2017 -0700
+++ b/piecrust/templating/pystacheengine.py	Sat Apr 29 21:27:33 2017 -0700
@@ -1,9 +1,7 @@
 import logging
 import collections.abc
-import pystache
-import pystache.common
 from piecrust.templating.base import (
-        TemplateEngine, TemplateNotFoundError, TemplatingError)
+    TemplateEngine, TemplateNotFoundError, TemplatingError)
 
 
 logger = logging.getLogger(__name__)
@@ -15,14 +13,16 @@
 
     def __init__(self):
         self.renderer = None
+        self._not_found_error = None
+        self._pystache_error = None
 
     def renderSegmentPart(self, path, seg_part, data):
         self._ensureLoaded()
         try:
             return self.renderer.render(seg_part.content, data)
-        except pystache.common.TemplateNotFoundError as ex:
+        except self._not_found_error as ex:
             raise TemplateNotFoundError() from ex
-        except pystache.common.PystacheError as ex:
+        except self._pystache_error as ex:
             raise TemplatingError(str(ex), path) from ex
 
     def renderFile(self, paths, data):
@@ -32,9 +32,9 @@
         for p in paths:
             if not p.endswith('.mustache'):
                 raise TemplatingError(
-                        "The Mustache template engine only accepts template "
-                        "filenames with a `.mustache` extension. Got: %s" %
-                        p)
+                    "The Mustache template engine only accepts template "
+                    "filenames with a `.mustache` extension. Got: %s" %
+                    p)
             name = p[:-9]  # strip `.mustache`
             try:
                 tpl = self.renderer.load_template(name)
@@ -47,35 +47,39 @@
 
         try:
             return self.renderer.render(tpl, data)
-        except pystache.common.PystacheError as ex:
+        except self._pystache_error as ex:
             raise TemplatingError(str(ex)) from ex
 
     def _ensureLoaded(self):
         if self.renderer:
             return
 
+        import pystache
+        import pystache.common
+
+        self._not_found_error = pystache.common.TemplateNotFoundError
+        self._pystache_error = pystache.common.PystacheError
+
+        class _WorkaroundRenderer(pystache.Renderer):
+            def _make_resolve_context(self):
+                mrc = super(_WorkaroundRenderer, self)._make_resolve_context()
+
+                def _workaround(stack, name):
+                    # Pystache will treat anything that's not a string or
+                    # a dict as a list. This is just plain wrong, but it will
+                    # take a while before the project can get patches on Pypi.
+                    res = mrc(stack, name)
+                    if res is not None and (
+                            res.__class__.__name__ in _knowns or
+                            isinstance(res, collections.abc.Mapping)):
+                        res = [res]
+                    return res
+
+                return _workaround
+
         self.renderer = _WorkaroundRenderer(
-                search_dirs=self.app.templates_dirs)
+            search_dirs=self.app.templates_dirs)
 
 
 _knowns = ['PieCrustData', 'LazyPageConfigData', 'Paginator', 'Assetor',
            'PageLinkerData']
-
-
-class _WorkaroundRenderer(pystache.Renderer):
-    def _make_resolve_context(self):
-        mrc = super(_WorkaroundRenderer, self)._make_resolve_context()
-
-        def _workaround(stack, name):
-            # Pystache will treat anything that's not a string or a dict as
-            # a list. This is just plain wrong, but it will take a while before
-            # the project can get patches on Pypi.
-            res = mrc(stack, name)
-            if res is not None and (
-                    res.__class__.__name__ in _knowns or
-                    isinstance(res, collections.abc.Mapping)):
-                res = [res]
-            return res
-
-        return _workaround
-