[ZPatterns] Why is class_default_for_ method unbound?
Phillip J. Eby
[email protected]
Tue, 21 Aug 2001 08:33:20 -0500
At 12:10 PM 8/21/01 +1000, Itai Tavor wrote:
>I got the following DataSkin class (Zope 2.3.2, ZPatterns 0.4.3p1):
>
>class MyClass(DataSkin):
>
> def class_default_for_method1(self, REQUEST):
> """ Display something """
> ...
>
>Calling http://mysite/myinstance/method1 returns:
>
>Error Type: TypeError
>Error Value: unbound Python method must be called with MyClass 1st argument
>
>Why is method1 unbound? Why does it behave any different than a method
>defined as def method1(self, REQUEST)? And what do I do to make this
>method work?
Congratulations, you just found a long-buried bug in DynPersist.c, that
hasn't hit anybody else yet (including me). I just looked over the code
and realized that DynPersist only calls the "__of__" method of an object
returned from __get_attr__, and does not perform instance method
binding. This works correctly with methods that are Zope objects, just not
methods that are Python functions or unbound methods. There is a
workaround, but of course I really should fix DynPersist.c, and will
attempt to do so. Here's the (untested) workaround:
import MethodObject
class Method(MethodObject.Method):
def __init__(self,func):
self.func = func
self.func_code = func.func_code
self.func_defaults = func.func_defaults
def __call__(self,*args,**kw):
return apply(self.func,args,kw)
class MyClass(DataSkin):
def class_default_for_method1(self, REQUEST):
...
class_default_for_method1 = Method(class_default_for_method1)
This should turn the Python function into a Zope "method" object with the
right magic. Sorry about the difficulty, I'll take a look and see if
there's a way to fix DynPersist.c to do the right thing with "unbound
method" objects.