@@ -95,6 +95,41 @@ class Callee:
9595
9696
9797BUILTIN_FUNCTION_OR_METHOD = type (print )
98+ METHOD_DESCRIPTOR_TYPE = type (dict .get )
99+
100+
101+ _unknown_module_fixup_cache = dict ()
102+
103+
104+ def _unkown_module_fixup (func ):
105+ # TODO: Doesn't work for everything (for example: `OrderedDict.fromkeys`, `object.__new__`)
106+
107+ module = func .__module__
108+ qualname = func .__qualname__
109+ cls_name , method_name = qualname .split ("." )
110+
111+ key = (module , qualname )
112+ if key in _unknown_module_fixup_cache :
113+ return _unknown_module_fixup_cache [key ]
114+
115+ matching_classes = list ()
116+ for klass in object .__subclasses__ ():
117+ # type(dict.get) == METHOD_DESCRIPTOR_TYPE
118+ # type(dict.__new__) == BUILTIN_FUNCTION_OR_METHOD
119+ if klass .__qualname__ == cls_name and type (
120+ getattr (klass , method_name , None )
121+ ) in [BUILTIN_FUNCTION_OR_METHOD , METHOD_DESCRIPTOR_TYPE ]:
122+ matching_classes .append (klass )
123+
124+ if len (matching_classes ) == 1 :
125+ klass = matching_classes [0 ]
126+ ret = klass .__module__
127+ else :
128+ if DEBUG :
129+ LOGGER .debug (f"Found more than one matching class for { module } { qualname } " )
130+ ret = None
131+ _unknown_module_fixup_cache [key ] = ret
132+ return ret
98133
99134
100135@better_compare_for_dataclass
@@ -109,9 +144,19 @@ class ExternalCallee(Callee):
109144
110145 @classmethod
111146 def from_arg (cls , func ):
147+ # builtin bound methods seems to always return `None` for __module__, but we
148+ # might be able to recover the lost information by looking through all classes.
149+ # For example, `dict().get.__module__ is None` and `dict().get.__qualname__ ==
150+ # "dict.get"`
151+
152+ module = func .__module__
153+ qualname = func .__qualname__
154+ if module is None and qualname .count ("." ) == 1 :
155+ module = _unkown_module_fixup (func )
156+
112157 return cls (
113- module = func . __module__ ,
114- qualname = func . __qualname__ ,
158+ module = module ,
159+ qualname = qualname ,
115160 is_builtin = type (func ) == BUILTIN_FUNCTION_OR_METHOD ,
116161 )
117162
0 commit comments