Hi Z3 community, I've written tuple and list widgets for the z3c.form framework, i.e. widgets for a schema-fields like
some_tuple_field = zope.schema.Tuple( title = u"Tuple of text lines", value_type = zope.schema.Text(title = u"Text line",), ) other_list_field = zope.schema.List( title = u"List of Integers", value_type = zope.schema.Int(title = u"Integer",), ) Maybe someone is interested in it and wants to reuse or improve it. The reason for me to write these widgets was that I liked the z3c.form package but my content objects have lots of tuples--my app is a sort of bibtex-database based on zope 3. So I decided to try to write the widget that was missing instead of lots of subforms... The tarball contains the widgets and a little demo app. The demo app comes with a skin called "SequenceDemo" and lets you add, edit and display tuples of integers. To try it, you have to include the sequence_demo.zcml in your config. To reuse the widgets in other apps you have to include sequence.zcml There are still 2 bugs that I know: 1) Reporting errors of subwidgets: The toFieldValue-method of the dataconverter looks up a dataconverter for the subwidgets and then uses it to convert and validate the values from the subwidgets. It collects the exceptions that occur on the conversion and finally raises the first exception that occured (see comment on code in sequence.py) When the validation of the subwidget fails there is a traversal error for a 'label' attribute on a widget. I did not yet dig that deep into the z3c.form framework to solve this. See traceback below. 2) If the schema defines a default value for the value_type of a tuple or list, this default value is displayed in edit and display forms instead of the actual value. If you want to reproduce this error, uncomment the default = 1 statement in IIntegerTuple (sequence_demo.py). I think to squashbug one would have to reimplement some steps of the update method which currently reuses the logic of the update method of z3c.form.widget.Widget (I think Step 1.2.1) Or: Maybe one yust would have to write a datamanager. Cheers, Christian PS. Here is the traceback for the first bug (I entered an integer that exceeds the max bound) Traceback (most recent call last): Module zope.publisher.publish, line 133, in publish result = publication.callObject(request, obj) Module zope.app.publication.zopepublication, line 166, in callObject return mapply(ob, request.getPositionalArguments(), request) Module zope.publisher.publish, line 108, in mapply return debug_call(obj, args) - __traceback_info__: <security proxied z3c.pagelet.zcml.IntegerTupleAddForm instance at 0xb15b22cc> Module zope.publisher.publish, line 114, in debug_call return obj(*args) Module z3c.formui.layout, line 51, in __call__ return layout(self) Module zope.app.pagetemplate.viewpagetemplatefile, line 51, in __call__ sourceAnnotations=getattr(debug_flags, 'sourceAnnotations', 0), Module zope.pagetemplate.pagetemplate, line 115, in pt_render strictinsert=0, sourceAnnotations=sourceAnnotations)() Module zope.tal.talinterpreter, line 271, in __call__ self.interpret(self.program) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 742, in do_insertStructure_tal structure = self.engine.evaluateStructure(expr) Module zope.tales.tales, line 696, in evaluate return expression(self) - /home/clueck/tools/sequencewidget/src/sequencewidget/sequence_demo.pt - Line 26, Column 4 - Expression: <StringExpr u'pagelet'> - Names: {'args': (), 'context': <zope.app.folder.folder.Folder object at 0xb7049e2c>, 'default': <object object at 0xb7dd3518>, 'loop': {}, 'nothing': None, 'options': {}, 'repeat': {}, 'request': <zope.publisher.browser.BrowserRequest instance URL=http://localhost:8080/++skin++SequenceDemo/@@addIntegerTuple.html>, 'template': <zope.app.pagetemplate.viewpagetemplatefile.ViewPageTemplateFile object at 0xb69764ec>, 'view': <z3c.pagelet.zcml.IntegerTupleAddForm object at 0xb15b22cc>, 'views': <zope.app.pagetemplate.viewpagetemplatefile.ViewMapper object at 0xb15b2b4c>} Module zope.contentprovider.tales, line 80, in __call__ return provider.render() Module z3c.pagelet.provider, line 44, in render return self.__parent__.render() Module z3c.formui.form, line 44, in render return template(self) Module zope.app.pagetemplate.viewpagetemplatefile, line 51, in __call__ sourceAnnotations=getattr(debug_flags, 'sourceAnnotations', 0), Module zope.pagetemplate.pagetemplate, line 115, in pt_render strictinsert=0, sourceAnnotations=sourceAnnotations)() Module zope.tal.talinterpreter, line 271, in __call__ self.interpret(self.program) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 858, in do_defineMacro self.interpret(macro) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 858, in do_defineMacro self.interpret(macro) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 533, in do_optTag_tal self.do_optTag(stuff) Module zope.tal.talinterpreter, line 518, in do_optTag return self.no_tag(start, program) Module zope.tal.talinterpreter, line 513, in no_tag self.interpret(program) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 954, in do_defineSlot self.interpret(block) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 954, in do_defineSlot self.interpret(block) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 533, in do_optTag_tal self.do_optTag(stuff) Module zope.tal.talinterpreter, line 518, in do_optTag return self.no_tag(start, program) Module zope.tal.talinterpreter, line 513, in no_tag self.interpret(program) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 858, in do_defineMacro self.interpret(macro) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 852, in do_condition self.interpret(block) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 858, in do_defineMacro self.interpret(macro) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 852, in do_condition self.interpret(block) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 821, in do_loop_tal self.interpret(block) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 852, in do_condition self.interpret(block) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 533, in do_optTag_tal self.do_optTag(stuff) Module zope.tal.talinterpreter, line 518, in do_optTag return self.no_tag(start, program) Module zope.tal.talinterpreter, line 513, in no_tag self.interpret(program) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 531, in do_optTag_tal self.no_tag(stuff[-2], stuff[-1]) Module zope.tal.talinterpreter, line 513, in no_tag self.interpret(program) Module zope.tal.talinterpreter, line 343, in interpret handlers[opcode](self, args) Module zope.tal.talinterpreter, line 620, in do_insertText_tal text = self.engine.evaluateText(stuff[0]) Module zope.tales.tales, line 704, in evaluateText text = self.evaluate(expr) Module zope.tales.tales, line 696, in evaluate return expression(self) - /home/clueck/.buildout-eggs/z3c.formui-1.4.2-py2.4.egg/z3c/formui/div-form.pt - Line 40, Column 14 - Expression: <PathExpr standard:u'error/widget/label'> - Names: {'args': (), 'context': <zope.app.folder.folder.Folder object at 0xb7049e2c>, 'default': <object object at 0xb7dd3518>, 'loop': {}, 'nothing': None, 'options': {}, 'repeat': {}, 'request': <zope.publisher.browser.BrowserRequest instance URL=http://localhost:8080/++skin++SequenceDemo/@@addIntegerTuple.html>, 'template': <zope.app.pagetemplate.viewpagetemplatefile.ViewPageTemplateFile object at 0xb69642ec>, 'view': <z3c.pagelet.zcml.IntegerTupleAddForm object at 0xb15b22cc>, 'views': <zope.app.pagetemplate.viewpagetemplatefile.ViewMapper object at 0xb15b2aec>} Module zope.tales.expressions, line 217, in __call__ return self._eval(econtext) Module zope.tales.expressions, line 194, in _eval ob = self._subexprs[-1](econtext) Module zope.tales.expressions, line 124, in _eval ob = self._traverser(ob, element, econtext) Module zope.app.pagetemplate.engine, line 68, in __call__ request=request) Module zope.traversing.adapters, line 164, in traversePathElement return traversable.traverse(nm, further_path) - __traceback_info__: (<TupleSequenceWidget 'form.widgets.integers'>, 'label') Module zope.traversing.adapters, line 52, in traverse raise TraversalError(subject, name) - __traceback_info__: (<TupleSequenceWidget 'form.widgets.integers'>, 'label', []) TraversalError: (<TupleSequenceWidget 'form.widgets.integers'>, 'label')
sequencewidget.tgz
Description: application/compressed-tar
_______________________________________________ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users