Versioning Schemas¶
During development, it is natural that the fields on objects in OTIO change. To accommodate this, OTIO has a system for handling version differences and upgrading older schemas to new ones. There are two components:
serializeable_label
on the class has a name and version field:Foo.5
–Foo
is the schema name and5
is the version.upgrade_function_for
decorator
Changing a Field¶
For example, lets say you have class:
import opentimelineio as otio
@otio.core.register_type
class SimpleClass(otio.core.SerializeableObject):
serializeable_label = "SimpleClass.1"
my_field = otio.core.serializeable_field("my_field", int)
And you want to change my_field
to new_field
. To do this:
Make the change in the class
Bump the version number in the label
add an upgrade function
So after the changes, you’ll have:
@otio.core.register_type
class SimpleClass(otio.core.SerializeableObject):
serializeable_label = "SimpleClass.2"
my_field = otio.core.serializeable_field("new_field", int)
@otio.core.upgrade_function_for(SimpleClass, 2)
def upgrade_one_to_two(data):
return {"new_field" : data["my_field"] }
Lets change it again, so that new_field
becomes even_newer_field
.
@otio.core.register_type
class SimpleClass(otio.core.SerializeableObject):
serializeable_label = "SimpleClass.2"
my_field = otio.core.serializeable_field("even_newer_field", int)
@otio.core.upgrade_function_for(SimpleClass, 2)
def upgrade_one_to_two(data):
return {"new_field" : data["my_field"] }
# NOTE we now have a second upgrade function
@otio.core.upgrade_function_for(SimpleClass, 3)
def upgrade_two_to_three(data):
return {"even_newer_field" : data["new_field"] }
Upgrade functions can be sparse - if version 3
to 4
doesn’t require a function, for example, you don’t need to write one.
Adding or Removing a Field¶
Starting from the same class:
@otio.core.register_type
class SimpleClass(otio.core.SerializeableObject):
serializeable_label = "SimpleClass.1"
my_field = otio.core.serializeable_field("my_field", int)
Adding or Removing a field is simpler. In these cases, you don’t need to write an upgrade function, since any new classes will be initialized through the constructor, and any removed fields will be ignored when reading from an older schema version.
So lets add a new field:
@otio.core.register_type
class SimpleClass(otio.core.SerializeableObject):
serializeable_label = "SimpleClass.2"
my_field = otio.core.serializeable_field("my_field", int)
other_field = otio.core.serializeable_field("other_field", int)
And then delete the original field:
@otio.core.register_type
class SimpleClass(otio.core.SerializeableObject):
serializeable_label = "SimpleClass.3"
other_field = otio.core.serializeable_field("other_field", int)