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.
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) –
-
default
¶
-
immutable
¶
-
in_dump
¶
-
is_nullable
¶
-
name
¶
-
nullable
¶
-
required
¶
-
type
¶
-
class
auxlib.entity.
BooleanField
(default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[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]¶
-
class
auxlib.entity.
DateField
(default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]¶
-
class
auxlib.entity.
EnumField
(enum_class, default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]¶
-
class
auxlib.entity.
ListField
(element_type, default=None, required=True, validation=None, in_dump=True, nullable=False, immutable=False)[source]¶