mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
inspect: return defargs[0] if obj.__dict__ raises exception
The fallback implemented in #2731 cannot return `obj.__dict__[name]` if the `__dict__` method has been redefined in such a way that it raises an exception when trying to access it. This commit adds a try-except block to work around this.
This commit is contained in:
parent
1dfa1a8d1e
commit
670049c262
@ -110,12 +110,23 @@ def safe_getattr(obj, name, *defargs):
|
|||||||
except Exception:
|
except Exception:
|
||||||
# sometimes accessing a property raises an exception (e.g.
|
# sometimes accessing a property raises an exception (e.g.
|
||||||
# NotImplementedError), so let's try to read the attribute directly
|
# NotImplementedError), so let's try to read the attribute directly
|
||||||
if name in obj.__dict__:
|
|
||||||
|
# We should also be aware that if `__dict__` has been overridden,
|
||||||
|
# this may also raise an exception.
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj_dict = obj.__dict__
|
||||||
|
except Exception as exc:
|
||||||
|
obj_dict = {}
|
||||||
|
|
||||||
|
if name in obj_dict:
|
||||||
return obj.__dict__[name]
|
return obj.__dict__[name]
|
||||||
|
|
||||||
# this is a catch-all for all the weird things that some modules do
|
# this is a catch-all for all the weird things that some modules do
|
||||||
# with attribute access
|
# with attribute access
|
||||||
if defargs:
|
if defargs:
|
||||||
return defargs[0]
|
return defargs[0]
|
||||||
|
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
|
|
||||||
|
|
||||||
|
58
tests/test_util_inspect.py
Normal file
58
tests/test_util_inspect.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
test_util_inspect
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Tests util.inspect functions.
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from sphinx.util import inspect
|
||||||
|
|
||||||
|
|
||||||
|
class TestSafeGetAttr(TestCase):
|
||||||
|
def test_safe_getattr_with_default(self):
|
||||||
|
class Foo(object):
|
||||||
|
def __getattr__(self, item):
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
obj = Foo()
|
||||||
|
|
||||||
|
result = inspect.safe_getattr(obj, 'bar', 'baz')
|
||||||
|
|
||||||
|
assert result == 'baz'
|
||||||
|
|
||||||
|
def test_safe_getattr_with_exception(self):
|
||||||
|
class Foo(object):
|
||||||
|
def __getattr__(self, item):
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
obj = Foo()
|
||||||
|
|
||||||
|
with self.assertRaisesRegexp(AttributeError, 'bar'):
|
||||||
|
inspect.safe_getattr(obj, 'bar')
|
||||||
|
|
||||||
|
def test_safe_getattr_with_property_exception(self):
|
||||||
|
class Foo(object):
|
||||||
|
@property
|
||||||
|
def bar(self):
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
obj = Foo()
|
||||||
|
|
||||||
|
with self.assertRaisesRegexp(AttributeError, 'bar'):
|
||||||
|
inspect.safe_getattr(obj, 'bar')
|
||||||
|
|
||||||
|
def test_safe_getattr_with___dict___override(self):
|
||||||
|
class Foo(object):
|
||||||
|
@property
|
||||||
|
def __dict__(self):
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
obj = Foo()
|
||||||
|
|
||||||
|
with self.assertRaisesRegexp(AttributeError, 'bar'):
|
||||||
|
inspect.safe_getattr(obj, 'bar')
|
Loading…
Reference in New Issue
Block a user