Like getattr, but with a few extra sanity checks: - If obj is a class, ignore everything except class methods - Check if obj is a proxy that claims to have all attributes - Catch attribute access failing with any exception - Check that the attribute is a callable object Returns
(obj: object, name: str)
| 54 | |
| 55 | |
| 56 | def get_real_method(obj: object, name: str) -> Callable[..., Any] | None: |
| 57 | """Like getattr, but with a few extra sanity checks: |
| 58 | |
| 59 | - If obj is a class, ignore everything except class methods |
| 60 | - Check if obj is a proxy that claims to have all attributes |
| 61 | - Catch attribute access failing with any exception |
| 62 | - Check that the attribute is a callable object |
| 63 | |
| 64 | Returns the method or None. |
| 65 | """ |
| 66 | try: |
| 67 | canary = getattr(obj, "_ipython_canary_method_should_not_exist_", None) |
| 68 | except Exception: |
| 69 | return None |
| 70 | |
| 71 | if canary is not None: |
| 72 | # It claimed to have an attribute it should never have |
| 73 | return None |
| 74 | |
| 75 | try: |
| 76 | m = getattr(obj, name, None) |
| 77 | except Exception: |
| 78 | return None |
| 79 | |
| 80 | if inspect.isclass(obj) and not isinstance(m, types.MethodType): |
| 81 | return None |
| 82 | |
| 83 | if callable(m): |
| 84 | return m |
| 85 | |
| 86 | return None |