1import unittest 2import idlelib.CallTips as ct 3CTi = ct.CallTips() # needed for get_entity test in 2.7 4import textwrap 5import types 6import warnings 7 8default_tip = '' 9 10# Test Class TC is used in multiple get_argspec test methods 11class TC(object): 12 'doc' 13 tip = "(ai=None, *args)" 14 def __init__(self, ai=None, *b): 'doc' 15 __init__.tip = "(self, ai=None, *args)" 16 def t1(self): 'doc' 17 t1.tip = "(self)" 18 def t2(self, ai, b=None): 'doc' 19 t2.tip = "(self, ai, b=None)" 20 def t3(self, ai, *args): 'doc' 21 t3.tip = "(self, ai, *args)" 22 def t4(self, *args): 'doc' 23 t4.tip = "(self, *args)" 24 def t5(self, ai, b=None, *args, **kw): 'doc' 25 t5.tip = "(self, ai, b=None, *args, **kwargs)" 26 def t6(no, self): 'doc' 27 t6.tip = "(no, self)" 28 def __call__(self, ci): 'doc' 29 __call__.tip = "(self, ci)" 30 # attaching .tip to wrapped methods does not work 31 @classmethod 32 def cm(cls, a): 'doc' 33 @staticmethod 34 def sm(b): 'doc' 35 36tc = TC() 37 38signature = ct.get_arg_text # 2.7 and 3.x use different functions 39class Get_signatureTest(unittest.TestCase): 40 # The signature function must return a string, even if blank. 41 # Test a variety of objects to be sure that none cause it to raise 42 # (quite aside from getting as correct an answer as possible). 43 # The tests of builtins may break if the docstrings change, 44 # but a red buildbot is better than a user crash (as has happened). 45 # For a simple mismatch, change the expected output to the actual. 46 47 def test_builtins(self): 48 # 2.7 puts '()\n' where 3.x does not, other minor differences 49 50 # Python class that inherits builtin methods 51 class List(list): "List() doc" 52 # Simulate builtin with no docstring for default argspec test 53 class SB: __call__ = None 54 55 def gtest(obj, out): 56 self.assertEqual(signature(obj), out) 57 58 if List.__doc__ is not None: 59 gtest(List, '()\n' + List.__doc__) 60 gtest(list.__new__, 61 'T.__new__(S, ...) -> a new object with type S, a subtype of T') 62 gtest(list.__init__, 63 'x.__init__(...) initializes x; see help(type(x)) for signature') 64 append_doc = "L.append(object) -- append object to end" 65 gtest(list.append, append_doc) 66 gtest([].append, append_doc) 67 gtest(List.append, append_doc) 68 69 gtest(types.MethodType, '()\ninstancemethod(function, instance, class)') 70 gtest(SB(), default_tip) 71 72 def test_signature_wrap(self): 73 # This is also a test of an old-style class 74 if textwrap.TextWrapper.__doc__ is not None: 75 self.assertEqual(signature(textwrap.TextWrapper), '''\ 76(width=70, initial_indent='', subsequent_indent='', expand_tabs=True, 77 replace_whitespace=True, fix_sentence_endings=False, break_long_words=True, 78 drop_whitespace=True, break_on_hyphens=True)''') 79 80 def test_docline_truncation(self): 81 def f(): pass 82 f.__doc__ = 'a'*300 83 self.assertEqual(signature(f), '()\n' + 'a' * (ct._MAX_COLS-3) + '...') 84 85 def test_multiline_docstring(self): 86 # Test fewer lines than max. 87 self.assertEqual(signature(list), 88 "()\nlist() -> new empty list\n" 89 "list(iterable) -> new list initialized from iterable's items") 90 91 # Test max lines and line (currently) too long. 92 def f(): 93 pass 94 s = 'a\nb\nc\nd\n' 95 f.__doc__ = s + 300 * 'e' + 'f' 96 self.assertEqual(signature(f), 97 '()\n' + s + (ct._MAX_COLS - 3) * 'e' + '...') 98 99 def test_functions(self): 100 def t1(): 'doc' 101 t1.tip = "()" 102 def t2(a, b=None): 'doc' 103 t2.tip = "(a, b=None)" 104 def t3(a, *args): 'doc' 105 t3.tip = "(a, *args)" 106 def t4(*args): 'doc' 107 t4.tip = "(*args)" 108 def t5(a, b=None, *args, **kwds): 'doc' 109 t5.tip = "(a, b=None, *args, **kwargs)" 110 111 doc = '\ndoc' if t1.__doc__ is not None else '' 112 for func in (t1, t2, t3, t4, t5, TC): 113 self.assertEqual(signature(func), func.tip + doc) 114 115 def test_methods(self): 116 doc = '\ndoc' if TC.__doc__ is not None else '' 117 for meth in (TC.t1, TC.t2, TC.t3, TC.t4, TC.t5, TC.t6, TC.__call__): 118 self.assertEqual(signature(meth), meth.tip + doc) 119 self.assertEqual(signature(TC.cm), "(a)" + doc) 120 self.assertEqual(signature(TC.sm), "(b)" + doc) 121 122 def test_bound_methods(self): 123 # test that first parameter is correctly removed from argspec 124 doc = '\ndoc' if TC.__doc__ is not None else '' 125 for meth, mtip in ((tc.t1, "()"), (tc.t4, "(*args)"), (tc.t6, "(self)"), 126 (tc.__call__, '(ci)'), (tc, '(ci)'), (TC.cm, "(a)"),): 127 self.assertEqual(signature(meth), mtip + doc) 128 129 def test_starred_parameter(self): 130 # test that starred first parameter is *not* removed from argspec 131 class C: 132 def m1(*args): pass 133 def m2(**kwds): pass 134 def f1(args, kwargs, *a, **k): pass 135 def f2(args, kwargs, args1, kwargs1, *a, **k): pass 136 c = C() 137 self.assertEqual(signature(C.m1), '(*args)') 138 self.assertEqual(signature(c.m1), '(*args)') 139 self.assertEqual(signature(C.m2), '(**kwargs)') 140 self.assertEqual(signature(c.m2), '(**kwargs)') 141 self.assertEqual(signature(f1), '(args, kwargs, *args1, **kwargs1)') 142 self.assertEqual(signature(f2), 143 '(args, kwargs, args1, kwargs1, *args2, **kwargs2)') 144 145 def test_no_docstring(self): 146 def nd(s): pass 147 TC.nd = nd 148 self.assertEqual(signature(nd), "(s)") 149 self.assertEqual(signature(TC.nd), "(s)") 150 self.assertEqual(signature(tc.nd), "()") 151 152 def test_attribute_exception(self): 153 class NoCall(object): 154 def __getattr__(self, name): 155 raise BaseException 156 class Call(NoCall): 157 def __call__(self, ci): 158 pass 159 for meth, mtip in ((NoCall, '()'), (Call, '()'), 160 (NoCall(), ''), (Call(), '(ci)')): 161 self.assertEqual(signature(meth), mtip) 162 163 def test_non_callables(self): 164 for obj in (0, 0.0, '0', b'0', [], {}): 165 self.assertEqual(signature(obj), '') 166 167class Get_entityTest(unittest.TestCase): 168 # In 3.x, get_entity changed from 'instance method' to module function 169 # since 'self' not used. Use dummy instance until change 2.7 also. 170 def test_bad_entity(self): 171 self.assertIsNone(CTi.get_entity('1//0')) 172 def test_good_entity(self): 173 self.assertIs(CTi.get_entity('int'), int) 174 175class Py2Test(unittest.TestCase): 176 def test_paramtuple_float(self): 177 # 18539: (a,b) becomes '.0' in code object; change that but not 0.0 178 with warnings.catch_warnings(): 179 # Suppess message of py3 deprecation of parameter unpacking 180 warnings.simplefilter("ignore") 181 exec "def f((a,b), c=0.0): pass" 182 self.assertEqual(signature(f), '(<tuple>, c=0.0)') 183 184if __name__ == '__main__': 185 unittest.main(verbosity=2, exit=False) 186