Revert "look up descriptor by objclass in _getattr instead of eval (#762)" (#774)
This reverts commit db3451220d2a8cf367777130f55c75e7fc9d8d36.
diff --git a/dill/_dill.py b/dill/_dill.py
index 9d115be..096a661 100644
--- a/dill/_dill.py
+++ b/dill/_dill.py
@@ -1032,20 +1032,23 @@
return capsule
def _getattr(objclass, name, repr_str):
- # grab the descriptor directly off its owning class; repr_str is kept
- # for backward compatibility with existing pickles but is not evaluated
- try:
- attr = objclass.__dict__
- if type(attr) is DictProxyType:
- if sys.hexversion > 0x30f00a0 and name in ('__weakref__','__dict__'):
- attr = _dictproxy_helper.__dict__[name]
+ # hack to grab the reference directly
+ try: #XXX: works only for __builtin__ ?
+ attr = repr_str.split("'")[3]
+ return eval(attr+'.__dict__["'+name+'"]')
+ except Exception:
+ try:
+ attr = objclass.__dict__
+ if type(attr) is DictProxyType:
+ if sys.hexversion > 0x30f00a0 and name in ('__weakref__','__dict__'):
+ attr = _dictproxy_helper.__dict__[name]
+ else:
+ attr = attr[name]
else:
- attr = attr[name]
- else:
+ attr = getattr(objclass,name)
+ except (AttributeError, KeyError):
attr = getattr(objclass,name)
- except (AttributeError, KeyError):
- attr = getattr(objclass,name)
- return attr
+ return attr
def _get_attr(self, name):
# stop recursive pickling
diff --git a/dill/tests/test_selected.py b/dill/tests/test_selected.py
index 5fcc691..b4edb34 100644
--- a/dill/tests/test_selected.py
+++ b/dill/tests/test_selected.py
@@ -62,21 +62,6 @@
assert ok
if verbose: print ("")
-# descriptors are restored via dill._dill._getattr; the attribute name
-# carried in the pickle must be looked up, never evaluated as code
-def test_descriptor_getattr():
- from dill._dill import _getattr
- for i in (int.__dict__['real'], str.__dict__['__len__']):
- assert dill.copy(i) is i
- # a crafted name that would run code if passed to eval() must instead be
- # treated as a plain (missing) lookup key
- name = '__doc__"].count("zz") or setattr(__import__("dill"), "_pwned", True) or object.__dict__["__doc__'
- try:
- _getattr(object, name, "x'x'x'object'x")
- except (AttributeError, KeyError):
- pass
- assert not getattr(dill, "_pwned", False)
-
# (__main__) class instance for new-style classes
def test_class():
o = _d()
@@ -133,5 +118,4 @@
test_dict_contents()
test_class()
test_class_descriptors()
- test_descriptor_getattr()
test_typing()