Beispiel #1
0
def test_attr_or_key_util():
    class Foo(object):

        bar = 'baz'

    foo_dict = {'bar': 'baz'}
    invalid = 'str'

    assert attr_or_key(Foo(), 'bar') == 'baz'
    assert attr_or_key(Foo(), 'qux') is None
    assert attr_or_key(foo_dict, 'bar') == 'baz'
    assert attr_or_key(foo_dict, 'qux') is None
    assert attr_or_key(invalid, 'bar') is None
Beispiel #2
0
def test_attr_or_key_util():

    class Foo(object):

        bar = 'baz'

    foo_dict = {'bar': 'baz'}
    invalid = 'str'

    assert attr_or_key(Foo(), 'bar') == 'baz'
    assert attr_or_key(Foo(), 'qux') is None
    assert attr_or_key(foo_dict, 'bar') == 'baz'
    assert attr_or_key(foo_dict, 'qux') is None
    assert attr_or_key(invalid, 'bar') is None
Beispiel #3
0
def test_attr_or_key_util_dot_syntax():
    class Bar(object):
        xyz = 'abc'

    class Foo(object):

        bar = Bar()

    foo_dict = {'bar': {'xyz': 'abc'}}

    assert attr_or_key(Foo(), 'bar.xyz') == 'abc'
    assert attr_or_key(Foo(), 'bar.qux') is None
    assert attr_or_key(foo_dict, 'bar.xyz') == 'abc'
    assert attr_or_key(foo_dict, 'bar.qux') is None
Beispiel #4
0
def test_attr_or_key_util_dot_syntax():

    class Bar(object):
        xyz = 'abc'

    class Foo(object):

        bar = Bar()

    foo_dict = {'bar': {'xyz': 'abc'}}

    assert attr_or_key(Foo(), 'bar.xyz') == 'abc'
    assert attr_or_key(Foo(), 'bar.qux') is None
    assert attr_or_key(foo_dict, 'bar.xyz') == 'abc'
    assert attr_or_key(foo_dict, 'bar.qux') is None
Beispiel #5
0
def marshall_collection(session):
    """iterate over each item in ``data`` and marshal the item through the
    wrapped field defined for this collection

    :param session: Kim pipeline session instance

    TODO(mike) this should be called marshal_collection
    """
    wrapped_field = session.field.opts.field
    existing_value = attr_or_key(session.output, session.field.opts.source)

    output = []

    if session.data is not None:
        if not hasattr(session.data, '__iter__'):
            raise session.field.invalid('type_error')

        for i, datum in enumerate(session.data):
            _output = {}
            # If the object already exists, try to match up the existing elements
            # with those in the input json
            if existing_value is not None:
                try:
                    _output[wrapped_field.opts.source] = existing_value[i]
                except IndexError:
                    pass

            mapper_session = session.mapper.get_mapper_session(datum, _output)
            wrapped_field.marshal(mapper_session, parent_session=session)

            result = _output[wrapped_field.opts.source]
            output.append(result)

    session.data = output
    return session.data
Beispiel #6
0
def get_data_from_name(session):
    """Extracts a specific key from data using ``field.name``.  This pipe is
    typically used as the entry point to a chain of input pipes.

    :param session: Kim pipeline session instance

    :rtype: mixed
    :returns: the key found in data using field.name

    """

    # If the field is wrapped by another field then the relevant data
    # will have already been pulled from the name.
    if session.field.opts._is_wrapped:
        return session.data

    value = attr_or_key(session.data, session.field.name)

    if value is None:
        if session.field.opts.required and session.field.opts.default is None:
            raise session.field.invalid(error_type='required')
        elif session.field.opts.default is not None:
            session.data = session.field.opts.default
            return session.data
        elif not session.field.opts.allow_none:
            raise session.field.invalid(error_type='none_not_allowed')

    session.data = value
    return session.data
