[Zope-dev] Re: Creating a namespace

2001-01-28 Thread Michael Halle


Stephan Richter [EMAIL PROTECTED] 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
[EMAIL PROTECTED]


___
Zope-Dev maillist  -  [EMAIL PROTECTED]
http://lists.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 http://lists.zope.org/mailman/listinfo/zope-announce
 http://lists.zope.org/mailman/listinfo/zope )




[Zope] specifying namespace stacks in dtml-with

2001-01-20 Thread Michael Halle


I was thinking about something I'd consider a useful addition to the
dtml-with tag; I'd like to get other people's opinions, especially
about a couple syntax issues.

Problem: In part because of the combination of the dtml namespace
stack and acquisition, it's often hard to get exactly the name
resolution you want in Zope.  For example, I think it's really useful
to want the following:

   "Call an object, found by acquisition, using its "natural" namespace,
except include a small number of symbols found in the local namespace.
When evaluating the local symbols, do so in the local namespace."

Why is this useful?  Because it cuts down on accidental interference
of the local namespace in the evaluation of an object, which
acquisition exacerbates because it multiplies the number of symbols in
the local namespace. I'd even go as far as to say that the above
action is what most people want to do most of the time.

How do you do it?  If you do:

dtml-with object
  dtml-with expr="_.namespace(name1=local_object1, name2=local_object2)"
dtml-var object
  /dtml-with
/dtml-with

(or the equivalent using an inner "let" tag instead of "with") you get
the right nesting, but "local_object1" and "local_object2" are
evaluated in "object"'s namespace, not the local one.  I *think* the
only way to do it right (I haven't tried it) is:

/dtml-let ns="_.namespace(name1=local_object1, name2=local_object2)"
  dtml-with object
/dtml-with ns
  dtml-var object
/dtml-with
  /dtml-with
/dtml-let

That way, you can get a namespace evaluated in the local scope onto
the top of the namespace stack to override the object's symbols.
You've got to go through contortions to swap the order of the
namespace stack without introducing unwanted evaluation side effects.

Yuck!

I think is would be much cooler, and more general, to be able to
specify a namespace stack as a list for dtml-with:

dtml-with "[_.namespace(name1=local_object1, name2=local_object2), object]"
/dtml-var object
/dtml-with

The "with" tag's entire expression would be evaluated in the local
scope, *then* a namespace stack would be constructed, using elements
of a list.  

If you had several objects already, the syntax is even cleaner:

dtml-with expr="[object1, object2, object3]"
  ...
/dtml-with

In short, this construct lets you build a well-defined namespace stack
without worrying as much about unwanted scope interaction.  It's even
not that hard to write the implementation, except for a couple
questions.

-- First, the "mapping" attribute to "with" is per-namespace; how do
you specify it for elements of the stack?  (The "only" attribute is
okay, it is specified once per stack.)  It would be limiting to say
that all namespaces pushed onto a stack would need to be all be
mappings or all be objects.

-- Second, is the expression for "with" currently ever a sequence?  If
so, then you'd have to recognize and distinguish between the old and
the new usages.  I don't think there's much of a problem here, although
the "with" tag code does do a little checking about whether its
expression is a tuple.

-- Finally, what's the natural order of the stack?  If you give the argument
"[a, b, c]" to "with", is "a" or "c" on the top of the namespace stack?
I'd probably say "a".

I'd appreciate any ideas/suggestions others may have.  Thanks!


Michael Halle
[EMAIL PROTECTED]

___
Zope maillist  -  [EMAIL PROTECTED]
http://lists.zope.org/mailman/listinfo/zope
**   No cross posts or HTML encoding!  **
(Related lists - 
 http://lists.zope.org/mailman/listinfo/zope-announce
 http://lists.zope.org/mailman/listinfo/zope-dev )