auxlib.entity

This module provides serializable, validatable, type-enforcing domain objects and data transfer objects. It has many of the same motivations as the python Marshmallow package. It is most similar to Schematics.

Tutorial

Chapter 1: Entity and Field Basics

>>> class Color(Enum):
...     blue = 0
...     black = 1
...     red = 2
>>> class Car(Entity):
...     weight = NumberField(required=False)
...     wheels = IntField(default=4, validation=lambda x: 3 <= x <= 4)
...     color = EnumField(Color)
>>> # create a new car object
>>> car = Car(color=Color.blue, weight=4242.46)
>>> car
Car(weight=4242.46, color=0)
>>> # it has 4 wheels, all by default
>>> car.wheels
4
>>> # but a car can't have 5 wheels!
>>> #  the `validation=` field is a simple callable that returns a
>>> #  boolean based on validity
>>> car.wheels = 5
Traceback (most recent call last):
ValidationError: Invalid value 5 for wheels
>>> # we can call .dump() on car, and just get back a standard
>>> #  python dict actually, it's an ordereddict to match attribute
>>> #  declaration order
>>> type(car.dump())
<class '...OrderedDict'>
>>> car.dump()
OrderedDict([('weight', 4242.46), ('wheels', 4), ('color', 0)])
>>> # and json too (note the order!)
>>> car.json()
'{"weight": 4242.46, "wheels": 4, "color": 0}'
>>> # green cars aren't allowed
>>> car.color = "green"
Traceback (most recent call last):
ValidationError: 'green' is not a valid Color
>>> # but black cars are!
>>> car.color = "black"
>>> car.color
<Color.black: 1>
>>> # car.color really is an enum, promise
>>> type(car.color)
<enum 'Color'>
>>> # enum assignment can be with any of (and preferentially)
>>> #   (1) an enum literal,
>>> #   (2) a valid enum value, or
>>> #   (3) a valid enum name
>>> car.color = Color.blue; car.color.value
0
>>> car.color = 1; car.color.name
'black'
>>> # let's do a round-trip marshalling of this thing
>>> same_car = Car.from_json(car.json())  # or equally Car.from_json(json.dumps(car.dump()))
>>> same_car == car
True
>>> # actually, they're two different instances
>>> same_car is not car
True
>>> # this works too
>>> cloned_car = Car(**car.dump())
>>> cloned_car == car
True
>>> # while we're at it, these are all equivalent too
>>> car == Car.from_objects(car)
True
>>> car == Car.from_objects({"weight": 4242.46, "wheels": 4, "color": 1})
True
>>> car == Car.from_json('{"weight": 4242.46, "color": 1}')
True
>>> # .from_objects() even lets you stack and combine objects
>>> class DumbClass:
...     color = 0
...     wheels = 3
>>> Car.from_objects(DumbClass(), dict(weight=2222, color=1))
Car(weight=2222, wheels=3, color=0)
>>> # and also pass kwargs that override properties pulled
>>> #  off any objects
>>> Car.from_objects(DumbClass(), {'weight': 2222, 'color': 1}, color=2, weight=33)
Car(weight=33, wheels=3, color=2)

Chapter 2: Entity and Field Composition

>>> # now let's get fancy
>>> # a ComposableField "nests" another valid Entity
>>> # a ListField's first argument is a "generic" type,
>>> #   which can be a valid Entity, any python primitive
>>> #   type, or a list of Entities/types
>>> class Fleet(Entity):
...     boss_car = ComposableField(Car)
...     cars = ListField(Car)
>>> # here's our fleet of company cars
>>> company_fleet = Fleet(boss_car=Car(color='red'), cars=[car, same_car, cloned_car])
>>> company_fleet.pretty_json()  
{
  "boss_car": {
    "wheels": 4
    "color": 2,
  },
  "cars": [
    {
      "weight": 4242.46,
      "wheels": 4
      "color": 1,
    },
    {
      "weight": 4242.46,
      "wheels": 4
      "color": 1,
    },
    {
      "weight": 4242.46,
      "wheels": 4
      "color": 1,
    }
  ]
}
>>> # the boss' car is red of course (and it's still an Enum)
>>> company_fleet.boss_car.color.name
'red'
>>> # and there are three cars left for the employees
>>> len(company_fleet.cars)
3

Chapter 3: Immutability