Beispiel #7
0
def marshall_collection(session):
    """iterate over each item in ``data`` and marshal the item through the
    wrapped field defined for this collection

    :param session: Kim pipeline session instance

    TODO(mike) this should be called marshal_collection
    """
    wrapped_field = session.field.opts.field
    existing_value = attr_or_key(session.output, session.field.opts.source)

    output = []

    if session.data is not None:
        if not hasattr(session.data, '__iter__'):
            raise session.field.invalid('type_error')

        for i, datum in enumerate(session.data):
            _output = {}
            # If the object already exists, try to match up the existing elements
            # with those in the input json
            if existing_value is not None:
                try:
                    _output[wrapped_field.opts.source] = existing_value[i]
                except IndexError:
                    pass

            mapper_session = session.mapper.get_mapper_session(datum, _output)
            wrapped_field.marshal(mapper_session, parent_session=session)

            result = _output[wrapped_field.opts.source]
            output.append(result)

    session.data = output
    return session.data
Beispiel #8
0
def get_data_from_name(session):
    """Extracts a specific key from data using ``field.name``.  This pipe is
    typically used as the entry point to a chain of input pipes.

    :param session: Kim pipeline session instance

    :rtype: mixed
    :returns: the key found in data using field.name

    """

    # If the field is wrapped by another field then the relevant data
    # will have already been pulled from the name.
    if session.field.opts._is_wrapped:
        return session.data

    value = attr_or_key(session.data, session.field.name)

    if value is None:
        if session.field.opts.required and session.field.opts.default is None:
            raise session.field.invalid(error_type='required')
        elif session.field.opts.default is not None:
            session.data = session.field.opts.default
            return session.data
        elif not session.field.opts.allow_none:
            raise session.field.invalid(error_type='none_not_allowed')

    session.data = value
    return session.data
Beispiel #9
0
def marshal_nested(session):
    """Marshal data using the nested mapper defined on this field.

    There are 6 possible scenarios, depending on the security setters and
    presence of a getter function

    * Getter function returns an object and no updates are allowed - Return the
      object immediately
    * Getter function returns an object and updates are allowed - Call the
      nested mapper with the object to update it
    * Object already exists, getter function returns None/does not exist and
      in place updates are allowed - Call the nested mapper with the existing
      object to update it
    * Getter function returns None/does not exist and creation of new objects
      is allowed - Call the nested mapper to create a new object
    * Getter function returns None/does not exist and creation of new objects
      is not allowed, nor are in place updates - Raise an exception.
    * Object already exists, getter function returns None/does not exist and
      partial updates are allowed - Call the nested mapper with the existing object
      to update it

    :param session: Kim pipeline session instance
    """

    resolved = _call_getter(session)

    partial = session.mapper_session.partial
    parent_mapper = session.mapper

    if session.parent and session.parent.nested_mapper:
        nested_mapper_class = session.parent.nested_mapper
    else:
        nested_mapper_class = session.field.get_mapper(as_class=True)

    if resolved is not None:
        if session.field.opts.allow_updates:
            nested_mapper = nested_mapper_class(
                data=session.data, obj=resolved, partial=partial,
                parent=parent_mapper)
            session.data = nested_mapper.marshal(role=session.field.opts.role)
        else:
            session.data = resolved
    else:
        existing_value = attr_or_key(session.output, session.field.name)
        if (session.field.opts.allow_updates_in_place or
                session.field.opts.allow_partial_updates) and \
                existing_value is not None:
            nested_mapper = nested_mapper_class(
                data=session.data, obj=existing_value, partial=partial,
                parent=parent_mapper)
            session.data = nested_mapper.marshal(role=session.field.opts.role)
        elif session.field.opts.allow_create:
            nested_mapper = nested_mapper_class(
                data=session.data, partial=partial, parent=parent_mapper)
            session.data = nested_mapper.marshal(role=session.field.opts.role)
        else:
            raise session.field.invalid(error_type='not_found')

    return session.data
