Skip to content

Commit

Permalink
improve coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Groszer committed Dec 8, 2008
1 parent 2a3b127 commit 02fffed
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 11 deletions.
59 changes: 55 additions & 4 deletions src/z3c/form/browser/object.txt
Expand Up @@ -27,10 +27,6 @@ examples:
>>> from z3c.form.testing import MySubObject
>>> from z3c.form.testing import MySecond

>>> from z3c.form.object import registerFactoryAdapter
>>> registerFactoryAdapter(IMySubObject, MySubObject)
>>> registerFactoryAdapter(IMySecond, MySecond)

>>> from z3c.form.object import SubformAdapter
>>> zope.component.provideAdapter(SubformAdapter)

Expand Down Expand Up @@ -255,6 +251,18 @@ The marker must stay (we have to modify the same object):

>>> converter = interfaces.IDataConverter(widget)

>>> value = converter.toFieldValue(wv)
Traceback (most recent call last):
...
ValueError: No IObjectFactory adapter registered for z3c.form.testing.IMySubObject

We have to register object factory adapters to allow the objectwidget to
create objects:

>>> from z3c.form.object import registerFactoryAdapter
>>> registerFactoryAdapter(IMySubObject, MySubObject)
>>> registerFactoryAdapter(IMySecond, MySecond)

>>> value = converter.toFieldValue(wv)
>>> value
<z3c.form.testing.MySubObject object at ...>
Expand All @@ -271,6 +279,49 @@ This is a different object:
AttributeError: 'MySubObject' object has no attribute '__marker__'


Setting missing values on the widget works too:

>>> widget.value = converter.toWidgetValue(field.missing_value)

>>> widget.update()

Default values get rendered:

>>> print widget.render()
<div class="object-widget required">
<div class="label">
<label for="subobject-widgets-foofield">
<span>My foo field</span>
<span class="required">*</span>
</label>
</div>
<div class="widget">
<input id="subobject-widgets-foofield"
name="subobject.widgets.foofield"
class="text-widget required int-field" value="2" type="text" />
</div>
<div class="label">
<label for="subobject-widgets-barfield">
<span>My dear bar</span>
</label>
</div>
<div class="widget">
<input id="subobject-widgets-barfield"
name="subobject.widgets.barfield"
class="text-widget int-field" value="999" type="text" />
</div>
<input name="subobject-empty-marker" type="hidden" value="1" />
</div>

But on the return we get default values back:

>>> widget.value
{'foofield': 2, 'barfield': 999}

>>> value = converter.toFieldValue(widget.value)
>>> value
<z3c.form.testing.MySubObject object at ...>

HMMMM.... do we have to test error handling here?
I'm tempted to leave it out as no widgets seem to do this.

Expand Down
7 changes: 1 addition & 6 deletions src/z3c/form/object.py
Expand Up @@ -290,6 +290,7 @@ def makeDummyObject(iface):
return dummy

######## special template factory that takes the field.schema into account
######## used by zcml.py

class ObjectWidgetTemplateFactory(object):
"""Widget template factory."""
Expand Down Expand Up @@ -341,9 +342,6 @@ def __call__(self):
obj = self.factory(self.context, self.request, self.widget)
return obj

def __repr__(self):
return '<%s %r>' % (self.__class__.__name__, self.__name__)

class FactoryAdapter(object):
"""Most basic-default object factory adapter"""

Expand All @@ -368,9 +366,6 @@ def __call__(self, value):
zope.event.notify(zope.lifecycleevent.ObjectCreatedEvent(obj))
return obj

def __repr__(self):
return '<%s %r>' % (self.__class__.__name__, self.__name__)

# XXX: Probably we should offer an register factrory method which allows to
# use all discriminators e.g. context, request, form, widget as optional
# arguments. But can probably do that later in a ZCML directive
Expand Down
3 changes: 2 additions & 1 deletion src/z3c/form/tests/test_doc.py
Expand Up @@ -141,6 +141,7 @@ def test_suite():
optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
checker=checker,
))
for setUp in (testing.setUpZPT, testing.setUpZ3CPT))
#for setUp in (testing.setUpZPT, testing.setUpZ3CPT))
for setUp in (testing.setUpZPT, ))

