1 "Test calltip, coverage 60%" 2 3 from idlelib import calltip 4 import unittest 5 import textwrap 6 import types 7 8 default_tip = calltip._default_callable_argspec 9 10 11 # Test Class TC is used in multiple get_argspec test methods 12 class TC(): 13 'doc' 14 tip = "(ai=None, *b)" 15 def __init__(self, ai=None, *b): 'doc' 16 __init__.tip = "(self, ai=None, *b)" 17 def t1(self): 'doc' 18 t1.tip = "(self)" 19 def t2(self, ai, b=None): 'doc' 20 t2.tip = "(self, ai, b=None)" 21 def t3(self, ai, *args): 'doc' 22 t3.tip = "(self, ai, *args)" 23 def t4(self, *args): 'doc' 24 t4.tip = "(self, *args)" 25 def t5(self, ai, b=None, *args, **kw): 'doc' 26 t5.tip = "(self, ai, b=None, *args, **kw)" 27 def t6(no, self): 'doc' 28 t6.tip = "(no, self)" 29 def __call__(self, ci): 'doc' 30 __call__.tip = "(self, ci)" 31 # attaching .tip to wrapped methods does not work 32 @classmethod 33 def cm(cls, a): 'doc' 34 @staticmethod 35 def sm(b): 'doc' 36 37 38 tc = TC() 39 signature = calltip.get_argspec # 2.7 and 3.x use different functions 40 41 42 class Get_signatureTest(unittest.TestCase): 43 # The signature function must return a string, even if blank. 44 # Test a variety of objects to be sure that none cause it to raise 45 # (quite aside from getting as correct an answer as possible). 46 # The tests of builtins may break if inspect or the docstrings change, 47 # but a red buildbot is better than a user crash (as has happened). 48 # For a simple mismatch, change the expected output to the actual. 49 50 def test_builtins(self): 51 52 # Python class that inherits builtin methods 53 class List(list): "List() doc" 54 55 # Simulate builtin with no docstring for default tip test 56 class SB: __call__ = None 57 58 def gtest(obj, out): 59 self.assertEqual(signature(obj), out) 60 61 if List.__doc__ is not None: 62 gtest(List, '(iterable=(), /)' + calltip._argument_positional 63 + '\n' + List.__doc__) 64 gtest(list.__new__, 65 '(*args, **kwargs)\n' 66 'Create and return a new object. ' 67 'See help(type) for accurate signature.') 68 gtest(list.__init__, 69 '(self, /, *args, **kwargs)' 70 + calltip._argument_positional + '\n' + 71 'Initialize self. See help(type(self)) for accurate signature.') 72 append_doc = (calltip._argument_positional 73 + "\nAppend object to the end of the list.") 74 gtest(list.append, '(self, object, /)' + append_doc) 75 gtest(List.append, '(self, object, /)' + append_doc) 76 gtest([].append, '(object, /)' + append_doc) 77 78 gtest(types.MethodType, "method(function, instance)") 79 gtest(SB(), default_tip) 80 import re 81 p = re.compile('') 82 gtest(re.sub, '''\ 83 (pattern, repl, string, count=0, flags=0) 84 Return the string obtained by replacing the leftmost 85 non-overlapping occurrences of the pattern in string by the 86 replacement repl. repl can be either a string or a callable; 87 if a string, backslash escapes in it are processed. If it is 88 a callable, it's passed the Match object and must return''') 89 gtest(p.sub, '''\ 90 (repl, string, count=0) 91 Return the string obtained by replacing the leftmost \ 92 non-overlapping occurrences o...''') 93 94 def test_signature_wrap(self): 95 if textwrap.TextWrapper.__doc__ is not None: 96 self.assertEqual(signature(textwrap.TextWrapper), '''\ 97 (width=70, initial_indent='', subsequent_indent='', expand_tabs=True, 98 replace_whitespace=True, fix_sentence_endings=False, break_long_words=True, 99 drop_whitespace=True, break_on_hyphens=True, tabsize=8, *, max_lines=None, 100 placeholder=' [...]')''') 101 102 def test_properly_formated(self): 103 def foo(s='a'*100): 104 pass 105 106 def bar(s='a'*100): 107 """Hello Guido""" 108 pass 109 110 def baz(s='a'*100, z='b'*100): 111 pass 112 113 indent = calltip._INDENT 114 115 str_foo = "(s='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"\ 116 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + indent + "aaaaaaaaa"\ 117 "aaaaaaaaaa')" 118 str_bar = "(s='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"\ 119 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + indent + "aaaaaaaaa"\ 120 "aaaaaaaaaa')\nHello Guido" 121 str_baz = "(s='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"\ 122 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + indent + "aaaaaaaaa"\ 123 "aaaaaaaaaa', z='bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"\ 124 "bbbbbbbbbbbbbbbbb\n" + indent + "bbbbbbbbbbbbbbbbbbbbbb"\ 125 "bbbbbbbbbbbbbbbbbbbbbb')" 126 127 self.assertEqual(calltip.get_argspec(foo), str_foo) 128 self.assertEqual(calltip.get_argspec(bar), str_bar) 129 self.assertEqual(calltip.get_argspec(baz), str_baz) 130 131 def test_docline_truncation(self): 132 def f(): pass 133 f.__doc__ = 'a'*300 134 self.assertEqual(signature(f), '()\n' + 'a' * (calltip._MAX_COLS-3) + '...') 135 136 def test_multiline_docstring(self): 137 # Test fewer lines than max. 138 self.assertEqual(signature(range), 139 "range(stop) -> range object\n" 140 "range(start, stop[, step]) -> range object") 141 142 # Test max lines 143 self.assertEqual(signature(bytes), '''\ 144 bytes(iterable_of_ints) -> bytes 145 bytes(string, encoding[, errors]) -> bytes 146 bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer 147 bytes(int) -> bytes object of size given by the parameter initialized with null bytes 148 bytes() -> empty bytes object''') 149 150 # Test more than max lines 151 def f(): pass 152 f.__doc__ = 'a\n' * 15 153 self.assertEqual(signature(f), '()' + '\na' * calltip._MAX_LINES) 154 155 def test_functions(self): 156 def t1(): 'doc' 157 t1.tip = "()" 158 def t2(a, b=None): 'doc' 159 t2.tip = "(a, b=None)" 160 def t3(a, *args): 'doc' 161 t3.tip = "(a, *args)" 162 def t4(*args): 'doc' 163 t4.tip = "(*args)" 164 def t5(a, b=None, *args, **kw): 'doc' 165 t5.tip = "(a, b=None, *args, **kw)" 166 167 doc = '\ndoc' if t1.__doc__ is not None else '' 168 for func in (t1, t2, t3, t4, t5, TC): 169 self.assertEqual(signature(func), func.tip + doc) 170 171 def test_methods(self): 172 doc = '\ndoc' if TC.__doc__ is not None else '' 173 for meth in (TC.t1, TC.t2, TC.t3, TC.t4, TC.t5, TC.t6, TC.__call__): 174 self.assertEqual(signature(meth), meth.tip + doc) 175 self.assertEqual(signature(TC.cm), "(a)" + doc) 176 self.assertEqual(signature(TC.sm), "(b)" + doc) 177 178 def test_bound_methods(self): 179 # test that first parameter is correctly removed from argspec 180 doc = '\ndoc' if TC.__doc__ is not None else '' 181 for meth, mtip in ((tc.t1, "()"), (tc.t4, "(*args)"), 182 (tc.t6, "(self)"), (tc.__call__, '(ci)'), 183 (tc, '(ci)'), (TC.cm, "(a)"),): 184 self.assertEqual(signature(meth), mtip + doc) 185 186 def test_starred_parameter(self): 187 # test that starred first parameter is *not* removed from argspec 188 class C: 189 def m1(*args): pass 190 c = C() 191 for meth, mtip in ((C.m1, '(*args)'), (c.m1, "(*args)"),): 192 self.assertEqual(signature(meth), mtip) 193 194 def test_invalid_method_signature(self): 195 class C: 196 def m2(**kwargs): pass 197 class Test: 198 def __call__(*, a): pass 199 200 mtip = calltip._invalid_method 201 self.assertEqual(signature(C().m2), mtip) 202 self.assertEqual(signature(Test()), mtip) 203 204 def test_non_ascii_name(self): 205 # test that re works to delete a first parameter name that 206 # includes non-ascii chars, such as various forms of A. 207 uni = "(A\u0391\u0410\u05d0\u0627\u0905\u1e00\u3042, a)" 208 assert calltip._first_param.sub('', uni) == '(a)' 209 210 def test_no_docstring(self): 211 def nd(s): 212 pass 213 TC.nd = nd 214 self.assertEqual(signature(nd), "(s)") 215 self.assertEqual(signature(TC.nd), "(s)") 216 self.assertEqual(signature(tc.nd), "()") 217 218 def test_attribute_exception(self): 219 class NoCall: 220 def __getattr__(self, name): 221 raise BaseException 222 class CallA(NoCall): 223 def __call__(oui, a, b, c): 224 pass 225 class CallB(NoCall): 226 def __call__(self, ci): 227 pass 228 229 for meth, mtip in ((NoCall, default_tip), (CallA, default_tip), 230 (NoCall(), ''), (CallA(), '(a, b, c)'), 231 (CallB(), '(ci)')): 232 self.assertEqual(signature(meth), mtip) 233 234 def test_non_callables(self): 235 for obj in (0, 0.0, '0', b'0', [], {}): 236 self.assertEqual(signature(obj), '') 237 238 239 class Get_entityTest(unittest.TestCase): 240 def test_bad_entity(self): 241 self.assertIsNone(calltip.get_entity('1/0')) 242 def test_good_entity(self): 243 self.assertIs(calltip.get_entity('int'), int) 244 245 246 if __name__ == '__main__': 247 unittest.main(verbosity=2) 248