diff --git a/spyder_kernels/utils/tests/test_dochelpers.py b/spyder_kernels/utils/tests/test_dochelpers.py index 220db9e2..0a2ef240 100644 --- a/spyder_kernels/utils/tests/test_dochelpers.py +++ b/spyder_kernels/utils/tests/test_dochelpers.py @@ -18,8 +18,14 @@ import pytest # Local imports -from spyder_kernels.utils.dochelpers import (getargtxt, getdoc, getobj, - isdefined) +from spyder_kernels.utils.dochelpers import ( + getargtxt, + getargspecfromtext, + getdoc, + getobj, + getsignaturefromtext, + isdefined, +) from spyder_kernels.py3compat import PY2 @@ -60,5 +66,83 @@ def test_dochelpers(): assert getobj('4.') == '4' +@pytest.mark.skipif(PY2, reason="Fails in Python 2") +def test_no_signature(): + """ + Test that we can get documentation for objects for which Python can't get a + signature directly because it gives an error. + + This is a regression test for issue spyder-ide/spyder#21148 + """ + import numpy as np + doc = getdoc(np.where) + signature = doc['argspec'] + assert signature and signature != "(...)" and signature.startswith("(") + assert doc['docstring'] + + +@pytest.mark.parametrize( + 'text, name, expected', + [ + ('foo(x, y)', 'foo', '(x, y)'), + ('foo(x, y)', '', '(x, y)'), + ] +) +def test_getsignaturefromtext_py2(text, name, expected): + assert getsignaturefromtext(text, name) == expected + + +@pytest.mark.skipif(PY2, reason="Don't work in Python 2") +@pytest.mark.parametrize( + 'text, name, expected', + [ + # Simple text with and without name + ('foo(x, y)', 'foo', '(x, y)'), + ('foo(x, y)', '', '(x, y)'), + # Single arg + ('foo(x)', '', '(x)'), + ('foo(x = {})', '', '(x = {})'), + # Not a valid identifier + ('1a(x, y)', '', ''), + # Valid identifier + ('a1(x, y=2)', '', '(x, y=2)'), + # Unicode identifier with and without name + ('ΣΔ(x, y)', 'ΣΔ', '(x, y)'), + ('ΣΔ(x, y)', '', '(x, y)'), + # Multiple signatures in a single line + ('ΣΔ(x, y) foo(a, b)', '', '(x, y)'), + ('1a(x, y) foo(a, b)', '', '(a, b)'), + # Multiple signatures in multiple lines + ('foo(a, b = 1)\n\nΣΔ(x, y=2)', '', '(a, b = 1)'), + ('1a(a, b = 1)\n\nΣΔ(x, y=2)', '', '(x, y=2)'), + # Signature after math operations + ('2(3 + 5) 3*(99) ΣΔ(x, y)', '', '(x, y)'), + # No identifier + ('(x, y)', '', ''), + ('foo (a=1, b = 2)', '', ''), + # Empty signature + ('foo()', '', ''), + ('foo()', 'foo', ''), + ] +) +def test_getsignaturefromtext(text, name, expected): + assert getsignaturefromtext(text, name) == expected + + +def test_multisignature(): + """ + Test that we can get at least one signature from an object with multiple + ones declared in its docstring. + """ + def foo(): + """ + foo(x, y) foo(a, b) + foo(c, d) + """ + + signature = getargspecfromtext(foo.__doc__) + assert signature == "(x, y)" + + if __name__ == "__main__": pytest.main()