-
-
Notifications
You must be signed in to change notification settings - Fork 30.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
inspect.getsource() on sourceless dataclass raises undocumented exception #98239
Comments
Note that |
Note there's a slightly different error with namedtuples. Note this is with 3.12.0a0: >>> from collections import namedtuple
>>> from inspect import getsource
>>>
>>> defs = {}
>>> exec("""
... T = namedtuple("T", [])
... """,
... {'namedtuple': namedtuple},
... defs,
... )
>>> getsource(defs["T"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "...\cpython\Lib\inspect.py", line 1255, in getsource
lines, lnum = getsourcelines(object)
^^^^^^^^^^^^^^^^^^^^^^
File "...\cpython\Lib\inspect.py", line 1237, in getsourcelines
lines, lnum = findsource(object)
^^^^^^^^^^^^^^^^^^
File "...\cpython\Lib\inspect.py", line 1048, in findsource
file = getsourcefile(object)
^^^^^^^^^^^^^^^^^^^^^
File "...\cpython\Lib\inspect.py", line 925, in getsourcefile
filename = getfile(object)
^^^^^^^^^^^^^^^
File "...\cpython\Lib\inspect.py", line 893, in getfile
raise OSError('source code not available')
OSError: source code not available
>>> from inspect import getmodule
>>> getmodule(defs["T"])
<module '__main__' (<class '_frozen_importlib.BuiltinImporter'>)>
>>> Maybe that will help point someone in the right direction. |
|
I doubt that these two cases are the same:
Classes are created according to the regular Python rules. When you This happens without from inspect import getsource
defs = {}
exec(
"""
class C:
"The source for this class cannot be located."
""",
defs,
)
print(defs["C"].__module__) # 'builtins'
try:
getsource(defs["C"])
except OSError:
print("Got the documented exception.")
# TypeError: <class 'C'> is a built-in class This is why you get an exception. Fix: exec(
"""
@dataclass
class C:
"The source for this class cannot be located."
""",
{"dataclass": dataclass, "__name__": "__main__"}, # pass `__name__`!
defs,
) So:
I will send a PR for this. |
It appears to me that this is a kind of introspection limitation for sourceless dataclasses. There are other ways to generate a sourceless dataclass, such as the >>> from dataclasses import *
>>> C = make_dataclass('C',
... [('x', int),
... 'y',
... ('z', int, field(default=5))],
... namespace={'add_one': lambda self: self.x + 1})
>>>
>>> C
<class 'types.C'>
>>> C.__module__
'types' Then in this case >>> inspect.getsource(C)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/leof/miniforge3/envs/opt_einsum_dev/lib/python3.8/inspect.py", line 997, in getsource
lines, lnum = getsourcelines(object)
File "/home/leof/miniforge3/envs/opt_einsum_dev/lib/python3.8/inspect.py", line 979, in getsourcelines
lines, lnum = findsource(object)
File "/home/leof/miniforge3/envs/opt_einsum_dev/lib/python3.8/inspect.py", line 824, in findsource
raise OSError('could not find class definition')
OSError: could not find class definition and this time the error makes better sense, because the actually codegen is buried somewhere else, and it's not possible (to my knowledge, at least) to infer the lines & line number. Ideally, in the case of sourceless dataclasses, one would likely want to overwrite |
|
Thank you, @sobolevn, it's nice to see this new But as I said above, even after C = make_dataclass(...) but I don't have good suggestion for how to make it 100% robust. |
…ror` (pythonGH-101689) (cherry picked from commit b613208) Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
…ror` (pythonGH-101689) (cherry picked from commit b613208) Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
I see we made the documentation change and sobolevn's #102104 helps here too. I'm not seeing a concrete additional suggestion (and maybe any such suggestion should be its own issue), so closing. Thanks all! :-) |
Bug report
If I run the following program in Python 3.10:
The output is:
The documentation states that
OSError
can be raised but does not mentionTypeError
.The implementation of
inspect.getsource()
assumes that if a class has no__module__
attribute, it must be a built-in class, but a sourceless dataclass doesn't have a__module__
attribute either. I don't know whether this is a bug ingetsource()
or whether the generation of the dataclass should set__module__
to'__main__'
, but in any case the behavior is not as documented.Your environment
Linked PRs
inspect.getsource()
can raiseTypeError
#101689inspect.getsource()
can raiseTypeError
(GH-101689) #102969inspect.getsource()
can raiseTypeError
(GH-101689) #102970The text was updated successfully, but these errors were encountered: