Skip to content
4 changes: 3 additions & 1 deletion Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,9 @@ def getfile(object):
if ismodule(object):
if getattr(object, '__file__', None):
return object.__file__
raise TypeError('{!r} is a built-in module'.format(object))
if getattr(object, '__spec__', None) is not None:
raise TypeError(f'{object!r} is a built-in module')
Copy link
Copy Markdown
Contributor

@caje731 caje731 Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the existence of spec does not always guarantee a built-in. The module could also be a pure-Python module loaded from a .py file, or a compiled extension module like .so, .pyd, .dylib, or a namespace package (init) or a built-in, or a frozen module (embedded bytecode in the executable, and so on.

I think it is best to use spec.origin if a spec exists:

            raise TypeError(f'{object!r} is: {object.__spec__.origin}')

In a limited number of cases, origin may be unset/None, but I feel that's better than clubbing everything as a built-in module. WDYT?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better will do it

raise TypeError(f'cannot get source from {object!r}')
if isclass(object):
if hasattr(object, '__module__'):
module = sys.modules.get(object.__module__)
Expand Down
8 changes: 7 additions & 1 deletion Lib/test/test_inspect/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from os.path import normcase
import _pickle
import pickle
import re
import shutil
import stat
import sys
Expand Down Expand Up @@ -858,6 +859,12 @@ def test_getfile_builtin_module(self):
inspect.getfile(sys)
self.assertStartsWith(str(e.exception), '<module')

def test_getfile_custom_module(self):
my_mod = types.ModuleType('my_mod')
msg = re.escape(f'cannot get source from {my_mod!r}')
with self.assertRaisesRegex(TypeError, msg) as e:
inspect.getfile(my_mod)

def test_getfile_builtin_class(self):
with self.assertRaises(TypeError) as e:
inspect.getfile(int)
Expand Down Expand Up @@ -6252,7 +6259,6 @@ def test_pwd_module_has_signatures(self):
self._test_module_has_signatures(pwd)

def test_re_module_has_signatures(self):
import re
methods_no_signature = {'Match': {'group'}}
self._test_module_has_signatures(re,
methods_no_signature=methods_no_signature,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix :func:`inspect.getfile` error message for custom module objects.
Loading