[Checkins] SVN: hurry.custom/trunk/src/hurry/custom/ Improve API for looking up collections. Use this API internally and

Martijn Faassen faassen at startifact.com
Wed Jun 10 09:23:11 EDT 2009


Log message for revision 100795:
  Improve API for looking up collections. Use this API internally and
  expose it.
  

Changed:
  U   hurry.custom/trunk/src/hurry/custom/README.txt
  U   hurry.custom/trunk/src/hurry/custom/__init__.py
  U   hurry.custom/trunk/src/hurry/custom/core.py
  U   hurry.custom/trunk/src/hurry/custom/interfaces.py

-=-
Modified: hurry.custom/trunk/src/hurry/custom/README.txt
===================================================================
--- hurry.custom/trunk/src/hurry/custom/README.txt	2009-06-10 12:40:40 UTC (rev 100794)
+++ hurry.custom/trunk/src/hurry/custom/README.txt	2009-06-10 13:23:11 UTC (rev 100795)
@@ -219,14 +219,20 @@
 So far all our work was done in the root (filesystem) database. We can
 get it now::
 
-  >>> from zope import component
-  >>> from hurry.custom.interfaces import ITemplateDatabase
-  >>> root_db = component.getUtility(ITemplateDatabase, name='templates')
+  >>> root_db = custom.root_collection('templates')
 
+Before any customization database was registered we could also have
+gotten it using ``custom.collection``, which gets the collection in
+context::
+
+  >>> custom.collection('templates') is root_db
+  True
+ 
 Let's now register a customization database for our collection, in a
 particular site. This means in such a site, the new customized
 template database will be used (with a fallback on the original one if
-no customization can be found).
+no customization can be found or if there is an error in the use of a
+customization).
 
 Let's create a site first::
 
@@ -237,6 +243,7 @@
 database::
 
   >>> mem_db = custom.InMemoryTemplateDatabase('templates', 'Templates')
+  >>> from hurry.custom.interfaces import ITemplateDatabase
   >>> sm1 = site1.getSiteManager()
   >>> sm1.registerUtility(mem_db, provided=ITemplateDatabase, 
   ...   name='templates')
@@ -245,6 +252,23 @@
 
   >>> setSite(site1)
 
+We can now find this collection using ``custom.collection``::
+
+  >>> custom.collection('templates') is mem_db
+  True
+
+The collection below it is the root collection::
+
+  >>> custom.next_collection('templates', mem_db) is root_db
+  True
+
+Below this, there is no collection and we'll get a lookup error::
+
+  >>> custom.next_collection('templates', root_db)
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: No collection available for: templates
+
 We haven't placed any customization in the customization database
 yet, so we'll see the same thing as before when we look up the
 template::
@@ -523,3 +547,58 @@
   Traceback (most recent call last):
     ...
   ComponentLookupError: (<InterfaceClass hurry.custom.interfaces.ITemplate>, '.unrecognized')
+
+If we try to look up a template in the root collection with a
+CompileError in it, we'll get a CompileError::
+
+  >>> compile_error = os.path.join(templates_path, 'compileerror.st')
+  >>> f = open(compile_error, 'w')
+  >>> f.write('A & compile error')
+  >>> f.close()
+  >>> compile_error_template = custom.lookup('templates', 'compileerror.st')
+  Traceback (most recent call last):
+    ...
+  CompileError: & in template!
+
+The same applies to trying to render it::
+
+  >>> custom.render('templates', 'compileerror.st', {})
+  Traceback (most recent call last):
+    ...
+  CompileError: & in template!
+
+If we try to render a template in the root collection we get a RenderError::
+  
+  >>> render_error = os.path.join(templates_path, 'rendererror.st')
+  >>> f = open(render_error, 'w')
+  >>> f.write('A $thang')
+  >>> f.close()
+  >>> custom.render('templates', 'rendererror.st', {'thing': 'thing'})
+  Traceback (most recent call last):
+    ...
+  RenderError: u'thang'
+
+
+We'll get a ComponentLookupError if we look for a collection with an
+unknown id::
+
+  >>> custom.collection('unknown_id')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass hurry.custom.interfaces.ITemplateDatabase>, 'unknown_id')
+
+We also can't look for a next collection if the id we specify is
+unknown::
+
+  >>> custom.next_collection('unknown_id', mem_db)
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: No more utilities for <InterfaceClass hurry.custom.interfaces.ITemplateDatabase>, 'unknown_id' have been found.
+
+Similarly we can't get a root collection if the id is unknown::
+
+  >>> custom.root_collection('unknown_id')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass hurry.custom.interfaces.ITemplateDatabase>, 'unknown_id')
+

Modified: hurry.custom/trunk/src/hurry/custom/__init__.py
===================================================================
--- hurry.custom/trunk/src/hurry/custom/__init__.py	2009-06-10 12:40:40 UTC (rev 100794)
+++ hurry.custom/trunk/src/hurry/custom/__init__.py	2009-06-10 13:23:11 UTC (rev 100795)
@@ -4,6 +4,9 @@
                                lookup,
                                check,
                                structure,
+                               collection,
+                               root_collection,
+                               next_collection,
                                register_language,
                                register_data_language,
                                register_collection,

