SVN: r23893 - in trunk/quixote: . doc

Neil Schemenauer <nascheme-fVcApmY9cLvQ3/1i3zOLAti2O/[email protected]> Tue, 06 Apr 2004 15:31:20 -0400
Newsgroups gmane.comp.web.quixote.cvs
Message-ID <[email protected]>
Author: nascheme
Date: 2004-04-06 15:31:20 -0400 (Tue, 06 Apr 2004)
New Revision: 23893

Modified:
   trunk/quixote/doc/programming.txt
   trunk/quixote/doc/static-files.txt
   trunk/quixote/publish.py
Log:
Allow _q_exports to contain mappings of external names to internal
names.


Modified: trunk/quixote/doc/programming.txt
===================================================================
--- trunk/quixote/doc/programming.txt	2004-04-06 19:11:19 UTC (rev 23892)
+++ trunk/quixote/doc/programming.txt	2004-04-06 19:31:20 UTC (rev 23893)
@@ -271,6 +271,12 @@
 
     _q_exports = ['foo']
 
+At times it is desirable for URLs to contain path components that are
+not valid Python identifiers.  In these cases you can provide an
+explicit external to internal name mapping.  For example::
+
+    _q_exports = ['foo', ('stylesheet.css', 'stylesheet_css')]
+
 When a function is callable from the web, it must expect a single
 parameter, which will be an instance of the HTTPRequest class.  This
 object contains everything Quixote could discover about the current HTTP

Modified: trunk/quixote/doc/static-files.txt
===================================================================
--- trunk/quixote/doc/static-files.txt	2004-04-06 19:11:19 UTC (rev 23892)
+++ trunk/quixote/doc/static-files.txt	2004-04-06 19:31:20 UTC (rev 23893)
@@ -25,7 +25,14 @@
             follow_symlinks=1, mime_type="text/css")
     
 
+If you want the URL of the file to have a ``.css`` extension, you use
+the external to internal name mapping feature of ``_q_exports``.  For
+example::
 
+    _q_exports = [ ..., ('stylesheet.css', 'stylesheet_css'), ...]
+
+
+
 Publishing a Directory
 ----------------------
 

Modified: trunk/quixote/publish.py
===================================================================
--- trunk/quixote/publish.py	2004-04-06 19:11:19 UTC (rev 23892)
+++ trunk/quixote/publish.py	2004-04-06 19:31:20 UTC (rev 23893)
@@ -719,6 +719,31 @@
     return object
 
 
+def _lookup_export (name, exports):
+    """Search an exports list for a name.  Returns the internal name for
+    'name' or return None if 'name' is not in 'exports'.
+    
+    Each element of the export list can be either a string or a 2-tuple
+    of strings that maps an external name into internal name.  The
+    mapping is useful when the desired external name is not a valid
+    Python identifier.
+    """
+    for value in exports:
+        if value == name:
+            internal_name = name
+            break
+        elif type(value) is types.TupleType:
+            if value[0] == name:
+                internal_name = value[1] # internal name is different
+                break
+    else:
+        if name == '_q_index':
+            internal_name = name # _q_index does not need to be in exports list
+        else:
+            internal_name = None # not found in exports
+    return internal_name
+
+
 def _get_component (container, component, path, request, namespace_stack):
     """Get one component of a path from a namespace.
     """
@@ -747,7 +772,8 @@
     # _q_lookup() doesn't exist or is None, a TraversalError is
     # raised.
 
-    if (component != "_q_index" and component not in container._q_exports):
+    internal_name = _lookup_export(component, container._q_exports)
+    if internal_name is None:
         # Component is not in exports list.
         object = None
         if hasattr(container, "_q_lookup"):
@@ -762,13 +788,12 @@
                                                     container,
                                                     component))
 
-    # From here on, you can assume that the name is either in
-    # _q_exports, or the name is '_q_index'
-    elif hasattr(container, component):
+    # From here on, you can assume that the internal_name is not None
+    elif hasattr(container, internal_name):
         # attribute is in _q_exports and exists
-        object = getattr(container, component)
+        object = getattr(container, internal_name)
 
-    elif component == '_q_index':
+    elif internal_name == '_q_index':
         if hasattr(container, "_q_lookup"):
             object = container._q_lookup(request, "")
         else:
@@ -776,21 +801,21 @@
                 private_msg=("_q_index not found in %r" % container))
 
     elif hasattr(container, "_q_resolve"):
-        object = container._q_resolve(component)
+        object = container._q_resolve(internal_name)
         if object is None:
-            raise RuntimeError, ("component %r listed in _q_exports, "
-                                 "but not returned by _q_resolve()"
-                                 % component)
+            raise RuntimeError, ("component listed in _q_exports, "
+                                 "but not returned by _q_resolve(%r)"
+                                 % internal_name)
         else:
             # Set the object, so _q_resolve won't need to be called again.
-            setattr(container, component, object)
+            setattr(container, internal_name, object)
 
     elif type(container) is types.ModuleType:
         # try importing it as a sub-module.  If we get an ImportError
         # here we don't catch it.  It means that something that
         # doesn't exist was exported or an exception was raised from
         # deeper in the code.
-        mod_name = container.__name__ + '.' + component
+        mod_name = container.__name__ + '.' + internal_name
         object = _get_module(mod_name)
 
     else: