Ignore:
Timestamp:
21 Mar 2012, 10:41:15 (13 years ago)
Author:
uli
Message:

Make import converters more modular (support special converters for special zope.schema field types) and support lists and result entries as import input.

Location:
main/waeup.kofa/trunk/src/waeup/kofa
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/interfaces.py

    r7927 r7932  
    819819        """
    820820
     821class IFieldConverter(Interface):
     822    def update_request_data(self, name, value, schema_field, prefix=''):
     823        """Create a dict with key-value mapping as created by a request.
     824
     825        `name` and `value` are expected to be parsed from CSV or a
     826        similar input and represent an attribute to be set to a
     827        representation of value.
     828
     829        :meth:`update_request_data` is then requested to turn this
     830        name and value into vars as they would be sent by a regular
     831        form submit. This means we do not create the real values to be
     832        set but we only define the values that would be sent in a
     833        browser request to request the creation of those values.
     834
     835        The returned dict should contain names and values of a faked
     836        browser request for the given `schema_field`.
     837
     838        Field converters are normally registered as adapters to some
     839        specific zope.schema field.
     840        """
     841
    821842class IObjectHistory(Interface):
    822843
  • main/waeup.kofa/trunk/src/waeup/kofa/utils/converters.py

    r7811 r7932  
    2424from zope.formlib.form import (
    2525    _widgetKey, WidgetInputError, ValidationError, InputErrors, expandPrefix)
    26 from zope.formlib.interfaces import IInputWidget, ISimpleInputWidget
     26from zope.formlib.interfaces import IInputWidget
    2727from zope.interface import Interface
    2828from zope.publisher.browser import TestRequest
    29 from waeup.kofa.interfaces import IObjectConverter
     29from zope.schema.interfaces import IList
     30from waeup.kofa.interfaces import (
     31    IObjectConverter, IResultEntryField, IFieldConverter, SubjectSource,
     32    GradeSource)
     33from waeup.kofa.schoolgrades import ResultEntry
    3034
    3135class ExtendedCheckBoxWidget(CheckBoxWidget):
     
    8589    store the fieldname for which a validation error happened in the
    8690    returned error list (what the original does not do).
    87 
    8891    """
    8992    errors = []
     
    108111    return errors
    109112
     113class DefaultFieldConverter(grok.Adapter):
     114    grok.context(Interface)
     115    grok.provides(IFieldConverter)
     116
     117    def request_data(self, name, value, schema_field, prefix=''):
     118        return {prefix: value}
     119
     120class ListFieldConverter(grok.Adapter):
     121    grok.context(IList)
     122    grok.provides(IFieldConverter)
     123
     124    def request_data(self, name, value, schema_field, prefix=''):
     125        value_type = schema_field.value_type
     126        try:
     127            items = eval(value)
     128        except:
     129            return {prefix: value}
     130        result = {'%s.count' % prefix: len(items)}
     131        for num, item in enumerate(items):
     132            sub_converter = IFieldConverter(value_type)
     133            result.update(sub_converter.request_data(
     134                unicode(num), unicode(item),
     135                value_type, "%s.%s." % (prefix, num)))
     136        return result
     137
     138class ResultEntryConverter(grok.Adapter):
     139    grok.context(IResultEntryField)
     140    grok.provides(IFieldConverter)
     141
     142    def request_data(self, name, value, schema_field, prefix=''):
     143        """Turn CSV values into ResultEntry-compatible form data.
     144
     145        Expects as `value` a _string_ like ``(u'mysubject',
     146        u'mygrade')`` and turns it into some dict like::
     147
     148          {
     149            'form.grade.subject': u'9234896395...',
     150            'form.grade.grade': u'7e67e9e777..'
     151            }
     152
     153        where the values are tokens from appropriate sources.
     154
     155        Such dicts can be transformed into real ResultEntry objects by
     156        input widgets used in converters.
     157        """
     158        try:
     159            entry = ResultEntry.from_string(value)
     160            subj, grade = entry.subject, entry.grade
     161        except:
     162            return {prefix: value}
     163        # web forms send tokens instead of real values
     164        s_token = SubjectSource().factory.getToken(subj)
     165        g_token = GradeSource().factory.getToken(grade)
     166        result = {
     167            "%ssubject" % (prefix): s_token,
     168            "%sgrade" % (prefix): g_token,
     169            }
     170        return result
    110171
    111172class DefaultObjectConverter(grok.Adapter):
     
    172233        request = TestRequest(form={})
    173234        for key, val in data_dict.items():
    174             request.form['form.%s' % key] = val
     235            field = form_fields.get(key, None)
     236            if field is not None:
     237                # let adapters to the respective schema fields do the
     238                # further fake-request processing
     239                schema_field = field.interface[field.__name__]
     240                field_converter = IFieldConverter(schema_field)
     241                request.form.update(
     242                    field_converter.request_data(
     243                        key, val, schema_field, 'form.%s' % key)
     244                    )
     245            else:
     246                request.form['form.%s' % key] = val
    175247
    176248        obj = context
     
    185257
    186258        invariant_errors = form.checkInvariants(form_fields, new_data)
     259
    187260        if errors or invariant_errors:
    188261            err_messages = [(key, err.args[0]) for key, err in errors]
  • main/waeup.kofa/trunk/src/waeup/kofa/utils/tests/test_converters.py

    r7819 r7932  
    3333from waeup.kofa.app import University
    3434from waeup.kofa.testing import FunctionalLayer, FunctionalTestCase
     35from waeup.kofa.interfaces import (
     36    SimpleKofaVocabulary, SubjectSource, GradeSource)
     37from waeup.kofa.schoolgrades import ResultEntryField
    3538from waeup.kofa.university import Faculty
    3639from waeup.kofa.utils.converters import IObjectConverter
    3740from waeup.kofa.utils.helpers import attrs_to_fields
    38 from waeup.kofa.interfaces import SimpleKofaVocabulary
    3941
    4042colors = SimpleKofaVocabulary(
     
    8587        vocabulary = car_nums,
    8688        )
     89    grades = schema.List(
     90        title = u'School Grades',
     91        value_type = ResultEntryField(),
     92        required = True,
     93        default = [],
     94        )
     95    friends = schema.List(
     96        title = u'Friends',
     97        value_type = schema.TextLine(
     98            title = u'Name',
     99            )
     100        )
     101
    87102    @invariant
    88103    def kevinIsYoung(contact):
     
    330345        assert data['num_cars'] == 1
    331346        return
     347
     348    def test_list_of_textlines(self):
     349        # We can convert lists of text lines
     350        converter = IObjectConverter(IContact)
     351        err, inv_err, data = converter.fromStringDict(
     352            {"friends": "['Fred', 'Wilma']"}, 'contact')
     353        self.assertEqual(
     354            data, {'friends': ['Fred', 'Wilma']})
     355        return
     356
     357    def test_list_of_resultentries(self):
     358        # We can handle lists of result entries
     359        converter = IObjectConverter(IContact)
     360        # get currently valid values
     361        s_src, g_src = SubjectSource(), GradeSource()
     362        s_val1, s_val2 = list(s_src.factory.getValues())[0:2]
     363        g_val1, g_val2 = list(g_src.factory.getValues())[0:2]
     364        req_string = u"[('%s', '%s'), ('%s', '%s')]" % (
     365                s_val1, g_val1, s_val2, g_val2)
     366        err, inv_err, data = converter.fromStringDict(
     367            {"grades": req_string,
     368             },
     369            'contact')
     370        result_grades = data['grades']
     371        self.assertTrue(isinstance(result_grades, list))
     372        self.assertEqual(len(result_grades), 2)
     373        self.assertEqual(result_grades[0].subject, s_val1)
     374        self.assertEqual(result_grades[0].grade, g_val1)
     375        return
Note: See TracChangeset for help on using the changeset viewer.