summaryrefslogtreecommitdiffstats
path: root/Lib/idlelib/idle_test/test_calltips.py
blob: eca24ec129396d5403993091fc61d5f80f32a251 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import unittest
import idlelib.CallTips as ct
import types

default_tip = ct._default_callable_argspec

# Test Class TC is used in multiple get_argspec test methods
class TC():
    'doc'
    tip = "(ai=None, *b)"
    def __init__(self, ai=None, *b): 'doc'
    __init__.tip = "(self, ai=None, *b)"
    def t1(self): 'doc'
    t1.tip = "(self)"
    def t2(self, ai, b=None): 'doc'
    t2.tip = "(self, ai, b=None)"
    def t3(self, ai, *args): 'doc'
    t3.tip = "(self, ai, *args)"
    def t4(self, *args): 'doc'
    t4.tip = "(self, *args)"
    def t5(self, ai, b=None, *args, **kw): 'doc'
    t5.tip = "(self, ai, b=None, *args, **kw)"
    def t6(no, self): 'doc'
    t6.tip = "(no, self)"
    def __call__(self, ci): 'doc'
    __call__.tip = "(self, ci)"
    # attaching .tip to wrapped methods does not work
    @classmethod
    def cm(cls, a): 'doc'
    @staticmethod
    def sm(b): 'doc'

tc = TC()

signature = ct.get_argspec  # 2.7 and 3.x use different functions
class Get_signatureTest(unittest.TestCase):
    # The signature function must return a string, even if blank.
    # Test a variety of objects to be sure that none cause it to raise
    # (quite aside from getting as correct an answer as possible).
    # The tests of builtins may break if inspect or the docstrings change,
    # but a red buildbot is better than a user crash (as has happened).
    # For a simple mismatch, change the expected output to the actual.

    def test_builtins(self):

        # Python class that inherits builtin methods
        class List(list): "List() doc"
        # Simulate builtin with no docstring for default tip test
        class SB:  __call__ = None

        def gtest(obj, out):
            self.assertEqual(signature(obj), out)

        gtest(List, List.__doc__)
        gtest(list.__new__,
               'T.__new__(S, ...) -> a new object with type S, a subtype of T')
        gtest(list.__init__,
               'x.__init__(...) initializes x; see help(type(x)) for signature')
        append_doc =  "L.append(object) -> None -- append object to end"
        gtest(list.append, append_doc)
        gtest([].append, append_doc)
        gtest(List.append, append_doc)

        gtest(types.MethodType, "method(function, instance)")
        gtest(SB(), default_tip)

    def test_multiline_docstring(self):
        # Test fewer lines than max.
        self.assertEqual(signature(list),
                "list() -> new empty list\n"
                "list(iterable) -> new list initialized from iterable's items")

        # Test max lines and line (currently) too long.
        self.assertEqual(signature(bytes),
"bytes(iterable_of_ints) -> bytes\n"
"bytes(string, encoding[, errors]) -> bytes\n"
"bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer\n"
#bytes(int) -> bytes object of size given by the parameter initialized with null bytes
"bytes(int) -> bytes object of size given by the parameter initialized with n...\n"
"bytes() -> empty bytes object")

    def test_functions(self):
        def t1(): 'doc'
        t1.tip = "()"
        def t2(a, b=None): 'doc'
        t2.tip = "(a, b=None)"
        def t3(a, *args): 'doc'
        t3.tip = "(a, *args)"
        def t4(*args): 'doc'
        t4.tip = "(*args)"
        def t5(a, b=None, *args, **kw): 'doc'
        t5.tip = "(a, b=None, *args, **kw)"

        for func in (t1, t2, t3, t4, t5, TC):
            self.assertEqual(signature(func), func.tip + '\ndoc')

    def test_methods(self):
        for meth in (TC.t1, TC.t2, TC.t3, TC.t4, TC.t5, TC.t6, TC.__call__):
            self.assertEqual(signature(meth), meth.tip + "\ndoc")
        self.assertEqual(signature(TC.cm), "(a)\ndoc")
        self.assertEqual(signature(TC.sm), "(b)\ndoc")

    def test_bound_methods(self):
        # test that first parameter is correctly removed from argspec
        for meth, mtip  in ((tc.t1, "()"), (tc.t4, "(*args)"), (tc.t6, "(self)"),
                            (tc.__call__, '(ci)'), (tc, '(ci)'), (TC.cm, "(a)"),):
            self.assertEqual(signature(meth), mtip + "\ndoc")

    def test_non_ascii_name(self):
        # test that re works to delete a first parameter name that
        # includes non-ascii chars, such as various forms of A.
        uni = "(A\u0391\u0410\u05d0\u0627\u0905\u1e00\u3042, a)"
        assert ct._first_param.sub('', uni) == '(a)'

    def test_no_docstring(self):
        def nd(s):
            pass
        TC.nd = nd
        self.assertEqual(signature(nd), "(s)")
        self.assertEqual(signature(TC.nd), "(s)")
        self.assertEqual(signature(tc.nd), "()")

    def test_attribute_exception(self):
        class NoCall:
            def __getattr__(self, name):
                raise BaseException
        class Call(NoCall):
            def __call__(self, ci):
                pass
        for meth, mtip  in ((NoCall, default_tip), (Call, default_tip),
                            (NoCall(), ''), (Call(), '(ci)')):
            self.assertEqual(signature(meth), mtip)

    def test_non_callables(self):
        for obj in (0, 0.0, '0', b'0', [], {}):
            self.assertEqual(signature(obj), '')

class Get_entityTest(unittest.TestCase):
    def test_bad_entity(self):
        self.assertIsNone(ct.get_entity('1/0'))
    def test_good_entity(self):
        self.assertIs(ct.get_entity('int'), int)

if __name__ == '__main__':
    unittest.main(verbosity=2, exit=False)