Examples¶
Class inheritance and migrations¶
By default local-migrator
uses migrations of parent class if defined:
Lets see this code sample:
import json
from datetime import date
from pydantic import BaseModel
from local_migrator import Encoder
class Person(BaseModel):
name: str
birth_date: date
class Employee(Person):
company: str
data = Employee(name="John Smith", birth_date=date(1980, 1, 15), company="napari")
with open("employee.json", "w") as f:
json.dump(data, f, cls=Encoder)
Assume that one would like to split Person.name
into
two fields: names
and last_name
.
Also there is a need to load data from previous version. Following code will do it:
import json
from datetime import date
from pydantic import BaseModel
from local_migrator import object_hook, register_class
def _migrate_person(dkt):
dkt = dict(dkt) # copy for safety
name_list = dkt["name"].rsplit(" ", 1)
if len(name_list) == 1:
dkt["names"] = name_list[0]
dkt["last_name"] = ""
else:
dkt["names"], dkt["last_name"] = name_list
return dkt
@register_class("0.0.1", migrations=[("0.0.1", _migrate_person)])
class Person(BaseModel):
names: str
last_name: str
birth_date: date
class Employee(Person):
company: str
data = Employee(names="John", last_name="Smith", birth_date=date(1980, 1, 15), company="napari")
with open("employee.json",) as f:
data2 = json.load(f, object_hook=object_hook)
assert data == data2
register_class()
has ause_parent_migrations
argument bydefault set to
True
. If set toFalse
, parents class migration will be ignored. This may be usefully in some rare examples, when fixing old data structures.
update_argument
¶
The nme.update_argument()
is a helper function that allow update
the dict
argument of a function to class based
(for example pydantic.BaseModel
based)
keeping backward compatibility.
Lets have function:
from typing import Dict
def my_function(arg: Dict[str, int]):
return arg.get("a", 1) + arg.get("b", 2)
assert my_function({"a":5}) == 7
And assume that we would like to use nme
for serialize argument of this
function and have option to use migration engine.
To keep backward compatibility we can wrote following code:
from typing import Dict
from pydantic import BaseModel
from local_migrator import update_argument
class MyArgument(BaseModel):
a: int = 1
b: int = 2
@update_argument("arg")
def my_function(arg: MyArgument):
return arg.a + arg.b
assert my_function({"a":5}) == 7
assert my_function(MyArgument(a=5)) == 7
update_argument
use inspect
module to
determine argument class.
CBOR support¶
cbor2
encoder (cbor_encoder
) and object hook
(cbor_decoder
) are available.
import cbor2
from pydantic import BaseModel
from local_migrator import cbor_encoder, cbor_decoder
class SampleModel(BaseModel):
field1: int
field2: str
data = SampleModel(field1=4, field2="abc")
with open("sample.cbor", "wb") as f_p:
cbor2.dump(data, f_p, default=cbor_encoder)
with open("sample.cbor", "rb") as f_p:
data2 = cbor2.load(f_p, object_hook=cbor_decoder)
assert data == data2