[Checkins] SVN: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/ Move zope.app.form.widget over to zope.formlib.
Martijn Faassen
faassen at startifact.com
Wed Dec 30 13:50:13 EST 2009
Log message for revision 107373:
Move zope.app.form.widget over to zope.formlib.
Changed:
U zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/__init__.py
U zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/boolwidgets.py
U zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/itemswidgets.py
U zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/objectwidget.py
U zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/sequencewidget.py
U zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/source.py
U zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/tests/test_browserwidget.py
U zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/tests/test_displaywidget.py
U zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/textwidgets.py
U zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/widget.py
-=-
Modified: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/__init__.py
===================================================================
--- zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/__init__.py 2009-12-30 18:41:15 UTC (rev 107372)
+++ zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/__init__.py 2009-12-30 18:50:13 UTC (rev 107373)
@@ -17,8 +17,8 @@
"""
__docformat__ = 'restructuredtext'
-from zope.app.form.browser.widget import BrowserWidget, DisplayWidget
-from zope.app.form.browser.widget import UnicodeDisplayWidget
+from zope.formlib.widget import BrowserWidget, DisplayWidget
+from zope.formlib.widget import UnicodeDisplayWidget
from zope.app.form.browser.textwidgets import TextWidget, BytesWidget
from zope.app.form.browser.textwidgets import TextAreaWidget, BytesAreaWidget
Modified: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/boolwidgets.py
===================================================================
--- zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/boolwidgets.py 2009-12-30 18:41:15 UTC (rev 107372)
+++ zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/boolwidgets.py 2009-12-30 18:50:13 UTC (rev 107373)
@@ -20,8 +20,8 @@
from zope.interface import implements
from zope.schema.vocabulary import SimpleVocabulary
-from zope.app.form.browser.widget import SimpleInputWidget, renderElement
-from zope.app.form.browser.widget import DisplayWidget
+from zope.formlib.widget import SimpleInputWidget, renderElement
+from zope.formlib.widget import DisplayWidget
from zope.app.form.browser.i18n import _
from zope.app.form.browser.itemswidgets import RadioWidget
from zope.app.form.browser.itemswidgets import SelectWidget, DropdownWidget
Modified: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/itemswidgets.py
===================================================================
--- zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/itemswidgets.py 2009-12-30 18:41:15 UTC (rev 107372)
+++ zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/itemswidgets.py 2009-12-30 18:50:13 UTC (rev 107373)
@@ -24,7 +24,7 @@
from zope.schema.interfaces import ValidationError, InvalidValue
from zope.schema.interfaces import ConstraintNotSatisfied, ITitledTokenizedTerm
-from zope.app.form.browser.widget import SimpleInputWidget, renderElement
+from zope.formlib.widget import SimpleInputWidget, renderElement
from zope.formlib.interfaces import IInputWidget, IDisplayWidget
from zope.formlib.interfaces import ConversionError
from zope.app.form.browser.i18n import _
Modified: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/objectwidget.py
===================================================================
--- zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/objectwidget.py 2009-12-30 18:41:15 UTC (rev 107372)
+++ zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/objectwidget.py 2009-12-30 18:50:13 UTC (rev 107373)
@@ -23,7 +23,7 @@
from zope.formlib.interfaces import IInputWidget
from zope.app.form import InputWidget
-from zope.app.form.browser.widget import BrowserWidget
+from zope.formlib.widget import BrowserWidget
from zope.app.form.utility import setUpWidgets, applyWidgetsChanges
from zope.browserpage import ViewPageTemplateFile
from zope.app.form.browser.interfaces import IWidgetInputErrorView
Modified: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/sequencewidget.py
===================================================================
--- zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/sequencewidget.py 2009-12-30 18:41:15 UTC (rev 107372)
+++ zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/sequencewidget.py 2009-12-30 18:50:13 UTC (rev 107373)
@@ -26,8 +26,8 @@
from zope.formlib.interfaces import WidgetInputError, MissingInputError
from zope.app.form import InputWidget
from zope.app.form.browser.i18n import _
-from zope.app.form.browser.widget import BrowserWidget
-from zope.app.form.browser.widget import DisplayWidget, renderElement
+from zope.formlib.widget import BrowserWidget
+from zope.formlib.widget import DisplayWidget, renderElement
from zope.browserpage import ViewPageTemplateFile
Modified: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/source.py
===================================================================
--- zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/source.py 2009-12-30 18:41:15 UTC (rev 107372)
+++ zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/source.py 2009-12-30 18:50:13 UTC (rev 107373)
@@ -28,7 +28,7 @@
ISourceQueriables, ValidationError, IVocabularyTokenized, IIterableSource
import zope.formlib.interfaces
-import zope.app.form.browser.widget
+import zope.formlib.widget
import zope.app.form.browser.interfaces
from zope.formlib.interfaces import WidgetInputError, MissingInputError
from zope.app.form.browser.i18n import _
@@ -39,7 +39,7 @@
import zope.app.form.browser.itemswidgets
-class SourceDisplayWidget(zope.app.form.browser.widget.DisplayWidget):
+class SourceDisplayWidget(zope.formlib.widget.DisplayWidget):
implements(zope.formlib.interfaces.IDisplayWidget)
Modified: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/tests/test_browserwidget.py
===================================================================
--- zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/tests/test_browserwidget.py 2009-12-30 18:41:15 UTC (rev 107372)
+++ zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/tests/test_browserwidget.py 2009-12-30 18:50:13 UTC (rev 107373)
@@ -22,7 +22,7 @@
from zope.schema import Text, Int
from zope.testing.doctest import DocTestSuite
-from zope.app.form.browser.widget import SimpleInputWidget
+from zope.formlib.widget import SimpleInputWidget
from zope.app.form.browser.tests import support
from zope.formlib.interfaces import ConversionError
from zope.formlib.interfaces import WidgetInputError, MissingInputError
@@ -207,7 +207,7 @@
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(Test))
- suite.addTest(DocTestSuite("zope.app.form.browser.widget"))
+ suite.addTest(DocTestSuite("zope.formlib.widget"))
return suite
if __name__ == '__main__':
Modified: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/tests/test_displaywidget.py
===================================================================
--- zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/tests/test_displaywidget.py 2009-12-30 18:41:15 UTC (rev 107372)
+++ zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/tests/test_displaywidget.py 2009-12-30 18:50:13 UTC (rev 107373)
@@ -22,7 +22,7 @@
from zope.schema import TextLine
from zope.testing.doctest import DocTestSuite
-from zope.app.form.browser.widget import DisplayWidget, UnicodeDisplayWidget
+from zope.formlib.widget import DisplayWidget, UnicodeDisplayWidget
def test_implemented_interfaces():
Modified: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/textwidgets.py
===================================================================
--- zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/textwidgets.py 2009-12-30 18:41:15 UTC (rev 107372)
+++ zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/textwidgets.py 2009-12-30 18:50:13 UTC (rev 107373)
@@ -27,8 +27,8 @@
from zope.formlib.interfaces import IInputWidget, ConversionError
from zope.app.form.browser.i18n import _
from zope.app.form.browser.interfaces import ITextBrowserWidget
-from zope.app.form.browser.widget import SimpleInputWidget, renderElement
-from zope.app.form.browser.widget import DisplayWidget
+from zope.formlib.widget import SimpleInputWidget, renderElement
+from zope.formlib.widget import DisplayWidget
def escape(str):
Modified: zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/widget.py
===================================================================
--- zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/widget.py 2009-12-30 18:41:15 UTC (rev 107372)
+++ zope.app.form/branches/faassen-zaf/src/zope/app/form/browser/widget.py 2009-12-30 18:50:13 UTC (rev 107373)
@@ -17,535 +17,13 @@
"""
__docformat__ = 'restructuredtext'
-from xml.sax.saxutils import quoteattr, escape
-
-from zope.component import getMultiAdapter
-from zope.interface import implements
-from zope.schema.interfaces import ValidationError
-from zope.publisher.browser import BrowserView
-
-from zope.app.form import Widget, InputWidget
-from zope.formlib.interfaces import ConversionError
-from zope.formlib.interfaces import InputErrors
-from zope.formlib.interfaces import WidgetInputError, MissingInputError
-from zope.app.form.browser.interfaces import IBrowserWidget
-from zope.app.form.browser.interfaces import ISimpleInputWidget
-from zope.app.form.browser.interfaces import IWidgetInputErrorView
-
-import warnings
-
-
-if quoteattr("\r") != '"&13;"':
- _quoteattr = quoteattr
-
- def quoteattr(data):
- return _quoteattr(
- data, {'\n': ' ', '\r': ' ', '\t':'	'})
-
-
-class BrowserWidget(Widget, BrowserView):
- """Base class for browser widgets.
-
- >>> setUp()
-
- The class provides some basic functionality common to all browser widgets.
-
- Browser widgets have a `required` attribute, which indicates whether or
- not the underlying field requires input. By default, the widget's required
- attribute is equal to the field's required attribute:
-
- >>> from zope.schema import Field
- >>> from zope.publisher.browser import TestRequest
- >>> field = Field(required=True)
- >>> widget = BrowserWidget(field, TestRequest())
- >>> widget.required
- True
- >>> field.required = False
- >>> widget = BrowserWidget(field, TestRequest())
- >>> widget.required
- False
-
- However, the two `required` values are independent of one another:
-
- >>> field.required = True
- >>> widget.required
- False
-
- Browser widgets have an error state, which can be rendered in a form using
- the `error()` method. The error method delegates the error rendering to a
- view that is registered as providing `IWidgetInputErrorView`. To
- illustrate, we can create and register a simple error display view:
-
- >>> from zope.formlib.interfaces import IWidgetInputError
- >>> class SnippetErrorView:
- ... implements(IWidgetInputErrorView)
- ... def __init__(self, context, request):
- ... self.context = context
- ... def snippet(self):
- ... return "The error: " + str(self.context.errors)
- >>> from zope.app.testing import ztapi
- >>> ztapi.browserViewProviding(IWidgetInputError, SnippetErrorView,
- ... IWidgetInputErrorView)
-
- Whever an error occurs, widgets should set _error:
-
- >>> widget._error = WidgetInputError('foo', 'Foo', ('Err1', 'Err2'))
-
- so that it can be displayed using the error() method:
-
- >>> widget.error()
- "The error: ('Err1', 'Err2')"
-
- >>> tearDown()
-
- """
-
- implements(IBrowserWidget)
-
- _error = None
-
- def __init__(self, context, request):
- super(BrowserWidget, self).__init__(context, request)
- self.required = context.required
-
- def error(self):
- if self._error:
- return getMultiAdapter((self._error, self.request),
- IWidgetInputErrorView).snippet()
- return ""
-
- def hidden(self):
- return ""
-
-
-class SimpleInputWidget(BrowserWidget, InputWidget):
- """A baseclass for simple HTML form widgets.
-
- >>> setUp()
-
- Simple input widgets read input from a browser form. To illustrate, we
- will use a test request with two form values:
-
- >>> from zope.publisher.browser import TestRequest
- >>> request = TestRequest(form={
- ... 'field.foo': u'hello\\r\\nworld',
- ... 'baz.foo': u'bye world'})
-
- Like all widgets, simple input widgets are a view to a field context:
-
- >>> from zope.schema import Field
- >>> field = Field(__name__='foo', title=u'Foo')
- >>> widget = SimpleInputWidget(field, request)
-
- Widgets are named using their field's name:
-
- >>> widget.name
- 'field.foo'
-
- The default implementation for the widget label is to use the field title:
-
- >>> widget.label
- u'Foo'
-
- According the request, the widget has input because 'field.foo' is
- present:
-
- >>> widget.hasInput()
- True
- >>> widget.getInputValue()
- u'hello\\r\\nworld'
-
- Widgets maintain an error state, which is used to communicate invalid
- input or other errors:
-
- >>> widget._error is None
- True
- >>> widget.error()
- ''
-
- `setRenderedValue` is used to specify the value displayed by the widget to
- the user. This value, however, is not the same as the input value, which
- is read from the request:
-
- >>> widget.setRenderedValue('Hey\\nfolks')
- >>> widget.getInputValue()
- u'hello\\r\\nworld'
- >>> widget._error is None
- True
- >>> widget.error()
- ''
-
- You can use 'setPrefix' to remove or modify the prefix used to create the
- widget name as follows:
-
- >>> widget.setPrefix('')
- >>> widget.name
- 'foo'
- >>> widget.setPrefix('baz')
- >>> widget.name
- 'baz.foo'
-
- `getInputValue` always returns a value that can legally be assigned to
- the widget field. To illustrate widget validation, we can add a constraint
- to its field:
-
- >>> import re
- >>> field.constraint = re.compile('.*hello.*').match
-
- Because we modified the widget's name, the widget will now read different
- form input:
-
- >>> request.form[widget.name]
- u'bye world'
-
- This input violates the new field constraint and therefore causes an
- error when `getInputValue` is called:
-
- >>> widget.getInputValue()
- Traceback (most recent call last):
- WidgetInputError: ('foo', u'Foo', ConstraintNotSatisfied(u'bye world'))
-
- Simple input widgets require that input be available in the form request.
- If input is not present, a ``MissingInputError`` is raised:
-
- >>> del request.form[widget.name]
- >>> widget.getInputValue()
- Traceback (most recent call last):
- MissingInputError: ('baz.foo', u'Foo', None)
-
- A ``MissingInputError`` indicates that input is missing from the form
- altogether. It does not indicate that the user failed to provide a value
- for a required field. The ``MissingInputError`` above was caused by the
- fact that the form does have any input for the widget:
-
- >>> request.form[widget.name]
- Traceback (most recent call last):
- KeyError: 'baz.foo'
-
- If a user fails to provide input for a field, the form will contain the
- input provided by the user, namely an empty string:
-
- >>> request.form[widget.name] = ''
-
- In such a case, if the field is required, a ``WidgetInputError`` will be
- raised on a call to `getInputValue`:
-
- >>> field.required = True
- >>> widget.getInputValue()
- Traceback (most recent call last):
- WidgetInputError: ('foo', u'Foo', RequiredMissing('foo'))
-
- However, if the field is not required, the empty string will be converted
- by the widget into the field's `missing_value` and read as a legal field
- value:
-
- >>> field.required = False
- >>> widget.getInputValue() is field.missing_value
- True
-
- Another type of exception is a conversion error. It is raised when a value
- cannot be converted to the desired Python object. Here is an example of a
- floating point.
-
- >>> from zope.schema import Float
- >>> field = Float(__name__='price', title=u'Price')
-
- >>> from zope.formlib.interfaces import ConversionError
- >>> class FloatWidget(SimpleInputWidget):
- ... def _toFieldValue(self, input):
- ... try:
- ... return float(input)
- ... except ValueError, v:
- ... raise ConversionError('Invalid floating point data', v)
- ...
- ... def _toFormValue(self, value):
- ... value = super(FloatWidget, self)._toFormValue(value)
- ... return '%.2f' % value
-
- >>> request = TestRequest(form={'field.price': u'32.0'})
- >>> widget = FloatWidget(field, request)
- >>> widget.getInputValue()
- 32.0
- >>> widget()
- u'<input class="textType" id="field.price" name="field.price" type="text" value="32.00" />'
-
- >>> request = TestRequest(form={'field.price': u'<p>foo</p>'})
- >>> widget = FloatWidget(field, request)
- >>> try:
- ... widget.getInputValue()
- ... except ConversionError, error:
- ... print error.doc()
- Invalid floating point data
- >>> widget()
- u'<input class="textType" id="field.price" name="field.price" type="text" value="<p>foo</p>" />'
-
-
- >>> tearDown()
- """
-
- implements(ISimpleInputWidget)
-
- tag = u'input'
- type = u'text'
- cssClass = u''
- extra = u''
- _missing = u''
-
- def hasInput(self):
- """See IWidget.hasInput.
-
- Returns ``True`` if the submitted request form contains a value for
- the widget, otherwise returns False.
-
- Some browser widgets may need to implement a more sophisticated test
- for input. E.g. checkbox values are not supplied in submitted
- forms when their value is 'off' -- in this case the widget will
- need to add a hidden element to signal its presence in the form.
- """
- return self.name in self.request.form
-
- def getInputValue(self):
- self._error = None
- field = self.context
-
- # form input is required, otherwise raise an error
- if not self.hasInput():
- raise MissingInputError(self.name, self.label, None)
-
- # convert input to suitable value - may raise conversion error
- try:
- value = self._toFieldValue(self._getFormInput())
- except ConversionError, error:
- # ConversionError is already a WidgetInputError
- self._error = error
- raise self._error
-
- # allow missing values only for non-required fields
- if value == field.missing_value and not field.required:
- return value
-
- # value must be valid per the field constraints
- try:
- field.validate(value)
- except ValidationError, v:
- self._error = WidgetInputError(
- self.context.__name__, self.label, v)
- raise self._error
- return value
-
- def _getFormInput(self):
- """Returns current form input.
-
- The value returned must be in a format that can be used as the 'input'
- argument to `_toFieldValue`.
-
- The default implementation returns the form value that corresponds to
- the widget's name. Subclasses may override this method if their form
- input consists of more than one form element or use an alternative
- naming convention.
- """
- return self.request.get(self.name)
-
- def _toFieldValue(self, input):
- """Converts input to a value appropriate for the field type.
-
- Widgets for non-string fields should override this method to
- perform an appropriate conversion.
-
- This method is used by getInputValue to perform the conversion
- of form input (provided by `_getFormInput`) to an appropriate field
- value.
- """
- if input == self._missing:
- return self.context.missing_value
- else:
- return input
-
- def _toFormValue(self, value):
- """Converts a field value to a string used as an HTML form value.
-
- This method is used in the default rendering of widgets that can
- represent their values in a single HTML form value. Widgets whose
- fields have more complex data structures should disregard this
- method and override the default rendering method (__call__).
- """
- if value == self.context.missing_value:
- return self._missing
- else:
- return value
-
- def _getCurrentValueHelper(self):
- """Helper to get the current input value.
-
- Raises InputErrors if the data could not be validated/converted.
- """
- input_value = None
- if self._renderedValueSet():
- input_value = self._data
- else:
- if self.hasInput():
- # It's insane to use getInputValue this way. It can
- # cause _error to get set spuriously. We'll work
- # around this by saving and restoring _error if
- # necessary.
- error = self._error
- try:
- input_value = self.getInputValue()
- finally:
- self._error = error
- else:
- input_value = self._getDefault()
- return input_value
-
- def _getCurrentValue(self):
- """Returns the current input value.
-
- Returns None if the data could not be validated/converted.
- """
- try:
- input_value = self._getCurrentValueHelper()
- except InputErrors:
- input_value = None
- return input_value
-
- def _getFormValue(self):
- """Returns a value suitable for use in an HTML form.
-
- Detects the status of the widget and selects either the input value
- that came from the request, the value from the _data attribute or the
- default value.
- """
- try:
- input_value = self._getCurrentValueHelper()
- except InputErrors:
- form_value = self.request.form.get(self.name, self._missing)
- else:
- form_value = self._toFormValue(input_value)
- return form_value
-
- def _getDefault(self):
- """Returns the default value for this widget."""
- return self.context.default
-
- def __call__(self):
- return renderElement(self.tag,
- type=self.type,
- name=self.name,
- id=self.name,
- value=self._getFormValue(),
- cssClass=self.cssClass,
- extra=self.extra)
-
- def hidden(self):
- return renderElement(self.tag,
- type='hidden',
- name=self.name,
- id=self.name,
- value=self._getFormValue(),
- cssClass=self.cssClass,
- extra=self.extra)
-
-class DisplayWidget(BrowserWidget):
-
- def __init__(self, context, request):
- super(DisplayWidget, self).__init__(context, request)
- self.required = False
-
-
- def __call__(self):
- if self._renderedValueSet():
- value = self._data
- else:
- value = self.context.default
- if value == self.context.missing_value:
- return ""
- return escape(value)
-
-
-class UnicodeDisplayWidget(DisplayWidget):
- """Display widget that converts the value to unicode before display."""
-
- def __call__(self):
- if self._renderedValueSet():
- value = self._data
- else:
- value = self.context.default
- if value == self.context.missing_value:
- return ""
- return escape(unicode(value))
-
-
-def renderTag(tag, **kw):
- """Render the tag. Well, not all of it, as we may want to / it."""
- attr_list = []
-
- # special case handling for cssClass
- cssClass = kw.pop('cssClass', u'')
-
- # If the 'type' attribute is given, append this plus 'Type' as a
- # css class. This allows us to do subselector stuff in css without
- # necessarily having a browser that supports css subselectors.
- # This is important if you want to style radio inputs differently than
- # text inputs.
- cssWidgetType = kw.get('type', u'')
- if cssWidgetType:
- cssWidgetType += u'Type'
- names = [c for c in (cssClass, cssWidgetType) if c]
- if names:
- attr_list.append(u'class="%s"' % u' '.join(names))
-
- style = kw.pop('style', u'')
- if style:
- attr_list.append(u'style=%s' % quoteattr(style))
-
- # special case handling for extra 'raw' code
- if 'extra' in kw:
- # could be empty string but we don't care
- extra = u" " + kw.pop('extra')
- else:
- extra = u''
-
- # handle other attributes
- if kw:
- items = kw.items()
- items.sort()
- for key, value in items:
- if value is None:
- warnings.warn(
- "None was passed for attribute %r. Passing None "
- "as attribute values to renderTag is deprecated. "
- "Passing None as an attribute value will be disallowed "
- "starting in Zope 3.3."
- % key,
- DeprecationWarning, stacklevel=2)
- value = key
- attr_list.append(u'%s=%s' % (key, quoteattr(unicode(value))))
-
- if attr_list:
- attr_str = u" ".join(attr_list)
- return u"<%s %s%s" % (tag, attr_str, extra)
- else:
- return u"<%s%s" % (tag, extra)
-
-
-def renderElement(tag, **kw):
- contents = kw.pop('contents', None)
- if contents is not None:
- # Do not quote contents, since it often contains generated HTML.
- return u"%s>%s</%s>" % (renderTag(tag, **kw), contents, tag)
- else:
- return renderTag(tag, **kw) + " />"
-
-
-def setUp():
- import zope.component.testing
- global setUp
- setUp = zope.component.testing.setUp
- setUp()
-
-
-def tearDown():
- import zope.component.testing
- global tearDown
- tearDown = zope.component.testing.tearDown
- tearDown()
+from zope.formlib.widget import (
+ quoteattr,
+ BrowserWidget,
+ SimpleInputWidget,
+ DisplayWidget,
+ UnicodeDisplayWidget,
+ renderTag,
+ renderElement,
+ setUp,
+ tearDown)
More information about the checkins
mailing list