
"Base class for objects that have per-context state."

class CacheEntry(object):
    def __init__(self, version, data):
        self.version = version
        self.data = data

class MultiContext(object):
    "Base class for objects that have per-context state."

    def __init__(self):
        self.version = 0

    def _context_create(self, ctx):
        "Create per-context state."
        raise NotImplementedError()

    def _context_update(self, ctx, old_data):
        "Update per-context state."
        raise NotImplementedError()

    def _context_delete(self, ctx, obj):
        "Delete per-context state."
        raise NotImplementedError()

    def context_delete(self, ctx):
        "Remove this object from the given context."

        cache = ctx.setdefault(self._context_key, {})
        entry = cache.get(self)

        if entry is not None:
            self._context_delete(ctx, entry.data)
            del cache[self]

    def context_get(self, ctx):
        """Get the instantiation of this object in the given context.

        This instantiates the object in the context if necessary.
        """

        cache = ctx.setdefault(self._context_key, {})
        entry = cache.get(self)

        if entry is not None:
            if entry.version < self.version:
                data = self._context_update(ctx, entry.data)
                entry.version = self.version
                entry.data = data
        else:
            data = self._context_create(ctx)
            entry = cache[self] = CacheEntry(self.version, data)

        return entry.data

