[Zope3-Users] Using formlib schema.Choice with zc.table FieldColumn

ksmith93940-dev at yahoo.com ksmith93940-dev at yahoo.com
Thu Jan 25 14:44:25 EST 2007


Thanks for the direction, Gary. :) 

Getting a Choice field working in doctests was quite a
challenge. It now fails as only as a zc.table
FieldColumn. I'm including the relevant doctests and
tests.py

I apologize in advance for the verbose post. :)

Kevin Smith




File
"/root/temp/zc.table-0.6/src/zc/table/fieldcolumn.txt",
line 131, in fieldcolumn.txt
Failed example:
    print formatter()
Exception raised:
    Traceback (most recent call last):
      File
"/root/temp/zc.table-0.6/eggs/zope.testing-3.0-py2.4.egg/zope/testing/doctest.py",
line 1348, in __run
        compileflags, 1) in test.globs
      File "<doctest fieldcolumn.txt[19]>", line 1, in
?
        print formatter()
      File
"/root/temp/zc.table-0.6/src/zc/table/table.py", line
66, in __call__
        return '\n<table%s>\n%s</table>\n%s' % (
      File
"/root/temp/zc.table-0.6/src/zc/table/table.py", line
75, in renderContents
        return '  <thead%s>\n%s  </thead>\n 
<tbody>\n%s  </tbody>\n' % (
      File
"/root/temp/zc.table-0.6/src/zc/table/table.py", line
98, in renderRows
        return ''.join([self.renderRow(item) for item
in self.getItems()])
      File
"/root/temp/zc.table-0.6/src/zc/table/table.py", line
106, in renderRow
        return '  <tr%s>\n%s  </tr>\n' % (
      File
"/root/temp/zc.table-0.6/src/zc/table/table.py", line
110, in renderCells
        return ''.join(
      File
"/root/temp/zc.table-0.6/src/zc/table/table.py", line
114, in renderCell
        return '    <td%s>\n      %s\n    </td>\n' % (
      File
"/root/temp/zc.table-0.6/src/zc/table/table.py", line
121, in getCell
        return column.renderCell(item, self)
      File
"/root/temp/zc.table-0.6/src/zc/table/fieldcolumn.py",
line 162, in renderCell
        return self.getRenderWidget(
      File
"/root/temp/zc.table-0.6/src/zc/table/fieldcolumn.py",
line 114, in getRenderWidget
        widget = self.getInputWidget(item, formatter)
      File
"/root/temp/zc.table-0.6/src/zc/table/fieldcolumn.py",
line 105, in getInputWidget
        widget = component.getMultiAdapter((field,
request), iface)
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/component/_api.py",
line 101, in getMultiAdapter
        adapter = queryMultiAdapter(objects,
interface, name, context=context)
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/component/_api.py",
line 114, in queryMultiAdapter
        return sitemanager.queryMultiAdapter(objects,
interface, name, default)
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/component/registry.py",
line 206, in queryMultiAdapter
        return self.adapters.queryMultiAdapter(
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/interface/adapter.py",
line 482, in queryMultiAdapter
        result = factory(*objects)
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/app/form/browser/itemswidgets.py",
line 44, in ChoiceInputWidget
        IInputWidget)
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/component/_api.py",
line 101, in getMultiAdapter
        adapter = queryMultiAdapter(objects,
interface, name, context=context)
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/component/_api.py",
line 114, in queryMultiAdapter
        return sitemanager.queryMultiAdapter(objects,
interface, name, default)
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/component/registry.py",
line 206, in queryMultiAdapter
        return self.adapters.queryMultiAdapter(
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/interface/adapter.py",
line 482, in queryMultiAdapter
        result = factory(*objects)
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/app/form/browser/itemswidgets.py",
line 315, in __init__
        super(ItemsEditWidgetBase,
self).__init__(field, vocabulary, request)
      File
"/root/temp/zc.table-0.6/parts/zope3/src/zope/app/form/browser/itemswidgets.py",
line 83, in __init__
        assert field.context is not None
    AssertionError




== fieldcolumn.txt ==

   
    >>> import re
    >>> from zope import schema, interface
    >>> class IContact(interface.Interface):
    ...     name = schema.TextLine(title=u'Name')
    ...     email = schema.TextLine(
    ...             title=u'Email Address',
    ...            
constraint=re.compile('\w+@\w+([.]\w+)+$').match)
    ...     salutation = schema.Choice( 
    ...		       title=u'Salutation',
    ...		       values = ['Mr','Ms'],
    ...		       )

    >>> class Contact:
    ...     interface.implements(IContact)
    ...     def __init__(self, id, name, email,
salutation):
    ...         self.id = id
    ...         self.name = name
    ...         self.email = email
    ...         self.salutation = salutation

    >>> contacts = (
    ...     Contact('1', 'Bob Smith', 'bob at zope.com',
'Mr'),
    ...     Contact('2', 'Sally Baker',
'sally at zope.com', 'Ms'),
    ...     Contact('3', 'Jethro Tul',
'jethro at zope.com', 'Mr'),
    ...     Contact('4', 'Joe Walsh', 'joe at zope.com',
'Mr'),
    ...     )

    >>> from zope.formlib import form



    >>> class MyForm(form.EditForm):
    ...	    form_fields = form.Fields( IContact )

Sanity test

    >>> from zope.publisher.browser import TestRequest
    >>> request = TestRequest()
    >>> myform = MyForm(contacts[0], request)
    >>> print myform()
    Name
    <input class="textType" id="form.name"
name="form.name" size="20" type="text" value="Bob
Smith"  />
    Email Address
    <input class="textType" id="form.email"
name="form.email" size="20" type="text"
value="bob at zope.com"  />
    Salutation
    <div>
    <div class="value">
    <select id="form.salutation"
name="form.salutation" size="1" >
    <option selected="selected" value="Mr">Mr</option>
    <option value="Ms">Ms</option>
    </select>
    </div>
    <input name="form.salutation-empty-marker"
type="hidden" value="1" />
    </div>
    <input type="submit" id="form.actions.apply"
name="form.actions.apply" value="Apply" class="button"
/>

We'll define columns that allow us to display and edit
name and
email addresses.

    >>> from zc.table import fieldcolumn
    >>> class ContactColumn(fieldcolumn.FieldColumn):
    ...     def getId(self, item, formatter):
    ...         return fieldcolumn.toSafe(item.id)
    >>> columns =
(ContactColumn(MyForm.form_fields["name"]),
    ...          
ContactColumn(MyForm.form_fields["email"]),
    ...	         
ContactColumn(MyForm.form_fields["salutation"],)
    ...		  )

Now, with this, we can create a table with input
widgets.  The columns don't 
need a context other than the items themselves, so we
ignore that part of the
table formatter instantiation:

    >>> from zc import table
    >>> import zope.publisher.browser
    >>> request = zope.publisher.browser.TestRequest()
    >>> context = None
    >>> formatter = table.Formatter(
    ...     context, request, contacts,
columns=columns, prefix='test')
    >>> print formatter()
    <table>
    <thead>
      <tr>
        <th>
          Name
        </th>
        <th>
          Email Address
        </th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>
          <input class="textType" id="test.1.name"
name="test.1.name"
                 size="20" type="text" value="Bob
Smith"  />
        </td>
        <td>
          <input class="textType" id="test.1.email"
name="test.1.email"
                 size="20" type="text"
value="bob at zope.com"  />
        </td>
      </tr>
      <tr>
        <td>
          <input class="textType" id="test.2.name"
name="test.2.name"
                 size="20" type="text" value="Sally
Baker"  />
        </td>
        <td>
          <input class="textType" id="test.2.email"
name="test.2.email"
                 size="20" type="text"
value="sally at zope.com"  />
        </td>
      </tr>
      <tr>
        <td>
          <input class="textType" id="test.3.name"
name="test.3.name"
                 size="20" type="text" value="Jethro
Tul"  />
        </td>
        <td>
          <input class="textType" id="test.3.email"
name="test.3.email"
                 size="20" type="text"
value="jethro at zope.com"  />
        </td>
      </tr>
      <tr>
        <td>
          <input class="textType" id="test.4.name"
name="test.4.name"
                 size="20" type="text" value="Joe
Walsh"  />
        </td>
        <td>
          <input class="textType" id="test.4.email"
name="test.4.email"
                 size="20" type="text"
value="joe at zope.com"  />
        </td>
      </tr>
    </tbody>
    </table>


== tests.py ==

This is a little messy, alot of setup goes into making
Choice fields work in doctests. Most of it was
shamelessly pasted from Daryl Cousins work.


import unittest
from zope import component
from zope.app.testing import placelesssetup
import zope.publisher.interfaces.browser
import zope.schema.interfaces
import zope.app.form.browser
from zope.formlib.tests import formSetUp
import zope.component.testing


from zope.app.testing import ztapi
from zope.schema.interfaces import IChoice
from zope.app.form.browser import ChoiceInputWidget
from zope.app.form.browser import ChoiceDisplayWidget
from zope.app.form.interfaces import IInputWidget
from zope.app.form.interfaces import IDisplayWidget
from zope.schema.interfaces import
IVocabularyTokenized
from zope.publisher.interfaces.browser import
IBrowserRequest
from zope.app.form.browser import DropdownWidget
from zope.app.form.browser import ChoiceDisplayWidget

def setupVocabularyWidgets():
    """Vocabulary Choice Widgets"""
    
    ztapi.browserViewProviding(IChoice,
ChoiceInputWidget, IInputWidget)
    ztapi.browserViewProviding(IChoice,
ChoiceDisplayWidget, IDisplayWidget)
    ztapi.provideMultiView((IChoice,
IVocabularyTokenized),
                           IBrowserRequest,
IInputWidget, '',
                           DropdownWidget)
    ztapi.provideMultiView((IChoice,
IVocabularyTokenized),
                           IBrowserRequest,
IDisplayWidget, '',
                           ChoiceDisplayWidget)
    
   

def columnSetUp(test):
    placelesssetup.setUp(test)
    component.provideAdapter(
        zope.app.form.browser.TextWidget,
        (zope.schema.interfaces.ITextLine,
        
zope.publisher.interfaces.browser.IBrowserRequest,
         ),
        zope.app.form.interfaces.IInputWidget)
    component.provideAdapter(
        zope.app.form.browser.CheckBoxWidget,
        (zope.schema.interfaces.IBool,
        
zope.publisher.interfaces.browser.IBrowserRequest,
         ),
        zope.app.form.interfaces.IInputWidget)

    component.provideAdapter(
        zope.app.form.browser.ChoiceDisplayWidget,
        [zope.schema.interfaces.IChoice,
        
zope.publisher.interfaces.browser.IBrowserRequest,
         ],
        zope.app.form.interfaces.IDisplayWidget,
        )
    component.provideAdapter(
        zope.app.form.browser.ChoiceInputWidget,
        [zope.schema.interfaces.IChoice,
        
zope.publisher.interfaces.browser.IBrowserRequest,
         ],
        zope.app.form.interfaces.IInputWidget,
        )
    setupVocabularyWidgets()
    component.provideAdapter(TestTemplate,
name='default')
    component.provideAdapter(render_submit_button,
name='render')
    
from zope import app, schema, publisher, i18n
from zope import component
from zope.app.form.browser.exception import
WidgetInputErrorView
from zope.formlib.form import render_submit_button
from zope.formlib import namedtemplate
from zope.formlib import interfaces
from zope.app.form.interfaces import WidgetInputError

def renderWidget(result, w):
    result.append(w())
    error = w.error()
    if error:
        result.append(str(error))
    return result

@component.adapter(interfaces.IForm)
@namedtemplate.NamedTemplateImplementation
def TestTemplate(self):
    status = self.status
    if status:
        print getStatus(status, self.request)
    result = []
    if self.errors:
        result = returnError(result, self.request,
self.errors)
    for w in self.widgets:
        result.append(w.label)
        result = renderWidget(result, w)
    for action in self.availableActions():
        result.append(action.render())
    return '\n'.join(result)
    
def test_suite():
    from zope.testing import doctest
    return unittest.TestSuite((
        doctest.DocFileSuite('README.txt',
             setUp = formSetUp,
tearDown=zope.component.testing.tearDown,
           
optionflags=doctest.NORMALIZE_WHITESPACE+doctest.ELLIPSIS,
            ),
        doctest.DocFileSuite(
            'column.txt',
            setUp = columnSetUp,
tearDown=placelesssetup.tearDown,
           
optionflags=doctest.NORMALIZE_WHITESPACE+doctest.ELLIPSIS,
            ),
        doctest.DocFileSuite(
            'fieldcolumn.txt',
            setUp = columnSetUp,
tearDown=placelesssetup.tearDown,
           
optionflags=doctest.NORMALIZE_WHITESPACE+doctest.ELLIPSIS,
            ),
        ))

if __name__ == '__main__':
    unittest.main(defaultTest='test_suite')





--- Gary Poster <gary at zope.com> wrote:

> 
> On Jan 24, 2007, at 2:02 AM,
> <ksmith93940-dev at yahoo.com> wrote:
> 
> > Does anyone know if there is a trick in getting
> Choice
> > schema's to work with zc.table FieldColumn or am I
> > likely doing something wrong?
> 
> We've used a Choice field, I'm pretty sure. 
> Maybe...try modifying  
> the doctest to add use of a choice field as an
> example for others to  
> follow?  If it works, then you have proof that you
> are on the right  
> track, and a useful addition to check in; and if it
> doesn't, you have  
> a more concrete error report and/or question to send
> to the list.
> 
> Gary
> 
> 



More information about the Zope3-users mailing list