Tim
Tim

Reputation: 99408

How can I get the definition of a class in a module?

Why can't I get the definition of Callable from module collections in the following code?

How can I get the definition of a class in a module? Thanks.

>>> from collections import Callable
>>> inspect.getsource(Callable)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/inspect.py", line 944, in getsource
    lines, lnum = getsourcelines(object)
  File "/usr/lib/python3.5/inspect.py", line 931, in getsourcelines
    lines, lnum = findsource(object)
  File "/usr/lib/python3.5/inspect.py", line 788, in findsource
    raise OSError('could not find class definition')
OSError: could not find class definition
>>> inspect.getsourcelines(Callable)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/inspect.py", line 931, in getsourcelines
    lines, lnum = findsource(object)
  File "/usr/lib/python3.5/inspect.py", line 788, in findsource
    raise OSError('could not find class definition')
OSError: could not find class definition
>>> inspect.getmodule(Callable)
<module 'collections.abc' from '/usr/lib/python3.5/collections/abc.py'>
>>> inspect.getfile(Callable)
'/usr/lib/python3.5/collections/abc.py'
>>> inspect.getsourcefile(Callable)
'/usr/lib/python3.5/collections/abc.py'

Upvotes: 4

Views: 1329

Answers (2)

Menglong Li
Menglong Li

Reputation: 2255

get_source(fullname) Return the source code for the specified module.

So you should return the whole module, as Callable is defined in the module of _collections_abc, so your code should be this:

import _collections_abc

import inspect

print(inspect.getsource(_collections_abc))

and you can see the definition of Callable in the print result.

Upvotes: 2

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160377

In general, this is easily done with inspect.getsource which accepts a module, a class, a method, a function, a traceback, a frame, or a code object. The source they represent should of course be written in Python else an error is raised.

In this specific case, you just happen to be unlucky because while Callable is defined in _collections_abc the Callable.__module__ name is callections.abc:

>>> Callable.__module__
'collections.abc'

This throws getsource off because it won't look in _collections_abc that contains Callables definition but, instead, in collections.abc which merely imports all definitions from _collections_abc:

>>> print(getsource(collections.abc))
from _collections_abc import *
from _collections_abc import __all__

Normally, getsource doesn't have an issue finding the source, for example, on itself:

>>> print(getsource(getsource))
def getsource(object):
    """Return the text of the source code for an object.

    The argument may be a module, class, method, function, traceback, frame,
    or code object.  The source code is returned as a single string.  An
    OSError is raised if the source code cannot be retrieved."""
    lines, lnum = getsourcelines(object)
    return ''.join(lines)

In this specific case, though, it does (due to Callable.__module__ returning collections.abc.) You could replace __module__ with '_collections_abc' for a tricky way to see the source:

>>> Callable.__module__ = '_collections_abc'
>>> src = getsource(Callable)  
>>> print(src)
class Callable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __call__(self, *args, **kwds):
        return False

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Callable:
            return _check_methods(C, "__call__")
        return NotImplemented

but this doesn't make me feel very comfortable.

Upvotes: 3

Related Questions