mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #7632 from eric-wieser/better-inspect-failure
Do not crash if `is_builtin_class_method` is passed a non-type
This commit is contained in:
commit
e49fc778e4
@ -389,12 +389,23 @@ def is_builtin_class_method(obj: Any, attr_name: str) -> bool:
|
||||
Why this function needed? CPython implements int.__init__ by Descriptor
|
||||
but PyPy implements it by pure Python code.
|
||||
"""
|
||||
classes = [c for c in inspect.getmro(obj) if attr_name in c.__dict__]
|
||||
cls = classes[0] if classes else object
|
||||
|
||||
if not hasattr(builtins, safe_getattr(cls, '__name__', '')):
|
||||
try:
|
||||
mro = inspect.getmro(obj)
|
||||
except AttributeError:
|
||||
# no __mro__, assume the object has no methods as we know them
|
||||
return False
|
||||
return getattr(builtins, safe_getattr(cls, '__name__', '')) is cls
|
||||
|
||||
try:
|
||||
cls = next(c for c in mro if attr_name in safe_getattr(c, '__dict__', {}))
|
||||
except StopIteration:
|
||||
return False
|
||||
|
||||
try:
|
||||
name = safe_getattr(cls, '__name__')
|
||||
except AttributeError:
|
||||
return False
|
||||
|
||||
return getattr(builtins, name, None) is cls
|
||||
|
||||
|
||||
def signature(subject: Callable, bound_method: bool = False) -> inspect.Signature:
|
||||
|
@ -18,7 +18,7 @@ from inspect import Parameter
|
||||
import pytest
|
||||
|
||||
from sphinx.util import inspect
|
||||
from sphinx.util.inspect import stringify_signature
|
||||
from sphinx.util.inspect import stringify_signature, is_builtin_class_method
|
||||
|
||||
|
||||
def test_signature():
|
||||
@ -579,3 +579,21 @@ def test_getdoc_inherited_decorated_method():
|
||||
|
||||
assert inspect.getdoc(Bar.meth, getattr, False, Bar, "meth") is None
|
||||
assert inspect.getdoc(Bar.meth, getattr, True, Bar, "meth") == "docstring."
|
||||
|
||||
|
||||
def test_is_builtin_class_method():
|
||||
class MyInt(int):
|
||||
def my_method(self):
|
||||
pass
|
||||
|
||||
assert inspect.is_builtin_class_method(MyInt, 'to_bytes')
|
||||
assert inspect.is_builtin_class_method(MyInt, '__init__')
|
||||
assert not inspect.is_builtin_class_method(MyInt, 'my_method')
|
||||
assert not inspect.is_builtin_class_method(MyInt, 'does_not_exist')
|
||||
assert not inspect.is_builtin_class_method(4, 'still does not crash')
|
||||
|
||||
class ObjectWithMroAttr:
|
||||
def __init__(self, mro_attr):
|
||||
self.__mro__ = mro_attr
|
||||
|
||||
assert not inspect.is_builtin_class_method(ObjectWithMroAttr([1, 2, 3]), 'still does not crash')
|
||||
|
Loading…
Reference in New Issue
Block a user