import weakref from mongoengine.common import _import_class __all__ = ("BaseDict", "BaseList") class BaseDict(dict): """A special dict so we can watch any changes """ _dereferenced = False _instance = None _name = None def __init__(self, dict_items, instance, name): Document = _import_class('Document') EmbeddedDocument = _import_class('EmbeddedDocument') if isinstance(instance, (Document, EmbeddedDocument)): self._instance = weakref.proxy(instance) self._name = name return super(BaseDict, self).__init__(dict_items) def __getitem__(self, *args, **kwargs): value = super(BaseDict, self).__getitem__(*args, **kwargs) EmbeddedDocument = _import_class('EmbeddedDocument') if isinstance(value, EmbeddedDocument) and value._instance is None: value._instance = self._instance return value def __setitem__(self, *args, **kwargs): self._mark_as_changed() return super(BaseDict, self).__setitem__(*args, **kwargs) def __delete__(self, *args, **kwargs): self._mark_as_changed() return super(BaseDict, self).__delete__(*args, **kwargs) def __delitem__(self, *args, **kwargs): self._mark_as_changed() return super(BaseDict, self).__delitem__(*args, **kwargs) def __delattr__(self, *args, **kwargs): self._mark_as_changed() return super(BaseDict, self).__delattr__(*args, **kwargs) def __getstate__(self): self.instance = None self._dereferenced = False return self def __setstate__(self, state): self = state return self def clear(self, *args, **kwargs): self._mark_as_changed() return super(BaseDict, self).clear(*args, **kwargs) def pop(self, *args, **kwargs): self._mark_as_changed() return super(BaseDict, self).pop(*args, **kwargs) def popitem(self, *args, **kwargs): self._mark_as_changed() return super(BaseDict, self).popitem(*args, **kwargs) def update(self, *args, **kwargs): self._mark_as_changed() return super(BaseDict, self).update(*args, **kwargs) def _mark_as_changed(self): if hasattr(self._instance, '_mark_as_changed'): self._instance._mark_as_changed(self._name) class BaseList(list): """A special list so we can watch any changes """ _dereferenced = False _instance = None _name = None def __init__(self, list_items, instance, name): Document = _import_class('Document') EmbeddedDocument = _import_class('EmbeddedDocument') if isinstance(instance, (Document, EmbeddedDocument)): self._instance = weakref.proxy(instance) self._name = name return super(BaseList, self).__init__(list_items) def __getitem__(self, *args, **kwargs): value = super(BaseList, self).__getitem__(*args, **kwargs) EmbeddedDocument = _import_class('EmbeddedDocument') if isinstance(value, EmbeddedDocument) and value._instance is None: value._instance = self._instance return value def __setitem__(self, *args, **kwargs): self._mark_as_changed() return super(BaseList, self).__setitem__(*args, **kwargs) def __delitem__(self, *args, **kwargs): self._mark_as_changed() return super(BaseList, self).__delitem__(*args, **kwargs) def __getstate__(self): self.instance = None self._dereferenced = False return self def __setstate__(self, state): self = state return self def append(self, *args, **kwargs): self._mark_as_changed() return super(BaseList, self).append(*args, **kwargs) def extend(self, *args, **kwargs): self._mark_as_changed() return super(BaseList, self).extend(*args, **kwargs) def insert(self, *args, **kwargs): self._mark_as_changed() return super(BaseList, self).insert(*args, **kwargs) def pop(self, *args, **kwargs): self._mark_as_changed() return super(BaseList, self).pop(*args, **kwargs) def remove(self, *args, **kwargs): self._mark_as_changed() return super(BaseList, self).remove(*args, **kwargs) def reverse(self, *args, **kwargs): self._mark_as_changed() return super(BaseList, self).reverse(*args, **kwargs) def sort(self, *args, **kwargs): self._mark_as_changed() return super(BaseList, self).sort(*args, **kwargs) def _mark_as_changed(self): if hasattr(self._instance, '_mark_as_changed'): self._instance._mark_as_changed(self._name)