##// END OF EJS Templates
Skip test that builtin signature can't be inspected...
Thomas Kluyver -
Show More
@@ -1,382 +1,383 b''
1 1 """Tests for the object inspection functionality.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (C) 2010-2011 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14 from __future__ import print_function
15 15
16 16 # Stdlib imports
17 17 import os
18 18 import re
19 19
20 20 # Third-party imports
21 21 import nose.tools as nt
22 22
23 23 # Our own imports
24 24 from .. import oinspect
25 25 from IPython.core.magic import (Magics, magics_class, line_magic,
26 26 cell_magic, line_cell_magic,
27 27 register_line_magic, register_cell_magic,
28 28 register_line_cell_magic)
29 29 from decorator import decorator
30 30 from IPython.testing.decorators import skipif
31 31 from IPython.testing.tools import AssertPrints
32 32 from IPython.utils.path import compress_user
33 33 from IPython.utils import py3compat
34 34
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Globals and constants
38 38 #-----------------------------------------------------------------------------
39 39
40 40 inspector = oinspect.Inspector()
41 41 ip = get_ipython()
42 42
43 43 #-----------------------------------------------------------------------------
44 44 # Local utilities
45 45 #-----------------------------------------------------------------------------
46 46
47 47 # WARNING: since this test checks the line number where a function is
48 48 # defined, if any code is inserted above, the following line will need to be
49 49 # updated. Do NOT insert any whitespace between the next line and the function
50 50 # definition below.
51 51 THIS_LINE_NUMBER = 51 # Put here the actual number of this line
52 52 def test_find_source_lines():
53 53 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
54 54 THIS_LINE_NUMBER+1)
55 55
56 56
57 57 # A couple of utilities to ensure these tests work the same from a source or a
58 58 # binary install
59 59 def pyfile(fname):
60 60 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
61 61
62 62
63 63 def match_pyfiles(f1, f2):
64 64 nt.assert_equal(pyfile(f1), pyfile(f2))
65 65
66 66
67 67 def test_find_file():
68 68 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
69 69
70 70
71 71 def test_find_file_decorated1():
72 72
73 73 @decorator
74 74 def noop1(f):
75 75 def wrapper():
76 76 return f(*a, **kw)
77 77 return wrapper
78 78
79 79 @noop1
80 80 def f(x):
81 81 "My docstring"
82 82
83 83 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
84 84 nt.assert_equal(f.__doc__, "My docstring")
85 85
86 86
87 87 def test_find_file_decorated2():
88 88
89 89 @decorator
90 90 def noop2(f, *a, **kw):
91 91 return f(*a, **kw)
92 92
93 93 @noop2
94 94 def f(x):
95 95 "My docstring 2"
96 96
97 97 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
98 98 nt.assert_equal(f.__doc__, "My docstring 2")
99 99
100 100
101 101 def test_find_file_magic():
102 102 run = ip.find_line_magic('run')
103 103 nt.assert_not_equal(oinspect.find_file(run), None)
104 104
105 105
106 106 # A few generic objects we can then inspect in the tests below
107 107
108 108 class Call(object):
109 109 """This is the class docstring."""
110 110
111 111 def __init__(self, x, y=1):
112 112 """This is the constructor docstring."""
113 113
114 114 def __call__(self, *a, **kw):
115 115 """This is the call docstring."""
116 116
117 117 def method(self, x, z=2):
118 118 """Some method's docstring"""
119 119
120 120 class SimpleClass(object):
121 121 def method(self, x, z=2):
122 122 """Some method's docstring"""
123 123
124 124
125 125 class OldStyle:
126 126 """An old-style class for testing."""
127 127 pass
128 128
129 129
130 130 def f(x, y=2, *a, **kw):
131 131 """A simple function."""
132 132
133 133
134 134 def g(y, z=3, *a, **kw):
135 135 pass # no docstring
136 136
137 137
138 138 @register_line_magic
139 139 def lmagic(line):
140 140 "A line magic"
141 141
142 142
143 143 @register_cell_magic
144 144 def cmagic(line, cell):
145 145 "A cell magic"
146 146
147 147
148 148 @register_line_cell_magic
149 149 def lcmagic(line, cell=None):
150 150 "A line/cell magic"
151 151
152 152
153 153 @magics_class
154 154 class SimpleMagics(Magics):
155 155 @line_magic
156 156 def Clmagic(self, cline):
157 157 "A class-based line magic"
158 158
159 159 @cell_magic
160 160 def Ccmagic(self, cline, ccell):
161 161 "A class-based cell magic"
162 162
163 163 @line_cell_magic
164 164 def Clcmagic(self, cline, ccell=None):
165 165 "A class-based line/cell magic"
166 166
167 167
168 168 class Awkward(object):
169 169 def __getattr__(self, name):
170 170 raise Exception(name)
171 171
172 172
173 173 def check_calltip(obj, name, call, docstring):
174 174 """Generic check pattern all calltip tests will use"""
175 175 info = inspector.info(obj, name)
176 176 call_line, ds = oinspect.call_tip(info)
177 177 nt.assert_equal(call_line, call)
178 178 nt.assert_equal(ds, docstring)
179 179
180 180 #-----------------------------------------------------------------------------
181 181 # Tests
182 182 #-----------------------------------------------------------------------------
183 183
184 184 def test_calltip_class():
185 185 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
186 186
187 187
188 188 def test_calltip_instance():
189 189 c = Call(1)
190 190 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
191 191
192 192
193 193 def test_calltip_method():
194 194 c = Call(1)
195 195 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
196 196
197 197
198 198 def test_calltip_function():
199 199 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
200 200
201 201
202 202 def test_calltip_function2():
203 203 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
204 204
205 205
206 @skipif(sys.version_info >= (3, 5))
206 207 def test_calltip_builtin():
207 208 check_calltip(sum, 'sum', None, sum.__doc__)
208 209
209 210
210 211 def test_calltip_line_magic():
211 212 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
212 213
213 214
214 215 def test_calltip_cell_magic():
215 216 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
216 217
217 218
218 219 def test_calltip_line_cell_magic():
219 220 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
220 221 "A line/cell magic")
221 222
222 223
223 224 def test_class_magics():
224 225 cm = SimpleMagics(ip)
225 226 ip.register_magics(cm)
226 227 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
227 228 "A class-based line magic")
228 229 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
229 230 "A class-based cell magic")
230 231 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
231 232 "A class-based line/cell magic")
232 233
233 234
234 235 def test_info():
235 236 "Check that Inspector.info fills out various fields as expected."
236 237 i = inspector.info(Call, oname='Call')
237 238 nt.assert_equal(i['type_name'], 'type')
238 239 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
239 240 nt.assert_equal(i['base_class'], expted_class)
240 241 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
241 242 fname = __file__
242 243 if fname.endswith(".pyc"):
243 244 fname = fname[:-1]
244 245 # case-insensitive comparison needed on some filesystems
245 246 # e.g. Windows:
246 247 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
247 248 nt.assert_equal(i['definition'], None)
248 249 nt.assert_equal(i['docstring'], Call.__doc__)
249 250 nt.assert_equal(i['source'], None)
250 251 nt.assert_true(i['isclass'])
251 252 nt.assert_equal(i['init_definition'], "Call(self, x, y=1)\n")
252 253 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
253 254
254 255 i = inspector.info(Call, detail_level=1)
255 256 nt.assert_not_equal(i['source'], None)
256 257 nt.assert_equal(i['docstring'], None)
257 258
258 259 c = Call(1)
259 260 c.__doc__ = "Modified instance docstring"
260 261 i = inspector.info(c)
261 262 nt.assert_equal(i['type_name'], 'Call')
262 263 nt.assert_equal(i['docstring'], "Modified instance docstring")
263 264 nt.assert_equal(i['class_docstring'], Call.__doc__)
264 265 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
265 266 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
266 267
267 268 # Test old-style classes, which for example may not have an __init__ method.
268 269 if not py3compat.PY3:
269 270 i = inspector.info(OldStyle)
270 271 nt.assert_equal(i['type_name'], 'classobj')
271 272
272 273 i = inspector.info(OldStyle())
273 274 nt.assert_equal(i['type_name'], 'instance')
274 275 nt.assert_equal(i['docstring'], OldStyle.__doc__)
275 276
276 277 def test_info_awkward():
277 278 # Just test that this doesn't throw an error.
278 279 i = inspector.info(Awkward())
279 280
280 281 def test_calldef_none():
281 282 # We should ignore __call__ for all of these.
282 283 for obj in [f, SimpleClass().method, any, str.upper]:
283 284 print(obj)
284 285 i = inspector.info(obj)
285 286 nt.assert_is(i['call_def'], None)
286 287
287 288 if py3compat.PY3:
288 289 exec("def f_kwarg(pos, *, kwonly): pass")
289 290
290 291 @skipif(not py3compat.PY3)
291 292 def test_definition_kwonlyargs():
292 293 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
293 294 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)\n")
294 295
295 296 def test_getdoc():
296 297 class A(object):
297 298 """standard docstring"""
298 299 pass
299 300
300 301 class B(object):
301 302 """standard docstring"""
302 303 def getdoc(self):
303 304 return "custom docstring"
304 305
305 306 class C(object):
306 307 """standard docstring"""
307 308 def getdoc(self):
308 309 return None
309 310
310 311 a = A()
311 312 b = B()
312 313 c = C()
313 314
314 315 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
315 316 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
316 317 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
317 318
318 319
319 320 def test_empty_property_has_no_source():
320 321 i = inspector.info(property(), detail_level=1)
321 322 nt.assert_is(i['source'], None)
322 323
323 324
324 325 def test_property_sources():
325 326 import zlib
326 327
327 328 class A(object):
328 329 @property
329 330 def foo(self):
330 331 return 'bar'
331 332
332 333 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
333 334
334 335 id = property(id)
335 336 compress = property(zlib.compress)
336 337
337 338 i = inspector.info(A.foo, detail_level=1)
338 339 nt.assert_in('def foo(self):', i['source'])
339 340 nt.assert_in('lambda self, v:', i['source'])
340 341
341 342 i = inspector.info(A.id, detail_level=1)
342 343 nt.assert_in('fget = <function id>', i['source'])
343 344
344 345 i = inspector.info(A.compress, detail_level=1)
345 346 nt.assert_in('fget = <function zlib.compress>', i['source'])
346 347
347 348
348 349 def test_property_docstring_is_in_info_for_detail_level_0():
349 350 class A(object):
350 351 @property
351 352 def foobar():
352 353 """This is `foobar` property."""
353 354 pass
354 355
355 356 ip.user_ns['a_obj'] = A()
356 357 nt.assert_equals(
357 358 'This is `foobar` property.',
358 359 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
359 360
360 361 ip.user_ns['a_cls'] = A
361 362 nt.assert_equals(
362 363 'This is `foobar` property.',
363 364 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
364 365
365 366
366 367 def test_pdef():
367 368 # See gh-1914
368 369 def foo(): pass
369 370 inspector.pdef(foo, 'foo')
370 371
371 372 def test_pinfo_nonascii():
372 373 # See gh-1177
373 374 from . import nonascii2
374 375 ip.user_ns['nonascii2'] = nonascii2
375 376 ip._inspect('pinfo', 'nonascii2', detail_level=1)
376 377
377 378 def test_pinfo_magic():
378 379 with AssertPrints('Docstring:'):
379 380 ip._inspect('pinfo', 'lsmagic', detail_level=0)
380 381
381 382 with AssertPrints('Source:'):
382 383 ip._inspect('pinfo', 'lsmagic', detail_level=1)
General Comments 0
You need to be logged in to leave comments. Login now