Skip to content

singleton

This is a singleton metaclass that can be used to cache and re-use existing objects.

In the Iceberg codebase we have a lot of objects that are stateless (for example Types such as StringType, BooleanType etc). FixedTypes have arguments (eg. Fixed[22]) that we also make part of the key when caching the newly created object.

The Singleton uses a metaclass which essentially defines a new type. When the Type gets created, it will first evaluate the __call__ method with all the arguments. If we already initialized a class earlier, we'll just return it.

More information on metaclasses: https://docs.python.org/3/reference/datamodel.html#metaclasses

Singleton

Source code in pyiceberg/utils/singleton.py
class Singleton:
    _instances: ClassVar[Dict] = {}  # type: ignore

    def __new__(cls, *args, **kwargs):  # type: ignore
        key = (cls, tuple(args), _convert_to_hashable_type(kwargs))
        if key not in cls._instances:
            cls._instances[key] = super().__new__(cls)
        return cls._instances[key]

    def __deepcopy__(self, memo: Dict[int, Any]) -> Any:
        """
        Prevent deep copy operations for singletons.

        The IcebergRootModel inherits from Pydantic RootModel,
        which has its own implementation of deepcopy. When deepcopy
        runs, it calls the RootModel __deepcopy__ method and ignores
        that it's a Singleton. To handle this, the order of inheritance
        is adjusted and a __deepcopy__ method is implemented for
        singletons that simply returns itself.
        """
        return self

__deepcopy__(memo)

Prevent deep copy operations for singletons.

The IcebergRootModel inherits from Pydantic RootModel, which has its own implementation of deepcopy. When deepcopy runs, it calls the RootModel deepcopy method and ignores that it's a Singleton. To handle this, the order of inheritance is adjusted and a deepcopy method is implemented for singletons that simply returns itself.

Source code in pyiceberg/utils/singleton.py
def __deepcopy__(self, memo: Dict[int, Any]) -> Any:
    """
    Prevent deep copy operations for singletons.

    The IcebergRootModel inherits from Pydantic RootModel,
    which has its own implementation of deepcopy. When deepcopy
    runs, it calls the RootModel __deepcopy__ method and ignores
    that it's a Singleton. To handle this, the order of inheritance
    is adjusted and a __deepcopy__ method is implemented for
    singletons that simply returns itself.
    """
    return self