Skip to content

Commit

Permalink
Merge pull request #13412 from bnavigator/backport-inspect
Browse files Browse the repository at this point in the history
Backport Python 3.10 fixes
  • Loading branch information
Carreau committed Dec 21, 2021
2 parents 2f5df18 + 4f26796 commit 7f253dc
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 103 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
python-version: ["3.7", "3.8", "3.9"]
python-version: ["3.7", "3.8", "3.9", "3.10"]
# Test all on ubuntu, test ends on macos
include:
- os: macos-latest
Expand All @@ -39,6 +39,7 @@ jobs:
- name: Check manifest
run: check-manifest
- name: iptest
if: matrix.python-version != '3.10'
run: |
cd /tmp && iptest --coverage xml && cd -
cp /tmp/ipy_coverage.xml ./
Expand Down
40 changes: 20 additions & 20 deletions IPython/core/oinspect.py
Expand Up @@ -182,11 +182,12 @@ def getsource(obj, oname='') -> Union[str,None]:
except TypeError:
# The object itself provided no meaningful source, try looking for
# its class definition instead.
if hasattr(obj, '__class__'):
try:
src = inspect.getsource(obj.__class__)
except TypeError:
return None
try:
src = inspect.getsource(obj.__class__)
except (OSError, TypeError):
return None
except OSError:
return None

return src

Expand Down Expand Up @@ -308,14 +309,14 @@ def find_file(obj) -> str:
except TypeError:
# For an instance, the file that matters is where its class was
# declared.
if hasattr(obj, '__class__'):
try:
fname = inspect.getabsfile(obj.__class__)
except TypeError:
# Can happen for builtins
pass
except:
try:
fname = inspect.getabsfile(obj.__class__)
except (OSError, TypeError):
# Can happen for builtins
pass
except OSError:
pass

return cast_unicode(fname)


Expand All @@ -338,15 +339,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
if hasattr(obj, '__class__'):
lineno = inspect.getsourcelines(obj.__class__)[1]
else:
lineno = None
except:
lineno = inspect.getsourcelines(obj.__class__)[1]
except (OSError, TypeError):
return None
except OSError:
return None

return lineno
Expand Down
13 changes: 13 additions & 0 deletions IPython/core/tests/test_completer.py
Expand Up @@ -12,6 +12,7 @@
from contextlib import contextmanager

import nose.tools as nt
import pytest

from traitlets.config.loader import Config
from IPython import get_ipython
Expand All @@ -29,6 +30,15 @@
)
from nose.tools import assert_in, assert_not_in

if sys.version_info >= (3, 10):
import jedi
from pkg_resources import parse_version

# Requires https://github.com/davidhalter/jedi/pull/1795
jedi_issue = parse_version(jedi.__version__) <= parse_version("0.18.0")
else:
jedi_issue = False

# -----------------------------------------------------------------------------
# Test functions
# -----------------------------------------------------------------------------
Expand Down Expand Up @@ -381,6 +391,8 @@ def test_all_completions_dups(self):
matches = c.all_completions("TestCl")
assert matches == ['TestClass'], jedi_status
matches = c.all_completions("TestClass.")
if jedi_status and jedi_issue:
continue
assert len(matches) > 2, jedi_status
matches = c.all_completions("TestClass.a")
assert matches == ['TestClass.a', 'TestClass.a1'], jedi_status
Expand Down Expand Up @@ -435,6 +447,7 @@ def test_completion_have_signature(self):
"encoding" in c.signature
), "Signature of function was not found by completer"

