Skip to content

Commit

Permalink
Fixed MultiConverter.toFieldValue tuple typed field support
Browse files Browse the repository at this point in the history
  • Loading branch information
agroszer committed Jul 29, 2021
1 parent 6c69746 commit 9b86fb4
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Expand Up @@ -5,6 +5,9 @@ Changelog
4.2 (unreleased)
----------------

- Fixed `MultiConverter.toFieldValue` tuple typed field support
(when `field._type` is a tuple of types, not a single type).

- Added Python 3.9 compatibility and testing.

- Applied `zopefoundation.meta` config
Expand Down
2 changes: 2 additions & 0 deletions src/z3c/form/converter.py
Expand Up @@ -400,6 +400,8 @@ def toFieldValue(self, value):

# convert the field values to a tuple or list
collectionType = self.field._type
if isinstance(collectionType, tuple):
collectionType = collectionType[-1]
return collectionType(values)


Expand Down
42 changes: 38 additions & 4 deletions src/z3c/form/converter.rst
Expand Up @@ -782,7 +782,7 @@ We now use the field and widget to instantiate the converter:

>>> csdv = converter.CollectionSequenceDataConverter(genders, seqWidget)

The converter uses the latter type (tuple) to convert:
The converter uses the last type (tuple in this case) to convert:

>>> csdv.toFieldValue(['m'])
(0,)
Expand Down Expand Up @@ -1009,7 +1009,7 @@ Just in case the field has sequence as its ``_type``:
... value_type=zope.schema.Int(),
... )

The converter will use the latter one.
The converter will use the last one, tuple in this case.

>>> tlWidget.field = ids
>>> tlc = converter.TextLinesConverter(ids, tlWidget)
Expand All @@ -1032,8 +1032,6 @@ What if we have a wrong number:
FormatterValidationError: ("invalid literal for int() with base 10: 'foo'", u'foo')




Multi Data Converter
--------------------

Expand Down Expand Up @@ -1083,6 +1081,42 @@ If the list is empty, the missing value is returned:
>>> conv.toFieldValue([]) is None
True

Just in case the field has sequence as its ``_type``:

>>> @zope.interface.implementer(zope.schema.interfaces.IList)
... class MySequence(zope.schema._field.AbstractCollection):
... _type = (list, tuple)

>>> numbers = MySequence(
... value_type=zope.schema.Int(),
... default=[],
... missing_value=None,
... )

>>> from z3c.form.browser import multi
>>> multiWidget = multi.MultiWidget(TestRequest())
>>> multiWidget.field = numbers

We now use the field and widget to instantiate the converter:

>>> conv = converter.MultiConverter(numbers, multiWidget)

We can now convert a list or tuple of integers to the multi-widget internal
representation:

>>> conv.toWidgetValue([1, 2, 3, 4])
[u'1', u'2', u'3', u'4']

>>> conv.toWidgetValue((1, 2, 3, 4))
[u'1', u'2', u'3', u'4']

Now, let's look at the reverse. We get a tuple because that's the last
type in ``_type``:

>>> conv.toFieldValue([u'1', u'2', u'3', u'4'])
(1, 2, 3, 4)


Dict Multi Data Converter
-------------------------

Expand Down

0 comments on commit 9b86fb4

Please sign in to comment.