A special list so we can watch any changes.
| 103 | |
| 104 | |
| 105 | class BaseList(list): |
| 106 | """A special list so we can watch any changes.""" |
| 107 | |
| 108 | _dereferenced = False |
| 109 | _instance = None |
| 110 | _name = None |
| 111 | |
| 112 | def __init__(self, list_items, instance, name): |
| 113 | BaseDocument = _import_class("BaseDocument") |
| 114 | |
| 115 | if isinstance(instance, BaseDocument): |
| 116 | if isinstance(instance, weakref.ProxyTypes): |
| 117 | self._instance = instance |
| 118 | else: |
| 119 | self._instance = weakref.proxy(instance) |
| 120 | |
| 121 | self._name = name |
| 122 | super().__init__(list_items) |
| 123 | |
| 124 | def __getitem__(self, key): |
| 125 | # change index to positive value because MongoDB does not support negative one |
| 126 | if isinstance(key, int) and key < 0: |
| 127 | key = len(self) + key |
| 128 | value = super().__getitem__(key) |
| 129 | |
| 130 | if isinstance(key, slice): |
| 131 | # When receiving a slice operator, we don't convert the structure and bind |
| 132 | # to parent's instance. This is buggy for now but would require more work to be handled properly |
| 133 | return value |
| 134 | |
| 135 | EmbeddedDocument = _import_class("EmbeddedDocument") |
| 136 | if isinstance(value, EmbeddedDocument) and value._instance is None: |
| 137 | value._instance = self._instance |
| 138 | elif isinstance(value, dict) and not isinstance(value, BaseDict): |
| 139 | # Replace dict by BaseDict |
| 140 | value = BaseDict(value, None, f"{self._name}.{key}") |
| 141 | super().__setitem__(key, value) |
| 142 | value._instance = self._instance |
| 143 | elif isinstance(value, list) and not isinstance(value, BaseList): |
| 144 | # Replace list by BaseList |
| 145 | value = BaseList(value, None, f"{self._name}.{key}") |
| 146 | super().__setitem__(key, value) |
| 147 | value._instance = self._instance |
| 148 | return value |
| 149 | |
| 150 | def __iter__(self): |
| 151 | yield from super().__iter__() |
| 152 | |
| 153 | def __getstate__(self): |
| 154 | self.instance = None |
| 155 | self._dereferenced = False |
| 156 | return self |
| 157 | |
| 158 | def __setstate__(self, state): |
| 159 | self = state |
| 160 | return self |
| 161 | |
| 162 | def __setitem__(self, key, value): |