@pytest.mark.xfail(jedi_issue, reason="Known failure on jedi<=0.18.0")
def test_deduplicate_completions(self):
"""
Test that completions are correctly deduplicated (even if ranges are not the same)
Expand Down
18 changes: 12 additions & 6 deletions IPython/core/tests/test_magic_arguments.py
Expand Up @@ -7,6 +7,7 @@
#-----------------------------------------------------------------------------

import argparse
import sys
from nose.tools import assert_equal

from IPython.core.magic_arguments import (argument, argument_group, kwds,
Expand Down Expand Up @@ -74,7 +75,12 @@ def foo(self, args):


def test_magic_arguments():
assert_equal(magic_foo1.__doc__, '::\n\n %foo1 [-f FOO]\n\n A docstring.\n\noptional arguments:\n -f FOO, --foo FOO an argument\n')
# “optional arguments” was replaced with “options” in argparse help
# https://docs.python.org/3/whatsnew/3.10.html#argparse
# https://bugs.python.org/issue9694
options = "optional arguments" if sys.version_info < (3, 10) else "options"

assert_equal(magic_foo1.__doc__, f"::\n\n %foo1 [-f FOO]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n")
assert_equal(getattr(magic_foo1, 'argcmd_name', None), None)
assert_equal(real_name(magic_foo1), 'foo1')
assert_equal(magic_foo1(None, ''), argparse.Namespace(foo=None))
Expand All @@ -86,32 +92,32 @@ def test_magic_arguments():
assert_equal(magic_foo2(None, ''), argparse.Namespace())
assert hasattr(magic_foo2, 'has_arguments')

assert_equal(magic_foo3.__doc__, '::\n\n %foo3 [-f FOO] [-b BAR] [-z BAZ]\n\n A docstring.\n\noptional arguments:\n -f FOO, --foo FOO an argument\n\nGroup:\n -b BAR, --bar BAR a grouped argument\n\nSecond Group:\n -z BAZ, --baz BAZ another grouped argument\n')
assert_equal(magic_foo3.__doc__, f"::\n\n %foo3 [-f FOO] [-b BAR] [-z BAZ]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n\nGroup:\n -b BAR, --bar BAR a grouped argument\n\nSecond Group:\n -z BAZ, --baz BAZ another grouped argument\n")
assert_equal(getattr(magic_foo3, 'argcmd_name', None), None)
assert_equal(real_name(magic_foo3), 'foo3')
assert_equal(magic_foo3(None, ''),
argparse.Namespace(bar=None, baz=None, foo=None))
assert hasattr(magic_foo3, 'has_arguments')

assert_equal(magic_foo4.__doc__, '::\n\n %foo4 [-f FOO]\n\n A docstring.\n\noptional arguments:\n -f FOO, --foo FOO an argument\n')
assert_equal(magic_foo4.__doc__, f"::\n\n %foo4 [-f FOO]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n")
assert_equal(getattr(magic_foo4, 'argcmd_name', None), None)
assert_equal(real_name(magic_foo4), 'foo4')
assert_equal(magic_foo4(None, ''), argparse.Namespace())
assert hasattr(magic_foo4, 'has_arguments')

assert_equal(magic_foo5.__doc__, '::\n\n %frobnicate [-f FOO]\n\n A docstring.\n\noptional arguments:\n -f FOO, --foo FOO an argument\n')
assert_equal(magic_foo5.__doc__, f"::\n\n %frobnicate [-f FOO]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n")
assert_equal(getattr(magic_foo5, 'argcmd_name', None), 'frobnicate')
assert_equal(real_name(magic_foo5), 'frobnicate')
assert_equal(magic_foo5(None, ''), argparse.Namespace(foo=None))
assert hasattr(magic_foo5, 'has_arguments')

assert_equal(magic_magic_foo.__doc__, '::\n\n %magic_foo [-f FOO]\n\n A docstring.\n\noptional arguments:\n -f FOO, --foo FOO an argument\n')
assert_equal(magic_magic_foo.__doc__, f"::\n\n %magic_foo [-f FOO]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n")
assert_equal(getattr(magic_magic_foo, 'argcmd_name', None), None)
assert_equal(real_name(magic_magic_foo), 'magic_foo')
assert_equal(magic_magic_foo(None, ''), argparse.Namespace(foo=None))
assert hasattr(magic_magic_foo, 'has_arguments')

assert_equal(foo.__doc__, '::\n\n %foo [-f FOO]\n\n A docstring.\n\noptional arguments:\n -f FOO, --foo FOO an argument\n')
assert_equal(foo.__doc__, f"::\n\n %foo [-f FOO]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n")
assert_equal(getattr(foo, 'argcmd_name', None), None)
assert_equal(real_name(foo), 'foo')
assert_equal(foo(None, ''), argparse.Namespace(foo=None))
Expand Down

0 comments on commit 7f253dc

Please sign in to comment.