change templates to remove all class/staticmethods, make Helpers a context-aware class, and fix defaults/URLIntegerType bugs in URLTree
authorTero Marttila <terom@fixme.fi>
Mon, 09 Feb 2009 04:38:23 +0200
changeset 50 e4fbf480fbee
parent 49 9b097385b463
child 51 a1da82870a6b
change templates to remove all class/staticmethods, make Helpers a context-aware class, and fix defaults/URLIntegerType bugs in URLTree
helpers.py
template.py
urltree.py
--- a/helpers.py	Mon Feb 09 03:05:19 2009 +0200
+++ b/helpers.py	Mon Feb 09 04:38:23 2009 +0200
@@ -6,44 +6,56 @@
 
 from qmsk.web import config
 
-def now () :
-    """
-        Returns the current date/time
+class Helpers (object) :
     """
-
-    return time.strftime(config.DATETIME_FMT)
-
-def copyright_year () :
-    """
-        Returns the current year
-    """
-
-    return time.strftime("%Y")
-
-def validation_notice (site_host) :
-    """
-        Returns a short "Validated XHTML & CSS" link text for the given site hostname
+        A bunch of useful helper methods for use in templates
     """
 
-    return 'Validated <a href="http://validator.w3.org/check?uri=http://%(host)s">XHTML 1.0 Strict</a> &amp; <a href="http://jigsaw.w3.org/css-validator/validator?uri=http://%(host)s">CSS 2.1</a>' % dict(
-        host = site_host
-    )
-
-def breadcrumb (trail, links=True) :
-    """
-        Returns a nicely formatted breadcrumb tail, optinally with links
-    """
+    def _bind_ctx (self, ctx) :
+        """
+            Initialize with the given render context
+        """
 
-    return ' &raquo; '.join(
-        (
-            '<a href="$site_url/%s">%s</a>' % (page.url, page.title) if links else page.title
-        ) for page in trail
-    )
+        self.ctx = ctx
 
-def escape (data) :
-    """
-        Escape data as HTML
-    """
+    def now (self) :
+        """
+            Returns the current date/time
+        """
 
-    return cgi.escape(data)
+        return time.strftime(config.DATETIME_FMT)
 
+    def copyright_year (self) :
+        """
+            Returns the current year
+        """
+
+        return time.strftime("%Y")
+
+    def validation_notice (self, site_host) :
+        """
+            Returns a short "Validated XHTML & CSS" link text for the given site hostname
+        """
+
+        return 'Validated <a href="http://validator.w3.org/check?uri=http://%(host)s">XHTML 1.0 Strict</a> &amp; <a href="http://jigsaw.w3.org/css-validator/validator?uri=http://%(host)s">CSS 2.1</a>' % dict(
+            host = site_host
+        )
+
+    def breadcrumb (self, trail, links=True) :
+        """
+            Returns a nicely formatted breadcrumb tail, optinally with links
+        """
+
+        return ' &raquo; '.join(
+            (
+                '<a href="$site_url/%s">%s</a>' % (page.url, page.title) if links else page.title
+            ) for page in trail
+        )
+
+    def escape (self, data) :
+        """
+            Escape data as HTML
+        """
+
+        return cgi.escape(data)
+
--- a/template.py	Mon Feb 09 03:05:19 2009 +0200
+++ b/template.py	Mon Feb 09 04:38:23 2009 +0200
@@ -2,7 +2,8 @@
     Template handler
 """
 
-from mako import exceptions
+from mako import exceptions, util
+from mako.runtime import Context
 from mako.template import Template
 import mako.lookup
 
@@ -29,46 +30,65 @@
         Our own specialization of mako's TemplateLookup
     """
 
-    def __init__ (self, path, fileext=TEMPLATE_EXT, **env) :
+    def __init__ (self, path, fileext=TEMPLATE_EXT, _helper_class=helpers.Helpers, **env) :
         """
             Initialize to load templates located at path, with the given file extension.
 
+            The given Helpers class is used to provide the helper methods
+
             The given **env list is supplied to every template render
         """
 
         # store
         self.path = path
         self.fileext = fileext
