SVN: r20318 - trunk/quixote

akuchlin-fVcApmY9cLvQ3/1i3zOLAti2O/[email protected] Tue, 21 Jan 2003 13:24:26 -0500
Newsgroups gmane.comp.web.quixote.cvs
Message-ID <[email protected]>
Author: akuchlin
Date: 2003-01-21 13:24:25 -0500 (Tue, 21 Jan 2003)
New Revision: 20318

Modified:
   trunk/quixote/publish.py
Log:
Use Neil's rearrangement of get_component(), with some minor tweaking
This makes get_component() clearer, and reduces the level of indentation.

I've verified that the vfab application still runs with this change.
Still, please proofread the new code to be sure that I haven't changed
some subtle semantic.  (The unified diffs are unfortunately a bit hard
to read; you're better off making context diffs or just reading the
new code.)



Modified: trunk/quixote/publish.py
==============================================================================
--- trunk/quixote/publish.py	(original)
+++ trunk/quixote/publish.py	2003-01-21 13:24:26.000000000 -0500
@@ -440,45 +440,51 @@
             # will raise AccessError if access failed
             container._q_access(request)
 
-        # Third security check: make sure the current name component is
-        # in the export list or is _q_index.
-        if (component == "_q_index") or (component in container._q_exports):
-            is_module = type(container) is types.ModuleType
-            has_component = hasattr(container, component)
-            if is_module and not has_component and component != "_q_index":
-                # get next module
-                mod_name = container.__name__ + '.' + component
-                # If we get an ImportError here we don't catch it.  It means
-                # that either someone exported something that doesn't exist or
-                # an exception was raised from deeping in the code.  A
-                # traceback should be generated in either case.
-                object = _get_module(mod_name)
-
-            elif has_component:
-                object = getattr(container, component)
-
-            else:
-                # not a module, doesn't have 'component'
-                raise errors.TraversalError(
-                    private_msg="object %r has no attribute %r" % (
-                                                         container,
-                                                         component))
-        else:
-            # Component is not in exports list.  Check if namespace provides a
-            # '_q_getname()' function, which translates an arbitrary string
-            # into an object that we continue traversing.  This is very handy;
-            # it lets you put user-space objects into your URL-space,
-            # eliminating the need for digging ID strings out of a query, or
-            # checking PATHINFO after Quixote's done with it.  But it is a
-            # compromise to security: it opens up the traversal algorithm to
-            # arbitrary names not listed in _q_exports!
+        # Third security check: make sure the current name component
+        # is in the export list or is '_q_index'.  If neither
+        # condition is true, check for a _q_getname() and call it.
+        # '_q_getname()' translates an arbitrary string into an object
+        # that we continue traversing.  (This is very handy; it lets
+        # you put user-space objects into your URL-space, eliminating
+        # the need for digging ID strings out of a query, or checking
+        # PATHINFO after Quixote's done with it.  But it is a
+        # compromise to security: it opens up the traversal algorithm
+        # to arbitrary names not listed in _q_exports!)  If
+        # _q_getname() doesn't exist or is None, a TraversalError is
+        # raised.
+
+        if (component != "_q_index" and component not in container._q_exports):
+            # Component is not in exports list.  
+            object = None
             if hasattr(container, "_q_getname"):
                 object = container._q_getname(request, component)
-            else:
+            if object is None:
                 raise errors.TraversalError(
-                    private_msg="%r not in _q_exports list for %r" % (
-                                                        component,
-                                                        container))
+                    private_msg="object %r has no attribute %r" % (
+                                                        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):
+            # attribute is in _q_exports and exists
+            object = getattr(container, component)
+
+        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
+            object = _get_module(mod_name)
+
+        else:
+            # a non-existent attribute is in _q_exports,
+            # and the container is not a module.  Give up.
+            raise errors.TraversalError(
+                    private_msg=("%r in _q_exports list, "
+                                 "but not found in %r" % (component,
+                                                          container)))
 
         self.namespace_stack.append(object)
         return object