zope.formlib-4.3.0a2/0000775000000000000000000000000012355055056013055 5ustar rootrootzope.formlib-4.3.0a2/bootstrap.py0000664000000000000000000002443512243456432015453 0ustar rootroot############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Bootstrap a buildout-based project Simply run this script in a directory containing a buildout.cfg. The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. """ import os, shutil, sys, tempfile, urllib, urllib2, subprocess from optparse import OptionParser if sys.platform == 'win32': def quote(c): if ' ' in c: return '"%s"' % c # work around spawn lamosity on windows else: return c else: quote = str # See zc.buildout.easy_install._has_broken_dash_S for motivation and comments. stdout, stderr = subprocess.Popen( [sys.executable, '-Sc', 'try:\n' ' import ConfigParser\n' 'except ImportError:\n' ' print 1\n' 'else:\n' ' print 0\n'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() has_broken_dash_S = bool(int(stdout.strip())) # In order to be more robust in the face of system Pythons, we want to # run without site-packages loaded. This is somewhat tricky, in # particular because Python 2.6's distutils imports site, so starting # with the -S flag is not sufficient. However, we'll start with that: if not has_broken_dash_S and 'site' in sys.modules: # We will restart with python -S. args = sys.argv[:] args[0:0] = [sys.executable, '-S'] args = map(quote, args) os.execv(sys.executable, args) # Now we are running with -S. We'll get the clean sys.path, import site # because distutils will do it later, and then reset the path and clean # out any namespace packages from site-packages that might have been # loaded by .pth files. clean_path = sys.path[:] import site # imported because of its side effects sys.path[:] = clean_path for k, v in sys.modules.items(): if k in ('setuptools', 'pkg_resources') or ( hasattr(v, '__path__') and len(v.__path__) == 1 and not os.path.exists(os.path.join(v.__path__[0], '__init__.py'))): # This is a namespace package. Remove it. sys.modules.pop(k) is_jython = sys.platform.startswith('java') setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py' distribute_source = 'http://python-distribute.org/distribute_setup.py' # parsing arguments def normalize_to_url(option, opt_str, value, parser): if value: if '://' not in value: # It doesn't smell like a URL. value = 'file://%s' % ( urllib.pathname2url( os.path.abspath(os.path.expanduser(value))),) if opt_str == '--download-base' and not value.endswith('/'): # Download base needs a trailing slash to make the world happy. value += '/' else: value = None name = opt_str[2:].replace('-', '_') setattr(parser.values, name, value) usage = '''\ [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] Bootstraps a buildout-based project. Simply run this script in a directory containing a buildout.cfg, using the Python that you want bin/buildout to use. Note that by using --setup-source and --download-base to point to local resources, you can keep this script from going over the network. ''' parser = OptionParser(usage=usage) parser.add_option("-v", "--version", dest="version", help="use a specific zc.buildout version") parser.add_option("-d", "--distribute", action="store_true", dest="use_distribute", default=False, help="Use Distribute rather than Setuptools.") parser.add_option("--setup-source", action="callback", dest="setup_source", callback=normalize_to_url, nargs=1, type="string", help=("Specify a URL or file location for the setup file. " "If you use Setuptools, this will default to " + setuptools_source + "; if you use Distribute, this " "will default to " + distribute_source + ".")) parser.add_option("--download-base", action="callback", dest="download_base", callback=normalize_to_url, nargs=1, type="string", help=("Specify a URL or directory for downloading " "zc.buildout and either Setuptools or Distribute. " "Defaults to PyPI.")) parser.add_option("--eggs", help=("Specify a directory for storing eggs. Defaults to " "a temporary directory that is deleted when the " "bootstrap script completes.")) parser.add_option("-t", "--accept-buildout-test-releases", dest='accept_buildout_test_releases', action="store_true", default=False, help=("Normally, if you do not specify a --version, the " "bootstrap script and buildout gets the newest " "*final* versions of zc.buildout and its recipes and " "extensions for you. If you use this flag, " "bootstrap and buildout will get the newest releases " "even if they are alphas or betas.")) parser.add_option("-c", None, action="store", dest="config_file", help=("Specify the path to the buildout configuration " "file to be used.")) options, args = parser.parse_args() if options.eggs: eggs_dir = os.path.abspath(os.path.expanduser(options.eggs)) else: eggs_dir = tempfile.mkdtemp() if options.setup_source is None: if options.use_distribute: options.setup_source = distribute_source else: options.setup_source = setuptools_source if options.accept_buildout_test_releases: args.insert(0, 'buildout:accept-buildout-test-releases=true') try: import pkg_resources import setuptools # A flag. Sometimes pkg_resources is installed alone. if not hasattr(pkg_resources, '_distribute'): raise ImportError except ImportError: ez_code = urllib2.urlopen( options.setup_source).read().replace('\r\n', '\n') ez = {} exec ez_code in ez setup_args = dict(to_dir=eggs_dir, download_delay=0) if options.download_base: setup_args['download_base'] = options.download_base if options.use_distribute: setup_args['no_fake'] = True if sys.version_info[:2] == (2, 4): setup_args['version'] = '0.6.32' ez['use_setuptools'](**setup_args) if 'pkg_resources' in sys.modules: reload(sys.modules['pkg_resources']) import pkg_resources # This does not (always?) update the default working set. We will # do it. for path in sys.path: if path not in pkg_resources.working_set.entries: pkg_resources.working_set.add_entry(path) cmd = [quote(sys.executable), '-c', quote('from setuptools.command.easy_install import main; main()'), '-mqNxd', quote(eggs_dir)] if not has_broken_dash_S: cmd.insert(1, '-S') find_links = options.download_base if not find_links: find_links = os.environ.get('bootstrap-testing-find-links') if not find_links and options.accept_buildout_test_releases: find_links = 'http://downloads.buildout.org/' if find_links: cmd.extend(['-f', quote(find_links)]) if options.use_distribute: setup_requirement = 'distribute' else: setup_requirement = 'setuptools' ws = pkg_resources.working_set setup_requirement_path = ws.find( pkg_resources.Requirement.parse(setup_requirement)).location env = dict( os.environ, PYTHONPATH=setup_requirement_path) requirement = 'zc.buildout' version = options.version if version is None and not options.accept_buildout_test_releases: # Figure out the most recent final version of zc.buildout. import setuptools.package_index _final_parts = '*final-', '*final' def _final_version(parsed_version): for part in parsed_version: if (part[:1] == '*') and (part not in _final_parts): return False return True index = setuptools.package_index.PackageIndex( search_path=[setup_requirement_path]) if find_links: index.add_find_links((find_links,)) req = pkg_resources.Requirement.parse(requirement) if index.obtain(req) is not None: best = [] bestv = None for dist in index[req.project_name]: distv = dist.parsed_version if distv >= pkg_resources.parse_version('2dev'): continue if _final_version(distv): if bestv is None or distv > bestv: best = [dist] bestv = distv elif distv == bestv: best.append(dist) if best: best.sort() version = best[-1].version if version: requirement += '=='+version else: requirement += '<2dev' cmd.append(requirement) if is_jython: import subprocess exitcode = subprocess.Popen(cmd, env=env).wait() else: # Windows prefers this, apparently; otherwise we would prefer subprocess exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) if exitcode != 0: sys.stdout.flush() sys.stderr.flush() print ("An error occurred when trying to install zc.buildout. " "Look above this message for any errors that " "were output by easy_install.") sys.exit(exitcode) ws.add_entry(eggs_dir) ws.require(requirement) import zc.buildout.buildout # If there isn't already a command in the args, add bootstrap if not [a for a in args if '=' not in a]: args.append('bootstrap') # if -c was provided, we push it back into args for buildout's main function if options.config_file is not None: args[0:0] = ['-c', options.config_file] zc.buildout.buildout.main(args) if not options.eggs: # clean up temporary egg directory shutil.rmtree(eggs_dir) zope.formlib-4.3.0a2/CHANGES.txt0000664000000000000000000001157212243456432014673 0ustar rootroot======= Changes ======= 4.3.0a2 (2013-11-21) ==================== - Support for CSRF protection. - Added support for restricting the acceptable request method for the form submit. 4.3.0a1 (2013-02-27) ==================== - Added support for Python 3.3. 4.2.1 (2013-02-22) ================== - Moved default values for the `BooleanDisplayWidget` from module to class definition to make them changeable in instance. 4.2.0 (2012-11-27) ================== - LP #1017884: Add redirect status codes (303, 307) to the set which prevent form rendering. - Replaced deprecated ``zope.component.adapts`` usage with equivalent ``zope.component.adapter`` decorator. - Replaced deprecated ``zope.interface.implements`` usage with equivalent ``zope.interface.implementer`` decorator. - Dropped support for Python 2.5. - Make separator of ``SourceSequenceDisplayWidget`` configurable. 4.1.1 (2012-03-16) ================== - Added `ignoreContext` attribute to form classes to control whether `checkInvariants` takes the context of the form into account when checking interface invariants. By default `ignoreContext` is set to ``False``. On the `AddForm` it is ``True`` by default because the context of this form is naturally not suitable as context for the interface invariant. 4.1.0 (2012-03-15) ================== - `checkInvariants` now takes the context of the form into account when checking interface invariants. - Tests are no longer compatible with Python 2.4. 4.0.6 (2011-08-20) ================== - Fixed bug in ``orderedSelectionList.pt`` template. 4.0.5 (2010-09-16) ================== - Fixed Action name parameter handling, since 4.0.3 all passed names were lowercased. 4.0.4 (2010-07-06) ================== - Fixed tests to pass under Python 2.7. - Fix validation of "multiple" attributes in orderedSelectionList.pt. 4.0.3 (2010-05-06) ================== - Keep Actions from raising exceptions when passed Unicode lables [LP:528468]. - Improve display of the "nothing selected" case for optional Choice fields [LP:269782]. - Improve truth testing for ItemDisplayWidget [LP:159232]. - Don't blow up if TypeError raised during token conversion [LP:98491]. 4.0.2 (2010-03-07) ================== - Adapted tests for Python 2.4 (enforce sorting for short pprint output) 4.0.1 (2010-02-21) ================== - Documentation uploaded to PyPI now contains widget documentation. - Escape MultiCheckBoxWidget content [LP:302427]. 4.0 (2010-01-08) ================ - Widget implementation and all widgets from zope.app.form have been moved into zope.formlib, breaking zope.formlib's dependency on zope.app.form (instead zope.app.form now depends on zope.formlib). Widgets can all be imported from ``zope.formlib.widgets``. Widget base classes and render functionality is in ``zope.formlib.widget``. All relevant widget interfaces are now in ``zope.formlib.interfaces``. 3.10.0 (2009-12-22) =================== - Use named template from zope.browserpage in favor of zope.app.pagetemplate. 3.9.0 (2009-12-22) ================== - Use ViewPageTemplateFile from zope.browserpage. 3.8.0 (2009-12-22) ================== - Adjusted test output to new zope.schema release. 3.7.0 (2009-12-18) ================== - Rid ourselves from zope.app test dependencies. - Fix: Button label needs escaping 3.6.0 (2009-05-18) ================== - Remove deprecated imports. - Remove dependency on zope.app.container (use ``IAdding`` from ``zope.browser.interfaces``) instead. Depend on ``zope.browser>=1.1`` (the version with ``IAdding``). - Moved ``namedtemplate`` to ``zope.app.pagetemplate``, to cut some dependencies on ``zope.formlib`` when using this feature. Left BBB imports here. 3.5.2 (2009-02-21) ================== - Adapt tests for Python 2.5 output. 3.5.1 (2009-01-31) ================== - Adapt tests to upcoming zope.schema release 3.5.1. 3.5.0 (2009-01-26) ================== New Features ------------ - Test dependencies are declared in a `test` extra now. - Introduced ``zope.formlib.form.applyData`` which works like ``applyChanges`` but returns a dictionary with information about which attribute of which schema changed. This information is then sent along with the ``IObjectModifiedEvent``. This fixes https://bugs.launchpad.net/zope3/+bug/98483. Bugs Fixed ---------- - Actions that cause a redirect (301, 302) do not cause the `render` method to be called anymore. - The zope.formlib.form.Action class didn't fully implement zope.formlib.interfaces.IAction. - zope.formlib.form.setupWidgets and zope.formlib.form.setupEditWidgets did not check for write access on the adapter but on context. This fixes https://bugs.launchpad.net/zope3/+bug/219948 3.4.0 (2007-09-28) ================== No further changes since 3.4.0a1. 3.4.0a1 (2007-04-22) ==================== Initial release as a separate project, corresponds to zope.formlib from Zope 3.4.0a1 zope.formlib-4.3.0a2/buildout.cfg0000664000000000000000000000117512243456432015370 0ustar rootroot[buildout] develop = . parts = test python coverage-test coverage-report versions = versions [test] recipe = zc.recipe.testrunner eggs = zope.formlib [test] [python] recipe = zc.recipe.egg eggs = zope.formlib interpreter = python [coverage-test] recipe = zc.recipe.testrunner eggs = ${test:eggs} defaults = ['--coverage', '../../coverage'] [coverage-report] recipe = zc.recipe.egg eggs = z3c.coverage scripts = coverage=coverage-report arguments = ('coverage', 'coverage/report') [versions] zope.browserpage = 4.1.0a1 zope.i18n = 4.0.0a4 zope.publisher = 4.0.0a2 zope.security = 4.0.0a3 zope.traversing = 4.0.0a2 zope.tal = 4.0.0a1 zope.formlib-4.3.0a2/tox.ini0000664000000000000000000000062412243456432014371 0ustar rootroot[tox] envlist = py26,py27,py33 [testenv] commands = python setup.py test -q deps = pytz zope.browser zope.browserpage zope.component zope.event zope.i18n zope.i18nmessageid zope.interface zope.lifecycleevent zope.publisher zope.schema zope.security zope.traversing zope.datetime zope.configuration zope.testing zope.testrunner zope.formlib-4.3.0a2/src/0000775000000000000000000000000012355055056013644 5ustar rootrootzope.formlib-4.3.0a2/src/zope/0000775000000000000000000000000012355055056014621 5ustar rootrootzope.formlib-4.3.0a2/src/zope/formlib/0000775000000000000000000000000012355055056016253 5ustar rootrootzope.formlib-4.3.0a2/src/zope/formlib/configure.zcml0000664000000000000000000004715212243456432021133 0ustar rootroot zope.formlib-4.3.0a2/src/zope/formlib/errors.txt0000664000000000000000000000514512243456432020334 0ustar rootroot============== Error handling ============== These are a couple of functional tests that were written on-the-go ... In the future this might become more extensive ... Displaying invalidation errors ============================== Validation errors, e.g. cause by invariants, are converted into readable text by adapting them to IWidgetInputErrorView: >>> from zope.publisher.browser import TestRequest >>> from zope.interface.exceptions import Invalid >>> from zope.component import getMultiAdapter >>> from zope.formlib.interfaces import IWidgetInputErrorView >>> error = Invalid("You are wrong!") >>> message = getMultiAdapter((error, TestRequest()), ... IWidgetInputErrorView).snippet() >>> message u'You are wrong!' Interface invariant methods raise zope.interface.Invalid exception. Test if this exception gets handled by the error_views. >>> myError = Invalid('My error message') >>> import zope.formlib.form >>> mybase = zope.formlib.form.FormBase(None, TestRequest()) >>> mybase.errors = (myError,) >>> save = mybase.error_views() >>> next(save) u'My error message' Now we need to set up the translation framework: >>> from zope import component, interface >>> from zope.i18n.interfaces import INegotiator >>> @interface.implementer(INegotiator) ... class Negotiator: ... def getLanguage(*ignored): return 'test' >>> component.provideUtility(Negotiator()) >>> from zope.i18n.testmessagecatalog import TestMessageFallbackDomain >>> component.provideUtility(TestMessageFallbackDomain) And yes, we can even handle an i18n message in an Invalid exception: >>> from zope.i18nmessageid import MessageFactory >>> _ = MessageFactory('my.domain') >>> myError = Invalid(_('My i18n error message')) >>> mybase = zope.formlib.form.FormBase(None, TestRequest()) >>> mybase.errors = (myError,) >>> save = mybase.error_views() >>> next(save) u'[[my.domain][My i18n error message]]' Displaying widget input errors ============================== WidgetInputError exceptions also work with i18n messages: >>> from zope.formlib.interfaces import WidgetInputError >>> myError = WidgetInputError( ... field_name='summary', ... widget_title=_(u'Summary'), ... errors=_(u'Foo')) >>> mybase = zope.formlib.form.FormBase(None, TestRequest()) >>> mybase.errors = (myError,) >>> save = mybase.error_views() >>> next(save) u'[[my.domain][Summary]]: [[my.domain][Foo]]' zope.formlib-4.3.0a2/src/zope/formlib/i18n.py0000664000000000000000000000022512243456432017402 0ustar rootroot"""\ I18N support for zope.formlib """ __docformat__ = "reStructuredText" import zope.i18nmessageid _ = zope.i18nmessageid.MessageFactory("zope") zope.formlib-4.3.0a2/src/zope/formlib/orderedSelectionList.pt0000664000000000000000000001417612243456432022756 0ustar rootroot


