source: main/waeup.sirp/trunk/src/waeup/sirp/utils/converters.py @ 6276

Last change on this file since 6276 was 6276, checked in by uli, 13 years ago

Remove old converters and disable tests for them.

File size: 4.5 KB
Line 
1"""Converters for zope.schema-based datatypes.
2"""
3import grok
4from zope.component import createObject
5from zope.formlib import form
6from zope.formlib.form import (
7    _widgetKey, WidgetInputError, ValidationError, InputErrors, expandPrefix)
8from zope.formlib.interfaces import IInputWidget
9from zope.interface import Interface
10from zope.publisher.browser import TestRequest
11from waeup.sirp.interfaces import IObjectConverter
12
13def getWidgetsData(widgets, form_prefix, data):
14    """Get data and validation errors from `widgets` for `data`.
15
16    Updates the dict in `data` with values from the widgets in
17    `widgets`.
18
19    Returns a list of tuples ``(<WIDGET_NAME>, <ERROR>)`` where
20    ``<WIDGET_NAME>`` is a widget name (normally the same as the
21    associated field name) and ``<ERROR>`` is the exception that
22    happened for that widget/field.
23
24    This is merely a copy from the same-named function in
25    :mod:`zope.formlib.form`. The only difference is that we also
26    store the fieldname for which a validation error happened in the
27    returned error list (what the original does not do).
28
29    """
30    errors = []
31    form_prefix = expandPrefix(form_prefix)
32
33    for input, widget in widgets.__iter_input_and_widget__():
34        if input and IInputWidget.providedBy(widget):
35            name = _widgetKey(widget, form_prefix)
36
37            if not widget.hasInput():
38                continue
39
40            try:
41                data[name] = widget.getInputValue()
42            except ValidationError, error:
43                # convert field ValidationError to WidgetInputError
44                error = WidgetInputError(widget.name, widget.label, error)
45                errors.append((name, error))
46            except InputErrors, error:
47                errors.append((name, error))
48
49    return errors
50
51class DefaultObjectConverter(grok.Adapter):
52    """Turn string values into real values.
53
54    A converter can convert string values for objects that implement a
55    certain interface into real values based on the given interface.
56    """
57
58    grok.context(Interface)
59    grok.provides(IObjectConverter)
60
61    def __init__(self, iface):
62        self.iface = iface
63        self.default_form_fields = form.Fields(iface)
64        return
65
66    def fromStringDict(self, data_dict, context, form_fields=None):
67        """Convert values in `data_dict`.
68
69        Converts data in `data_dict` into real values based on
70        `context` and `form_fields`.
71
72        `data_dict` is a mapping (dict) from field names to values
73        represented as strings.
74
75        The fields (keys) to convert can be given in optional
76        `form_fields`. If given, form_fields should be an instance of
77        :class:`zope.formlib.form.Fields`. Suitable instances are for
78        example created by :class:`grok.AutoFields`.
79
80        If no `form_fields` are given, a default is computed from the
81        associated interface.
82
83        The `context` can be an existing object (implementing the
84        associated interface) or a factory name. If it is a string, we
85        try to create an object using
86        :func:`zope.component.createObject`.
87
88        Returns a tuple ``(<FIELD_ERRORS>, <INVARIANT_ERRORS>,
89        <DATA_DICT>)`` where
90
91        ``<FIELD_ERRORS>``
92           is a list of tuples ``(<FIELD_NAME>, <ERROR>)`` for each
93           error that happened when validating the input data in
94           `data_dict`
95
96        ``<INVARIANT_ERRORS>``
97           is a list of invariant errors concerning several fields
98
99        ``<DATA_DICT>``
100           is a dict with the values from input dict converted.
101
102        If errors happen, i.e. the error lists are not empty, always
103        an empty ``<DATA_DICT>`` is returned.
104
105        If ``<DATA_DICT>` is non-empty, there were no errors.
106        """
107        if form_fields is None:
108            form_fields = self.default_form_fields
109
110        request = TestRequest(form={})
111        for key, val in data_dict.items():
112            request.form['form.%s' % key] = val
113
114        obj = context
115        if isinstance(context, basestring):
116            obj = createObject(context)
117
118        widgets = form.setUpInputWidgets(
119            form_fields, 'form', obj, request)
120
121        new_data = dict()
122        errors = getWidgetsData(widgets, 'form', new_data)
123
124        invariant_errors = form.checkInvariants(form_fields, new_data)
125        if errors or invariant_errors:
126            err_messages = [(key, err.args[0]) for key, err in errors]
127            invariant_errors = [err.message for err in invariant_errors]
128            return err_messages, invariant_errors, {}
129
130        return errors, invariant_errors, new_data
Note: See TracBrowser for help on using the repository browser.