Beispiel #10
0
def marshal_nested(session):
    """Marshal data using the nested mapper defined on this field.

    There are 6 possible scenarios, depending on the security setters and
    presence of a getter function

    * Getter function returns an object and no updates are allowed - Return the
      object immediately
    * Getter function returns an object and updates are allowed - Call the
      nested mapper with the object to update it
    * Object already exists, getter function returns None/does not exist and
      in place updates are allowed - Call the nested mapper with the existing
      object to update it
    * Getter function returns None/does not exist and creation of new objects
      is allowed - Call the nested mapper to create a new object
    * Getter function returns None/does not exist and creation of new objects
      is not allowed, nor are in place updates - Raise an exception.
    * Object already exists, getter function returns None/does not exist and
      partial updates are allowed - Call the nested mapper with the existing object
      to update it

    :param session: Kim pipeline session instance
    """

    resolved = _call_getter(session)

    partial = session.mapper_session.partial
    parent = session.mapper

    if resolved is not None:
        if session.field.opts.allow_updates:
            nested_mapper = session.field.get_mapper(data=session.data,
                                                     obj=resolved,
                                                     partial=partial,
                                                     parent=parent)
            session.data = nested_mapper.marshal(role=session.field.opts.role)
        else:
            session.data = resolved
    else:
        existing_value = attr_or_key(session.output, session.field.name)
        if (session.field.opts.allow_updates_in_place or
                session.field.opts.allow_partial_updates) and \
                existing_value is not None:
            nested_mapper = session.field.get_mapper(data=session.data,
                                                     obj=existing_value,
                                                     partial=partial,
                                                     parent=parent)
            session.data = nested_mapper.marshal(role=session.field.opts.role)
        elif session.field.opts.allow_create:
            nested_mapper = session.field.get_mapper(data=session.data,
                                                     partial=partial,
                                                     parent=parent)
            session.data = nested_mapper.marshal(role=session.field.opts.role)
        else:
            raise session.field.invalid(error_type='not_found')

    return session.data
Beispiel #11
0
def check_duplicates(session):
    """iterate over collection and check for duplicates if th unique_on FieldOpt has been
    set of this Collection field

    TODO(mike) This should only run if the wrapped field is a nested collection

    """
    data = session.data
    key = session.field.opts.unique_on
    if key:
        keys = [attr_or_key(a, key) for a in data]
        if len(keys) != len(set(keys)):
            raise session.field.invalid(error_type='duplicates')
    return data
Beispiel #12
0
def check_duplicates(session):
    """iterate over collection and check for duplicates if th unique_on FieldOpt has been
    set of this Collection field

    TODO(mike) This should only run if the wrapped field is a nested collection

    """
    data = session.data
    key = session.field.opts.unique_on
    if key:
        keys = [attr_or_key(a, key) for a in data]
        if len(keys) != len(set(keys)):
            raise session.field.invalid(error_type='duplicates')
    return data
Beispiel #13
0
def get_data_from_source(session):
    """Extracts a specific key from data using ``field.source``.  This pipe is
    typically used as the entry point to a chain of output pipes.

    :param session: Kim pipeline session instance

    :rtype: mixed
    :returns: the key found in data using field.source

    """

    source = session.field.opts.source

    # If the field is wrapped by another field then the relevant data
    # will have already been pulled from the source.
    if session.field.opts._is_wrapped or source == '__self__':
        return session.data

    value = attr_or_key(session.data, source)
    session.data = value
    return session.data
Beispiel #14
0
def get_data_from_source(session):
    """Extracts a specific key from data using ``field.source``.  This pipe is
    typically used as the entry point to a chain of output pipes.

    :param session: Kim pipeline session instance

    :rtype: mixed
    :returns: the key found in data using field.source

    """

    source = session.field.opts.source

    # If the field is wrapped by another field then the relevant data
    # will have already been pulled from the source.
    if session.field.opts._is_wrapped or source == '__self__':
        return session.data

    value = attr_or_key(session.data, source)
    session.data = value
    return session.data
Beispiel #15
0
def test_attr_or_key_util_dot_syntax_escape():

    foo_dict = {"bar.xyz": "abc"}

    assert attr_or_key(foo_dict, "bar\\.xyz") == "abc"