##// END OF EJS Templates
cleanup
Srinivas Reddy Thatiparthy -
Show More
@@ -1,74 +1,74 b''
1 1 # coding: utf-8
2 2 """Tests for the compilerop module.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2010-2011 The IPython Development Team.
6 6 #
7 7 # Distributed under the terms of the BSD License.
8 8 #
9 9 # The full license is in the file COPYING.txt, distributed with this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 16 # Stdlib imports
17 17 import linecache
18 18 import sys
19 19
20 20 # Third-party imports
21 21 import nose.tools as nt
22 22
23 23 # Our own imports
24 24 from IPython.core import compilerop
25 25 from IPython.utils import py3compat
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Test functions
29 29 #-----------------------------------------------------------------------------
30 30
31 31 def test_code_name():
32 32 code = 'x=1'
33 33 name = compilerop.code_name(code)
34 34 nt.assert_true(name.startswith('<ipython-input-0'))
35 35
36 36
37 37 def test_code_name2():
38 38 code = 'x=1'
39 39 name = compilerop.code_name(code, 9)
40 40 nt.assert_true(name.startswith('<ipython-input-9'))
41 41
42 42
43 43 def test_cache():
44 44 """Test the compiler correctly compiles and caches inputs
45 45 """
46 46 cp = compilerop.CachingCompiler()
47 47 ncache = len(linecache.cache)
48 48 cp.cache('x=1')
49 49 nt.assert_true(len(linecache.cache) > ncache)
50 50
51 51 def setUp():
52 52 # Check we're in a proper Python 2 environment (some imports, such
53 53 # as GTK, can change the default encoding, which can hide bugs.)
54 nt.assert_equal(sys.getdefaultencoding(), "utf-8" if py3compat.PY3 else "ascii")
54 nt.assert_equal(sys.getdefaultencoding(), "utf-8")
55 55
56 56 def test_cache_unicode():
57 57 cp = compilerop.CachingCompiler()
58 58 ncache = len(linecache.cache)
59 59 cp.cache(u"t = 'žćčőđ'")
60 60 nt.assert_true(len(linecache.cache) > ncache)
61 61
62 62 def test_compiler_check_cache():
63 63 """Test the compiler properly manages the cache.
64 64 """
65 65 # Rather simple-minded tests that just exercise the API
66 66 cp = compilerop.CachingCompiler()
67 67 cp.cache('x=1', 99)
68 68 # Ensure now that after clearing the cache, our entries survive
69 69 linecache.checkcache()
70 70 for k in linecache.cache:
71 71 if k.startswith('<ipython-input-99'):
72 72 break
73 73 else:
74 74 raise AssertionError('Entry for input-99 missing from linecache')
@@ -1,419 +1,418 b''
1 1 """Tests for the object inspection functionality.
2 2 """
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7
8 8 from inspect import Signature, Parameter
9 9 import os
10 10 import re
11 11 import sys
12 12
13 13 import nose.tools as nt
14 14
15 15 from .. import oinspect
16 16 from IPython.core.magic import (Magics, magics_class, line_magic,
17 17 cell_magic, line_cell_magic,
18 18 register_line_magic, register_cell_magic,
19 19 register_line_cell_magic)
20 20 from decorator import decorator
21 21 from IPython import get_ipython
22 22 from IPython.testing.decorators import skipif
23 23 from IPython.testing.tools import AssertPrints, AssertNotPrints
24 24 from IPython.utils.path import compress_user
25 25 from IPython.utils import py3compat
26 26
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Globals and constants
30 30 #-----------------------------------------------------------------------------
31 31
32 32 inspector = oinspect.Inspector()
33 33 ip = get_ipython()
34 34
35 35 #-----------------------------------------------------------------------------
36 36 # Local utilities
37 37 #-----------------------------------------------------------------------------
38 38
39 39 # WARNING: since this test checks the line number where a function is
40 40 # defined, if any code is inserted above, the following line will need to be
41 41 # updated. Do NOT insert any whitespace between the next line and the function
42 42 # definition below.
43 43 THIS_LINE_NUMBER = 43 # Put here the actual number of this line
44 44
45 45 from unittest import TestCase
46 46
47 47 class Test(TestCase):
48 48
49 49 def test_find_source_lines(self):
50 50 self.assertEqual(oinspect.find_source_lines(Test.test_find_source_lines),
51 51 THIS_LINE_NUMBER+6)
52 52
53 53
54 54 # A couple of utilities to ensure these tests work the same from a source or a
55 55 # binary install
56 56 def pyfile(fname):
57 57 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
58 58
59 59
60 60 def match_pyfiles(f1, f2):
61 61 nt.assert_equal(pyfile(f1), pyfile(f2))
62 62
63 63
64 64 def test_find_file():
65 65 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
66 66
67 67
68 68 def test_find_file_decorated1():
69 69
70 70 @decorator
71 71 def noop1(f):
72 72 def wrapper(*a, **kw):
73 73 return f(*a, **kw)
74 74 return wrapper
75 75
76 76 @noop1
77 77 def f(x):
78 78 "My docstring"
79 79
80 80 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
81 81 nt.assert_equal(f.__doc__, "My docstring")
82 82
83 83
84 84 def test_find_file_decorated2():
85 85
86 86 @decorator
87 87 def noop2(f, *a, **kw):
88 88 return f(*a, **kw)
89 89
90 90 @noop2
91 91 @noop2
92 92 @noop2
93 93 def f(x):
94 94 "My docstring 2"
95 95
96 96 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
97 97 nt.assert_equal(f.__doc__, "My docstring 2")
98 98
99 99
100 100 def test_find_file_magic():
101 101 run = ip.find_line_magic('run')
102 102 nt.assert_not_equal(oinspect.find_file(run), None)
103 103
104 104
105 105 # A few generic objects we can then inspect in the tests below
106 106
107 107 class Call(object):
108 108 """This is the class docstring."""
109 109
110 110 def __init__(self, x, y=1):
111 111 """This is the constructor docstring."""
112 112
113 113 def __call__(self, *a, **kw):
114 114 """This is the call docstring."""
115 115
116 116 def method(self, x, z=2):
117 117 """Some method's docstring"""
118 118
119 119 class HasSignature(object):
120 120 """This is the class docstring."""
121 121 __signature__ = Signature([Parameter('test', Parameter.POSITIONAL_OR_KEYWORD)])
122 122
123 123 def __init__(self, *args):
124 124 """This is the init docstring"""
125 125
126 126
127 127 class SimpleClass(object):
128 128 def method(self, x, z=2):
129 129 """Some method's docstring"""
130 130
131 131
132 132 class OldStyle:
133 133 """An old-style class for testing."""
134 134 pass
135 135
136 136
137 137 def f(x, y=2, *a, **kw):
138 138 """A simple function."""
139 139
140 140
141 141 def g(y, z=3, *a, **kw):
142 142 pass # no docstring
143 143
144 144
145 145 @register_line_magic
146 146 def lmagic(line):
147 147 "A line magic"
148 148
149 149
150 150 @register_cell_magic
151 151 def cmagic(line, cell):
152 152 "A cell magic"
153 153
154 154
155 155 @register_line_cell_magic
156 156 def lcmagic(line, cell=None):
157 157 "A line/cell magic"
158 158
159 159
160 160 @magics_class
161 161 class SimpleMagics(Magics):
162 162 @line_magic
163 163 def Clmagic(self, cline):
164 164 "A class-based line magic"
165 165
166 166 @cell_magic
167 167 def Ccmagic(self, cline, ccell):
168 168 "A class-based cell magic"
169 169
170 170 @line_cell_magic
171 171 def Clcmagic(self, cline, ccell=None):
172 172 "A class-based line/cell magic"
173 173
174 174
175 175 class Awkward(object):
176 176 def __getattr__(self, name):
177 177 raise Exception(name)
178 178
179 179 class NoBoolCall:
180 180 """
181 181 callable with `__bool__` raising should still be inspect-able.
182 182 """
183 183
184 184 def __call__(self):
185 185 """does nothing"""
186 186 pass
187 187
188 188 def __bool__(self):
189 189 """just raise NotImplemented"""
190 190 raise NotImplementedError('Must be implemented')
191 191
192 192
193 193 class SerialLiar(object):
194 194 """Attribute accesses always get another copy of the same class.
195 195
196 196 unittest.mock.call does something similar, but it's not ideal for testing
197 197 as the failure mode is to eat all your RAM. This gives up after 10k levels.
198 198 """
199 199 def __init__(self, max_fibbing_twig, lies_told=0):
200 200 if lies_told > 10000:
201 201 raise RuntimeError('Nose too long, honesty is the best policy')
202 202 self.max_fibbing_twig = max_fibbing_twig
203 203 self.lies_told = lies_told
204 204 max_fibbing_twig[0] = max(max_fibbing_twig[0], lies_told)
205 205
206 206 def __getattr__(self, item):
207 207 return SerialLiar(self.max_fibbing_twig, self.lies_told + 1)
208 208
209 209 #-----------------------------------------------------------------------------
210 210 # Tests
211 211 #-----------------------------------------------------------------------------
212 212
213 213 def test_info():
214 214 "Check that Inspector.info fills out various fields as expected."
215 215 i = inspector.info(Call, oname='Call')
216 216 nt.assert_equal(i['type_name'], 'type')
217 217 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
218 218 nt.assert_equal(i['base_class'], expted_class)
219 219 nt.assert_regex(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>")
220 220 fname = __file__
221 221 if fname.endswith(".pyc"):
222 222 fname = fname[:-1]
223 223 # case-insensitive comparison needed on some filesystems
224 224 # e.g. Windows:
225 225 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
226 226 nt.assert_equal(i['definition'], None)
227 227 nt.assert_equal(i['docstring'], Call.__doc__)
228 228 nt.assert_equal(i['source'], None)
229 229 nt.assert_true(i['isclass'])
230 _self_py2 = '' if py3compat.PY3 else 'self, '
231 nt.assert_equal(i['init_definition'], "Call(%sx, y=1)" % _self_py2)
230 nt.assert_equal(i['init_definition'], "Call(x, y=1)")
232 231 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
233 232
234 233 i = inspector.info(Call, detail_level=1)
235 234 nt.assert_not_equal(i['source'], None)
236 235 nt.assert_equal(i['docstring'], None)
237 236
238 237 c = Call(1)
239 238 c.__doc__ = "Modified instance docstring"
240 239 i = inspector.info(c)
241 240 nt.assert_equal(i['type_name'], 'Call')
242 241 nt.assert_equal(i['docstring'], "Modified instance docstring")
243 242 nt.assert_equal(i['class_docstring'], Call.__doc__)
244 243 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
245 244 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
246 245
247 246 # Test old-style classes, which for example may not have an __init__ method.
248 247 if not py3compat.PY3:
249 248 i = inspector.info(OldStyle)
250 249 nt.assert_equal(i['type_name'], 'classobj')
251 250
252 251 i = inspector.info(OldStyle())
253 252 nt.assert_equal(i['type_name'], 'instance')
254 253 nt.assert_equal(i['docstring'], OldStyle.__doc__)
255 254
256 255 def test_class_signature():
257 256 info = inspector.info(HasSignature, 'HasSignature')
258 257 nt.assert_equal(info['init_definition'], "HasSignature(test)")
259 258 nt.assert_equal(info['init_docstring'], HasSignature.__init__.__doc__)
260 259
261 260 def test_info_awkward():
262 261 # Just test that this doesn't throw an error.
263 262 inspector.info(Awkward())
264 263
265 264 def test_bool_raise():
266 265 inspector.info(NoBoolCall())
267 266
268 267 def test_info_serialliar():
269 268 fib_tracker = [0]
270 269 inspector.info(SerialLiar(fib_tracker))
271 270
272 271 # Nested attribute access should be cut off at 100 levels deep to avoid
273 272 # infinite loops: https://github.com/ipython/ipython/issues/9122
274 273 nt.assert_less(fib_tracker[0], 9000)
275 274
276 275 def test_calldef_none():
277 276 # We should ignore __call__ for all of these.
278 277 for obj in [f, SimpleClass().method, any, str.upper]:
279 278 print(obj)
280 279 i = inspector.info(obj)
281 280 nt.assert_is(i['call_def'], None)
282 281
283 282 def f_kwarg(pos, *, kwonly):
284 283 pass
285 284
286 285 def test_definition_kwonlyargs():
287 286 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
288 287 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)")
289 288
290 289 def test_getdoc():
291 290 class A(object):
292 291 """standard docstring"""
293 292 pass
294 293
295 294 class B(object):
296 295 """standard docstring"""
297 296 def getdoc(self):
298 297 return "custom docstring"
299 298
300 299 class C(object):
301 300 """standard docstring"""
302 301 def getdoc(self):
303 302 return None
304 303
305 304 a = A()
306 305 b = B()
307 306 c = C()
308 307
309 308 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
310 309 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
311 310 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
312 311
313 312
314 313 def test_empty_property_has_no_source():
315 314 i = inspector.info(property(), detail_level=1)
316 315 nt.assert_is(i['source'], None)
317 316
318 317
319 318 def test_property_sources():
320 319 import zlib
321 320
322 321 class A(object):
323 322 @property
324 323 def foo(self):
325 324 return 'bar'
326 325
327 326 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
328 327
329 328 id = property(id)
330 329 compress = property(zlib.compress)
331 330
332 331 i = inspector.info(A.foo, detail_level=1)
333 332 nt.assert_in('def foo(self):', i['source'])
334 333 nt.assert_in('lambda self, v:', i['source'])
335 334
336 335 i = inspector.info(A.id, detail_level=1)
337 336 nt.assert_in('fget = <function id>', i['source'])
338 337
339 338 i = inspector.info(A.compress, detail_level=1)
340 339 nt.assert_in('fget = <function zlib.compress>', i['source'])
341 340
342 341
343 342 def test_property_docstring_is_in_info_for_detail_level_0():
344 343 class A(object):
345 344 @property
346 345 def foobar(self):
347 346 """This is `foobar` property."""
348 347 pass
349 348
350 349 ip.user_ns['a_obj'] = A()
351 350 nt.assert_equal(
352 351 'This is `foobar` property.',
353 352 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
354 353
355 354 ip.user_ns['a_cls'] = A
356 355 nt.assert_equal(
357 356 'This is `foobar` property.',
358 357 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
359 358
360 359
361 360 def test_pdef():
362 361 # See gh-1914
363 362 def foo(): pass
364 363 inspector.pdef(foo, 'foo')
365 364
366 365
367 366 def test_pinfo_nonascii():
368 367 # See gh-1177
369 368 from . import nonascii2
370 369 ip.user_ns['nonascii2'] = nonascii2
371 370 ip._inspect('pinfo', 'nonascii2', detail_level=1)
372 371
373 372
374 373 def test_pinfo_docstring_no_source():
375 374 """Docstring should be included with detail_level=1 if there is no source"""
376 375 with AssertPrints('Docstring:'):
377 376 ip._inspect('pinfo', 'str.format', detail_level=0)
378 377 with AssertPrints('Docstring:'):
379 378 ip._inspect('pinfo', 'str.format', detail_level=1)
380 379
381 380
382 381 def test_pinfo_no_docstring_if_source():
383 382 """Docstring should not be included with detail_level=1 if source is found"""
384 383 def foo():
385 384 """foo has a docstring"""
386 385
387 386 ip.user_ns['foo'] = foo
388 387
389 388 with AssertPrints('Docstring:'):
390 389 ip._inspect('pinfo', 'foo', detail_level=0)
391 390 with AssertPrints('Source:'):
392 391 ip._inspect('pinfo', 'foo', detail_level=1)
393 392 with AssertNotPrints('Docstring:'):
394 393 ip._inspect('pinfo', 'foo', detail_level=1)
395 394
396 395
397 396 def test_pinfo_magic():
398 397 with AssertPrints('Docstring:'):
399 398 ip._inspect('pinfo', 'lsmagic', detail_level=0)
400 399
401 400 with AssertPrints('Source:'):
402 401 ip._inspect('pinfo', 'lsmagic', detail_level=1)
403 402
404 403
405 404 def test_init_colors():
406 405 # ensure colors are not present in signature info
407 406 info = inspector.info(HasSignature)
408 407 init_def = info['init_definition']
409 408 nt.assert_not_in('[0m', init_def)
410 409
411 410
412 411 def test_builtin_init():
413 412 info = inspector.info(list)
414 413 init_def = info['init_definition']
415 414 # Python < 3.4 can't get init definition from builtins,
416 415 # but still exercise the inspection in case of error-raising bugs.
417 416 if sys.version_info >= (3,4):
418 417 nt.assert_is_not_none(init_def)
419 418
General Comments 0
You need to be logged in to leave comments. Login now