From d001cd1433512185d45cc32d8e24b3530dbee4d5 2021-12-04 16:44:53 From: Nikita Kniazev Date: 2021-12-04 16:44:53 Subject: [PATCH] Handle OSError from inspect.getsource/getsourcelines (bpo-44648) https://bugs.python.org/issue44648 (Python 3.10+) --- diff --git a/IPython/core/oinspect.py b/IPython/core/oinspect.py index 35a1461..9e52f1e 100644 --- a/IPython/core/oinspect.py +++ b/IPython/core/oinspect.py @@ -184,8 +184,10 @@ def getsource(obj, oname='') -> Union[str,None]: # its class definition instead. try: src = inspect.getsource(obj.__class__) - except TypeError: + except (OSError, TypeError): return None + except OSError: + return None return src @@ -315,8 +317,9 @@ def find_file(obj) -> str: except (OSError, TypeError): # Can happen for builtins pass - except: + except OSError: pass + return cast_unicode(fname) @@ -339,12 +342,14 @@ def find_source_lines(obj): obj = _get_wrapped(obj) try: + lineno = inspect.getsourcelines(obj)[1] + except TypeError: + # For instances, try the class object like getsource() does try: - lineno = inspect.getsourcelines(obj)[1] - except TypeError: - # For instances, try the class object like getsource() does lineno = inspect.getsourcelines(obj.__class__)[1] - except: + except (OSError, TypeError): + return None + except OSError: return None return lineno diff --git a/IPython/core/tests/test_oinspect.py b/IPython/core/tests/test_oinspect.py index 58d07db..94deb35 100644 --- a/IPython/core/tests/test_oinspect.py +++ b/IPython/core/tests/test_oinspect.py @@ -6,8 +6,11 @@ from inspect import signature, Signature, Parameter +import inspect import os +import pytest import re +import sys from .. import oinspect @@ -28,6 +31,10 @@ def setup_module(): inspector = oinspect.Inspector() +class SourceModuleMainTest: + __module__ = "__main__" + + #----------------------------------------------------------------------------- # Local utilities #----------------------------------------------------------------------------- @@ -36,15 +43,28 @@ def setup_module(): # defined, if any code is inserted above, the following line will need to be # updated. Do NOT insert any whitespace between the next line and the function # definition below. -THIS_LINE_NUMBER = 39 # Put here the actual number of this line +THIS_LINE_NUMBER = 46 # Put here the actual number of this line + + +def test_find_source_lines(): + assert oinspect.find_source_lines(test_find_source_lines) == THIS_LINE_NUMBER + 3 + assert oinspect.find_source_lines(type) is None + assert oinspect.find_source_lines(SourceModuleMainTest) is None + assert oinspect.find_source_lines(SourceModuleMainTest()) is None + -from unittest import TestCase +def test_getsource(): + assert oinspect.getsource(type) is None + assert oinspect.getsource(SourceModuleMainTest) is None + assert oinspect.getsource(SourceModuleMainTest()) is None -class Test(TestCase): - def test_find_source_lines(self): - self.assertEqual(oinspect.find_source_lines(Test.test_find_source_lines), - THIS_LINE_NUMBER+6) +def test_inspect_getfile_raises_exception(): + """Check oinspect.find_file/getsource/find_source_lines expectations""" + with pytest.raises(TypeError): + inspect.getfile(type) + with pytest.raises(OSError if sys.version_info >= (3, 10) else TypeError): + inspect.getfile(SourceModuleMainTest) # A couple of utilities to ensure these tests work the same from a source or a @@ -59,6 +79,9 @@ def match_pyfiles(f1, f2): def test_find_file(): match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__)) + assert oinspect.find_file(type) is None + assert oinspect.find_file(SourceModuleMainTest) is None + assert oinspect.find_file(SourceModuleMainTest()) is None def test_find_file_decorated1():