Re: [Zope3-Users] Problems with custom EditForm

2007-01-24 Thread Marius Gedminas
Hello,

On Mon, Jan 22, 2007 at 05:03:43PM +0100, Alex Furlong wrote:
 i have some problems with creating a custom edit form. Here is my complete 
 test code:
 
 from zope.formlib import form
 from zope.publisher.browser import TestRequest
 
 class MyEdit(form.EditForm):
 
 def __init__(self, context, request):
 self.context = context
 self.request = request
 
 import pdb;pdb.set_trace() # set debugger break point
 action = form.Action('Edit', success='handle_edit_action')

Ah, this is going to be fun :)

 self.actions = form.Actions(action)
 
 def test():
 request = TestRequest()
 obj = object()
 
 myform = MyEdit(obj, request)
 
 If i use this code in Zope then i get an error like this: Action
 object does not have an attribute 'form' .

*nod*

 So my first question is, where does the 'form' attribute come from?

Magic.

Do you know how methods work in Python?  You assign a function to a
class attribute, and when you access that attribute on an instance of
the class, you get back a bound method.  The bound method knows which
instance you used -- that's why it's called a bound method.

Under the hood this is implemented using descriptors.  A descriptor is
an object that has a special __get__ method.  When the value of a class
attribute is a descriptor, and you access that attribute on an instance,
the descriptor's __get__ gets called and return the value that you'll
get.

The __get__ of an unbound method will create a bound method object.
Likewise, the formlib's form.Action class has a __get__ method that
returns a copy of the action, with the 'form' attribute set.

This mechanism only works when you assign descriptors to class
attributes.  It does not work when you assign descriptors to object
attributes, or local variables, like you did.

The simplest way to fix your problem is to bind the actions manually:

  def __init__(self, context, request):
  self.context = context
  self.request = request
  action = form.Action('Edit', success='handle_edit_action')
  action = action.__get__(self)
  self.actions = form.Actions(action)

Or you can do it all in one go

  def __init__(self, context, request):
  self.context = context
  self.request = request
  action1 = form.Action('Edit', success='handle_edit_action')
  action2 = form.Action('Edit Again', success='handle_edit_action')
  actions = form.Actions(action1, action2)
  self.actions = form.Actions(actions).__get__(self)

I do not know whether there are cleaner solutions.  (I always feel a bit
dirty when I call a method that starts with an underscore on an object
other than 'self'.)

HTH,
Marius Gedminas
-- 
TCP_UP - The 16-bit TCP Urgent Pointer, encoded as the hex
  representation of the value of the field.  The hex string MUST be
  capitalized since it is urgent.
-- RFC 3093


signature.asc
Description: Digital signature
___
Zope3-users mailing list
Zope3-users@zope.org
http://mail.zope.org/mailman/listinfo/zope3-users


[Zope3-Users] Problems with custom EditForm

2007-01-22 Thread Alex Furlong
Hi,

i have some problems with creating a custom edit form. Here is my complete test 
code:

from zope.formlib import form
from zope.publisher.browser import TestRequest

class MyEdit(form.EditForm):

def __init__(self, context, request):
self.context = context
self.request = request

import pdb;pdb.set_trace() # set debugger break point
action = form.Action('Edit', success='handle_edit_action')
self.actions = form.Actions(action)

def test():
request = TestRequest()
obj = object()

myform = MyEdit(obj, request)

If i use this code in Zope then i get an error like this: Action object does 
not have an attribute 'form' . So i used the debugger to analyze the code. 
After entering the debugger i looked closer at the 'actions' attribute and the 
'Action' object.

print form.EditForm.actions.actions[0].__dict__ delivers this:

{'failure_handler': None, 'success_handler': function handle_edit_action at 
0xb797c3ac, 'label': u'Apply', 'validator': None, '__name__': 
u'actions.apply', 'data': {}, 'condition': function haveInputWidgets at 
0xb797c09c}

OK. This is the standard 'Apply' action from the EditForm class.

print self.actions.actions[0].__dict__ delivers this:

{'validator': None, 'failure_handler': None, '__provides__': 
zope.interface.Provides object at 0xb7780f6c, 'form': test.MyEdit object at 
0xb7767b6c, 'success_handler': function handle_edit_action at 0xb797c3ac, 
'__name__': u'form.actions.apply', 'data': {}, 'condition': function 
haveInputWidgets at 0xb797c09c, 'label': u'Apply'}

So my first question is, where does the 'form' attribute come from?

If i step over the following lines:
action = form.Action('Edit', success='handle_edit_action')
self.actions = form.Actions(action)

then print self.actions.actions[0].__dict__ delivers this:

{'failure_handler': None, 'success_handler': function lambda at 0xb7784844, 
'label': 'Edit', 'validator': None, '__name__': u'actions.edit', 'data': {}, 
'condition': None}

So the 'form' attribute ist gone, and will be heavily missed by ZOPE. :)
Does anyone know why this happens?

Thanks

Alex



-- 
Der GMX SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen! 
Ideal für Modem und ISDN: http://www.gmx.net/de/go/smartsurfer
___
Zope3-users mailing list
Zope3-users@zope.org
http://mail.zope.org/mailman/listinfo/zope3-users