On Fri, 02 Feb 2007 13:53:21 -0800, manstey wrote:
Hi,
There was a mistake above, and then I'll explain what we're doing:
>>>insCacheClas s = CacheClass(oref )
insCacheProp erty = CacheProperty(i nsOref,'Chapter ')
should have been
>>>insCacheClas s = CacheClass(oref )
insCacheProp erty = CacheProperty(i nsCacheClass ,'Chapter')
Now, to answer some questions.
1. Cache refers to Intersystems Cache database, an powerful oo dbase
that holds our data.
2. It comes with a pythonbinding, but unfortunatley the API, written
in C as a python extension, only provides old-style classes, which is
why we wrap the oref (an in-memory instance of a Cache class/table)
with CacheClass. This allows us to add attributes and methods to the
CacheClass, the most important being CacheProperty, which is a class
corresponding to the Cache property/field classes of the dbase.
You can add attributes and methods to old-style classes.
3. The pythonbind also has a strange behaviour, to our view. It gets
and sets values of its properties (which are classes),
Are you sure you're using the word "classes" correctly? That seems ...
strange. I'm wondering whether the properties are class _instances_.
via the
'parent' oref, i.e. oref.set('Name' ,'Peter'). But we want a pythonic
way to interact with Cache, such as, insCacheClass.N ame='Peter'. and
insOref.Name.Se t().
Okay, let me see that I understand what happens. Here's some pseudo-code
of what I think you are currently doing:
oref = get_a_reference _to_Cache_datab ase() # or whatever
# now do work on it using the python bindings.
oref.set("Name" , "Peter")
oref.set("Somet hing", "Else")
Here's a wrapper for the bindings, so they work more pythonically:
class Oref_Wrapper(ob ject):
def __init__(self, oref):
self._oref = oref # save the oref for later use
# Delegate attribute access to the oref
def __setattr__(sel f, name, value):
return self._oref.set( name, value)
def __getattr__(sel f, name):
return self._oref.get( name) # or whatever the oref does
def __delattr__(sel f, name):
return self._oref.del( name) # or whatever the oref does
This is how you use it:
oref = get_a_reference _to_Cache_datab ase() # or whatever
# re-bind the name to a wrapped version
oref = Oref_Wrapper(or ef)
# now do work on it
oref.Name = "Peter"
oref.Something = "Else"
The code above (in post 7) does this, but as I
asked, by storing the parent instance (insCacheClass) inside each of
its attributes (insCacheProper ty1,2, etc).
Do you use insCacheClass and insCachePropert y for anything other than
making the bindings more Pythonic? Because for the life of me I can't work
out what they're supposed to do!
4. Another reason we want a new-style class wrapped around the oref,
is that each oref has many methods on the server-side Cache database,
but they are all called the same way, namely,
oref.run_obj_me thod('%METHODNA ME',[lisArgs]). We want to call these in
python in the much better insCacheClass.M ETHODNAME(Args) . E.g. we
prefer insCacheClass.S ave() to oref.run_obj_me thod('%Save',[None]).
Using my code above, oref.METHODNAME (args) would resolve to:
oref._oref.get( "METHODNAME")(a rgs)
which may not do what you want.
If you know all the possible METHODNAMES, then that's easy enough to fix:
create methods at runtime. (If you don't know the methods, the problem
becomes too hard for me to work out at 3am, but will probably still be
solvable.)
Change the __init__ method above to something like this (untested):
import new
class Oref_Wrapper(ob ject):
def __init__(self, oref):
self._oref = oref # save the oref for later use
METHODNAMES = ["Save", "Clear", "Something"]
for name in METHODNAMES:
function = lambda self, *args: \
self._oref.run_ obj_method("%"+ name, args)
method = new.instancemet hod(function, name)
self.__dict__[name] = method
then define the __getattr__ etc. methods as before, and (hopefully!) you
are done:
oref.Save()
oref.Clear(1, 2, 3, 7)
I hope this was of some help.
--
Steven.