Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

get_name() changes to handle class property case #3

Open
wants to merge 4 commits into from

2 participants

Alex Bendig Jacob Alheid
Alex Bendig

The get_name() code resulted in a RuntimeError (due to deep recursion), if the passed frame referred to a class property. The main fix was to not use getattr(), since that resulted in executing the property get code. This pull request contains the updated get_name() as well as two new test cases.

Jacob Alheid shakefu commented on the diff
pytool/json.py
@@ -10,7 +10,11 @@
"""
from datetime import datetime
-import simplejson as json
+try:
+ import simplejson as json
+except:
+ import json
Jacob Alheid Owner
shakefu added a note

Simplejson is required for Pytool. See the comment about the 'for_json()' hook on line 75.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Jacob Alheid shakefu commented on the diff
pytool/lang.py
@@ -31,10 +31,12 @@ def get_name(frame):
maybe_cls = frame.f_locals[varname]
# Get the actual method, if it exists on the class
- maybe_func = getattr(maybe_cls, frame.f_code.co_name)
Jacob Alheid Owner
shakefu added a note

Try replacing this line with:

maybe_func = object.__getattribute__(maybe_cls, frame.f_code.co_name)

... which should avoid recursion issues while still using the standard MRO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 36 additions and 7 deletions.
  1. +5 −1 pytool/json.py
  2. +8 −6 pytool/lang.py
  3. +23 −0 test/test_lang.py
6 pytool/json.py
View
@@ -10,7 +10,11 @@
"""
from datetime import datetime
-import simplejson as json
+try:
+ import simplejson as json
+except:
+ import json
Jacob Alheid Owner
shakefu added a note

Simplejson is required for Pytool. See the comment about the 'for_json()' hook on line 75.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
# Conditionally handle bson import so we don't have to depend on pymongo
try:
import bson
14 pytool/lang.py
View
@@ -31,10 +31,12 @@ def get_name(frame):
maybe_cls = frame.f_locals[varname]
# Get the actual method, if it exists on the class
- maybe_func = getattr(maybe_cls, frame.f_code.co_name)
Jacob Alheid Owner
shakefu added a note

Try replacing this line with:

maybe_func = object.__getattribute__(maybe_cls, frame.f_code.co_name)

... which should avoid recursion issues while still using the standard MRO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
-
+ if isinstance(maybe_cls, type):
+ maybe_func = maybe_cls.__dict__[frame.f_code.co_name]
+ else:
+ maybe_func = maybe_cls.__class__.__dict__[frame.f_code.co_name]
# If we have self, or a classmethod, we need the class name
- if (varname == 'self' or maybe_func.im_self == maybe_cls):
+ if (varname in ('self', 'cls') or maybe_func.im_self == maybe_cls):
cls_name = (getattr(maybe_cls, '__name__', None)
or getattr(getattr(maybe_cls, '__class__', None),
'__name__', None))
@@ -236,7 +238,7 @@ class UNSET(object):
>>> # Is good for checking default values
>>> if {}.get('example', UNSET) is UNSET:
... print "Key is missing."
- ...
+ ...
Key is missing.
>>> # Has no length
>>> len(UNSET)
@@ -285,7 +287,7 @@ class Namespace(object):
>>> # Namespaces are iterable
>>> for name, value in myns:
... print name, value
- ...
+ ...
hello world
example.value True
>>> # Namespaces that are empty evaluate as False
@@ -300,7 +302,7 @@ class Namespace(object):
>>> class MyDescriptor(object):
... def __get__(self, instance, owner):
... return 'Hello World'
- ...
+ ...
>>> myns.descriptor = MyDescriptor()
>>> myns.descriptor
'Hello World'
23 test/test_lang.py
View
@@ -35,6 +35,29 @@ def test(self):
Test().test()
+def test_get_name_class_method():
+ class Test(object):
+ @classmethod
+ def test(cls):
+ frame = inspect.currentframe()
+ eq_(pytool.lang.get_name(frame),
+ 'test.test_lang.Test.test')
+ del frame
+
+ Test.test()
+
+
+def test_get_name_class_property():
+ class Test(object):
+ @property
+ def test(self):
+ frame = inspect.currentframe()
+ this_name = pytool.lang.get_name(frame)
+ del frame
+ return this_name
+ eq_(Test().test, 'test.test_lang.Test.test')
+
+
def test_classproperty():
class Test(object):
value = 'Test'
Something went wrong with that request. Please try again.