[Zope-dev] Re: Creating a namespace
Michael Halle
halazar@media.mit.edu
Sun, 28 Jan 2001 17:38:42 -0500
Stephan Richter <srichter@cbu.edu> writes:
> I want to make my own name space with the following situation:
> class X:
> attributes = {'foo': 'bar'}
> x = X()
> Then I want to use it like that:
> <dtml-with x>
> <dtml-var foo>
> </dtml-with>
I puzzled through a related problem a little, but for (I think) a
different reason. I have an External Method that takes a significant
amount of time to run, and returns a collection of data. I didn't want
to have to push the names of all the subvariables returned onto the
stack; that pollutes the name space. What I wanted to do was the
following:
<dtml-let x="MyExternalMethod(arg1, arg2)">
Variable 1: <dtml-var expr="x.variable1"> <br>
Variable 2: <dtml-var expr="x.variable2"> <br>
</dtml-let>
(But, as in your case, I could also have done:
<dtml-with expr="MyExternalMethod(arg1, arg2)">
Variable 1: <dtml-var expr="variable1"> <br>
Variable 2: <dtml-var expr="variable2"> <br>
</dtml-let> )
To me, this first example seemed like a pretty common and obvious
thing to to. I didn't need "x" to be persistent, I didn't need or
want acqusition, I just wanted to keep my variables containerized in a
structure. For this purpose, FunctionTemplate, InstanceDict, and
TemplateDict all seemed either inappropriate, too complex, or too
heavyweight.
So, I wrote the simple container class at the end of this message that
contains a grab-bag of methods that can be used for my application as
well as with a variety of others that use <dtml-with> and <dtml-in>.
It essentially provides all that "_.namespace()" does, plus some extra
introspection. It's concocted from various pieces of Zope and the
HowTos.
Now, philosophical Zope questions:
* To those in the know, is there any problems returning non-persistent
structures?
* Next, it there a reason that there's no sanctioned class for this
purpose?
* Can you return a populated namespace from a DTML Method or a Python Script
using existing mechanisms?
* Why can't you set values in "_.namespace()" in DTML after a
namespace has been created?
* To me, it would make so much more sense to be able create a namespace
with temporary variables (as shown in one of the HowTos) rather than
forcing people to hack them using REQUEST.set(). The namespace
could be used directly as a structure (eg, "ns.x") or as a scope
(eg, <dtml-with ns> <dtml-var x> </dtml-with> ). Is there a deep
reason it doesn't exist?
Anyway, here's my "no-guarantee" class. Notice the magic member
"__allow_access_to_unprotected_subobjects__", which the documentation
(read, code) says can also be set to a list of members that you want
to be publicly accessible and unprotected. Use this code as a guide;
you can trim it down to get what you want. An instance of this class
can be used directly as an argument to <dtml-with>; to use with
<dtml-in>, use either the "getItems" or "getMap()" methods.
-------------------------------------
class StructureInstance:
"""A simple, non-persistent, class-based dictionary
that's useful for returning arguments to Zope"""
__allow_access_to_unprotected_subobjects__ = 1
def __init__(self, dict={}):
self.__d=dict
def __getattr__(self, name):
try: return self.__d[name]
except KeyError: raise AttributeError, name
def __getitem__(self, name):
try: return self.__d[name]
except KeyError: raise KeyError, name
def __setitem__(self, name, value):
self.__d[name] = value
def update(self, dict):
self.__d.update(dict)
def getKeys(self, spec=None):
if spec is None:
return self.__d.keys()
return filter((lambda x, spec=spec: x in spec), self.__d.keys())
def getValues(self, spec=None):
if spec is None:
return self.__d.values()
return map(lambda y: y[1],
filter((lambda x, spec=spec: x[0] in spec),
self.__d.keys()))
def getItems(self, spec=None):
if spec is None:
return self.__d.items()
return filter((lambda x, spec=spec: x[0] in spec), self.__d.items())
def getMap(self, spec=None):
items = self.getItems(spec)
dict = {}
for (i, j) in items:
dict[i] = j
return dict
def set(self, **args):
self.update(args)
setitem=__setitem__
-----------------------------------------------
Michael Halle
mhalle@media.mit.edu