-
Notifications
You must be signed in to change notification settings - Fork 924
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented LazyObject class, which provides a 'lazy' class method to create instances with lazy initialization. Th… #665
Conversation
self._request() | ||
|
||
def _request(self): | ||
# TODO(crunkleton@google.com): create new connection? or make |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@crunk1 so what is the intention with the todo? to raise a separate PR later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I need to look into this later.
LGTM +1 |
pass | ||
|
||
def __getattribute__(self, attr): | ||
lazy_obj = object.__getattribute__(self, 'lazy_obj') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should you prefix the lazy_obj
attr with an underscore (_lazy_obj
) to indicate it's intended to be a private attr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I believe if you override __getattr__
instead of __getattribute__
then you can just check the attribute value without having to invoke __getattribute__
directly like this:
if self.lazy_obj is None:
But maybe there's something subtle here I'm missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed LazyObject.Proxy.lazy_obj
to LazyObject.Proxy._lazy_obj
.
Regarding the __getattr__
vs __getattribute__
discussion, see http://stackoverflow.com/a/3278104/1436495.
My considerations:
__getattr__
is only called if attribute resolution fails by normal means__getattribute__
is ALWAYS called (even on bound methods); easier to handle given my next point- the
Proxy
metaclass inherits fromlazy_cls
(I wantProxy
to be as transparent as possible as a wrapper; I want the returnedProxy
instance to have the class info forlazy_cls
), meaning thatProxy
inherits all methods and class attributes oflazy_cls
. Therefore, weird things happen when you call methods or use class-level attributes intended for the lazy object instead of theProxy
.
…e lazy class method returns a Proxy object that subclasses the target object class. Upon accessing the proxy object in any way, the object is initialized. Modified Google Compute Engine License objects, GCELicense, to be such a lazy object. This addresses https://issues.apache.org/jira/browse/LIBCLOUD-786. Tests/Verification: tox -e lint python setup.py test Added test/common/test_base.py which has LazyObjectTest
pass | ||
|
||
def __getattribute__(self, attr): | ||
lazy_obj = object.__getattribute__(self, '_get_lazy_obj')() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrapping it in a method was nice, but I don't think you need to use __getattribute__
to call that method since it's defined in the same class here, so any invocation of this method is guaranteed to have self._get_lazy_obj()
available to call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the Proxy class has __getattribute__
defined, self._get_lazy_obj()
will first call Proxy.__getattribute__(self, '_get_lazy_obj')
to get the bound method. That leads to an infinite recursion loop. See an example here: https://repl.it/Bavg/1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, right, derp. I should stop doing code reviews before I get any caffeine in me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All good, thanks for all your help!
One last nitpick, but otherwise lgtm. |
Ok, this lgtm too and I've done some additional testing. The Merging now. |
This has now been merged: 81a8dbc |
…e lazy class method returns a Proxy object that subclasses the target object class. Upon accessing the proxy object in any way, the object is initialized.
Modified Google Compute Engine License objects, GCELicense, to be such a lazy object. This addresses https://issues.apache.org/jira/browse/LIBCLOUD-786.
Tests/Verification:
tox -e lint
python setup.py test
Added test/common/test_base.py which has LazyObjectTest