0
  • When I load the source code of a class from a module directly, it's fine:

    import arg_master

    inspect.getsource(func)

  • When I load a module with spec_from_file_location and go for a function it's fine.

  • When I load a module with spec_from_file_location and go for a class, it fails with:

    TypeError: <class 'mymod.ArgMaster'> is a built-in class
    

    (it's not. I wrote it.)

Here is my full source:

import os, inspect, importlib

filename = 'arg_master.py'
spec = importlib.util.spec_from_file_location("mymod", filename)
mymod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mymod)
func = vars(mymod)['ArgMaster']
inspect.getsource(func)            #<<< Fails

Load method number 2 also fails:

import importlib, types

filename = 'arg_master.py'
loader = importlib.machinery.SourceFileLoader('mod', filename)
mod = types.ModuleType(loader.name)
loader.exec_module(mod)
func = vars(mod)['ArgMaster']
inspect.getsource(func)

Edit: I found a hackish solution:

import inspect

filename = 'arg_master.py'
name = os.path.basename(filename)
name = os.path.splitext(name)[0]
importlib.import_module(name)
func = vars(mod)['ArgMaster']
inspect.getsource(func)
SurpriseDog
  • 259
  • 3
  • 14
  • Debugging time. Trace the internals of `inspect` -- why it thinks it's a built-in class. My guess is a module object produced in this way is somehow not considered a source-based module. – ivan_pozdeev May 23 '21 at 19:55
  • 1
    Trouble seems to start here: https://github.com/python/cpython/blob/099e6a4096382697dda55d58d3a96f68375ea546/Lib/inspect.py#L662 – SurpriseDog May 23 '21 at 20:29

1 Answers1

0

I get the same error with your code, which oddly enough works for functions, but not classes. This below is essentially the same as your solution, just slightly less "hacky" as you don't have to mess with file paths:

import inspect, importlib
cls = getattr(importlib.import_module('arg_master'), 'ArgMaster')
print(inspect.getsource(cls))

This will work if the two modules in the same dir. If you need to do relative imports, might have to mess around with package=__pckage__ or similar

Dmytro Bugayev
  • 356
  • 4
  • 7