+        self.helper_class = _helper_class
         self.env = env
             
         # build the TemplateLookup
         super(TemplateLoader, self).__init__(directories=[path], module_directory=CACHE_DIR)
     
-    @staticmethod
-    def _render (tpl, env, params) :
+    def _render (self, tpl, env, params) :
         """
             Render the given template with given env/params, returning the output as a unicode string, or raising a TemplateError
         """
 
-        # build the context from our superglobals, env, and params
+        # build our Helpers class
+        helpers = self.helper_class()
+
+        # build the context from our env, and params
         ctx = dict(
             h       = helpers,
         )
         ctx.update(env)
         ctx.update(params)
 
+        # the buffer to use for unicode output
+        buf = util.FastEncodingBuffer(unicode=True)
+
+        # the context to use
+        context = Context(buf, **ctx)
+        
+        # bind our helper
+        helpers._bind_ctx(context)
+        
         try :
-            return tpl.render_unicode(**ctx)
+            # render template
+            tpl.render_context(context)
         
         # a template may render other templates
         except TemplateError :
             raise
 
         except :
+            # raise a TemplateError with the details
             details = exceptions.text_error_template().render()
 
             raise TemplateError("Template render failed", status='500 Internal Server Error', details=details)
-
+        
+        else :
+            # return the unicode data
+            return buf.getvalue()
 
     def lookup (self, name) :
         """
@@ -95,8 +115,7 @@
 
         return http.Response(self.render(name, **params))
 
-    @classmethod
-    def load (cls, path) :
+    def load (self, path) :
         """
             Loads a template from a specific file
         """
@@ -107,18 +126,17 @@
         except :
             raise TemplateError("Template broken: %r" % (path, ), status='500 Internal Server Error', details=exceptions.text_error_template().render())
     
-    @classmethod
-    def render_file (cls, path, **params) :
+    def render_file (self, path, **params) :
         """
             Render a template, using load() on the given path. No global environment vars are defined for the render.
         """
 
-        return cls._render(cls.load(path), dict(), params)
+        return self._render(self.load(path), dict(), params)
 
-    @classmethod
-    def render_template (cls, template, **params) :
+    def render_template (self, template, **params) :
         """
             Render the given template object. No global environment vars are defined for the render.
         """
         
-        return cls._render(template, dict(), params)
+        return self._render(template, dict(), params)
+
--- a/urltree.py	Mon Feb 09 03:05:19 2009 +0200
+++ b/urltree.py	Mon Feb 09 04:38:23 2009 +0200
@@ -240,7 +240,7 @@
         """
         
         # default?
-        if value is None and self.default :
+        if value is None and self.default is not None :
             return LabelValue(self, self.default)
         
         # only non-empty values!
@@ -322,14 +322,14 @@
         A URLType for simple integers
     """
 
-    def __init__ (self, negative=True, zero=True, max=None) :
+    def __init__ (self, allow_negative=True, allow_zero=True, max=None) :
         """
-            Pass in negative=False to disallow negative numbers, zero=False to disallow zero, or non-zero max
-            to specifiy maximum value
+            Pass in allow_negative=False to disallow negative numbers, allow_zero=False to disallow zero, or non-zero
+            max to specifiy maximum value
         """
 
-        self.negative = negative
-        self.zero = zero
+        self.allow_negative = allow_negative
+        self.allow_zero = allow_zero
         self.max = max
     
     def _validate (self, value) :
@@ -338,11 +338,11 @@
         """
 
         # negative?
-        if self.negative and value < 0 :
+        if not self.allow_negative and value < 0 :
             raise ValueError("value is negative")
         
         # zero?
-        if self.zero and value == 0 :
+        if not self.allow_zero and value == 0 :
             raise ValueError("value is zero")
         
         # max?