Modified: hurry.custom/trunk/src/hurry/custom/core.py
===================================================================
--- hurry.custom/trunk/src/hurry/custom/core.py	2009-06-10 12:40:40 UTC (rev 100794)
+++ hurry.custom/trunk/src/hurry/custom/core.py	2009-06-10 13:23:11 UTC (rev 100795)
@@ -2,6 +2,7 @@
 from datetime import datetime
 from zope.interface import implements
 from zope import component
+from zope.component.interfaces import ComponentLookupError
 from hurry.custom.interfaces import (
     ITemplate, IManagedTemplate, ITemplateDatabase, IDataLanguage,
     ISampleExtension, CompileError, RenderError, NotSupported)
@@ -36,32 +37,58 @@
     while True:
         try:
             return template(input)
-        except RenderError:
-            template = lookup(
-                id, template_path,
-                db=getNextUtility(template.db, ITemplateDatabase, name=id))
+        except RenderError, render_error:
+            try:
+                next_db = next_collection(id, template.db)
+            except ComponentLookupError:
+                # cannot find any next collection, so this error is it
+                raise render_error
+            template = lookup(id, template_path, db=next_db)
 
 def lookup(id, template_path, db=None):
     dummy, ext = os.path.splitext(template_path)
     template_class = component.getUtility(ITemplate, name=ext)
 
-    db = db or component.getUtility(ITemplateDatabase, name=id)
-    
+    db = db or collection(id)
+
     while True:
         source = db.get_source(template_path)
         if source is not None:
             try:
                 return ManagedTemplate(template_class, db, template_path)
-            except CompileError:
+            except CompileError, e:
                 pass
-        db = getNextUtility(db, ITemplateDatabase, name=id)
+        try:
+            db = next_collection(id, db)
+        except ComponentLookupError:
+            # if we cannot find a next collection, this means the
+            # last collection had a fatal compilation error
+            raise e
 
+def collection(id):
+    return component.getUtility(ITemplateDatabase, name=id)
+
+def next_collection(id, db):
+    result = getNextUtility(db, ITemplateDatabase, name=id)
+    if result is db:
+        raise ComponentLookupError("No collection available for: %s" % id)
+    return result
+
+def root_collection(id):
+    db = collection(id)
+    while True:
+        try:
+            next_db = next_collection(id, db)
+        except ComponentLookupError:
+            return db
+        db = next_db
+
 def check(id, template_path, source):
     dummy, ext = os.path.splitext(template_path)
     template_class = component.getUtility(ITemplate, name=ext)
     # can raise CompileError
     template = template_class(source)
-    db = _get_root_database(id)
+    db = root_collection(id)
     samples = db.get_samples(template_path)
     for key, value in samples.items():
         try:
@@ -74,7 +101,7 @@
 def structure(id):
     extensions = set([extension for
                       (extension, language) in recognized_languages()])
-    db = _get_root_database(id)
+    db = root_collection(id)
     return _get_structure_helper(db.path, db.path, extensions)
 
 class ManagedTemplate(object):
@@ -212,13 +239,6 @@
             result.append(info)
     return result
 
-def _get_root_database(id):
-    # assume root database is always a FilesystemTemplateDatabase
-    db = component.getUtility(ITemplateDatabase, name=id)
-    while not isinstance(db, FilesystemTemplateDatabase):
-        db = getNextUtility(db, ITemplateDatabase, name=id)
-    return db
-
 # XXX copied from zope.app.component to avoid dependency on it
 # note that newer versions of zope.component have this, so
 # when the target app depends on that we can switch and
@@ -250,9 +270,9 @@
     """
     util = queryNextUtility(context, interface, name, _marker)
     if util is _marker:
-        raise zope.component.interfaces.ComponentLookupError(
-              "No more utilities for %s, '%s' have been found." % (
-                  interface, name))
+        raise ComponentLookupError(
+            "No more utilities for %s, '%s' have been found." % (
+                interface, name))
     return util
 
 # XXX this code comes from Python 2.6 - when switching to this

Modified: hurry.custom/trunk/src/hurry/custom/interfaces.py
===================================================================
--- hurry.custom/trunk/src/hurry/custom/interfaces.py	2009-06-10 12:40:40 UTC (rev 100794)
+++ hurry.custom/trunk/src/hurry/custom/interfaces.py	2009-06-10 13:23:11 UTC (rev 100795)
@@ -47,11 +47,39 @@
     def lookup(id, template_path):
         """Look up template.
         
-        id - the id for the collection
+        id - the id of the collection
         template_path - the relative path (or filename) of the template
                         itself, under the path of the collection
         """
 
+    def collection(id):
+        """Look up ITemplateDatabase for id.
+
+        id - the id of the collection
+
+        Will raise ComponentLookupError if no collection with this id exists.
+        """
+
+    def next_collection(id, db):
+        """Look up the collection below this one.
+
+        id - the id of the collection
+        db - the db below which to look.
+
+        Will raise ComponentLookupError if there is no db below this
+        collection.
+
+        Will also raise ComponentLookupError if no collection with this id exists.
+        """
+
+    def root_collection(id):
+        """Look up the root collection.
+
+        id - the id of the collection.
+
+        Will raise ComponentLookupError if no collection with this id exists.
+        """
+        
     def check(id, template_path, source):
         """Test a template (before customization).
 



More information about the Checkins mailing list