Source code for serpy.fields

import six
import types


[docs]class Field(object): """:class:`Field` is used to define what attributes will be serialized. A :class:`Field` maps a property or function on an object to a value in the serialized result. Subclass this to make custom fields. For most simple cases, overriding :meth:`Field.to_value` should give enough flexibility. If more control is needed, override :meth:`Field.as_getter`. :param str attr: The attribute to get on the object, using the same format as ``operator.attrgetter``. If this is not supplied, the name this field was assigned to on the serializer will be used. :param bool call: Whether the value should be called after it is retrieved from the object. Useful if an object has a method to be serialized. :param str label: A label to use as the name of the serialized field instead of using the attribute name of the field. :param bool required: Whether the field is required. If set to ``False``, :meth:`Field.to_value` will not be called if the value is ``None``. """ #: Set to ``True`` if the value function returned from #: :meth:`Field.as_getter` requires the serializer to be passed in as the #: first argument. Otherwise, the object will be the only parameter. getter_takes_serializer = False def __init__(self, attr=None, call=False, label=None, required=True): self.attr = attr self.call = call self.label = label self.required = required
[docs] def to_value(self, value): """Transform the serialized value. Override this method to clean and validate values serialized by this field. For example to implement an ``int`` field: :: def to_value(self, value): return int(value) :param value: The value fetched from the object being serialized. """ return value
to_value._serpy_base_implementation = True def _is_to_value_overridden(self): to_value = self.to_value # If to_value isn't a method, it must have been overridden. if not isinstance(to_value, types.MethodType): return True return not getattr(to_value, '_serpy_base_implementation', False)
[docs] def as_getter(self, serializer_field_name, serializer_cls): """Returns a function that fetches an attribute from an object. Return ``None`` to use the default getter for the serializer defined in :attr:`Serializer.default_getter`. When a :class:`Serializer` is defined, each :class:`Field` will be converted into a getter function using this method. During serialization, each getter will be called with the object being serialized, and the return value will be passed through :meth:`Field.to_value`. If a :class:`Field` has ``getter_takes_serializer = True``, then the getter returned from this method will be called with the :class:`Serializer` instance as the first argument, and the object being serialized as the second. :param str serializer_field_name: The name this field was assigned to on the serializer. :param serializer_cls: The :class:`Serializer` this field is a part of. """ return None
[docs]class StrField(Field): """A :class:`Field` that converts the value to a string.""" to_value = staticmethod(six.text_type)
[docs]class IntField(Field): """A :class:`Field` that converts the value to an integer.""" to_value = staticmethod(int)
[docs]class FloatField(Field): """A :class:`Field` that converts the value to a float.""" to_value = staticmethod(float)
[docs]class BoolField(Field): """A :class:`Field` that converts the value to a boolean.""" to_value = staticmethod(bool)
[docs]class MethodField(Field): """A :class:`Field` that calls a method on the :class:`Serializer`. This is useful if a :class:`Field` needs to serialize a value that may come from multiple attributes on an object. For example: :: class FooSerializer(Serializer): plus = MethodField() minus = MethodField('do_minus') def get_plus(self, foo_obj): return foo_obj.bar + foo_obj.baz def do_minus(self, foo_obj): return foo_obj.bar - foo_obj.baz foo = Foo(bar=5, baz=10) FooSerializer(foo).data # {'plus': 15, 'minus': -5} :param str method: The method on the serializer to call. Defaults to ``'get_<field name>'``. """ getter_takes_serializer = True def __init__(self, method=None, **kwargs): super(MethodField, self).__init__(**kwargs) self.method = method
[docs] def as_getter(self, serializer_field_name, serializer_cls): method_name = self.method if method_name is None: method_name = 'get_{0}'.format(serializer_field_name) return getattr(serializer_cls, method_name)