Opened 13 years ago
Closed 13 years ago
#16945 closed New feature (wontfix)
Extend LazyObject to accept constructor parameters
Reported by: | Mitar | Owned by: | nobody |
---|---|---|---|
Component: | Core (Other) | Version: | 1.3 |
Severity: | Normal | Keywords: | |
Cc: | mmitar@… | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
It would be very useful to extend LazyObject to accept constructor parameters. Currently it seems it is only possible to use it for parameter-less classes.
Something like this seems to work:
class LazyObject(object): """ A wrapper for another class that can be used to delay instantiation of the wrapped class. """ def __init__(self, *args, **kwargs): self._wrapped = None self._wrapped_args = args self._wrapped_kwargs = kwargs def __getattr__(self, name): if self._wrapped is None: self._setup() return getattr(self._wrapped, name) def __setattr__(self, name, value): if name in ["_wrapped", "_wrapped_args", "_wrapped_kwargs"]: # Assign to __dict__ to avoid infinite __setattr__ loops. self.__dict__[name] = value else: if self._wrapped is None: self._setup() setattr(self._wrapped, name, value) def __delattr__(self, name): if name == ["_wrapped", "_wrapped_args", "_wrapped_kwargs"]: raise TypeError("can't delete %s." % (name,)) if self._wrapped is None: self._setup() delattr(self._wrapped, name) def _setup(self): """ Must be implemented by subclasses to initialise the wrapped object. """ raise NotImplementedError # introspection support: __members__ = property(lambda self: self.__dir__()) def __dir__(self): if self._wrapped is None: self._setup() return dir(self._wrapped) def __call__(self, *args, **kwargs): if self._wrapped is None: self._setup() return self._wrapped(*args, **kwargs)
It is based on the code from Django 1.2. I can update it to newer version if needed.
Change History (6)
comment:1 by , 13 years ago
Resolution: | → needsinfo |
---|---|
Status: | new → closed |
comment:2 by , 13 years ago
Oh, sorry. Currently it is possible only to use LazyObject on classes where constructors do not take arguments. But if constructors do take arguments, then above version of LazyObject is needed.
I have come above this problem in my Django project where I have one class for URL dispatching/manipulating and it cannot yet be created at load time (because URLs are not loaded). So using LazyObject was an easy way to solve the problem. But my class requires some constructor arguments. So I had to extend LazyObject.
So this addition is not directly needed for Django, but if we ship such utility class, we can make it a bit more generic for other its uses when developing with Django (so that you do not have to reimplement).
Example is then:
class LazyHref(lazy.LazyObject): def _setup(self): self._wrapped = web.href.Href(*self._wrapped_args, **self._wrapped_kwargs)
comment:3 by , 13 years ago
Resolution: | needsinfo |
---|---|
Status: | closed → reopened |
comment:5 by , 13 years ago
It is in utils.functional? But probably it was not meant to be used outside. But it is one "batter included" which developers could use/reuse.
comment:6 by , 13 years ago
Resolution: | → wontfix |
---|---|
Status: | reopened → closed |
Marking as wontfix, this is not part of the public API, it isn't needed in Django, and if you insist on using it in your own code anyways, you can easily add this functionality in your own subclass.
I don't exactly understand what this is useful for as the code example doesn't show how
_wrapped_args
and_wrapped_kwargs
are used. Please provide a specific use case this would be useful for.