[Checkins] SVN: hurry.custom/trunk/ Introduce the notion of a broken template and proper fallback.
Martijn Faassen
faassen at startifact.com
Tue Jun 9 10:23:52 EDT 2009
Log message for revision 100760:
Introduce the notion of a broken template and proper fallback.
Changed:
U hurry.custom/trunk/CHANGES.txt
U hurry.custom/trunk/src/hurry/custom/README.txt
U hurry.custom/trunk/src/hurry/custom/core.py
U hurry.custom/trunk/src/hurry/custom/interfaces.py
-=-
Modified: hurry.custom/trunk/CHANGES.txt
===================================================================
--- hurry.custom/trunk/CHANGES.txt 2009-06-09 14:21:55 UTC (rev 100759)
+++ hurry.custom/trunk/CHANGES.txt 2009-06-09 14:23:51 UTC (rev 100760)
@@ -4,9 +4,12 @@
0.6 (unreleased)
~~~~~~~~~~~~~~~~
-- Nothing changed yet.
+* Introduce the notion of a ``BrokenTemplate``. If a customized
+ template is broken, the system falls back to using the original
+ version of the template. A template is broken if it raises
+ the ``hurry.custom.interfaces.BrokenTemplate`` exception when it is
+ created.
-
0.5 (2009-05-22)
~~~~~~~~~~~~~~~~
Modified: hurry.custom/trunk/src/hurry/custom/README.txt
===================================================================
--- hurry.custom/trunk/src/hurry/custom/README.txt 2009-06-09 14:21:55 UTC (rev 100759)
+++ hurry.custom/trunk/src/hurry/custom/README.txt 2009-06-09 14:23:51 UTC (rev 100760)
@@ -60,7 +60,7 @@
takes the input data (in whatever format is native to the template
language). The ``ITemplate`` interface defines such an object::
- >>> from hurry.custom.interfaces import ITemplate
+ >>> from hurry.custom.interfaces import ITemplate, BrokenTemplate
For the purposes of demonstrating the functionality in this package,
we supply a very simplistic push-only templating language, based on
@@ -71,6 +71,8 @@
>>> class StringTemplate(object):
... implements(ITemplate)
... def __init__(self, text):
+ ... if '&' in text:
+ ... raise BrokenTemplate("& in template!")
... self.source = text
... self.template = string.Template(text)
... def __call__(self, input):
@@ -83,6 +85,17 @@
>>> template({'thing': 'world'})
'Hello world'
+Note we have put some special logic in the ``__init__`` that triggers a
+``BrokenTemplate`` error if the string ``&`` is found in the
+template. This is so we can easily demonstrate templates that are
+broken - treat a template with ``&`` as a template with a syntax
+(compilation) error. Let's try it::
+
+ >>> template = StringTemplate('Hello & bye')
+ Traceback (most recent call last):
+ ...
+ BrokenTemplate: & in template!
+
The template class defines a template language. Let's register the
template language so the system is aware of it and treats ``.st`` files
on the filesystem as a string template::
@@ -111,6 +124,13 @@
>>> f.write('Hello $thing')
>>> f.close()
+We also create an extra template::
+
+ >>> test2_path = os.path.join(templates_path, 'test2.st')
+ >>> f = open(test2_path, 'w')
+ >>> f.write("It's full of $thing")
+ >>> f.close()
+
In order for the system to work, we need to register this collection
of templates on the filesystem. We need to supply a globally unique
collection id, the templates path, and (optionally) a title::
@@ -133,6 +153,11 @@
>>> template({'thing': 'world'})
u'Hello world'
+We'll try another template::
+
+ >>> custom.lookup('templates', 'test2.st')({'thing': 'stars'})
+ u"It's full of stars"
+
The underlying template will not be reloaded unless it is changed on
the filesystem::
@@ -255,6 +280,25 @@
This could be used to implement a "revert" functionality in a
customization UI, for instance.
+Broken custom template
+----------------------
+
+If a custom template is broken, the system falls back on the
+filesystem template instead. We construct a broken custom template by
+adding ``&`` to it::
+
+ >>> template2 = custom.lookup('templates', 'test2.st')
+ >>> source = template2.source
+ >>> source = source.replace('full of', 'filled with &')
+ >>> mem_db.update('test2.st', source)
+
+We try to render this template, but instead we'll see the original
+template::
+
+ >>> template2 = custom.lookup('templates', 'test2.st')
+ >>> template2({'thing': 'planets'})
+ u"It's full of planets"
+
Checking which template languages are recognized
------------------------------------------------
@@ -292,7 +336,11 @@
[{'extension': '.st',
'name': 'test1',
'path': 'test1.st',
- 'template': 'test1.st'}]
+ 'template': 'test1.st'},
+ {'extension': '.st',
+ 'name': 'test2',
+ 'path': 'test2.st',
+ 'template': 'test2.st'}]
Samples
-------
Modified: hurry.custom/trunk/src/hurry/custom/core.py
===================================================================
--- hurry.custom/trunk/src/hurry/custom/core.py 2009-06-09 14:21:55 UTC (rev 100759)
+++ hurry.custom/trunk/src/hurry/custom/core.py 2009-06-09 14:23:51 UTC (rev 100760)
@@ -5,7 +5,7 @@
from hurry.custom.interfaces import NotSupported
from hurry.custom.interfaces import (
ITemplate, IManagedTemplate, ITemplateDatabase, IDataLanguage,
- ISampleExtension)
+ ISampleExtension, BrokenTemplate)
def register_language(template_class, extension, sample_extension=None):
component.provideUtility(template_class,
@@ -34,12 +34,19 @@
def lookup(id, template_path):
db = component.getUtility(ITemplateDatabase, name=id)
- while db.get_source(template_path) is None:
- db = getNextUtility(db, ITemplateDatabase, name=id)
- dummy, ext = os.path.splitext(template_path)
- template_class = component.getUtility(ITemplate, name=ext)
- return ManagedTemplate(template_class, db, template_path)
-
+ while True:
+ source = db.get_source(template_path)
+ if source is None:
+ db = getNextUtility(db, ITemplateDatabase, name=id)
+ continue
+ dummy, ext = os.path.splitext(template_path)
+ template_class = component.getUtility(ITemplate, name=ext)
+ try:
+ return ManagedTemplate(template_class, db, template_path)
+ except BrokenTemplate:
+ db = getNextUtility(db, ITemplateDatabase, name=id)
+ continue
+
def sample_datas(id, template_path):
db = get_filesystem_database(id)
@@ -88,7 +95,7 @@
def samples(self):
db = _get_root_database(self.db.id)
return db.get_samples(self.template_path)
-
+
class FilesystemTemplateDatabase(object):
implements(ITemplateDatabase)
Modified: hurry.custom/trunk/src/hurry/custom/interfaces.py
===================================================================
--- hurry.custom/trunk/src/hurry/custom/interfaces.py 2009-06-09 14:21:55 UTC (rev 100759)
+++ hurry.custom/trunk/src/hurry/custom/interfaces.py 2009-06-09 14:23:51 UTC (rev 100760)
@@ -76,7 +76,11 @@
input - opaque template-language native data structure.
"""
-
+
+class BrokenTemplate(Exception):
+ """Error when a template is broken.
+ """
+
class IDataLanguage(Interface):
def __call__(data):
"""Parse data into data structure that can be passed to ITemplate()"""
@@ -128,6 +132,16 @@
raised.
"""
+ def test(template_id, source):
+ """Test a template.
+
+ This tries a test-compile of the template, and if sample
+ inputs are known, test-renders of the template.
+
+ Return False if the compilation or any of the test renderings
+ fails. Returns True if there was no error.
+ """
+
def get_source(template_id):
"""Get the source of a given template.
@@ -151,4 +165,3 @@
keys are the unique ids for the sample inputs.
values are the actual template-language native data structures.
"""
-
More information about the Checkins
mailing list