[PEAK] sitemaps: <content> in non-root <location>

Radek Kanovsky rk at dat.cz
Wed Jan 5 09:27:15 EST 2005


On Mon, Dec 20, 2004 at 12:22:27PM -0500, Phillip J. Eby wrote:

> >    <location id='root'>
> >      <location name='nums'>
> >         <container object="{'1':1,'2':2,'3':3}"/>
> >         <view name='index_html' resource='test/show.pwt'/>
> >         <content type='int'>
> >            <view name='index_html' resource='test/show_num.pwt'/>
> >         </content>
> >      </location>
> >    </location>
> >
> >It doesn't work as I would expect. View 'index_html' (i.e. 'show_num.pwt'
> >template) is not found for int objects returned from container when
> >traversing URLs like '/nums/X/'. Workaround for this is to move whole
> >'<content>..</content>' block one level up:
> 
> That's weird.  I could've sworn there are unit tests that do basically the 
> same thing as you're doing.  Indeed, if you look at 
> peak.web.tests.test_resources.LocationTests, there are several that 
> register views on a nested location.
> 
> Maybe there's a problem with the sitemap mechanism itself, though, as 
> test_sitemap doesn't seem to do any tests with registering a view with a 
> nested location like this.  So, I guess another test case is needed.

The problem is in traversal mechanism over containers. View 'show_num.pwt'
is registered correctly on <Location place_url=/nums> for int type. But
traversing '/nums/1/@@index_html' we get such context stack:

    ctx.current == 1
    ctx.current == {'1':1,'2':2,'3':3}
    ctx.current == <Location place_url=/>

As <Location place_url=/nums> is missing in context stack, IViewService
for top cxt is <Location place_url=/> that has no adapter from int type
to registered view protocol. BTW, thats why moving <content> block one
level up helps.

I could see two solutions:

    1. Location.traverseTo leaves context for 'self' in context stack
       instead of cloned context for container.

    2. Context.viewHandler algorithm will count with context clones.

Variant 1 is better if one relies on some location helper defined via
'class' attribute. Containers could remain accessible for example by
names from location:

    <container name='numbers' object='....'/>

Although, there is question, if anybody need multiple containers in one
location. Such special cases could be implemented by Location subclass
specified in 'class' attribute of location tag and container mechanism
can be simplified.

Variant 2 works now. It is necessary to keep 'clone_from' attribute in
Context instances:

--- environ.py	(revision 33)
+++ environ.py	(working copy)
@@ -184,14 +184,17 @@
                 kw[attr] = getattr(self,attr)
         kw.setdefault('clone_from',self)
         return self.__class__(**kw)
+    
+    clone_from = None
 
     def _setup(self,kw):
         if 'clone_from' in kw:
             cfg = kw['clone_from'].__getattribute__
-            del kw['clone_from']
             for attr in self._clone_attrs:
                 if attr not in kw:
                     kw[attr] = cfg(attr)
+        else :
+            kw['clone_from'] = None
 
         klass = self.__class__
         for k,v in kw.iteritems():
@@ -248,6 +251,8 @@
         vs = IViewService(self.current,None)
         if vs is not None:
             return vs.viewHandler
+        if self.clone_from is not None :
+            return self.clone_from.viewHandler
         if self.previous is None:
             return lambda name,ob,default=None: default
         return self.previous.viewHandler


RadekK



More information about the PEAK mailing list