[TransWarp] Refactoring/renaming plans for peak.web

Phillip J. Eby pje at telecommunity.com
Thu Jul 24 12:12:35 EDT 2003


This is a rough outline of the changes I'll be making in peak.web over the 
next few days.  As usual, comments and questions are welcome.

Traversal Terminology
---------------------

After analyzing and discussing the issues with locations being traversal 
handlers, security guards, and presentation decorators, I've decided to 
make the following name changes:

1. locationProtocol -> pathProtocol
2. behaviorProtocol -> pageProtocol
3. IWebMethod       -> IWebPage
4. IWebLocation     -> IWebTraversable
5. *AsMethod        -> *AsPage
6. *Location        -> *Traversable

IOW, there will be no such thing as a "location" any more; the term was 
wrong.  We want to have objects' fields (for example) be "traversable", but 
they are not necessarily "locations".  The interaction's protocol for this 
will be called the 'pathProtocol', emphasizing that its purpose is how that 
interaction will interpret paths.

There will be a new class, 'web.Decorator', that you will subclass in order 
to provide "traversal adapters" for domain components.  The idea is that 
you define any UI or presentation-specific methods in the decorator 
subclass, and declare it as an adapter for the domain class it 
decorates.  The base class will support IWebTraversable, so subclasses will 
only need to define methods, bindings, and page templates as desired.  When 
traversing, the decorator's attributes will be checked first, and then 
those of the adapted object.


Security
--------

After discussion with Ty, we decided not to introduce proxies at this 
time.  Traversables will still be required to handle security checks in the 
same fashion as at present.  Python code written in Decorator classes will 
be considered "trusted" at the present time.  (That is, able to violate 
declared security rules by direct object access.)

binding.Attribute will be extended to support a 'permissions' keyword 
argument, allowing security declarations to be made on bindings.  Note that 
this is advisory data only; if a Traversable or other class doesn't 
actually check permissions using peak.security, these declarations will 
have no effect.

We will also make it possible to declare permissions on plain ol' Python 
methods of Components, probably via something like 'methodName.permissions 
= [security.Anybody]' in the class.

There may be some refactoring of the security declaration APIs.  Notably, 
'security.allow()' will likely only be needed for non-Component classes, as 
binding.Component will be able to implement IGuardedObject directly.  Also, 
it's likely that 'security.allow()' will be changed to use some sort of 
"permission declaration" interface, instead of hacking into the class it's 
used on.


DOMlet Rendering
----------------

Currently, the IDOMletNode.renderTo() method takes four arguments: the 
interaction, a 'write' function, a traversable representing the current 
target data, and an "execution context" object.  My experience writing 
DOMlets so far is that dealing with four arguments is awkward; I can never 
remember their order or correct names.

I made these things arguments so that they can be changed by parent DOMlets 
supplying them to child DOMlets.  But, as it happens, they are not all 
changed with the same frequency of occurrence.  The target data, for 
example, changes regularly, whereas the interaction and write function are 
likely to never change at all.  The execution context will only change when 
a DOMlet wants to make some dynamic data or services available to 
collaborating child DOMlets.

Thus, I would like to combine execution context with the interaction and 
write function, wrapping all three in a new object called a "state", which 
will be defined by an IDOMletState interface.  The 'state' will have 
'write' and 'interaction' attributes, and it will also "be" the old 
"execution context" argument.  There will be a simple DOMletState base 
class used to bootstrap rendering.

Components that want to provide dynamic data or services to subcomponents 
will create a new state instance with the previous one as its parent 
component, which they'll then pass to their subcomponents.  States will 
probably have a 'findState(interface)' method, that can be used to find the 
nearest state in the state chain that implements a particular 
interface.  The idea is similar to finding utilities in a component tree, 
except that here the utilities *are* the tree.

So, the renderTo(...) method will become 'renderFor(data, state)', where 
'data' is a traversable, and state is an IDOMletState carrying the 
interaction and write function.  In this way, changing the current data 
element for child DOMlets is still easy, and to change anything else, a 
DOMlet will just create a child state and pass it along.  To supply a 
special service or data to children, the DOMlet should have a state 
subclass that implements an interface identifying the service, and the 
children will use 'findState()' to retrieve it.

On a related note, some DOMlets may wish to provide data to their children 
that's accessible via data paths in 'domlet' attributes.  For example, we 
might want the "list" DOMlet to allow access to things like a sequence 
index.  To do this, such a DOMlet would simply instantiate a traversable, 
using the current data as its parent traversable, and then use that new 
traversable as the parent when wrapping each item in the sequence, passing 
it to the child components.  Thus, the tree would look something like:

       ...
      /
     traversable for value being iterated over
    /
   traversable for sequence data
  /
traversable for the current item in the sequence (passed to listItem DOMlet)

Thus, if the "sequence data" traversable had a 'sequence_index' field 
containing the index of the current item, you could in your 'listItem' 
definition have a table cell marked 'domlet="text:../sequence_index"', 
which would go up from the item to the sequence-data traversable.

Notice that for this kind of data tree manipulation to be useful, a DOMlet 
*must* document for the user exactly what it does to the tree.  Otherwise, 
users' paths in child DOMlets will be thrown off base.  Also note that 
another approach to this for the "list" DOMlet would be to just provide a 
"sequence data" component as data, and require explicit reference to the 
sequence item, ala DTML's 'sequence-item'.  In practice, though, it'll 
almost certainly be more common to need to reference data from the sequence 
item, than to refer to values like the roman numeral version of the current 
sequence index.  :)  So, I think we'll use the '..' approach for the "list" 
DOMlet.




More information about the PEAK mailing list