When the following script is run directly, it operates as anticipated:
import inspect
__module__ = "__main__"
__file__ = "classes.py"
test_str = "test"
class met(type):
def __init__(cls, name, bases, dct):
setattr(cls, "source", inspect.getsource(cls))
#setattr(cls, "source", test_str)
super(met, cls).__init__(name, bases, dct)
class ParentModel(object):
__metaclass__ = met
def __init__(self):
super(object, self).__init__(ParentModel.__class__)
def setsource(self):
self.source = inspect.getsource(self.__class__)
#self.source = test_str
def getsource(self):
return self.source
class ChildB(ParentModel):
name = "childb"
pass
class ChildA(ChildB):
name = "childa"
pass
class ChildC(ChildA):
name = "childc"
pass
The difficulty arises when attempting to run this script through exec or execfile in the python shell or another script. For instance:
>>> execfile("classes.py")
Runs without issue, however:
>>> ns = {}
>>> execfile("classes.py", ns)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "classes.py", line 13, in <module>
class ParentModel(object):
File "classes.py", line 9, in __init__
setattr(cls, "source", inspect.getsource(cls))
File "D:\Python27\lib\inspect.py", line 701, in getsource
lines, lnum = getsourcelines(object)
File "D:\Python27\lib\inspect.py", line 690, in getsourcelines
lines, lnum = findsource(object)
File "D:\Python27\lib\inspect.py", line 526, in findsource
file = getfile(object)
File "D:\Python27\lib\inspect.py", line 408, in getfile
raise TypeError('{!r} is a built-in class'.format(object))
TypeError: <module '__builtin__' (built-in)> is a built-in class
This results in an error, which is confusing given dictionaries are accepted for the global namespace argument of execfile. But:
>>> execfile("classes.py", globals())
Again, runs without issue, though:
>>> ns = dict(globals())
>>> execfile("classes.py", ns)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "classes.py", line 13, in <module>
class ParentModel(object):
File "classes.py", line 9, in __init__
setattr(cls, "source", inspect.getsource(cls))
File "D:\Python27\lib\inspect.py", line 701, in getsource
lines, lnum = getsourcelines(object)
File "D:\Python27\lib\inspect.py", line 690, in getsourcelines
lines, lnum = findsource(object)
File "D:\Python27\lib\inspect.py", line 526, in findsource
file = getfile(object)
File "D:\Python27\lib\inspect.py", line 408, in getfile
raise TypeError('{!r} is a built-in class'.format(object))
TypeError: <module '__builtin__' (built-in)> is a built-in class
From the traceback, its related to inspect, however it should error on execfile("classes.py") or execfile("classes.py", globals()) as well.
So, in terms of this error, how is dict(globals()) != globals() and why does this cause this error ?
EDIT: Reader should refer to both Martijn Pieters and Lennart Regebro answers for a complete picture.