return unittest.TestSuite(itertools.chain(*tests))
141 changes: 141 additions & 0 deletions src/z3c/form/zcml.txt
Expand Up @@ -107,6 +107,147 @@ immediately:
ConfigurationError: ('No such file', '...unknown.pt')


Object Widget template directive
--------------------------------

Show how we can use the objectwidget template directive.

The big difference between the 'simple' Widget template and the Object Widget
directive is that the Object Widget template takes the field's schema into
account. That makes it easy to register different widget templates for different
sub-schemas. You can use this together with SubformAdapter to get a totally
custom subwidget.

We need a custom widget template

>>> file = os.path.join(temp_dir, 'widget.pt')
>>> open(file, 'w').write('''
... <html xmlns="http://www.w3.org/1999/xhtml"
... xmlns:tal="http://xml.zope.org/namespaces/tal"
... tal:omit-tag="">
... <div class="object-widget" tal:attributes="class view/klass">
... yeah, this can get comlex
... </div>
... </html>
... ''')

and a interface

>>> class IMyObjectWidget(interfaces.IObjectWidget):
... """My objectwidget interface."""

and a widget class:

>>> from z3c.form.browser import object
>>> class MyObjectWidget(object.ObjectWidget):
... zope.interface.implements(IMyObjectWidget)
>>> request = TestRequest()
>>> myObjectWidget = MyObjectWidget(request)

>>> from z3c.form.testing import IMySubObject
>>> import zope.schema
>>> field = zope.schema.Object(
... __name__='subobject',
... title=u'my object widget',
... schema=IMySubObject)
>>> myObjectWidget.field = field

Make them available under the fake package ``custom``:

>>> sys.modules['custom'] = type(
... 'Module', (),
... {'IMyObjectWidget': IMyObjectWidget})()

and register them as a widget template within the ``z3c:objectWidgetTemplate``
directive:

>>> context = xmlconfig.string("""
... <configure
... xmlns:z3c="http://namespaces.zope.org/z3c">
... <z3c:objectWidgetTemplate
... template="%s"
... widget="custom.IMyObjectWidget"
... />
... </configure>
... """ % file, context=context)

Let's get the template

>>> template = zope.component.queryMultiAdapter((None, request, None, None,
... myObjectWidget, None), interface=IPageTemplate, name='input')

and check it:

>>> isinstance(template, ViewPageTemplateFile)
True

Let's use the template within the widget.

>>> print template(myObjectWidget)
<div class="object-widget">yeah, this can get comlex</div>

We normally render the widget which returns the registered template.

>>> print myObjectWidget.render()
<div class="object-widget">yeah, this can get comlex</div>

If the template does not exist, then the widget directive should fail
immediately:

>>> unknownFile = os.path.join(temp_dir, 'unknown.pt')
>>> context = xmlconfig.string("""
... <configure
... xmlns:z3c="http://namespaces.zope.org/z3c">
... <z3c:objectWidgetTemplate
... template="%s"
... widget="custom.IMyObjectWidget"
... />
... </configure>
... """ % unknownFile, context=context)
Traceback (most recent call last):
...
ZopeXMLConfigurationError: File "<string>", line 4.2-7.8
ConfigurationError: ('No such file', '...unknown.pt')


Register a specific template for a schema:

We need a custom widget template

>>> file = os.path.join(temp_dir, 'widgetspec.pt')
>>> open(file, 'w').write('''
... <html xmlns="http://www.w3.org/1999/xhtml"
... xmlns:tal="http://xml.zope.org/namespaces/tal"
... tal:omit-tag="">
... <div class="object-widget" tal:attributes="class view/klass">
... this one is specific
... </div>
... </html>
... ''')

>>> context = xmlconfig.string("""
... <configure
... xmlns:z3c="http://namespaces.zope.org/z3c">
... <z3c:objectWidgetTemplate
... template="%s"
... widget="custom.IMyObjectWidget"
... schema="z3c.form.testing.IMySubObject"
... />
... </configure>
... """ % file, context=context)

Let's get the template

>>> template = zope.component.queryMultiAdapter((None, request, None, None,
... myObjectWidget, None), interface=IPageTemplate, name='input')

and check it:

>>> print myObjectWidget.render()
<div class="object-widget">this one is specific</div>



Cleanup
-------

Expand Down

0 comments on commit 02fffed

Please sign in to comment.