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