(
value,
module_name: str,
access_path: Sequence[str],
method_name: str,
)
| 148 | |
| 149 | |
| 150 | def _has_original_dunder_external( |
| 151 | value, |
| 152 | module_name: str, |
| 153 | access_path: Sequence[str], |
| 154 | method_name: str, |
| 155 | ): |
| 156 | if module_name not in sys.modules: |
| 157 | full_module_path = ".".join([module_name, *access_path]) |
| 158 | if full_module_path not in sys.modules: |
| 159 | # LBYLB as it is faster |
| 160 | return False |
| 161 | try: |
| 162 | member_type = _get_external(module_name, access_path) |
| 163 | value_type = type(value) |
| 164 | if type(value) == member_type: |
| 165 | return True |
| 166 | if isinstance(member_type, ModuleType): |
| 167 | value_module = getmodule(value_type) |
| 168 | if not value_module or not value_module.__name__: |
| 169 | return False |
| 170 | if ( |
| 171 | value_module.__name__ == member_type.__name__ |
| 172 | or value_module.__name__.startswith(member_type.__name__ + ".") |
| 173 | ): |
| 174 | return True |
| 175 | if method_name == "__getattribute__": |
| 176 | # we have to short-circuit here due to an unresolved issue in |
| 177 | # `isinstance` implementation: https://bugs.python.org/issue32683 |
| 178 | return False |
| 179 | if not isinstance(member_type, ModuleType) and isinstance(value, member_type): |
| 180 | method = getattr(value_type, method_name, None) |
| 181 | member_method = getattr(member_type, method_name, None) |
| 182 | if member_method == method: |
| 183 | return True |
| 184 | if isinstance(member_type, ModuleType): |
| 185 | method = getattr(value_type, method_name, None) |
| 186 | for base_class in value_type.__mro__[1:]: |
| 187 | base_module = getmodule(base_class) |
| 188 | if base_module and ( |
| 189 | base_module.__name__ == member_type.__name__ |
| 190 | or base_module.__name__.startswith(member_type.__name__ + ".") |
| 191 | ): |
| 192 | # Check if the method comes from this trusted base class |
| 193 | base_method = getattr(base_class, method_name, None) |
| 194 | if base_method is not None and base_method == method: |
| 195 | return True |
| 196 | except (AttributeError, KeyError): |
| 197 | return False |
| 198 | |
| 199 | |
| 200 | def _has_original_dunder( |
no test coverage detected
searching dependent graphs…