A wrapper for another class that can be used to delay instantiation of the wrapped class. By subclassing, you have the opportunity to intercept and alter the instantiation. If you don't need to do that, use SimpleLazyObject.
| 257 | |
| 258 | |
| 259 | class LazyObject: |
| 260 | """ |
| 261 | A wrapper for another class that can be used to delay instantiation of the |
| 262 | wrapped class. |
| 263 | |
| 264 | By subclassing, you have the opportunity to intercept and alter the |
| 265 | instantiation. If you don't need to do that, use SimpleLazyObject. |
| 266 | """ |
| 267 | |
| 268 | # Avoid infinite recursion when tracing __init__ (#19456). |
| 269 | _wrapped = None |
| 270 | |
| 271 | def __init__(self): |
| 272 | # Note: if a subclass overrides __init__(), it will likely need to |
| 273 | # override __copy__() and __deepcopy__() as well. |
| 274 | self._wrapped = empty |
| 275 | |
| 276 | def __getattribute__(self, name): |
| 277 | if name == "_wrapped": |
| 278 | # Avoid recursion when getting wrapped object. |
| 279 | return super().__getattribute__(name) |
| 280 | value = super().__getattribute__(name) |
| 281 | # If attribute is a proxy method, raise an AttributeError to call |
| 282 | # __getattr__() and use the wrapped object method. |
| 283 | if not getattr(value, "_mask_wrapped", True): |
| 284 | raise AttributeError |
| 285 | return value |
| 286 | |
| 287 | __getattr__ = new_method_proxy(getattr) |
| 288 | |
| 289 | def __setattr__(self, name, value): |
| 290 | if name == "_wrapped": |
| 291 | # Assign to __dict__ to avoid infinite __setattr__ loops. |
| 292 | self.__dict__["_wrapped"] = value |
| 293 | else: |
| 294 | if self._wrapped is empty: |
| 295 | self._setup() |
| 296 | setattr(self._wrapped, name, value) |
| 297 | |
| 298 | def __delattr__(self, name): |
| 299 | if name == "_wrapped": |
| 300 | raise TypeError("can't delete _wrapped.") |
| 301 | if self._wrapped is empty: |
| 302 | self._setup() |
| 303 | delattr(self._wrapped, name) |
| 304 | |
| 305 | def _setup(self): |
| 306 | """ |
| 307 | Must be implemented by subclasses to initialize the wrapped object. |
| 308 | """ |
| 309 | raise NotImplementedError( |
| 310 | "subclasses of LazyObject must provide a _setup() method" |
| 311 | ) |
| 312 | |
| 313 | # Because we have messed with __class__ below, we confuse pickle as to what |
| 314 | # class we are pickling. We're going to have to initialize the wrapped |
| 315 | # object to successfully pickle it, so we might as well just pickle the |
| 316 | # wrapped object since they're supposed to act the same way. |
nothing calls this directly
no test coverage detected