Spoof inspect source handling

I want to manipulate python source code using the inspect module.

Given some source text I can create a module from it

from types import ModuleType
mod = ModuleType('sample','Sample module doc')
exec('i=13\nj=14*i',mod.__dict__)
mod.__file__ = '<something>'

however inspect cannot give information about the source because ‘<something>’ is not a real filesystem thing.

Is there a way to spoof the inspect module source handling so it knows about my generated module? I tried a couple of things eg mod. __file__ = StringIO(…) etc, but did not succeed.

If you look at the implementation of findsource:

You can see that there are specific conditions for allowing fake files of the format <something>, they just need to be added to linecache.cache. I haven’t actually tried this myself and can’t right now, but that should be a working solution.

Thanks for the advice. I had already looked at using linecache, but although ‘<something>’ is a pass through in inspect.findsource it seems to be a nogo in linecache.lazycache so I have to use a more regular name. This seems to work

from types import ModuleType
mod = ModuleType('sample','Sample module doc')
src = 'i=13\nj=14*i'
exec(src,mod.__dict__)
class _502Loader:
	def __init__(self,src):
		self._src = src
	def get_source(self,filename):
		return self._src
mod.__file__ = 'sample-fn'
mod.__loader__ = _502Loader(src)
linecache.lazycache(mod.__file__,mod.__dict__)

print(f'{mod.__name__=} {inspect.getsource(mod)=!r}')
``` and produces

$ python devel/s.py
mod.name=‘sample’ inspect.getsource(mod)=‘i=13\nj=14*i\n’