Skip to content

Commit

Permalink
Merge pull request marshmallow-code#1188 from marshmallow-code/remove…
Browse files Browse the repository at this point in the history
…-container-attribute

Remove special-casing for accessing attributes of objects in a list
  • Loading branch information
sloria committed Apr 7, 2019
2 parents 12148ec + 21c005d commit deabe89
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 45 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Changelog
---------

3.0.0 (unreleased)
++++++++++++++++++

Other changes:

- *Backwards-incompatible*: Remove special-casing in ``fields.List`` and
``fields.Tuple`` for accessing nested attributes (:pr:`1188`).
Use ``fields.List(fields.Pluck(...))`` instead.

3.0.0rc5 (2019-03-30)
+++++++++++++++++++++

Expand Down
18 changes: 18 additions & 0 deletions docs/upgrading.rst
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,24 @@ In marshmallow 2.x, when a string was passed to a ``Nested`` field's ```only`` p
name = fields.Str()
friends = fields.Pluck('self', 'name', many=True)
Accessing attributes on objects within a list
*********************************************

In order to serialize attributes on inner objects within a list, use the
``Pluck`` field.

.. code-block:: python
# 2.x
class FactorySchema(Schema):
widget_ids = fields.List(fields.Int(attribute='id'))
# 3.x
class FactorySchema(Schema):
widget_ids = fields.List(fields.Pluck(WidgetSchema, 'id'))
``Float`` field takes a new ``allow_nan`` parameter
***************************************************

Expand Down
27 changes: 0 additions & 27 deletions src/marshmallow/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,18 +580,6 @@ def __init__(self, cls_or_instance, **kwargs):
'marshmallow.base.FieldABC.',
)

def get_value(self, obj, attr, accessor=None):
"""Return the value for a given key from an object."""
value = super(List, self).get_value(obj, attr, accessor=accessor)
if self.container.attribute:
if utils.is_collection(value):
return [
self.container.get_value(each, self.container.attribute)
for each in value
]
return self.container.get_value(value, self.container.attribute)
return value

def _bind_to_schema(self, field_name, schema):
super(List, self)._bind_to_schema(field_name, schema)
self.container = copy.deepcopy(self.container)
Expand Down Expand Up @@ -677,21 +665,6 @@ def _bind_to_schema(self, field_name, schema):
new_tuple_fields.append(new_container)
self.tuple_fields = new_tuple_fields

def get_value(self, obj, attr, accessor=None):
"""Return the value for a given key from an object."""
value = super(Tuple, self).get_value(obj, attr, accessor=accessor)
if any(container.attribute for container in self.tuple_fields):
if not utils.is_collection(value):
self.fail('invalid')
result = []
for container, each in zip(self.tuple_fields, value):
if container.attribute is None:
result.append(each)
else:
result.append(container.get_value(each, container.attribute))
return tuple(result)
return value

def _serialize(self, value, attr, obj, **kwargs):
if value is None:
return None
Expand Down
18 changes: 0 additions & 18 deletions tests/test_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,18 +712,6 @@ def test_list_field_serialize_none_returns_none(self):
field = fields.List(fields.DateTime)
assert field.serialize('dtimes', obj) is None

def test_list_field_respect_inner_attribute(self):
now = dt.datetime.now()
obj = DateTimeList([now])
field = fields.List(fields.Int(attribute='day'))
assert field.serialize('dtimes', obj) == [now.day]

def test_list_field_respect_inner_attribute_single_value(self):
now = dt.datetime.now()
obj = DateTimeList(now)
field = fields.List(fields.Int(attribute='day'))
assert field.serialize('dtimes', obj) == [now.day]

def test_list_field_work_with_generator_single_value(self):
def custom_generator():
yield dt.datetime.utcnow()
Expand Down Expand Up @@ -826,12 +814,6 @@ def test_tuple_field_serialize_none_returns_none(self):
field = fields.Tuple([fields.DateTime, fields.Integer])
assert field.serialize('dtime_int', obj) is None

def test_tuple_field_respect_inner_attribute(self):
now = dt.datetime.now()
obj = DateTimeIntegerTuple((now, 42))
field = fields.Tuple([fields.Int(attribute='day'), fields.Integer])
assert field.serialize('dtime_int', obj) == (now.day, 42)

def test_bad_tuple_field(self):
class ASchema(Schema):
id = fields.Int()
Expand Down

0 comments on commit deabe89

Please sign in to comment.