zope.formlib-4.3.0a2/src/zope/formlib/TODO.txt0000664000000000000000000000006112243456432017555 0ustar rootroot- test coverage - return error icon to templates zope.formlib-4.3.0a2/src/zope/formlib/_compat.py0000664000000000000000000000236512243456432020254 0ustar rootroot############################################################################## # # Copyright (c) 2005 Zope Foundation and Contributors. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Compatibility between Python versions """ import base64 import sys PY3 = sys.version_info[0] >= 3 if PY3: from io import StringIO unicode = str imap = map basestring = str def toUnicode(obj): return obj.decode() if isinstance(obj, bytes) else str(obj) def safeBase64Encode(obj): return base64.b64encode( obj.encode()).strip().replace(b'=', b'_').decode() else: from StringIO import StringIO from itertools import imap unicode = toUnicode = unicode basestring = basestring def safeBase64Encode(obj): return base64.b64encode(toUnicode(obj)).strip().replace('=', '_') zope.formlib-4.3.0a2/src/zope/formlib/widgets.txt0000664000000000000000000001660612243456432020472 0ustar rootroot=============== Browser Widgets =============== Formlib defines widgets: views on bound schema fields. Many of these are straightforward. For instance, see the `TextWidget` in textwidgets.py, which is a subclass of BrowserWidget in widget.py. It is registered as an `IBrowserRequest` view of an `ITextLine` schema field, providing the `IInputWidget` interface:: The widget then receives the field and the request as arguments to the factory (i.e., the `TextWidget` class). Some widgets in formlib extend this pattern. The widget registration is extended for `Choice` fields and for the `collection` fields. Default Choice Field Widget Registration and Lookup =================================================== All field widgets are obtained by looking up a browser `IInputWidget` or `IDisplayWidget` view for the field object. For `Choice` fields, the default registered widget defers all of its behavior to the result of another lookup: a browser widget view for the field *and* the Choice field's vocabulary. This allows registration of Choice widgets that differ on the basis of the vocabulary type. For example, a widget for a vocabulary of images might have a significantly different user interface than a widget for a vocabulary of words. A dynamic vocabulary might implement `IIterableVocabulary` if its contents are below a certain length, but not implement the marker "iterable" interface if the number of possible values is above the threshhold. This also means that choice widget factories are called with with an additional argument. Rather than being called with the field and the request as arguments, choice widgets receive the field, vocabulary, and request as arguments. Some `Choice` widgets may also need to provide a source interface, particularly if the vocabulary is too big to iterate over. Default Collection Field Widget Registration and Lookup ======================================================= The default configured lookup for collection fields -- List, Tuple, and Set, for instance -- begins with the usual lookup for a browser widget view for the field object. This widget defers its display to the result of another lookup: a browser widget view registered for the field and the field's `value_type` (the type of the contained values). This allows registrations for collection widgets that differ on the basis of the members -- a widget for entering a list of text strings might differ significantly from a widget for entering a list of dates...or even a list of choices, as discussed below. This registration pattern has three implications that should be highlighted. * First, collection fields that do not specify a `value_type` probably cannot have a reasonable widget. * Second, collection widgets that wish to be the default widget for a collection with any `value_type` should be registered for the collection field and a generic value_type: the `IField` interface. Do not register the generic widget for the collection field only or you will break the lookup behavior as described here. * Third, like choice widget factories, sequence widget factories (classes or functions) take three arguments. Typical sequence widgets receive the field, the `value_type`, and the request as arguments. Collections of Choices ---------------------- If a collection field's `value_type` is a `Choice` field, the second widget again defers its behavior, this time to a third lookup based on the collection field and the choice's vocabulary. This means that a widget for a list of large image choices can be different than a widget for a list of small image choices (with a different vocabulary interface), different from a widget for a list of keyword choices, and different from a set of keyword choices. Some advanced applications may wish to do a further lookup on the basis of the unique attribute of the collection field--perhaps looking up a named view with a "unique" or "lenient" token depending on the field's value, but this is not enabled in the default Zope 3 configuration. Registering Widgets for a New Collection Field Type --------------------------------------------------- Because of this lookup pattern, basic widget registrations for new field types must follow a recipe. For example, a developer may introduce a new Bag field type for simple shopping cart functionality and wishes to add widgets for it within the default Zope 3 collection widget registration. The bag widgets should be registered something like this. The only hard requirement is that the developer must register the bag + choice widget: the widget is just the factory for the third dispatch as described above, so the developer can use the already implemented widgets listed below:: Beyond this, the developer may also have a generic bag widget she wishes to register. This might look something like this, assuming there's a `BagSequenceWidget` available in this package:: Then any widgets for the bag and a vocabulary would be registered according to this general pattern, in which `IIterableVocabulary` would be the interface of any appropriate vocabulary and `BagWidget` is some appropriate widget:: Choice widgets and the missing value ==================================== Choice widgets for a non-required field include a "no value" item to allow for not selecting any value at all. This value used to be omitted for required fields on the assumption that the widget should avoid invalid input from the start. However, if the context object doesn't yet have a field value set and there's no default value, a dropdown widget would have to select an arbitrary value due to the way it is displayed in the browser. This way, the field would always validate, but possibly with a value the user never chose consciously. Starting with version zope.app.form 3.6.0, dropdown widgets for required fields display a "no value" item even for required fields if an arbitrary value would have to be selected by the widget otherwise. To switch the old behaviour back on for backwards compatibility, do zope.formlib.itemswidgets.EXPLICIT_EMPTY_SELECTION = False during application start-up. zope.formlib-4.3.0a2/src/zope/formlib/utility.py0000664000000000000000000001432612243456432020335 0ustar rootroot############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Form utility functions This is an implementation only used by zope.formlib.objectwidget, not by the rest of the widgets in zope.formlib. We would like to keep it this way. This module is not directly tested: zope.app.form does have tests to test this, and the objectwidget implementation tests this indirectly. At some point we would like to rewrite zope.formlib.objectwidget so it uses the infrastructure provided by zope.formlib itself. """ __docformat__ = 'restructuredtext' from zope import component from zope.schema import getFieldsInOrder from zope.formlib.interfaces import IWidget from zope.formlib.interfaces import WidgetsError from zope.formlib.interfaces import InputErrors from zope.formlib.interfaces import IInputWidget from zope.formlib.interfaces import IWidgetFactory # A marker that indicates 'no value' for any of the utility functions that # accept a 'value' argument. no_value = object() def _fieldlist(names, schema): if not names: fields = getFieldsInOrder(schema) else: fields = [ (name, schema[name]) for name in names ] return fields def _createWidget(context, field, viewType, request): """Creates a widget given a `context`, `field`, and `viewType`.""" field = field.bind(context) return component.getMultiAdapter((field, request), viewType) def _widgetHasStickyValue(widget): """Returns ``True`` if the widget has a sticky value. A sticky value is input from the user that should not be overridden by an object's current field value. E.g. a user may enter an invalid postal code, submit the form, and receive a validation error - the postal code should be treated as 'sticky' until the user successfully updates the object. """ return IInputWidget.providedBy(widget) and widget.hasInput() def setUpWidget(view, name, field, viewType, value=no_value, prefix=None, ignoreStickyValues=False, context=None): """Sets up a single view widget. The widget will be an attribute of the `view`. If there is already an attribute of the given name, it must be a widget and it will be initialized with the given `value` if not ``no_value``. If there isn't already a `view` attribute of the given name, then a widget will be created and assigned to the attribute. """ if context is None: context = view.context widgetName = name + '_widget' # check if widget already exists widget = getattr(view, widgetName, None) if widget is None: # does not exist - create it widget = _createWidget(context, field, viewType, view.request) setattr(view, widgetName, widget) elif IWidgetFactory.providedBy(widget): # exists, but is actually a factory - use it to create the widget widget = widget(field.bind(context), view.request) setattr(view, widgetName, widget) # widget must implement IWidget if not IWidget.providedBy(widget): raise TypeError( "Unable to configure a widget for %s - attribute %s does not " "implement IWidget" % (name, widgetName)) if prefix: widget.setPrefix(prefix) if value is not no_value and ( ignoreStickyValues or not _widgetHasStickyValue(widget)): widget.setRenderedValue(value) def setUpWidgets(view, schema, viewType, prefix=None, ignoreStickyValues=False, initial={}, names=None, context=None): """Sets up widgets for the fields defined by a `schema`. Appropriate for collecting input without a current object implementing the schema (such as an add form). `view` is the view that will be configured with widgets. `viewType` is the type of widgets to create (e.g. IInputWidget or IDisplayWidget). `schema` is an interface containing the fields that widgets will be created for. `prefix` is a string that is prepended to the widget names in the generated HTML. This can be used to differentiate widgets for different schemas. `ignoreStickyValues` is a flag that, when ``True``, will cause widget sticky values to be replaced with the context field value or a value specified in initial. `initial` is a mapping of field names to initial values. `names` is an optional iterable that provides an ordered list of field names to use. If names is ``None``, the list of fields will be defined by the schema. `context` provides an alternative context for acquisition. """ for (name, field) in _fieldlist(names, schema): setUpWidget(view, name, field, viewType, value=initial.get(name, no_value), prefix=prefix, ignoreStickyValues=ignoreStickyValues, context=context) def applyWidgetsChanges(view, schema, target=None, names=None): """Updates an object with values from a view's widgets. `view` contained the widgets that perform the update. By default, the widgets will update the view's context. `target` can be specified as an alternative object to update. `schema` contrains the values provided by the widgets. `names` can be specified to update a subset of the schema constrained values. """ errors = [] changed = False if target is None: target = view.context for name, field in _fieldlist(names, schema): widget = getattr(view, name + '_widget') if IInputWidget.providedBy(widget) and widget.hasInput(): try: changed = widget.applyChanges(target) or changed except InputErrors as v: errors.append(v) if errors: raise WidgetsError(errors) return changed zope.formlib-4.3.0a2/src/zope/formlib/pageform.pt0000664000000000000000000001304312243456432020420 0ustar rootroot

Do something

Form status summary
  • Error Type
Extra top
error
Extra bottom

Do something

Form status summary
  • Error Type
Extra top
error
Extra bottom