Skip to content

Commit

Permalink
Merge pull request #109 from mikeywaites/fix/nested-self-marshal
Browse files Browse the repository at this point in the history
fix use of __self__ when marshaling
  • Loading branch information
mikeywaites authored Jun 16, 2016
2 parents 90e5e2f + 55b067c commit 7ed6881
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
8 changes: 6 additions & 2 deletions kim/pipelines/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from functools import wraps

from kim.exception import StopPipelineExecution, FieldError
from kim.utils import attr_or_key, set_attr_or_key
from kim.utils import attr_or_key, set_attr_or_key, attr_or_key_update


class Pipe(object):
Expand Down Expand Up @@ -255,8 +255,12 @@ def update_output_to_source(session):
:returns: None
"""

source = session.field.opts.source
try:
set_attr_or_key(session.output, session.field.opts.source, session.data)
if source == '__self__':
attr_or_key_update(session.output, session.data)
else:
set_attr_or_key(session.output, session.field.opts.source, session.data)
except (TypeError, AttributeError):
raise FieldError('output does not support attribute or '
'key based set operations')
12 changes: 12 additions & 0 deletions kim/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ def set_attr_or_key(obj, name, value):
_set_attr_or_key(obj, components[-1], value)


def attr_or_key_update(obj, value):
"""If obj is a dict, add keys from value to it with update(),
otherwise use setattr to set every attribute from value on obj
"""
if obj is not None and value is not None:
if isinstance(obj, dict):
obj.update(value)
else:
for k, v in value.items():
setattr(obj, k, v)


def recursive_defaultdict():
"""A simple recurrsive version of ``collections.defaultdict``
Expand Down
19 changes: 19 additions & 0 deletions tests/test_pipelines/test_nested.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,3 +448,22 @@ class PostMapper(Mapper):
mapper = PostMapper(data=data)
mapper.marshal()
assert called['called']


def test_self_nesting_marshal():
class Inner(Mapper):
__type__ = dict

name = field.String(source='user_name')

class Outer(Mapper):
__type__ = dict

user = field.Nested(Inner, source='__self__', allow_create=True)
status = field.Integer()

data = {'user': {'name': 'jack'}, 'status': 200}

result = Outer(data=data).marshal()

assert result == {'user_name': 'jack', 'status': 200}

0 comments on commit 7ed6881

Please sign in to comment.