[Zope-dev] XMLRPCMethod product

Phillip J. Eby pje@telecommunity.com
Wed, 27 Oct 1999 11:56:44 -0500


At 02:10 AM 10/28/99 +1000, you wrote:
>
>Below is a snippet of code which is the closet I've come to getting this
>to work. Unfortunately this totally kills and persistance
>
>
>    def __getattr__(self, name):
>        if name in ('ages', 'add', 'multiply'):
>                myserv = xmlrpclib.Server(self.server)
>                return (getattr(myserv,name))
>        else:
>                return Acquisition.Acquired
>

here's some code to do what you want:

class MethodMaker(ExtensionClass.Base):

	def __init__(self,name):
		self.name=self.name

	def __of__(self,client):
		myserv = xmlrpclib.Server(client.server)
		return getattr(myserv,self.name)


class DemoClient(XMLRPCClient):
	ages = MethodMaker('ages')
	add = MethodMaker('add')
	multiply = MethodMaker('multiply')


Instances of DemoClient will now have ages, add, and multiply 'methods'.

Of course, you don't have to put these in the class, you can put them in
the instance.  Just have your Client class capable of adding and removing
MethodMaker objects from its instance dictionary.  (Note, by the way that
MethodMaker doesn't need to be persistent; it suffices for it to be
storable in a persistent object.)

Now, if you want to know how the above actually works, here's the short
rundown:

ExtensionClasses (such as Acquisition and Persistence) provide a really
neat hook known as the __of__ hook.  If you retrieve an ExtensionClass
instance as an attribute of another ExtensionClass instance, the retrieved
instance's __of__ method (if it exists) is called, passing in the object it
was retrieved from.  The return value of the method then replaces the
original object.

So, when you ask a DemoClient instance for its 'ages' attribute, the
ExtensionClass machinery retrieves the MethodMaker instance, then calls its
__of__ method, passing in the DemoClient instance as the 'client'
parameter.  The return value of the __of__ method (the 'real' XML-RPC
method) is then returned as if that were what was stored in the DemoClient.

When you don't need a generic __getattr__ function (or can't use one due to
Persistence), but need to do some type of calculation masquerading as an
attribute, use of __of__ (or the ComputedAttribute class) is usually the
way to go.