>>> class ImmutableCar(ImmutableEntity):
...     wheels = IntField(default=4, validation=lambda x: 3 <= x <= 4)
...     color = EnumField(Color)
>>> icar = ImmutableCar.from_objects({'wheels': 3, 'color': 'blue'})
>>> icar
ImmutableCar(wheels=3, color=0)
>>> icar.wheels = 4
Traceback (most recent call last):
AttributeError: Assignment not allowed. ImmutableCar is immutable.
>>> class FixedWheelCar(Entity):
...     wheels = IntField(default=4, immutable=True)
...     color = EnumField(Color)
>>> fwcar = FixedWheelCar.from_objects(icar)
>>> fwcar.json()
'{"wheels": 3, "color": 0}'
>>> # repainting the car is easy
>>> fwcar.color = Color.red
>>> fwcar.color.name
'red'
>>> # can't really change the number of wheels though
>>> fwcar.wheels = 18
Traceback (most recent call last):
AttributeError: The wheels field is immutable.

Chapter X: The del and null Weeds

>>> old_date = lambda: isoparse('1982-02-17')
>>> class CarBattery(Entity):
...     # NOTE: default value can be a callable!
...     first_charge = DateField(required=False)  # default=None, nullable=False
...     latest_charge = DateField(default=old_date, nullable=True)  # required=True
...     expiration = DateField(default=old_date, required=False, nullable=False)
>>> # starting point
>>> battery = CarBattery()
>>> battery
CarBattery()
>>> battery.json()
'{"latest_charge": "1982-02-17T00:00:00", "expiration": "1982-02-17T00:00:00"}'
>>> # first_charge is not assigned a default value. Once one is assigned, it can be deleted,
>>> #   but it can't be made null.
>>> battery.first_charge = isoparse('2016-03-23')
>>> battery
CarBattery(first_charge=datetime.datetime(2016, 3, 23, 0, 0))
>>> battery.first_charge = None
Traceback (most recent call last):
ValidationError: Value for first_charge not given or invalid.
>>> del battery.first_charge
>>> battery
CarBattery()
>>> # latest_charge can be null, but it can't be deleted. The default value is a callable.
>>> del battery.latest_charge
Traceback (most recent call last):
AttributeError: The latest_charge field is required and cannot be deleted.
>>> battery.latest_charge = None
>>> battery.json()
'{"latest_charge": null, "expiration": "1982-02-17T00:00:00"}'
>>> # expiration is assigned by default, can't be made null, but can be deleted.
>>> battery.expiration
datetime.datetime(1982, 2, 17, 0, 0)
>>> battery.expiration = None
Traceback (most recent call last):
ValidationError: Value for expiration not given or invalid.
>>> del battery.expiration
>>> battery.json()
'{"latest_charge": null}'
class auxlib.entity.Entity(**kwargs)[source]
dump()[source]
classmethod from_json(json_str)[source]
classmethod from_objects(*objects, **override_fields)[source]
json(indent=None, separators=None, **kwargs)[source]
classmethod load(data_dict)[source]
pretty_json(indent=2, separators=(', ', ': '), **kwargs)[source]
validate()[source]
class auxlib.entity.ImmutableEntity(**kwargs)[source]
class auxlib.entity.Field(default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]

Fields are doing something very similar to boxing and unboxing of c#/java primitives. __set__ should take a “primitive” or “raw” value and create a “boxed” or “programatically useable” value of it. While __get__ should return the boxed value, dump in turn should unbox the value into a primitive or raw value.

Parameters:
  • types (primitive literal or type or sequence of types) –
  • default (any, callable, optional) – If default is callable, it’s guaranteed to return a valid value at the time of Entity creation.
  • required (boolean, optional) –
  • validation (callable, optional) –
  • dump (boolean, optional) –
box(instance, val)[source]
default
dump(val)[source]
immutable
in_dump
is_nullable
name
nullable
required
set_name(name)[source]
type
unbox(instance, instance_type, val)[source]
validate(instance, val)[source]
Returns:if val is valid
Return type:True
Raises:ValidationError
class auxlib.entity.BooleanField(default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]
box(instance, val)[source]
auxlib.entity.BoolField

alias of BooleanField

class auxlib.entity.IntegerField(default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]
auxlib.entity.IntField

alias of IntegerField

class auxlib.entity.NumberField(default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]
class auxlib.entity.StringField(default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]
box(instance, val)[source]
class auxlib.entity.DateField(default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]
box(instance, val)[source]
dump(val)[source]
class auxlib.entity.EnumField(enum_class, default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]
box(instance, val)[source]
dump(val)[source]
class auxlib.entity.ListField(element_type, default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]
box(instance, val)[source]
dump(val)[source]
unbox(instance, instance_type, val)[source]
validate(instance, val)[source]
class auxlib.entity.MapField(default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]
__eq__

x.__eq__(y) <==> x==y

class auxlib.entity.ComposableField(field_class, default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]
box(instance, val)[source]
dump(val)[source]