diff options
| author | Benjamin Peterson <benjamin@python.org> | 2008-11-17 22:39:09 +0000 |
|---|---|---|
| committer | Benjamin Peterson <benjamin@python.org> | 2008-11-17 22:39:09 +0000 |
| commit | 273c233c78d36f65059342981dcdc5b212a7e558 (patch) | |
| tree | fad34c76f3329915666c8831dd70f2754a42b040 /Lib | |
| parent | 233bb00c1c8fef8434710c7891e955323f48f256 (diff) | |
| download | cpython-git-273c233c78d36f65059342981dcdc5b212a7e558.tar.gz | |
when __getattr__ is a descriptor, call it correctly; fixes #4230
patch from Ziga Seilnacht
Diffstat (limited to 'Lib')
| -rw-r--r-- | Lib/test/test_descr.py | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index f74073811f..b57e0fae05 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4289,6 +4289,46 @@ order (MRO) for bases """ c[1:2] = 3 self.assertEqual(c.value, 3) + def test_getattr_hooks(self): + # issue 4230 + + class Descriptor(object): + counter = 0 + def __get__(self, obj, objtype=None): + def getter(name): + self.counter += 1 + raise AttributeError(name) + return getter + + descr = Descriptor() + class A(object): + __getattribute__ = descr + class B(object): + __getattr__ = descr + class C(object): + __getattribute__ = descr + __getattr__ = descr + + self.assertRaises(AttributeError, getattr, A(), "attr") + self.assertEquals(descr.counter, 1) + self.assertRaises(AttributeError, getattr, B(), "attr") + self.assertEquals(descr.counter, 2) + self.assertRaises(AttributeError, getattr, C(), "attr") + self.assertEquals(descr.counter, 4) + + import gc + class EvilGetattribute(object): + # This used to segfault + def __getattr__(self, name): + raise AttributeError(name) + def __getattribute__(self, name): + del EvilGetattribute.__getattr__ + for i in range(5): + gc.collect() + raise AttributeError(name) + + self.assertRaises(AttributeError, getattr, EvilGetattribute(), "attr") + class DictProxyTests(unittest.TestCase): def setUp(self): |
