Skip to main content

API Reference: Serialization & Schema Evolution

The yourdb/utils.py file contains the core logic for serializing custom Python objects, deserializing them, and handling schema evolution automatically.

Decorators

These decorators are used in your application code to integrate your data models with yourdb.

@register_class

from yourdb.utils import register_class

@register_class
class MyDataModel:
__version__ = 1 # Optional, defaults to 1
# ... attributes and methods ...
  • Purpose: Registers a class with yourdb's serialization and schema evolution system. This is required for any custom class you want to store directly in the database.

  • Versioning: The decorator automatically reads the version = X class attribute. If omitted, the version defaults to 1. This version number is stored with the object data in the log file.

  • Effect: Allows the YourDBEncoder to serialize instances of this class and the yourdb_decoder to reconstruct them and apply upgrades.

from yourdb.utils import register_upgrade

@register_upgrade(class_name: str, from_version: int, to_version: int)
def my_upgrade_function(old_data_dict: dict) -> dict:
# ... logic to transform old_data_dict ...
return new_data_dict
  • Purpose: Registers a function that knows how to upgrade the data of a specific class from one version to the immediate next version.

Arguments:

  • class_name (str): The name of the class this upgrader applies to (must match the class name registered with @register_class).

  • from_version (int): The version the input data dictionary represents.

  • to_version (int): The version the output data dictionary should represent (must be from_version + 1).

Function Signature: The decorated function must:

  • Accept one argument: a dictionary (old_data_dict) representing the data part of the object from the from_version.

  • Return one argument: a dictionary (new_data_dict) representing the data part for the to_version.

Effect: Allows the yourdb_decoder to automatically find and apply this function during lazy reads or eager migrations when it encounters data from from_version.


Core Components (Internal)

These classes and functions are used internally by yourdb but are useful to understand.

YourDBEncoder (Class)

  • A custom json.JSONEncoder subclass.

  • Purpose: Handles the serialization of registered custom objects into a specific JSON format.

  • Output Format: When it encounters an instance of a registered class (obj), it outputs a dictionary like this:

{
"__class__": "ClassName",
"__version__": 1, // Version from obj.__version__ or default
"__data__": { ... obj.__dict__ ... }
}
  • For standard Python types (int, str, list, dict), it uses the default JSON encoding.

yourdb_decoder (Function) A custom object_hook function used with json.loads.

Purpose: Handles the deserialization of JSON data back into Python objects, including applying schema evolution upgrades.

Logic:

  • Looks for the "class" key in the incoming dictionary.

  • If found, identifies the registered class and its latest version from _CLASS_REGISTRY.

  • Checks the "version" from the JSON data (defaults to 1 if missing).

  • If stored_version < latest_version:

    • Enters a loop, finding and applying the necessary @register_upgrade functions (v1->v2, v2->v3, etc.) in sequence to the "data" dictionary until it reaches the latest_version.

    • Raises an error if a required upgrade function is missing.

  • Creates a new, empty instance of the latest class version (cls.new(cls)).

  • Populates the instance's dict with the (now fully upgraded) data.

  • Returns the reconstructed Python object.

  • If "class" is not found, returns the dictionary as is.