##// END OF EJS Templates
Merge pull request #13098 from Carreau/less-nose-II...
Matthias Bussonnier -
r26735:8dddfe2f merge
parent child Browse files
Show More
@@ -1,447 +1,455 b''
1 """Tests for the object inspection functionality.
1 """Tests for the object inspection functionality.
2 """
2 """
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7
7
8 from inspect import signature, Signature, Parameter
8 from inspect import signature, Signature, Parameter
9 import os
9 import os
10 import re
10 import re
11
11
12 import nose.tools as nt
12 import nose.tools as nt
13
13
14 from .. import oinspect
14 from .. import oinspect
15
15
16 from decorator import decorator
16 from decorator import decorator
17
17
18 from IPython.testing.tools import AssertPrints, AssertNotPrints
18 from IPython.testing.tools import AssertPrints, AssertNotPrints
19 from IPython.utils.path import compress_user
19 from IPython.utils.path import compress_user
20
20
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Globals and constants
23 # Globals and constants
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 inspector = None
26 inspector = None
27
27
28 def setup_module():
28 def setup_module():
29 global inspector
29 global inspector
30 inspector = oinspect.Inspector()
30 inspector = oinspect.Inspector()
31
31
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Local utilities
34 # Local utilities
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36
36
37 # WARNING: since this test checks the line number where a function is
37 # WARNING: since this test checks the line number where a function is
38 # defined, if any code is inserted above, the following line will need to be
38 # defined, if any code is inserted above, the following line will need to be
39 # updated. Do NOT insert any whitespace between the next line and the function
39 # updated. Do NOT insert any whitespace between the next line and the function
40 # definition below.
40 # definition below.
41 THIS_LINE_NUMBER = 41 # Put here the actual number of this line
41 THIS_LINE_NUMBER = 41 # Put here the actual number of this line
42
42
43 from unittest import TestCase
43 from unittest import TestCase
44
44
45 class Test(TestCase):
45 class Test(TestCase):
46
46
47 def test_find_source_lines(self):
47 def test_find_source_lines(self):
48 self.assertEqual(oinspect.find_source_lines(Test.test_find_source_lines),
48 self.assertEqual(oinspect.find_source_lines(Test.test_find_source_lines),
49 THIS_LINE_NUMBER+6)
49 THIS_LINE_NUMBER+6)
50
50
51
51
52 # A couple of utilities to ensure these tests work the same from a source or a
52 # A couple of utilities to ensure these tests work the same from a source or a
53 # binary install
53 # binary install
54 def pyfile(fname):
54 def pyfile(fname):
55 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
55 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
56
56
57
57
58 def match_pyfiles(f1, f2):
58 def match_pyfiles(f1, f2):
59 nt.assert_equal(pyfile(f1), pyfile(f2))
59 assert pyfile(f1) == pyfile(f2)
60
60
61
61
62 def test_find_file():
62 def test_find_file():
63 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
63 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
64
64
65
65
66 def test_find_file_decorated1():
66 def test_find_file_decorated1():
67
67
68 @decorator
68 @decorator
69 def noop1(f):
69 def noop1(f):
70 def wrapper(*a, **kw):
70 def wrapper(*a, **kw):
71 return f(*a, **kw)
71 return f(*a, **kw)
72 return wrapper
72 return wrapper
73
73
74 @noop1
74 @noop1
75 def f(x):
75 def f(x):
76 "My docstring"
76 "My docstring"
77
77
78 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
78 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
79 nt.assert_equal(f.__doc__, "My docstring")
79 assert f.__doc__ == "My docstring"
80
80
81
81
82 def test_find_file_decorated2():
82 def test_find_file_decorated2():
83
83
84 @decorator
84 @decorator
85 def noop2(f, *a, **kw):
85 def noop2(f, *a, **kw):
86 return f(*a, **kw)
86 return f(*a, **kw)
87
87
88 @noop2
88 @noop2
89 @noop2
89 @noop2
90 @noop2
90 @noop2
91 def f(x):
91 def f(x):
92 "My docstring 2"
92 "My docstring 2"
93
93
94 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
94 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
95 nt.assert_equal(f.__doc__, "My docstring 2")
95 assert f.__doc__ == "My docstring 2"
96
96
97
97
98 def test_find_file_magic():
98 def test_find_file_magic():
99 run = ip.find_line_magic('run')
99 run = ip.find_line_magic('run')
100 nt.assert_not_equal(oinspect.find_file(run), None)
100 nt.assert_not_equal(oinspect.find_file(run), None)
101
101
102
102
103 # A few generic objects we can then inspect in the tests below
103 # A few generic objects we can then inspect in the tests below
104
104
105 class Call(object):
105 class Call(object):
106 """This is the class docstring."""
106 """This is the class docstring."""
107
107
108 def __init__(self, x, y=1):
108 def __init__(self, x, y=1):
109 """This is the constructor docstring."""
109 """This is the constructor docstring."""
110
110
111 def __call__(self, *a, **kw):
111 def __call__(self, *a, **kw):
112 """This is the call docstring."""
112 """This is the call docstring."""
113
113
114 def method(self, x, z=2):
114 def method(self, x, z=2):
115 """Some method's docstring"""
115 """Some method's docstring"""
116
116
117 class HasSignature(object):
117 class HasSignature(object):
118 """This is the class docstring."""
118 """This is the class docstring."""
119 __signature__ = Signature([Parameter('test', Parameter.POSITIONAL_OR_KEYWORD)])
119 __signature__ = Signature([Parameter('test', Parameter.POSITIONAL_OR_KEYWORD)])
120
120
121 def __init__(self, *args):
121 def __init__(self, *args):
122 """This is the init docstring"""
122 """This is the init docstring"""
123
123
124
124
125 class SimpleClass(object):
125 class SimpleClass(object):
126 def method(self, x, z=2):
126 def method(self, x, z=2):
127 """Some method's docstring"""
127 """Some method's docstring"""
128
128
129
129
130 class Awkward(object):
130 class Awkward(object):
131 def __getattr__(self, name):
131 def __getattr__(self, name):
132 raise Exception(name)
132 raise Exception(name)
133
133
134 class NoBoolCall:
134 class NoBoolCall:
135 """
135 """
136 callable with `__bool__` raising should still be inspect-able.
136 callable with `__bool__` raising should still be inspect-able.
137 """
137 """
138
138
139 def __call__(self):
139 def __call__(self):
140 """does nothing"""
140 """does nothing"""
141 pass
141 pass
142
142
143 def __bool__(self):
143 def __bool__(self):
144 """just raise NotImplemented"""
144 """just raise NotImplemented"""
145 raise NotImplementedError('Must be implemented')
145 raise NotImplementedError('Must be implemented')
146
146
147
147
148 class SerialLiar(object):
148 class SerialLiar(object):
149 """Attribute accesses always get another copy of the same class.
149 """Attribute accesses always get another copy of the same class.
150
150
151 unittest.mock.call does something similar, but it's not ideal for testing
151 unittest.mock.call does something similar, but it's not ideal for testing
152 as the failure mode is to eat all your RAM. This gives up after 10k levels.
152 as the failure mode is to eat all your RAM. This gives up after 10k levels.
153 """
153 """
154 def __init__(self, max_fibbing_twig, lies_told=0):
154 def __init__(self, max_fibbing_twig, lies_told=0):
155 if lies_told > 10000:
155 if lies_told > 10000:
156 raise RuntimeError('Nose too long, honesty is the best policy')
156 raise RuntimeError('Nose too long, honesty is the best policy')
157 self.max_fibbing_twig = max_fibbing_twig
157 self.max_fibbing_twig = max_fibbing_twig
158 self.lies_told = lies_told
158 self.lies_told = lies_told
159 max_fibbing_twig[0] = max(max_fibbing_twig[0], lies_told)
159 max_fibbing_twig[0] = max(max_fibbing_twig[0], lies_told)
160
160
161 def __getattr__(self, item):
161 def __getattr__(self, item):
162 return SerialLiar(self.max_fibbing_twig, self.lies_told + 1)
162 return SerialLiar(self.max_fibbing_twig, self.lies_told + 1)
163
163
164 #-----------------------------------------------------------------------------
164 #-----------------------------------------------------------------------------
165 # Tests
165 # Tests
166 #-----------------------------------------------------------------------------
166 #-----------------------------------------------------------------------------
167
167
168 def test_info():
168 def test_info():
169 "Check that Inspector.info fills out various fields as expected."
169 "Check that Inspector.info fills out various fields as expected."
170 i = inspector.info(Call, oname='Call')
170 i = inspector.info(Call, oname="Call")
171 nt.assert_equal(i['type_name'], 'type')
171 assert i["type_name"] == "type"
172 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
172 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
173 nt.assert_equal(i['base_class'], expted_class)
173 assert i["base_class"] == expted_class
174 nt.assert_regex(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>")
174 nt.assert_regex(
175 i["string_form"],
176 "<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>",
177 )
175 fname = __file__
178 fname = __file__
176 if fname.endswith(".pyc"):
179 if fname.endswith(".pyc"):
177 fname = fname[:-1]
180 fname = fname[:-1]
178 # case-insensitive comparison needed on some filesystems
181 # case-insensitive comparison needed on some filesystems
179 # e.g. Windows:
182 # e.g. Windows:
180 nt.assert_equal(i['file'].lower(), compress_user(fname).lower())
183 assert i["file"].lower() == compress_user(fname).lower()
181 nt.assert_equal(i['definition'], None)
184 assert i["definition"] == None
182 nt.assert_equal(i['docstring'], Call.__doc__)
185 assert i["docstring"] == Call.__doc__
183 nt.assert_equal(i['source'], None)
186 assert i["source"] == None
184 nt.assert_true(i['isclass'])
187 nt.assert_true(i["isclass"])
185 nt.assert_equal(i['init_definition'], "Call(x, y=1)")
188 assert i["init_definition"] == "Call(x, y=1)"
186 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
189 assert i["init_docstring"] == Call.__init__.__doc__
187
190
188 i = inspector.info(Call, detail_level=1)
191 i = inspector.info(Call, detail_level=1)
189 nt.assert_not_equal(i['source'], None)
192 nt.assert_not_equal(i["source"], None)
190 nt.assert_equal(i['docstring'], None)
193 assert i["docstring"] == None
191
194
192 c = Call(1)
195 c = Call(1)
193 c.__doc__ = "Modified instance docstring"
196 c.__doc__ = "Modified instance docstring"
194 i = inspector.info(c)
197 i = inspector.info(c)
195 nt.assert_equal(i['type_name'], 'Call')
198 assert i["type_name"] == "Call"
196 nt.assert_equal(i['docstring'], "Modified instance docstring")
199 assert i["docstring"] == "Modified instance docstring"
197 nt.assert_equal(i['class_docstring'], Call.__doc__)
200 assert i["class_docstring"] == Call.__doc__
198 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
201 assert i["init_docstring"] == Call.__init__.__doc__
199 nt.assert_equal(i['call_docstring'], Call.__call__.__doc__)
202 assert i["call_docstring"] == Call.__call__.__doc__
203
200
204
201 def test_class_signature():
205 def test_class_signature():
202 info = inspector.info(HasSignature, 'HasSignature')
206 info = inspector.info(HasSignature, "HasSignature")
203 nt.assert_equal(info['init_definition'], "HasSignature(test)")
207 assert info["init_definition"] == "HasSignature(test)"
204 nt.assert_equal(info['init_docstring'], HasSignature.__init__.__doc__)
208 assert info["init_docstring"] == HasSignature.__init__.__doc__
209
205
210
206 def test_info_awkward():
211 def test_info_awkward():
207 # Just test that this doesn't throw an error.
212 # Just test that this doesn't throw an error.
208 inspector.info(Awkward())
213 inspector.info(Awkward())
209
214
210 def test_bool_raise():
215 def test_bool_raise():
211 inspector.info(NoBoolCall())
216 inspector.info(NoBoolCall())
212
217
213 def test_info_serialliar():
218 def test_info_serialliar():
214 fib_tracker = [0]
219 fib_tracker = [0]
215 inspector.info(SerialLiar(fib_tracker))
220 inspector.info(SerialLiar(fib_tracker))
216
221
217 # Nested attribute access should be cut off at 100 levels deep to avoid
222 # Nested attribute access should be cut off at 100 levels deep to avoid
218 # infinite loops: https://github.com/ipython/ipython/issues/9122
223 # infinite loops: https://github.com/ipython/ipython/issues/9122
219 nt.assert_less(fib_tracker[0], 9000)
224 nt.assert_less(fib_tracker[0], 9000)
220
225
221 def support_function_one(x, y=2, *a, **kw):
226 def support_function_one(x, y=2, *a, **kw):
222 """A simple function."""
227 """A simple function."""
223
228
224 def test_calldef_none():
229 def test_calldef_none():
225 # We should ignore __call__ for all of these.
230 # We should ignore __call__ for all of these.
226 for obj in [support_function_one, SimpleClass().method, any, str.upper]:
231 for obj in [support_function_one, SimpleClass().method, any, str.upper]:
227 i = inspector.info(obj)
232 i = inspector.info(obj)
228 nt.assert_is(i['call_def'], None)
233 nt.assert_is(i['call_def'], None)
229
234
230 def f_kwarg(pos, *, kwonly):
235 def f_kwarg(pos, *, kwonly):
231 pass
236 pass
232
237
233 def test_definition_kwonlyargs():
238 def test_definition_kwonlyargs():
234 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
239 i = inspector.info(f_kwarg, oname="f_kwarg") # analysis:ignore
235 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)")
240 assert i["definition"] == "f_kwarg(pos, *, kwonly)"
241
236
242
237 def test_getdoc():
243 def test_getdoc():
238 class A(object):
244 class A(object):
239 """standard docstring"""
245 """standard docstring"""
240 pass
246 pass
241
247
242 class B(object):
248 class B(object):
243 """standard docstring"""
249 """standard docstring"""
244 def getdoc(self):
250 def getdoc(self):
245 return "custom docstring"
251 return "custom docstring"
246
252
247 class C(object):
253 class C(object):
248 """standard docstring"""
254 """standard docstring"""
249 def getdoc(self):
255 def getdoc(self):
250 return None
256 return None
251
257
252 a = A()
258 a = A()
253 b = B()
259 b = B()
254 c = C()
260 c = C()
255
261
256 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
262 assert oinspect.getdoc(a) == "standard docstring"
257 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
263 assert oinspect.getdoc(b) == "custom docstring"
258 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
264 assert oinspect.getdoc(c) == "standard docstring"
259
265
260
266
261 def test_empty_property_has_no_source():
267 def test_empty_property_has_no_source():
262 i = inspector.info(property(), detail_level=1)
268 i = inspector.info(property(), detail_level=1)
263 nt.assert_is(i['source'], None)
269 nt.assert_is(i['source'], None)
264
270
265
271
266 def test_property_sources():
272 def test_property_sources():
267 import posixpath
273 import posixpath
268 # A simple adder whose source and signature stays
274 # A simple adder whose source and signature stays
269 # the same across Python distributions
275 # the same across Python distributions
270 def simple_add(a, b):
276 def simple_add(a, b):
271 "Adds two numbers"
277 "Adds two numbers"
272 return a + b
278 return a + b
273
279
274 class A(object):
280 class A(object):
275 @property
281 @property
276 def foo(self):
282 def foo(self):
277 return 'bar'
283 return 'bar'
278
284
279 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
285 foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
280
286
281 dname = property(posixpath.dirname)
287 dname = property(posixpath.dirname)
282 adder = property(simple_add)
288 adder = property(simple_add)
283
289
284 i = inspector.info(A.foo, detail_level=1)
290 i = inspector.info(A.foo, detail_level=1)
285 nt.assert_in('def foo(self):', i['source'])
291 nt.assert_in('def foo(self):', i['source'])
286 nt.assert_in('lambda self, v:', i['source'])
292 nt.assert_in('lambda self, v:', i['source'])
287
293
288 i = inspector.info(A.dname, detail_level=1)
294 i = inspector.info(A.dname, detail_level=1)
289 nt.assert_in('def dirname(p)', i['source'])
295 nt.assert_in('def dirname(p)', i['source'])
290
296
291 i = inspector.info(A.adder, detail_level=1)
297 i = inspector.info(A.adder, detail_level=1)
292 nt.assert_in('def simple_add(a, b)', i['source'])
298 nt.assert_in('def simple_add(a, b)', i['source'])
293
299
294
300
295 def test_property_docstring_is_in_info_for_detail_level_0():
301 def test_property_docstring_is_in_info_for_detail_level_0():
296 class A(object):
302 class A(object):
297 @property
303 @property
298 def foobar(self):
304 def foobar(self):
299 """This is `foobar` property."""
305 """This is `foobar` property."""
300 pass
306 pass
301
307
302 ip.user_ns['a_obj'] = A()
308 ip.user_ns["a_obj"] = A()
303 nt.assert_equal(
309 assert (
304 'This is `foobar` property.',
310 "This is `foobar` property."
305 ip.object_inspect('a_obj.foobar', detail_level=0)['docstring'])
311 == ip.object_inspect("a_obj.foobar", detail_level=0)["docstring"]
312 )
306
313
307 ip.user_ns['a_cls'] = A
314 ip.user_ns["a_cls"] = A
308 nt.assert_equal(
315 assert (
309 'This is `foobar` property.',
316 "This is `foobar` property."
310 ip.object_inspect('a_cls.foobar', detail_level=0)['docstring'])
317 == ip.object_inspect("a_cls.foobar", detail_level=0)["docstring"]
318 )
311
319
312
320
313 def test_pdef():
321 def test_pdef():
314 # See gh-1914
322 # See gh-1914
315 def foo(): pass
323 def foo(): pass
316 inspector.pdef(foo, 'foo')
324 inspector.pdef(foo, 'foo')
317
325
318
326
319 def test_pinfo_nonascii():
327 def test_pinfo_nonascii():
320 # See gh-1177
328 # See gh-1177
321 from . import nonascii2
329 from . import nonascii2
322 ip.user_ns['nonascii2'] = nonascii2
330 ip.user_ns['nonascii2'] = nonascii2
323 ip._inspect('pinfo', 'nonascii2', detail_level=1)
331 ip._inspect('pinfo', 'nonascii2', detail_level=1)
324
332
325 def test_pinfo_type():
333 def test_pinfo_type():
326 """
334 """
327 type can fail in various edge case, for example `type.__subclass__()`
335 type can fail in various edge case, for example `type.__subclass__()`
328 """
336 """
329 ip._inspect('pinfo', 'type')
337 ip._inspect('pinfo', 'type')
330
338
331
339
332 def test_pinfo_docstring_no_source():
340 def test_pinfo_docstring_no_source():
333 """Docstring should be included with detail_level=1 if there is no source"""
341 """Docstring should be included with detail_level=1 if there is no source"""
334 with AssertPrints('Docstring:'):
342 with AssertPrints('Docstring:'):
335 ip._inspect('pinfo', 'str.format', detail_level=0)
343 ip._inspect('pinfo', 'str.format', detail_level=0)
336 with AssertPrints('Docstring:'):
344 with AssertPrints('Docstring:'):
337 ip._inspect('pinfo', 'str.format', detail_level=1)
345 ip._inspect('pinfo', 'str.format', detail_level=1)
338
346
339
347
340 def test_pinfo_no_docstring_if_source():
348 def test_pinfo_no_docstring_if_source():
341 """Docstring should not be included with detail_level=1 if source is found"""
349 """Docstring should not be included with detail_level=1 if source is found"""
342 def foo():
350 def foo():
343 """foo has a docstring"""
351 """foo has a docstring"""
344
352
345 ip.user_ns['foo'] = foo
353 ip.user_ns['foo'] = foo
346
354
347 with AssertPrints('Docstring:'):
355 with AssertPrints('Docstring:'):
348 ip._inspect('pinfo', 'foo', detail_level=0)
356 ip._inspect('pinfo', 'foo', detail_level=0)
349 with AssertPrints('Source:'):
357 with AssertPrints('Source:'):
350 ip._inspect('pinfo', 'foo', detail_level=1)
358 ip._inspect('pinfo', 'foo', detail_level=1)
351 with AssertNotPrints('Docstring:'):
359 with AssertNotPrints('Docstring:'):
352 ip._inspect('pinfo', 'foo', detail_level=1)
360 ip._inspect('pinfo', 'foo', detail_level=1)
353
361
354
362
355 def test_pinfo_docstring_if_detail_and_no_source():
363 def test_pinfo_docstring_if_detail_and_no_source():
356 """ Docstring should be displayed if source info not available """
364 """ Docstring should be displayed if source info not available """
357 obj_def = '''class Foo(object):
365 obj_def = '''class Foo(object):
358 """ This is a docstring for Foo """
366 """ This is a docstring for Foo """
359 def bar(self):
367 def bar(self):
360 """ This is a docstring for Foo.bar """
368 """ This is a docstring for Foo.bar """
361 pass
369 pass
362 '''
370 '''
363
371
364 ip.run_cell(obj_def)
372 ip.run_cell(obj_def)
365 ip.run_cell('foo = Foo()')
373 ip.run_cell('foo = Foo()')
366
374
367 with AssertNotPrints("Source:"):
375 with AssertNotPrints("Source:"):
368 with AssertPrints('Docstring:'):
376 with AssertPrints('Docstring:'):
369 ip._inspect('pinfo', 'foo', detail_level=0)
377 ip._inspect('pinfo', 'foo', detail_level=0)
370 with AssertPrints('Docstring:'):
378 with AssertPrints('Docstring:'):
371 ip._inspect('pinfo', 'foo', detail_level=1)
379 ip._inspect('pinfo', 'foo', detail_level=1)
372 with AssertPrints('Docstring:'):
380 with AssertPrints('Docstring:'):
373 ip._inspect('pinfo', 'foo.bar', detail_level=0)
381 ip._inspect('pinfo', 'foo.bar', detail_level=0)
374
382
375 with AssertNotPrints('Docstring:'):
383 with AssertNotPrints('Docstring:'):
376 with AssertPrints('Source:'):
384 with AssertPrints('Source:'):
377 ip._inspect('pinfo', 'foo.bar', detail_level=1)
385 ip._inspect('pinfo', 'foo.bar', detail_level=1)
378
386
379
387
380 def test_pinfo_magic():
388 def test_pinfo_magic():
381 with AssertPrints('Docstring:'):
389 with AssertPrints('Docstring:'):
382 ip._inspect('pinfo', 'lsmagic', detail_level=0)
390 ip._inspect('pinfo', 'lsmagic', detail_level=0)
383
391
384 with AssertPrints('Source:'):
392 with AssertPrints('Source:'):
385 ip._inspect('pinfo', 'lsmagic', detail_level=1)
393 ip._inspect('pinfo', 'lsmagic', detail_level=1)
386
394
387
395
388 def test_init_colors():
396 def test_init_colors():
389 # ensure colors are not present in signature info
397 # ensure colors are not present in signature info
390 info = inspector.info(HasSignature)
398 info = inspector.info(HasSignature)
391 init_def = info['init_definition']
399 init_def = info['init_definition']
392 nt.assert_not_in('[0m', init_def)
400 nt.assert_not_in('[0m', init_def)
393
401
394
402
395 def test_builtin_init():
403 def test_builtin_init():
396 info = inspector.info(list)
404 info = inspector.info(list)
397 init_def = info['init_definition']
405 init_def = info['init_definition']
398 nt.assert_is_not_none(init_def)
406 nt.assert_is_not_none(init_def)
399
407
400
408
401 def test_render_signature_short():
409 def test_render_signature_short():
402 def short_fun(a=1): pass
410 def short_fun(a=1): pass
403 sig = oinspect._render_signature(
411 sig = oinspect._render_signature(
404 signature(short_fun),
412 signature(short_fun),
405 short_fun.__name__,
413 short_fun.__name__,
406 )
414 )
407 nt.assert_equal(sig, 'short_fun(a=1)')
415 assert sig == "short_fun(a=1)"
408
416
409
417
410 def test_render_signature_long():
418 def test_render_signature_long():
411 from typing import Optional
419 from typing import Optional
412
420
413 def long_function(
421 def long_function(
414 a_really_long_parameter: int,
422 a_really_long_parameter: int,
415 and_another_long_one: bool = False,
423 and_another_long_one: bool = False,
416 let_us_make_sure_this_is_looong: Optional[str] = None,
424 let_us_make_sure_this_is_looong: Optional[str] = None,
417 ) -> bool: pass
425 ) -> bool: pass
418
426
419 sig = oinspect._render_signature(
427 sig = oinspect._render_signature(
420 signature(long_function),
428 signature(long_function),
421 long_function.__name__,
429 long_function.__name__,
422 )
430 )
423 nt.assert_in(sig, [
431 nt.assert_in(sig, [
424 # Python >=3.9
432 # Python >=3.9
425 '''\
433 '''\
426 long_function(
434 long_function(
427 a_really_long_parameter: int,
435 a_really_long_parameter: int,
428 and_another_long_one: bool = False,
436 and_another_long_one: bool = False,
429 let_us_make_sure_this_is_looong: Optional[str] = None,
437 let_us_make_sure_this_is_looong: Optional[str] = None,
430 ) -> bool\
438 ) -> bool\
431 ''',
439 ''',
432 # Python >=3.7
440 # Python >=3.7
433 '''\
441 '''\
434 long_function(
442 long_function(
435 a_really_long_parameter: int,
443 a_really_long_parameter: int,
436 and_another_long_one: bool = False,
444 and_another_long_one: bool = False,
437 let_us_make_sure_this_is_looong: Union[str, NoneType] = None,
445 let_us_make_sure_this_is_looong: Union[str, NoneType] = None,
438 ) -> bool\
446 ) -> bool\
439 ''', # Python <=3.6
447 ''', # Python <=3.6
440 '''\
448 '''\
441 long_function(
449 long_function(
442 a_really_long_parameter:int,
450 a_really_long_parameter:int,
443 and_another_long_one:bool=False,
451 and_another_long_one:bool=False,
444 let_us_make_sure_this_is_looong:Union[str, NoneType]=None,
452 let_us_make_sure_this_is_looong:Union[str, NoneType]=None,
445 ) -> bool\
453 ) -> bool\
446 ''',
454 ''',
447 ])
455 ])
@@ -1,88 +1,85 b''
1 """Tests for pylab tools module.
1 """Tests for pylab tools module.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2011, the IPython Development Team.
4 # Copyright (c) 2011, the IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified 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
14
15 # Stdlib imports
15 # Stdlib imports
16 import time
16 import time
17
17
18 # Third-party imports
19 import nose.tools as nt
20
21 # Our own imports
18 # Our own imports
22 from IPython.lib import backgroundjobs as bg
19 from IPython.lib import backgroundjobs as bg
23
20
24 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
25 # Globals and constants
22 # Globals and constants
26 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
27 t_short = 0.0001 # very short interval to wait on jobs
24 t_short = 0.0001 # very short interval to wait on jobs
28
25
29 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
30 # Local utilities
27 # Local utilities
31 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
32 def sleeper(interval=t_short, *a, **kw):
29 def sleeper(interval=t_short, *a, **kw):
33 args = dict(interval=interval,
30 args = dict(interval=interval,
34 other_args=a,
31 other_args=a,
35 kw_args=kw)
32 kw_args=kw)
36 time.sleep(interval)
33 time.sleep(interval)
37 return args
34 return args
38
35
39 def crasher(interval=t_short, *a, **kw):
36 def crasher(interval=t_short, *a, **kw):
40 time.sleep(interval)
37 time.sleep(interval)
41 raise Exception("Dead job with interval %s" % interval)
38 raise Exception("Dead job with interval %s" % interval)
42
39
43 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
44 # Classes and functions
41 # Classes and functions
45 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
46
43
47 def test_result():
44 def test_result():
48 """Test job submission and result retrieval"""
45 """Test job submission and result retrieval"""
49 jobs = bg.BackgroundJobManager()
46 jobs = bg.BackgroundJobManager()
50 j = jobs.new(sleeper)
47 j = jobs.new(sleeper)
51 j.join()
48 j.join()
52 nt.assert_equal(j.result['interval'], t_short)
49 assert j.result["interval"] == t_short
53
50
54
51
55 def test_flush():
52 def test_flush():
56 """Test job control"""
53 """Test job control"""
57 jobs = bg.BackgroundJobManager()
54 jobs = bg.BackgroundJobManager()
58 j = jobs.new(sleeper)
55 j = jobs.new(sleeper)
59 j.join()
56 j.join()
60 nt.assert_equal(len(jobs.completed), 1)
57 assert len(jobs.completed) == 1
61 nt.assert_equal(len(jobs.dead), 0)
58 assert len(jobs.dead) == 0
62 jobs.flush()
59 jobs.flush()
63 nt.assert_equal(len(jobs.completed), 0)
60 assert len(jobs.completed) == 0
64
61
65
62
66 def test_dead():
63 def test_dead():
67 """Test control of dead jobs"""
64 """Test control of dead jobs"""
68 jobs = bg.BackgroundJobManager()
65 jobs = bg.BackgroundJobManager()
69 j = jobs.new(crasher)
66 j = jobs.new(crasher)
70 j.join()
67 j.join()
71 nt.assert_equal(len(jobs.completed), 0)
68 assert len(jobs.completed) == 0
72 nt.assert_equal(len(jobs.dead), 1)
69 assert len(jobs.dead) == 1
73 jobs.flush()
70 jobs.flush()
74 nt.assert_equal(len(jobs.dead), 0)
71 assert len(jobs.dead) == 0
75
72
76
73
77 def test_longer():
74 def test_longer():
78 """Test control of longer-running jobs"""
75 """Test control of longer-running jobs"""
79 jobs = bg.BackgroundJobManager()
76 jobs = bg.BackgroundJobManager()
80 # Sleep for long enough for the following two checks to still report the
77 # Sleep for long enough for the following two checks to still report the
81 # job as running, but not so long that it makes the test suite noticeably
78 # job as running, but not so long that it makes the test suite noticeably
82 # slower.
79 # slower.
83 j = jobs.new(sleeper, 0.1)
80 j = jobs.new(sleeper, 0.1)
84 nt.assert_equal(len(jobs.running), 1)
81 assert len(jobs.running) == 1
85 nt.assert_equal(len(jobs.completed), 0)
82 assert len(jobs.completed) == 0
86 j.join()
83 j.join()
87 nt.assert_equal(len(jobs.running), 0)
84 assert len(jobs.running) == 0
88 nt.assert_equal(len(jobs.completed), 1)
85 assert len(jobs.completed) == 1
@@ -1,266 +1,272 b''
1 """Tests for IPython.lib.display.
1 """Tests for IPython.lib.display.
2
2
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2012, the IPython Development Team.
5 # Copyright (c) 2012, the IPython Development Team.
6 #
6 #
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8 #
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 from tempfile import NamedTemporaryFile, mkdtemp
15 from tempfile import NamedTemporaryFile, mkdtemp
16 from os.path import split, join as pjoin, dirname
16 from os.path import split, join as pjoin, dirname
17 import pathlib
17 import pathlib
18 from unittest import TestCase, mock
18 from unittest import TestCase, mock
19 import struct
19 import struct
20 import wave
20 import wave
21 from io import BytesIO
21 from io import BytesIO
22
22
23 # Third-party imports
23 # Third-party imports
24 import nose.tools as nt
24 import nose.tools as nt
25
25
26 try:
26 try:
27 import numpy
27 import numpy
28 except ImportError:
28 except ImportError:
29 pass
29 pass
30
30
31 # Our own imports
31 # Our own imports
32 from IPython.lib import display
32 from IPython.lib import display
33
33
34 from IPython.testing.decorators import skipif_not_numpy
34 from IPython.testing.decorators import skipif_not_numpy
35
35
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37 # Classes and functions
37 # Classes and functions
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39
39
40 #--------------------------
40 #--------------------------
41 # FileLink tests
41 # FileLink tests
42 #--------------------------
42 #--------------------------
43
43
44 def test_instantiation_FileLink():
44 def test_instantiation_FileLink():
45 """FileLink: Test class can be instantiated"""
45 """FileLink: Test class can be instantiated"""
46 fl = display.FileLink('example.txt')
46 fl = display.FileLink('example.txt')
47 # TODO: remove if when only Python >= 3.6 is supported
47 # TODO: remove if when only Python >= 3.6 is supported
48 fl = display.FileLink(pathlib.PurePath('example.txt'))
48 fl = display.FileLink(pathlib.PurePath('example.txt'))
49
49
50 def test_warning_on_non_existent_path_FileLink():
50 def test_warning_on_non_existent_path_FileLink():
51 """FileLink: Calling _repr_html_ on non-existent files returns a warning
51 """FileLink: Calling _repr_html_ on non-existent files returns a warning
52 """
52 """
53 fl = display.FileLink('example.txt')
53 fl = display.FileLink('example.txt')
54 nt.assert_true(fl._repr_html_().startswith('Path (<tt>example.txt</tt>)'))
54 nt.assert_true(fl._repr_html_().startswith('Path (<tt>example.txt</tt>)'))
55
55
56 def test_existing_path_FileLink():
56 def test_existing_path_FileLink():
57 """FileLink: Calling _repr_html_ functions as expected on existing filepath
57 """FileLink: Calling _repr_html_ functions as expected on existing filepath
58 """
58 """
59 tf = NamedTemporaryFile()
59 tf = NamedTemporaryFile()
60 fl = display.FileLink(tf.name)
60 fl = display.FileLink(tf.name)
61 actual = fl._repr_html_()
61 actual = fl._repr_html_()
62 expected = "<a href='%s' target='_blank'>%s</a><br>" % (tf.name,tf.name)
62 expected = "<a href='%s' target='_blank'>%s</a><br>" % (tf.name, tf.name)
63 nt.assert_equal(actual,expected)
63 assert actual == expected
64
64
65
65 def test_existing_path_FileLink_repr():
66 def test_existing_path_FileLink_repr():
66 """FileLink: Calling repr() functions as expected on existing filepath
67 """FileLink: Calling repr() functions as expected on existing filepath
67 """
68 """
68 tf = NamedTemporaryFile()
69 tf = NamedTemporaryFile()
69 fl = display.FileLink(tf.name)
70 fl = display.FileLink(tf.name)
70 actual = repr(fl)
71 actual = repr(fl)
71 expected = tf.name
72 expected = tf.name
72 nt.assert_equal(actual,expected)
73 assert actual == expected
74
73
75
74 def test_error_on_directory_to_FileLink():
76 def test_error_on_directory_to_FileLink():
75 """FileLink: Raises error when passed directory
77 """FileLink: Raises error when passed directory
76 """
78 """
77 td = mkdtemp()
79 td = mkdtemp()
78 nt.assert_raises(ValueError,display.FileLink,td)
80 nt.assert_raises(ValueError,display.FileLink,td)
79
81
80 #--------------------------
82 #--------------------------
81 # FileLinks tests
83 # FileLinks tests
82 #--------------------------
84 #--------------------------
83
85
84 def test_instantiation_FileLinks():
86 def test_instantiation_FileLinks():
85 """FileLinks: Test class can be instantiated
87 """FileLinks: Test class can be instantiated
86 """
88 """
87 fls = display.FileLinks('example')
89 fls = display.FileLinks('example')
88
90
89 def test_warning_on_non_existent_path_FileLinks():
91 def test_warning_on_non_existent_path_FileLinks():
90 """FileLinks: Calling _repr_html_ on non-existent files returns a warning
92 """FileLinks: Calling _repr_html_ on non-existent files returns a warning
91 """
93 """
92 fls = display.FileLinks('example')
94 fls = display.FileLinks('example')
93 nt.assert_true(fls._repr_html_().startswith('Path (<tt>example</tt>)'))
95 nt.assert_true(fls._repr_html_().startswith('Path (<tt>example</tt>)'))
94
96
95 def test_existing_path_FileLinks():
97 def test_existing_path_FileLinks():
96 """FileLinks: Calling _repr_html_ functions as expected on existing dir
98 """FileLinks: Calling _repr_html_ functions as expected on existing dir
97 """
99 """
98 td = mkdtemp()
100 td = mkdtemp()
99 tf1 = NamedTemporaryFile(dir=td)
101 tf1 = NamedTemporaryFile(dir=td)
100 tf2 = NamedTemporaryFile(dir=td)
102 tf2 = NamedTemporaryFile(dir=td)
101 fl = display.FileLinks(td)
103 fl = display.FileLinks(td)
102 actual = fl._repr_html_()
104 actual = fl._repr_html_()
103 actual = actual.split('\n')
105 actual = actual.split('\n')
104 actual.sort()
106 actual.sort()
105 # the links should always have forward slashes, even on windows, so replace
107 # the links should always have forward slashes, even on windows, so replace
106 # backslashes with forward slashes here
108 # backslashes with forward slashes here
107 expected = ["%s/<br>" % td,
109 expected = ["%s/<br>" % td,
108 "&nbsp;&nbsp;<a href='%s' target='_blank'>%s</a><br>" %\
110 "&nbsp;&nbsp;<a href='%s' target='_blank'>%s</a><br>" %\
109 (tf2.name.replace("\\","/"),split(tf2.name)[1]),
111 (tf2.name.replace("\\","/"),split(tf2.name)[1]),
110 "&nbsp;&nbsp;<a href='%s' target='_blank'>%s</a><br>" %\
112 "&nbsp;&nbsp;<a href='%s' target='_blank'>%s</a><br>" %\
111 (tf1.name.replace("\\","/"),split(tf1.name)[1])]
113 (tf1.name.replace("\\","/"),split(tf1.name)[1])]
112 expected.sort()
114 expected.sort()
113 # We compare the sorted list of links here as that's more reliable
115 # We compare the sorted list of links here as that's more reliable
114 nt.assert_equal(actual,expected)
116 assert actual == expected
117
115
118
116 def test_existing_path_FileLinks_alt_formatter():
119 def test_existing_path_FileLinks_alt_formatter():
117 """FileLinks: Calling _repr_html_ functions as expected w/ an alt formatter
120 """FileLinks: Calling _repr_html_ functions as expected w/ an alt formatter
118 """
121 """
119 td = mkdtemp()
122 td = mkdtemp()
120 tf1 = NamedTemporaryFile(dir=td)
123 tf1 = NamedTemporaryFile(dir=td)
121 tf2 = NamedTemporaryFile(dir=td)
124 tf2 = NamedTemporaryFile(dir=td)
122 def fake_formatter(dirname,fnames,included_suffixes):
125 def fake_formatter(dirname,fnames,included_suffixes):
123 return ["hello","world"]
126 return ["hello","world"]
124 fl = display.FileLinks(td,notebook_display_formatter=fake_formatter)
127 fl = display.FileLinks(td,notebook_display_formatter=fake_formatter)
125 actual = fl._repr_html_()
128 actual = fl._repr_html_()
126 actual = actual.split('\n')
129 actual = actual.split('\n')
127 actual.sort()
130 actual.sort()
128 expected = ["hello","world"]
131 expected = ["hello","world"]
129 expected.sort()
132 expected.sort()
130 # We compare the sorted list of links here as that's more reliable
133 # We compare the sorted list of links here as that's more reliable
131 nt.assert_equal(actual,expected)
134 assert actual == expected
135
132
136
133 def test_existing_path_FileLinks_repr():
137 def test_existing_path_FileLinks_repr():
134 """FileLinks: Calling repr() functions as expected on existing directory """
138 """FileLinks: Calling repr() functions as expected on existing directory """
135 td = mkdtemp()
139 td = mkdtemp()
136 tf1 = NamedTemporaryFile(dir=td)
140 tf1 = NamedTemporaryFile(dir=td)
137 tf2 = NamedTemporaryFile(dir=td)
141 tf2 = NamedTemporaryFile(dir=td)
138 fl = display.FileLinks(td)
142 fl = display.FileLinks(td)
139 actual = repr(fl)
143 actual = repr(fl)
140 actual = actual.split('\n')
144 actual = actual.split('\n')
141 actual.sort()
145 actual.sort()
142 expected = ['%s/' % td, ' %s' % split(tf1.name)[1],' %s' % split(tf2.name)[1]]
146 expected = ['%s/' % td, ' %s' % split(tf1.name)[1],' %s' % split(tf2.name)[1]]
143 expected.sort()
147 expected.sort()
144 # We compare the sorted list of links here as that's more reliable
148 # We compare the sorted list of links here as that's more reliable
145 nt.assert_equal(actual,expected)
149 assert actual == expected
146
150
151
147 def test_existing_path_FileLinks_repr_alt_formatter():
152 def test_existing_path_FileLinks_repr_alt_formatter():
148 """FileLinks: Calling repr() functions as expected w/ alt formatter
153 """FileLinks: Calling repr() functions as expected w/ alt formatter
149 """
154 """
150 td = mkdtemp()
155 td = mkdtemp()
151 tf1 = NamedTemporaryFile(dir=td)
156 tf1 = NamedTemporaryFile(dir=td)
152 tf2 = NamedTemporaryFile(dir=td)
157 tf2 = NamedTemporaryFile(dir=td)
153 def fake_formatter(dirname,fnames,included_suffixes):
158 def fake_formatter(dirname,fnames,included_suffixes):
154 return ["hello","world"]
159 return ["hello","world"]
155 fl = display.FileLinks(td,terminal_display_formatter=fake_formatter)
160 fl = display.FileLinks(td,terminal_display_formatter=fake_formatter)
156 actual = repr(fl)
161 actual = repr(fl)
157 actual = actual.split('\n')
162 actual = actual.split('\n')
158 actual.sort()
163 actual.sort()
159 expected = ["hello","world"]
164 expected = ["hello","world"]
160 expected.sort()
165 expected.sort()
161 # We compare the sorted list of links here as that's more reliable
166 # We compare the sorted list of links here as that's more reliable
162 nt.assert_equal(actual,expected)
167 assert actual == expected
163
168
169
164 def test_error_on_file_to_FileLinks():
170 def test_error_on_file_to_FileLinks():
165 """FileLinks: Raises error when passed file
171 """FileLinks: Raises error when passed file
166 """
172 """
167 td = mkdtemp()
173 td = mkdtemp()
168 tf1 = NamedTemporaryFile(dir=td)
174 tf1 = NamedTemporaryFile(dir=td)
169 nt.assert_raises(ValueError,display.FileLinks,tf1.name)
175 nt.assert_raises(ValueError,display.FileLinks,tf1.name)
170
176
171 def test_recursive_FileLinks():
177 def test_recursive_FileLinks():
172 """FileLinks: Does not recurse when recursive=False
178 """FileLinks: Does not recurse when recursive=False
173 """
179 """
174 td = mkdtemp()
180 td = mkdtemp()
175 tf = NamedTemporaryFile(dir=td)
181 tf = NamedTemporaryFile(dir=td)
176 subtd = mkdtemp(dir=td)
182 subtd = mkdtemp(dir=td)
177 subtf = NamedTemporaryFile(dir=subtd)
183 subtf = NamedTemporaryFile(dir=subtd)
178 fl = display.FileLinks(td)
184 fl = display.FileLinks(td)
179 actual = str(fl)
185 actual = str(fl)
180 actual = actual.split('\n')
186 actual = actual.split('\n')
181 nt.assert_equal(len(actual), 4, actual)
187 assert len(actual) == 4, actual
182 fl = display.FileLinks(td, recursive=False)
188 fl = display.FileLinks(td, recursive=False)
183 actual = str(fl)
189 actual = str(fl)
184 actual = actual.split('\n')
190 actual = actual.split('\n')
185 nt.assert_equal(len(actual), 2, actual)
191 assert len(actual) == 2, actual
186
192
187 def test_audio_from_file():
193 def test_audio_from_file():
188 path = pjoin(dirname(__file__), 'test.wav')
194 path = pjoin(dirname(__file__), 'test.wav')
189 display.Audio(filename=path)
195 display.Audio(filename=path)
190
196
191 class TestAudioDataWithNumpy(TestCase):
197 class TestAudioDataWithNumpy(TestCase):
192
198
193 @skipif_not_numpy
199 @skipif_not_numpy
194 def test_audio_from_numpy_array(self):
200 def test_audio_from_numpy_array(self):
195 test_tone = get_test_tone()
201 test_tone = get_test_tone()
196 audio = display.Audio(test_tone, rate=44100)
202 audio = display.Audio(test_tone, rate=44100)
197 nt.assert_equal(len(read_wav(audio.data)), len(test_tone))
203 assert len(read_wav(audio.data)) == len(test_tone)
198
204
199 @skipif_not_numpy
205 @skipif_not_numpy
200 def test_audio_from_list(self):
206 def test_audio_from_list(self):
201 test_tone = get_test_tone()
207 test_tone = get_test_tone()
202 audio = display.Audio(list(test_tone), rate=44100)
208 audio = display.Audio(list(test_tone), rate=44100)
203 nt.assert_equal(len(read_wav(audio.data)), len(test_tone))
209 assert len(read_wav(audio.data)) == len(test_tone)
204
210
205 @skipif_not_numpy
211 @skipif_not_numpy
206 def test_audio_from_numpy_array_without_rate_raises(self):
212 def test_audio_from_numpy_array_without_rate_raises(self):
207 nt.assert_raises(ValueError, display.Audio, get_test_tone())
213 nt.assert_raises(ValueError, display.Audio, get_test_tone())
208
214
209 @skipif_not_numpy
215 @skipif_not_numpy
210 def test_audio_data_normalization(self):
216 def test_audio_data_normalization(self):
211 expected_max_value = numpy.iinfo(numpy.int16).max
217 expected_max_value = numpy.iinfo(numpy.int16).max
212 for scale in [1, 0.5, 2]:
218 for scale in [1, 0.5, 2]:
213 audio = display.Audio(get_test_tone(scale), rate=44100)
219 audio = display.Audio(get_test_tone(scale), rate=44100)
214 actual_max_value = numpy.max(numpy.abs(read_wav(audio.data)))
220 actual_max_value = numpy.max(numpy.abs(read_wav(audio.data)))
215 nt.assert_equal(actual_max_value, expected_max_value)
221 assert actual_max_value == expected_max_value
216
222
217 @skipif_not_numpy
223 @skipif_not_numpy
218 def test_audio_data_without_normalization(self):
224 def test_audio_data_without_normalization(self):
219 max_int16 = numpy.iinfo(numpy.int16).max
225 max_int16 = numpy.iinfo(numpy.int16).max
220 for scale in [1, 0.5, 0.2]:
226 for scale in [1, 0.5, 0.2]:
221 test_tone = get_test_tone(scale)
227 test_tone = get_test_tone(scale)
222 test_tone_max_abs = numpy.max(numpy.abs(test_tone))
228 test_tone_max_abs = numpy.max(numpy.abs(test_tone))
223 expected_max_value = int(max_int16 * test_tone_max_abs)
229 expected_max_value = int(max_int16 * test_tone_max_abs)
224 audio = display.Audio(test_tone, rate=44100, normalize=False)
230 audio = display.Audio(test_tone, rate=44100, normalize=False)
225 actual_max_value = numpy.max(numpy.abs(read_wav(audio.data)))
231 actual_max_value = numpy.max(numpy.abs(read_wav(audio.data)))
226 nt.assert_equal(actual_max_value, expected_max_value)
232 assert actual_max_value == expected_max_value
227
233
228 def test_audio_data_without_normalization_raises_for_invalid_data(self):
234 def test_audio_data_without_normalization_raises_for_invalid_data(self):
229 nt.assert_raises(
235 nt.assert_raises(
230 ValueError,
236 ValueError,
231 lambda: display.Audio([1.001], rate=44100, normalize=False))
237 lambda: display.Audio([1.001], rate=44100, normalize=False))
232 nt.assert_raises(
238 nt.assert_raises(
233 ValueError,
239 ValueError,
234 lambda: display.Audio([-1.001], rate=44100, normalize=False))
240 lambda: display.Audio([-1.001], rate=44100, normalize=False))
235
241
236 def simulate_numpy_not_installed():
242 def simulate_numpy_not_installed():
237 try:
243 try:
238 import numpy
244 import numpy
239 return mock.patch('numpy.array', mock.MagicMock(side_effect=ImportError))
245 return mock.patch('numpy.array', mock.MagicMock(side_effect=ImportError))
240 except ModuleNotFoundError:
246 except ModuleNotFoundError:
241 return lambda x:x
247 return lambda x:x
242
248
243 @simulate_numpy_not_installed()
249 @simulate_numpy_not_installed()
244 class TestAudioDataWithoutNumpy(TestAudioDataWithNumpy):
250 class TestAudioDataWithoutNumpy(TestAudioDataWithNumpy):
245 # All tests from `TestAudioDataWithNumpy` are inherited.
251 # All tests from `TestAudioDataWithNumpy` are inherited.
246
252
247 @skipif_not_numpy
253 @skipif_not_numpy
248 def test_audio_raises_for_nested_list(self):
254 def test_audio_raises_for_nested_list(self):
249 stereo_signal = [list(get_test_tone())] * 2
255 stereo_signal = [list(get_test_tone())] * 2
250 nt.assert_raises(
256 nt.assert_raises(
251 TypeError,
257 TypeError,
252 lambda: display.Audio(stereo_signal, rate=44100))
258 lambda: display.Audio(stereo_signal, rate=44100))
253
259
254 @skipif_not_numpy
260 @skipif_not_numpy
255 def get_test_tone(scale=1):
261 def get_test_tone(scale=1):
256 return numpy.sin(2 * numpy.pi * 440 * numpy.linspace(0, 1, 44100)) * scale
262 return numpy.sin(2 * numpy.pi * 440 * numpy.linspace(0, 1, 44100)) * scale
257
263
258 def read_wav(data):
264 def read_wav(data):
259 with wave.open(BytesIO(data)) as wave_file:
265 with wave.open(BytesIO(data)) as wave_file:
260 wave_data = wave_file.readframes(wave_file.getnframes())
266 wave_data = wave_file.readframes(wave_file.getnframes())
261 num_samples = wave_file.getnframes() * wave_file.getnchannels()
267 num_samples = wave_file.getnframes() * wave_file.getnchannels()
262 return struct.unpack('<%sh' % num_samples, wave_data)
268 return struct.unpack('<%sh' % num_samples, wave_data)
263
269
264 def test_code_from_file():
270 def test_code_from_file():
265 c = display.Code(filename=__file__)
271 c = display.Code(filename=__file__)
266 assert c._repr_html_().startswith('<style>')
272 assert c._repr_html_().startswith('<style>')
@@ -1,34 +1,32 b''
1 """Test installing editor hooks"""
1 """Test installing editor hooks"""
2 import sys
2 import sys
3 from unittest import mock
3 from unittest import mock
4
4
5 import nose.tools as nt
6
7 from IPython import get_ipython
5 from IPython import get_ipython
8 from IPython.lib import editorhooks
6 from IPython.lib import editorhooks
9
7
10 def test_install_editor():
8 def test_install_editor():
11 called = []
9 called = []
12 def fake_popen(*args, **kwargs):
10 def fake_popen(*args, **kwargs):
13 called.append({
11 called.append({
14 'args': args,
12 'args': args,
15 'kwargs': kwargs,
13 'kwargs': kwargs,
16 })
14 })
17 return mock.MagicMock(**{'wait.return_value': 0})
15 return mock.MagicMock(**{'wait.return_value': 0})
18 editorhooks.install_editor('foo -l {line} -f {filename}', wait=False)
16 editorhooks.install_editor('foo -l {line} -f {filename}', wait=False)
19
17
20 with mock.patch('subprocess.Popen', fake_popen):
18 with mock.patch('subprocess.Popen', fake_popen):
21 get_ipython().hooks.editor('the file', 64)
19 get_ipython().hooks.editor('the file', 64)
22
20
23 nt.assert_equal(len(called), 1)
21 assert len(called) == 1
24 args = called[0]['args']
22 args = called[0]["args"]
25 kwargs = called[0]['kwargs']
23 kwargs = called[0]["kwargs"]
26
24
27 nt.assert_equal(kwargs, {'shell': True})
25 assert kwargs == {"shell": True}
28
26
29 if sys.platform.startswith('win'):
27 if sys.platform.startswith("win"):
30 expected = ['foo', '-l', '64', '-f', 'the file']
28 expected = ["foo", "-l", "64", "-f", "the file"]
31 else:
29 else:
32 expected = "foo -l 64 -f 'the file'"
30 expected = "foo -l 64 -f 'the file'"
33 cmd = args[0]
31 cmd = args[0]
34 nt.assert_equal(cmd, expected)
32 assert cmd == expected
@@ -1,191 +1,191 b''
1 """Tests for IPython.utils.path.py"""
1 """Tests for IPython.utils.path.py"""
2 # Copyright (c) IPython Development Team.
2 # Copyright (c) IPython Development Team.
3 # Distributed under the terms of the Modified BSD License.
3 # Distributed under the terms of the Modified BSD License.
4
4
5 from contextlib import contextmanager
5 from contextlib import contextmanager
6 from unittest.mock import patch
6 from unittest.mock import patch
7
7
8 import nose.tools as nt
8 import nose.tools as nt
9 import pytest
9 import pytest
10
10
11 from IPython.lib import latextools
11 from IPython.lib import latextools
12 from IPython.testing.decorators import (
12 from IPython.testing.decorators import (
13 onlyif_cmds_exist,
13 onlyif_cmds_exist,
14 skipif_not_matplotlib,
14 skipif_not_matplotlib,
15 skip_iptest_but_not_pytest,
15 skip_iptest_but_not_pytest,
16 )
16 )
17 from IPython.utils.process import FindCmdError
17 from IPython.utils.process import FindCmdError
18
18
19
19
20 @pytest.mark.parametrize('command', ['latex', 'dvipng'])
20 @pytest.mark.parametrize('command', ['latex', 'dvipng'])
21 @skip_iptest_but_not_pytest
21 @skip_iptest_but_not_pytest
22 def test_check_latex_to_png_dvipng_fails_when_no_cmd(command):
22 def test_check_latex_to_png_dvipng_fails_when_no_cmd(command):
23 def mock_find_cmd(arg):
23 def mock_find_cmd(arg):
24 if arg == command:
24 if arg == command:
25 raise FindCmdError
25 raise FindCmdError
26
26
27 with patch.object(latextools, "find_cmd", mock_find_cmd):
27 with patch.object(latextools, "find_cmd", mock_find_cmd):
28 assert latextools.latex_to_png_dvipng("whatever", True) == None
28 assert latextools.latex_to_png_dvipng("whatever", True) is None
29
29
30
30
31 @contextmanager
31 @contextmanager
32 def no_op(*args, **kwargs):
32 def no_op(*args, **kwargs):
33 yield
33 yield
34
34
35
35
36 @skip_iptest_but_not_pytest
36 @skip_iptest_but_not_pytest
37 @onlyif_cmds_exist("latex", "dvipng")
37 @onlyif_cmds_exist("latex", "dvipng")
38 @pytest.mark.parametrize("s, wrap", [(u"$$x^2$$", False), (u"x^2", True)])
38 @pytest.mark.parametrize("s, wrap", [(u"$$x^2$$", False), (u"x^2", True)])
39 def test_latex_to_png_dvipng_runs(s, wrap):
39 def test_latex_to_png_dvipng_runs(s, wrap):
40 """
40 """
41 Test that latex_to_png_dvipng just runs without error.
41 Test that latex_to_png_dvipng just runs without error.
42 """
42 """
43 def mock_kpsewhich(filename):
43 def mock_kpsewhich(filename):
44 assert filename == "breqn.sty"
44 assert filename == "breqn.sty"
45 return None
45 return None
46
46
47 latextools.latex_to_png_dvipng(s, wrap)
47 latextools.latex_to_png_dvipng(s, wrap)
48
48
49 with patch_latextool(mock_kpsewhich):
49 with patch_latextool(mock_kpsewhich):
50 latextools.latex_to_png_dvipng(s, wrap)
50 latextools.latex_to_png_dvipng(s, wrap)
51
51
52
52
53 def mock_kpsewhich(filename):
53 def mock_kpsewhich(filename):
54 assert filename == "breqn.sty"
54 assert filename == "breqn.sty"
55 return None
55 return None
56
56
57 @contextmanager
57 @contextmanager
58 def patch_latextool(mock=mock_kpsewhich):
58 def patch_latextool(mock=mock_kpsewhich):
59 with patch.object(latextools, "kpsewhich", mock):
59 with patch.object(latextools, "kpsewhich", mock):
60 yield
60 yield
61
61
62 @pytest.mark.parametrize('context', [no_op, patch_latextool])
62 @pytest.mark.parametrize('context', [no_op, patch_latextool])
63 @pytest.mark.parametrize('s_wrap', [("$x^2$", False), ("x^2", True)])
63 @pytest.mark.parametrize('s_wrap', [("$x^2$", False), ("x^2", True)])
64 @skip_iptest_but_not_pytest
64 @skip_iptest_but_not_pytest
65 def test_latex_to_png_mpl_runs(s_wrap, context):
65 def test_latex_to_png_mpl_runs(s_wrap, context):
66 """
66 """
67 Test that latex_to_png_mpl just runs without error.
67 Test that latex_to_png_mpl just runs without error.
68 """
68 """
69 try:
69 try:
70 import matplotlib
70 import matplotlib
71 except ImportError:
71 except ImportError:
72 pytest.skip("This needs matplotlib to be available")
72 pytest.skip("This needs matplotlib to be available")
73 return
73 return
74 s, wrap = s_wrap
74 s, wrap = s_wrap
75 with context():
75 with context():
76 latextools.latex_to_png_mpl(s, wrap)
76 latextools.latex_to_png_mpl(s, wrap)
77
77
78 @skipif_not_matplotlib
78 @skipif_not_matplotlib
79 def test_latex_to_html():
79 def test_latex_to_html():
80 img = latextools.latex_to_html("$x^2$")
80 img = latextools.latex_to_html("$x^2$")
81 assert "data:image/png;base64,iVBOR" in img
81 assert "data:image/png;base64,iVBOR" in img
82
82
83
83
84 def test_genelatex_no_wrap():
84 def test_genelatex_no_wrap():
85 """
85 """
86 Test genelatex with wrap=False.
86 Test genelatex with wrap=False.
87 """
87 """
88 def mock_kpsewhich(filename):
88 def mock_kpsewhich(filename):
89 assert False, ("kpsewhich should not be called "
89 assert False, ("kpsewhich should not be called "
90 "(called with {0})".format(filename))
90 "(called with {0})".format(filename))
91
91
92 with patch_latextool(mock_kpsewhich):
92 with patch_latextool(mock_kpsewhich):
93 assert '\n'.join(latextools.genelatex("body text", False)) == r'''\documentclass{article}
93 assert '\n'.join(latextools.genelatex("body text", False)) == r'''\documentclass{article}
94 \usepackage{amsmath}
94 \usepackage{amsmath}
95 \usepackage{amsthm}
95 \usepackage{amsthm}
96 \usepackage{amssymb}
96 \usepackage{amssymb}
97 \usepackage{bm}
97 \usepackage{bm}
98 \pagestyle{empty}
98 \pagestyle{empty}
99 \begin{document}
99 \begin{document}
100 body text
100 body text
101 \end{document}'''
101 \end{document}'''
102
102
103
103
104 def test_genelatex_wrap_with_breqn():
104 def test_genelatex_wrap_with_breqn():
105 """
105 """
106 Test genelatex with wrap=True for the case breqn.sty is installed.
106 Test genelatex with wrap=True for the case breqn.sty is installed.
107 """
107 """
108 def mock_kpsewhich(filename):
108 def mock_kpsewhich(filename):
109 assert filename == "breqn.sty"
109 assert filename == "breqn.sty"
110 return "path/to/breqn.sty"
110 return "path/to/breqn.sty"
111
111
112 with patch_latextool(mock_kpsewhich):
112 with patch_latextool(mock_kpsewhich):
113 assert '\n'.join(latextools.genelatex("x^2", True)) == r'''\documentclass{article}
113 assert '\n'.join(latextools.genelatex("x^2", True)) == r'''\documentclass{article}
114 \usepackage{amsmath}
114 \usepackage{amsmath}
115 \usepackage{amsthm}
115 \usepackage{amsthm}
116 \usepackage{amssymb}
116 \usepackage{amssymb}
117 \usepackage{bm}
117 \usepackage{bm}
118 \usepackage{breqn}
118 \usepackage{breqn}
119 \pagestyle{empty}
119 \pagestyle{empty}
120 \begin{document}
120 \begin{document}
121 \begin{dmath*}
121 \begin{dmath*}
122 x^2
122 x^2
123 \end{dmath*}
123 \end{dmath*}
124 \end{document}'''
124 \end{document}'''
125
125
126
126
127 def test_genelatex_wrap_without_breqn():
127 def test_genelatex_wrap_without_breqn():
128 """
128 """
129 Test genelatex with wrap=True for the case breqn.sty is not installed.
129 Test genelatex with wrap=True for the case breqn.sty is not installed.
130 """
130 """
131 def mock_kpsewhich(filename):
131 def mock_kpsewhich(filename):
132 assert filename == "breqn.sty"
132 assert filename == "breqn.sty"
133 return None
133 return None
134
134
135 with patch_latextool(mock_kpsewhich):
135 with patch_latextool(mock_kpsewhich):
136 assert '\n'.join(latextools.genelatex("x^2", True)) == r'''\documentclass{article}
136 assert '\n'.join(latextools.genelatex("x^2", True)) == r'''\documentclass{article}
137 \usepackage{amsmath}
137 \usepackage{amsmath}
138 \usepackage{amsthm}
138 \usepackage{amsthm}
139 \usepackage{amssymb}
139 \usepackage{amssymb}
140 \usepackage{bm}
140 \usepackage{bm}
141 \pagestyle{empty}
141 \pagestyle{empty}
142 \begin{document}
142 \begin{document}
143 $$x^2$$
143 $$x^2$$
144 \end{document}'''
144 \end{document}'''
145
145
146
146
147 @skipif_not_matplotlib
147 @skipif_not_matplotlib
148 @onlyif_cmds_exist('latex', 'dvipng')
148 @onlyif_cmds_exist('latex', 'dvipng')
149 def test_latex_to_png_color():
149 def test_latex_to_png_color():
150 """
150 """
151 Test color settings for latex_to_png.
151 Test color settings for latex_to_png.
152 """
152 """
153 latex_string = "$x^2$"
153 latex_string = "$x^2$"
154 default_value = latextools.latex_to_png(latex_string, wrap=False)
154 default_value = latextools.latex_to_png(latex_string, wrap=False)
155 default_hexblack = latextools.latex_to_png(latex_string, wrap=False,
155 default_hexblack = latextools.latex_to_png(latex_string, wrap=False,
156 color='#000000')
156 color='#000000')
157 dvipng_default = latextools.latex_to_png_dvipng(latex_string, False)
157 dvipng_default = latextools.latex_to_png_dvipng(latex_string, False)
158 dvipng_black = latextools.latex_to_png_dvipng(latex_string, False, 'Black')
158 dvipng_black = latextools.latex_to_png_dvipng(latex_string, False, 'Black')
159 assert dvipng_default == dvipng_black
159 assert dvipng_default == dvipng_black
160 mpl_default = latextools.latex_to_png_mpl(latex_string, False)
160 mpl_default = latextools.latex_to_png_mpl(latex_string, False)
161 mpl_black = latextools.latex_to_png_mpl(latex_string, False, 'Black')
161 mpl_black = latextools.latex_to_png_mpl(latex_string, False, 'Black')
162 assert mpl_default == mpl_black
162 assert mpl_default == mpl_black
163 assert default_value in [dvipng_black, mpl_black]
163 assert default_value in [dvipng_black, mpl_black]
164 assert default_hexblack in [dvipng_black, mpl_black]
164 assert default_hexblack in [dvipng_black, mpl_black]
165
165
166 # Test that dvips name colors can be used without error
166 # Test that dvips name colors can be used without error
167 dvipng_maroon = latextools.latex_to_png_dvipng(latex_string, False,
167 dvipng_maroon = latextools.latex_to_png_dvipng(latex_string, False,
168 'Maroon')
168 'Maroon')
169 # And that it doesn't return the black one
169 # And that it doesn't return the black one
170 assert dvipng_black != dvipng_maroon
170 assert dvipng_black != dvipng_maroon
171
171
172 mpl_maroon = latextools.latex_to_png_mpl(latex_string, False, 'Maroon')
172 mpl_maroon = latextools.latex_to_png_mpl(latex_string, False, 'Maroon')
173 assert mpl_black != mpl_maroon
173 assert mpl_black != mpl_maroon
174 mpl_white = latextools.latex_to_png_mpl(latex_string, False, 'White')
174 mpl_white = latextools.latex_to_png_mpl(latex_string, False, 'White')
175 mpl_hexwhite = latextools.latex_to_png_mpl(latex_string, False, '#FFFFFF')
175 mpl_hexwhite = latextools.latex_to_png_mpl(latex_string, False, '#FFFFFF')
176 assert mpl_white == mpl_hexwhite
176 assert mpl_white == mpl_hexwhite
177
177
178 mpl_white_scale = latextools.latex_to_png_mpl(latex_string, False,
178 mpl_white_scale = latextools.latex_to_png_mpl(latex_string, False,
179 'White', 1.2)
179 'White', 1.2)
180 assert mpl_white != mpl_white_scale
180 assert mpl_white != mpl_white_scale
181
181
182
182
183 def test_latex_to_png_invalid_hex_colors():
183 def test_latex_to_png_invalid_hex_colors():
184 """
184 """
185 Test that invalid hex colors provided to dvipng gives an exception.
185 Test that invalid hex colors provided to dvipng gives an exception.
186 """
186 """
187 latex_string = "$x^2$"
187 latex_string = "$x^2$"
188 nt.assert_raises(ValueError, lambda: latextools.latex_to_png(latex_string,
188 nt.assert_raises(ValueError, lambda: latextools.latex_to_png(latex_string,
189 backend='dvipng', color="#f00bar"))
189 backend='dvipng', color="#f00bar"))
190 nt.assert_raises(ValueError, lambda: latextools.latex_to_png(latex_string,
190 nt.assert_raises(ValueError, lambda: latextools.latex_to_png(latex_string,
191 backend='dvipng', color="#f00"))
191 backend='dvipng', color="#f00"))
@@ -1,492 +1,502 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for IPython.lib.pretty."""
2 """Tests for IPython.lib.pretty."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7
7
8 from collections import Counter, defaultdict, deque, OrderedDict
8 from collections import Counter, defaultdict, deque, OrderedDict
9 import os
9 import os
10 import types
10 import types
11 import string
11 import string
12 import unittest
12 import unittest
13
13
14 import nose.tools as nt
14 import nose.tools as nt
15 import pytest
15 import pytest
16
16
17 from IPython.lib import pretty
17 from IPython.lib import pretty
18 from IPython.testing.decorators import skip_without, skip_iptest_but_not_pytest
18 from IPython.testing.decorators import skip_without, skip_iptest_but_not_pytest
19
19
20 from io import StringIO
20 from io import StringIO
21
21
22
22
23 class MyList(object):
23 class MyList(object):
24 def __init__(self, content):
24 def __init__(self, content):
25 self.content = content
25 self.content = content
26 def _repr_pretty_(self, p, cycle):
26 def _repr_pretty_(self, p, cycle):
27 if cycle:
27 if cycle:
28 p.text("MyList(...)")
28 p.text("MyList(...)")
29 else:
29 else:
30 with p.group(3, "MyList(", ")"):
30 with p.group(3, "MyList(", ")"):
31 for (i, child) in enumerate(self.content):
31 for (i, child) in enumerate(self.content):
32 if i:
32 if i:
33 p.text(",")
33 p.text(",")
34 p.breakable()
34 p.breakable()
35 else:
35 else:
36 p.breakable("")
36 p.breakable("")
37 p.pretty(child)
37 p.pretty(child)
38
38
39
39
40 class MyDict(dict):
40 class MyDict(dict):
41 def _repr_pretty_(self, p, cycle):
41 def _repr_pretty_(self, p, cycle):
42 p.text("MyDict(...)")
42 p.text("MyDict(...)")
43
43
44 class MyObj(object):
44 class MyObj(object):
45 def somemethod(self):
45 def somemethod(self):
46 pass
46 pass
47
47
48
48
49 class Dummy1(object):
49 class Dummy1(object):
50 def _repr_pretty_(self, p, cycle):
50 def _repr_pretty_(self, p, cycle):
51 p.text("Dummy1(...)")
51 p.text("Dummy1(...)")
52
52
53 class Dummy2(Dummy1):
53 class Dummy2(Dummy1):
54 _repr_pretty_ = None
54 _repr_pretty_ = None
55
55
56 class NoModule(object):
56 class NoModule(object):
57 pass
57 pass
58
58
59 NoModule.__module__ = None
59 NoModule.__module__ = None
60
60
61 class Breaking(object):
61 class Breaking(object):
62 def _repr_pretty_(self, p, cycle):
62 def _repr_pretty_(self, p, cycle):
63 with p.group(4,"TG: ",":"):
63 with p.group(4,"TG: ",":"):
64 p.text("Breaking(")
64 p.text("Breaking(")
65 p.break_()
65 p.break_()
66 p.text(")")
66 p.text(")")
67
67
68 class BreakingRepr(object):
68 class BreakingRepr(object):
69 def __repr__(self):
69 def __repr__(self):
70 return "Breaking(\n)"
70 return "Breaking(\n)"
71
71
72 class BadRepr(object):
72 class BadRepr(object):
73
73
74 def __repr__(self):
74 def __repr__(self):
75 return 1/0
75 return 1/0
76
76
77
77
78 def test_indentation():
78 def test_indentation():
79 """Test correct indentation in groups"""
79 """Test correct indentation in groups"""
80 count = 40
80 count = 40
81 gotoutput = pretty.pretty(MyList(range(count)))
81 gotoutput = pretty.pretty(MyList(range(count)))
82 expectedoutput = "MyList(\n" + ",\n".join(" %d" % i for i in range(count)) + ")"
82 expectedoutput = "MyList(\n" + ",\n".join(" %d" % i for i in range(count)) + ")"
83
83
84 nt.assert_equal(gotoutput, expectedoutput)
84 assert gotoutput == expectedoutput
85
85
86
86
87 def test_dispatch():
87 def test_dispatch():
88 """
88 """
89 Test correct dispatching: The _repr_pretty_ method for MyDict
89 Test correct dispatching: The _repr_pretty_ method for MyDict
90 must be found before the registered printer for dict.
90 must be found before the registered printer for dict.
91 """
91 """
92 gotoutput = pretty.pretty(MyDict())
92 gotoutput = pretty.pretty(MyDict())
93 expectedoutput = "MyDict(...)"
93 expectedoutput = "MyDict(...)"
94
94
95 nt.assert_equal(gotoutput, expectedoutput)
95 assert gotoutput == expectedoutput
96
96
97
97
98 def test_callability_checking():
98 def test_callability_checking():
99 """
99 """
100 Test that the _repr_pretty_ method is tested for callability and skipped if
100 Test that the _repr_pretty_ method is tested for callability and skipped if
101 not.
101 not.
102 """
102 """
103 gotoutput = pretty.pretty(Dummy2())
103 gotoutput = pretty.pretty(Dummy2())
104 expectedoutput = "Dummy1(...)"
104 expectedoutput = "Dummy1(...)"
105
105
106 nt.assert_equal(gotoutput, expectedoutput)
106 assert gotoutput == expectedoutput
107
107
108
108
109 @pytest.mark.parametrize(
109 @pytest.mark.parametrize(
110 "obj,expected_output",
110 "obj,expected_output",
111 zip(
111 zip(
112 [
112 [
113 set(),
113 set(),
114 frozenset(),
114 frozenset(),
115 set([1]),
115 set([1]),
116 frozenset([1]),
116 frozenset([1]),
117 set([1, 2]),
117 set([1, 2]),
118 frozenset([1, 2]),
118 frozenset([1, 2]),
119 set([-1, -2, -3]),
119 set([-1, -2, -3]),
120 ],
120 ],
121 [
121 [
122 "set()",
122 "set()",
123 "frozenset()",
123 "frozenset()",
124 "{1}",
124 "{1}",
125 "frozenset({1})",
125 "frozenset({1})",
126 "{1, 2}",
126 "{1, 2}",
127 "frozenset({1, 2})",
127 "frozenset({1, 2})",
128 "{-3, -2, -1}",
128 "{-3, -2, -1}",
129 ],
129 ],
130 ),
130 ),
131 )
131 )
132 @skip_iptest_but_not_pytest
132 @skip_iptest_but_not_pytest
133 def test_sets(obj, expected_output):
133 def test_sets(obj, expected_output):
134 """
134 """
135 Test that set and frozenset use Python 3 formatting.
135 Test that set and frozenset use Python 3 formatting.
136 """
136 """
137 got_output = pretty.pretty(obj)
137 got_output = pretty.pretty(obj)
138 nt.assert_equal(got_output, expected_output)
138 assert got_output == expected_output
139
139
140
140
141 @skip_without('xxlimited')
141 @skip_without('xxlimited')
142 def test_pprint_heap_allocated_type():
142 def test_pprint_heap_allocated_type():
143 """
143 """
144 Test that pprint works for heap allocated types.
144 Test that pprint works for heap allocated types.
145 """
145 """
146 import xxlimited
146 import xxlimited
147 output = pretty.pretty(xxlimited.Null)
147 output = pretty.pretty(xxlimited.Null)
148 nt.assert_equal(output, 'xxlimited.Null')
148 assert output == "xxlimited.Null"
149
149
150
150 def test_pprint_nomod():
151 def test_pprint_nomod():
151 """
152 """
152 Test that pprint works for classes with no __module__.
153 Test that pprint works for classes with no __module__.
153 """
154 """
154 output = pretty.pretty(NoModule)
155 output = pretty.pretty(NoModule)
155 nt.assert_equal(output, 'NoModule')
156 assert output == "NoModule"
156
157
158
157 def test_pprint_break():
159 def test_pprint_break():
158 """
160 """
159 Test that p.break_ produces expected output
161 Test that p.break_ produces expected output
160 """
162 """
161 output = pretty.pretty(Breaking())
163 output = pretty.pretty(Breaking())
162 expected = "TG: Breaking(\n ):"
164 expected = "TG: Breaking(\n ):"
163 nt.assert_equal(output, expected)
165 assert output == expected
164
166
165 def test_pprint_break_repr():
167 def test_pprint_break_repr():
166 """
168 """
167 Test that p.break_ is used in repr
169 Test that p.break_ is used in repr
168 """
170 """
169 output = pretty.pretty([[BreakingRepr()]])
171 output = pretty.pretty([[BreakingRepr()]])
170 expected = "[[Breaking(\n )]]"
172 expected = "[[Breaking(\n )]]"
171 nt.assert_equal(output, expected)
173 assert output == expected
172
174
173 output = pretty.pretty([[BreakingRepr()]*2])
175 output = pretty.pretty([[BreakingRepr()]*2])
174 expected = "[[Breaking(\n ),\n Breaking(\n )]]"
176 expected = "[[Breaking(\n ),\n Breaking(\n )]]"
175 nt.assert_equal(output, expected)
177 assert output == expected
176
178
177 def test_bad_repr():
179 def test_bad_repr():
178 """Don't catch bad repr errors"""
180 """Don't catch bad repr errors"""
179 with nt.assert_raises(ZeroDivisionError):
181 with nt.assert_raises(ZeroDivisionError):
180 pretty.pretty(BadRepr())
182 pretty.pretty(BadRepr())
181
183
182 class BadException(Exception):
184 class BadException(Exception):
183 def __str__(self):
185 def __str__(self):
184 return -1
186 return -1
185
187
186 class ReallyBadRepr(object):
188 class ReallyBadRepr(object):
187 __module__ = 1
189 __module__ = 1
188 @property
190 @property
189 def __class__(self):
191 def __class__(self):
190 raise ValueError("I am horrible")
192 raise ValueError("I am horrible")
191
193
192 def __repr__(self):
194 def __repr__(self):
193 raise BadException()
195 raise BadException()
194
196
195 def test_really_bad_repr():
197 def test_really_bad_repr():
196 with nt.assert_raises(BadException):
198 with nt.assert_raises(BadException):
197 pretty.pretty(ReallyBadRepr())
199 pretty.pretty(ReallyBadRepr())
198
200
199
201
200 class SA(object):
202 class SA(object):
201 pass
203 pass
202
204
203 class SB(SA):
205 class SB(SA):
204 pass
206 pass
205
207
206 class TestsPretty(unittest.TestCase):
208 class TestsPretty(unittest.TestCase):
207
209
208 def test_super_repr(self):
210 def test_super_repr(self):
209 # "<super: module_name.SA, None>"
211 # "<super: module_name.SA, None>"
210 output = pretty.pretty(super(SA))
212 output = pretty.pretty(super(SA))
211 self.assertRegex(output, r"<super: \S+.SA, None>")
213 self.assertRegex(output, r"<super: \S+.SA, None>")
212
214
213 # "<super: module_name.SA, <module_name.SB at 0x...>>"
215 # "<super: module_name.SA, <module_name.SB at 0x...>>"
214 sb = SB()
216 sb = SB()
215 output = pretty.pretty(super(SA, sb))
217 output = pretty.pretty(super(SA, sb))
216 self.assertRegex(output, r"<super: \S+.SA,\s+<\S+.SB at 0x\S+>>")
218 self.assertRegex(output, r"<super: \S+.SA,\s+<\S+.SB at 0x\S+>>")
217
219
218
220
219 def test_long_list(self):
221 def test_long_list(self):
220 lis = list(range(10000))
222 lis = list(range(10000))
221 p = pretty.pretty(lis)
223 p = pretty.pretty(lis)
222 last2 = p.rsplit('\n', 2)[-2:]
224 last2 = p.rsplit('\n', 2)[-2:]
223 self.assertEqual(last2, [' 999,', ' ...]'])
225 self.assertEqual(last2, [' 999,', ' ...]'])
224
226
225 def test_long_set(self):
227 def test_long_set(self):
226 s = set(range(10000))
228 s = set(range(10000))
227 p = pretty.pretty(s)
229 p = pretty.pretty(s)
228 last2 = p.rsplit('\n', 2)[-2:]
230 last2 = p.rsplit('\n', 2)[-2:]
229 self.assertEqual(last2, [' 999,', ' ...}'])
231 self.assertEqual(last2, [' 999,', ' ...}'])
230
232
231 def test_long_tuple(self):
233 def test_long_tuple(self):
232 tup = tuple(range(10000))
234 tup = tuple(range(10000))
233 p = pretty.pretty(tup)
235 p = pretty.pretty(tup)
234 last2 = p.rsplit('\n', 2)[-2:]
236 last2 = p.rsplit('\n', 2)[-2:]
235 self.assertEqual(last2, [' 999,', ' ...)'])
237 self.assertEqual(last2, [' 999,', ' ...)'])
236
238
237 def test_long_dict(self):
239 def test_long_dict(self):
238 d = { n:n for n in range(10000) }
240 d = { n:n for n in range(10000) }
239 p = pretty.pretty(d)
241 p = pretty.pretty(d)
240 last2 = p.rsplit('\n', 2)[-2:]
242 last2 = p.rsplit('\n', 2)[-2:]
241 self.assertEqual(last2, [' 999: 999,', ' ...}'])
243 self.assertEqual(last2, [' 999: 999,', ' ...}'])
242
244
243 def test_unbound_method(self):
245 def test_unbound_method(self):
244 output = pretty.pretty(MyObj.somemethod)
246 output = pretty.pretty(MyObj.somemethod)
245 self.assertIn('MyObj.somemethod', output)
247 self.assertIn('MyObj.somemethod', output)
246
248
247
249
248 class MetaClass(type):
250 class MetaClass(type):
249 def __new__(cls, name):
251 def __new__(cls, name):
250 return type.__new__(cls, name, (object,), {'name': name})
252 return type.__new__(cls, name, (object,), {'name': name})
251
253
252 def __repr__(self):
254 def __repr__(self):
253 return "[CUSTOM REPR FOR CLASS %s]" % self.name
255 return "[CUSTOM REPR FOR CLASS %s]" % self.name
254
256
255
257
256 ClassWithMeta = MetaClass('ClassWithMeta')
258 ClassWithMeta = MetaClass('ClassWithMeta')
257
259
258
260
259 def test_metaclass_repr():
261 def test_metaclass_repr():
260 output = pretty.pretty(ClassWithMeta)
262 output = pretty.pretty(ClassWithMeta)
261 nt.assert_equal(output, "[CUSTOM REPR FOR CLASS ClassWithMeta]")
263 assert output == "[CUSTOM REPR FOR CLASS ClassWithMeta]"
262
264
263
265
264 def test_unicode_repr():
266 def test_unicode_repr():
265 u = u"üniçodé"
267 u = u"üniçodé"
266 ustr = u
268 ustr = u
267
269
268 class C(object):
270 class C(object):
269 def __repr__(self):
271 def __repr__(self):
270 return ustr
272 return ustr
271
273
272 c = C()
274 c = C()
273 p = pretty.pretty(c)
275 p = pretty.pretty(c)
274 nt.assert_equal(p, u)
276 assert p == u
275 p = pretty.pretty([c])
277 p = pretty.pretty([c])
276 nt.assert_equal(p, u'[%s]' % u)
278 assert p == u"[%s]" % u
277
279
278
280
279 def test_basic_class():
281 def test_basic_class():
280 def type_pprint_wrapper(obj, p, cycle):
282 def type_pprint_wrapper(obj, p, cycle):
281 if obj is MyObj:
283 if obj is MyObj:
282 type_pprint_wrapper.called = True
284 type_pprint_wrapper.called = True
283 return pretty._type_pprint(obj, p, cycle)
285 return pretty._type_pprint(obj, p, cycle)
284 type_pprint_wrapper.called = False
286 type_pprint_wrapper.called = False
285
287
286 stream = StringIO()
288 stream = StringIO()
287 printer = pretty.RepresentationPrinter(stream)
289 printer = pretty.RepresentationPrinter(stream)
288 printer.type_pprinters[type] = type_pprint_wrapper
290 printer.type_pprinters[type] = type_pprint_wrapper
289 printer.pretty(MyObj)
291 printer.pretty(MyObj)
290 printer.flush()
292 printer.flush()
291 output = stream.getvalue()
293 output = stream.getvalue()
292
294
293 nt.assert_equal(output, '%s.MyObj' % __name__)
295 assert output == "%s.MyObj" % __name__
294 nt.assert_true(type_pprint_wrapper.called)
296 nt.assert_true(type_pprint_wrapper.called)
295
297
296
298
299 # TODO : pytest.mark.parametrise once nose is gone.
297 def test_collections_defaultdict():
300 def test_collections_defaultdict():
298 # Create defaultdicts with cycles
301 # Create defaultdicts with cycles
299 a = defaultdict()
302 a = defaultdict()
300 a.default_factory = a
303 a.default_factory = a
301 b = defaultdict(list)
304 b = defaultdict(list)
302 b['key'] = b
305 b['key'] = b
303
306
304 # Dictionary order cannot be relied on, test against single keys.
307 # Dictionary order cannot be relied on, test against single keys.
305 cases = [
308 cases = [
306 (defaultdict(list), 'defaultdict(list, {})'),
309 (defaultdict(list), 'defaultdict(list, {})'),
307 (defaultdict(list, {'key': '-' * 50}),
310 (defaultdict(list, {'key': '-' * 50}),
308 "defaultdict(list,\n"
311 "defaultdict(list,\n"
309 " {'key': '--------------------------------------------------'})"),
312 " {'key': '--------------------------------------------------'})"),
310 (a, 'defaultdict(defaultdict(...), {})'),
313 (a, 'defaultdict(defaultdict(...), {})'),
311 (b, "defaultdict(list, {'key': defaultdict(...)})"),
314 (b, "defaultdict(list, {'key': defaultdict(...)})"),
312 ]
315 ]
313 for obj, expected in cases:
316 for obj, expected in cases:
314 nt.assert_equal(pretty.pretty(obj), expected)
317 assert pretty.pretty(obj) == expected
315
318
316
319
320 # TODO : pytest.mark.parametrise once nose is gone.
317 def test_collections_ordereddict():
321 def test_collections_ordereddict():
318 # Create OrderedDict with cycle
322 # Create OrderedDict with cycle
319 a = OrderedDict()
323 a = OrderedDict()
320 a['key'] = a
324 a['key'] = a
321
325
322 cases = [
326 cases = [
323 (OrderedDict(), 'OrderedDict()'),
327 (OrderedDict(), 'OrderedDict()'),
324 (OrderedDict((i, i) for i in range(1000, 1010)),
328 (OrderedDict((i, i) for i in range(1000, 1010)),
325 'OrderedDict([(1000, 1000),\n'
329 'OrderedDict([(1000, 1000),\n'
326 ' (1001, 1001),\n'
330 ' (1001, 1001),\n'
327 ' (1002, 1002),\n'
331 ' (1002, 1002),\n'
328 ' (1003, 1003),\n'
332 ' (1003, 1003),\n'
329 ' (1004, 1004),\n'
333 ' (1004, 1004),\n'
330 ' (1005, 1005),\n'
334 ' (1005, 1005),\n'
331 ' (1006, 1006),\n'
335 ' (1006, 1006),\n'
332 ' (1007, 1007),\n'
336 ' (1007, 1007),\n'
333 ' (1008, 1008),\n'
337 ' (1008, 1008),\n'
334 ' (1009, 1009)])'),
338 ' (1009, 1009)])'),
335 (a, "OrderedDict([('key', OrderedDict(...))])"),
339 (a, "OrderedDict([('key', OrderedDict(...))])"),
336 ]
340 ]
337 for obj, expected in cases:
341 for obj, expected in cases:
338 nt.assert_equal(pretty.pretty(obj), expected)
342 assert pretty.pretty(obj) == expected
339
343
340
344
345 # TODO : pytest.mark.parametrise once nose is gone.
341 def test_collections_deque():
346 def test_collections_deque():
342 # Create deque with cycle
347 # Create deque with cycle
343 a = deque()
348 a = deque()
344 a.append(a)
349 a.append(a)
345
350
346 cases = [
351 cases = [
347 (deque(), 'deque([])'),
352 (deque(), 'deque([])'),
348 (deque(i for i in range(1000, 1020)),
353 (deque(i for i in range(1000, 1020)),
349 'deque([1000,\n'
354 'deque([1000,\n'
350 ' 1001,\n'
355 ' 1001,\n'
351 ' 1002,\n'
356 ' 1002,\n'
352 ' 1003,\n'
357 ' 1003,\n'
353 ' 1004,\n'
358 ' 1004,\n'
354 ' 1005,\n'
359 ' 1005,\n'
355 ' 1006,\n'
360 ' 1006,\n'
356 ' 1007,\n'
361 ' 1007,\n'
357 ' 1008,\n'
362 ' 1008,\n'
358 ' 1009,\n'
363 ' 1009,\n'
359 ' 1010,\n'
364 ' 1010,\n'
360 ' 1011,\n'
365 ' 1011,\n'
361 ' 1012,\n'
366 ' 1012,\n'
362 ' 1013,\n'
367 ' 1013,\n'
363 ' 1014,\n'
368 ' 1014,\n'
364 ' 1015,\n'
369 ' 1015,\n'
365 ' 1016,\n'
370 ' 1016,\n'
366 ' 1017,\n'
371 ' 1017,\n'
367 ' 1018,\n'
372 ' 1018,\n'
368 ' 1019])'),
373 ' 1019])'),
369 (a, 'deque([deque(...)])'),
374 (a, 'deque([deque(...)])'),
370 ]
375 ]
371 for obj, expected in cases:
376 for obj, expected in cases:
372 nt.assert_equal(pretty.pretty(obj), expected)
377 assert pretty.pretty(obj) == expected
373
378
379
380 # TODO : pytest.mark.parametrise once nose is gone.
374 def test_collections_counter():
381 def test_collections_counter():
375 class MyCounter(Counter):
382 class MyCounter(Counter):
376 pass
383 pass
377 cases = [
384 cases = [
378 (Counter(), 'Counter()'),
385 (Counter(), 'Counter()'),
379 (Counter(a=1), "Counter({'a': 1})"),
386 (Counter(a=1), "Counter({'a': 1})"),
380 (MyCounter(a=1), "MyCounter({'a': 1})"),
387 (MyCounter(a=1), "MyCounter({'a': 1})"),
381 ]
388 ]
382 for obj, expected in cases:
389 for obj, expected in cases:
383 nt.assert_equal(pretty.pretty(obj), expected)
390 assert pretty.pretty(obj) == expected
384
391
392 # TODO : pytest.mark.parametrise once nose is gone.
385 def test_mappingproxy():
393 def test_mappingproxy():
386 MP = types.MappingProxyType
394 MP = types.MappingProxyType
387 underlying_dict = {}
395 underlying_dict = {}
388 mp_recursive = MP(underlying_dict)
396 mp_recursive = MP(underlying_dict)
389 underlying_dict[2] = mp_recursive
397 underlying_dict[2] = mp_recursive
390 underlying_dict[3] = underlying_dict
398 underlying_dict[3] = underlying_dict
391
399
392 cases = [
400 cases = [
393 (MP({}), "mappingproxy({})"),
401 (MP({}), "mappingproxy({})"),
394 (MP({None: MP({})}), "mappingproxy({None: mappingproxy({})})"),
402 (MP({None: MP({})}), "mappingproxy({None: mappingproxy({})})"),
395 (MP({k: k.upper() for k in string.ascii_lowercase}),
403 (MP({k: k.upper() for k in string.ascii_lowercase}),
396 "mappingproxy({'a': 'A',\n"
404 "mappingproxy({'a': 'A',\n"
397 " 'b': 'B',\n"
405 " 'b': 'B',\n"
398 " 'c': 'C',\n"
406 " 'c': 'C',\n"
399 " 'd': 'D',\n"
407 " 'd': 'D',\n"
400 " 'e': 'E',\n"
408 " 'e': 'E',\n"
401 " 'f': 'F',\n"
409 " 'f': 'F',\n"
402 " 'g': 'G',\n"
410 " 'g': 'G',\n"
403 " 'h': 'H',\n"
411 " 'h': 'H',\n"
404 " 'i': 'I',\n"
412 " 'i': 'I',\n"
405 " 'j': 'J',\n"
413 " 'j': 'J',\n"
406 " 'k': 'K',\n"
414 " 'k': 'K',\n"
407 " 'l': 'L',\n"
415 " 'l': 'L',\n"
408 " 'm': 'M',\n"
416 " 'm': 'M',\n"
409 " 'n': 'N',\n"
417 " 'n': 'N',\n"
410 " 'o': 'O',\n"
418 " 'o': 'O',\n"
411 " 'p': 'P',\n"
419 " 'p': 'P',\n"
412 " 'q': 'Q',\n"
420 " 'q': 'Q',\n"
413 " 'r': 'R',\n"
421 " 'r': 'R',\n"
414 " 's': 'S',\n"
422 " 's': 'S',\n"
415 " 't': 'T',\n"
423 " 't': 'T',\n"
416 " 'u': 'U',\n"
424 " 'u': 'U',\n"
417 " 'v': 'V',\n"
425 " 'v': 'V',\n"
418 " 'w': 'W',\n"
426 " 'w': 'W',\n"
419 " 'x': 'X',\n"
427 " 'x': 'X',\n"
420 " 'y': 'Y',\n"
428 " 'y': 'Y',\n"
421 " 'z': 'Z'})"),
429 " 'z': 'Z'})"),
422 (mp_recursive, "mappingproxy({2: {...}, 3: {2: {...}, 3: {...}}})"),
430 (mp_recursive, "mappingproxy({2: {...}, 3: {2: {...}, 3: {...}}})"),
423 (underlying_dict,
431 (underlying_dict,
424 "{2: mappingproxy({2: {...}, 3: {...}}), 3: {...}}"),
432 "{2: mappingproxy({2: {...}, 3: {...}}), 3: {...}}"),
425 ]
433 ]
426 for obj, expected in cases:
434 for obj, expected in cases:
427 nt.assert_equal(pretty.pretty(obj), expected)
435 assert pretty.pretty(obj) == expected
428
436
429
437
438 # TODO : pytest.mark.parametrise once nose is gone.
430 def test_simplenamespace():
439 def test_simplenamespace():
431 SN = types.SimpleNamespace
440 SN = types.SimpleNamespace
432
441
433 sn_recursive = SN()
442 sn_recursive = SN()
434 sn_recursive.first = sn_recursive
443 sn_recursive.first = sn_recursive
435 sn_recursive.second = sn_recursive
444 sn_recursive.second = sn_recursive
436 cases = [
445 cases = [
437 (SN(), "namespace()"),
446 (SN(), "namespace()"),
438 (SN(x=SN()), "namespace(x=namespace())"),
447 (SN(x=SN()), "namespace(x=namespace())"),
439 (SN(a_long_name=[SN(s=string.ascii_lowercase)]*3, a_short_name=None),
448 (SN(a_long_name=[SN(s=string.ascii_lowercase)]*3, a_short_name=None),
440 "namespace(a_long_name=[namespace(s='abcdefghijklmnopqrstuvwxyz'),\n"
449 "namespace(a_long_name=[namespace(s='abcdefghijklmnopqrstuvwxyz'),\n"
441 " namespace(s='abcdefghijklmnopqrstuvwxyz'),\n"
450 " namespace(s='abcdefghijklmnopqrstuvwxyz'),\n"
442 " namespace(s='abcdefghijklmnopqrstuvwxyz')],\n"
451 " namespace(s='abcdefghijklmnopqrstuvwxyz')],\n"
443 " a_short_name=None)"),
452 " a_short_name=None)"),
444 (sn_recursive, "namespace(first=namespace(...), second=namespace(...))"),
453 (sn_recursive, "namespace(first=namespace(...), second=namespace(...))"),
445 ]
454 ]
446 for obj, expected in cases:
455 for obj, expected in cases:
447 nt.assert_equal(pretty.pretty(obj), expected)
456 assert pretty.pretty(obj) == expected
448
457
449
458
450 def test_pretty_environ():
459 def test_pretty_environ():
451 dict_repr = pretty.pretty(dict(os.environ))
460 dict_repr = pretty.pretty(dict(os.environ))
452 # reindent to align with 'environ' prefix
461 # reindent to align with 'environ' prefix
453 dict_indented = dict_repr.replace('\n', '\n' + (' ' * len('environ')))
462 dict_indented = dict_repr.replace('\n', '\n' + (' ' * len('environ')))
454 env_repr = pretty.pretty(os.environ)
463 env_repr = pretty.pretty(os.environ)
455 nt.assert_equal(env_repr, 'environ' + dict_indented)
464 assert env_repr == "environ" + dict_indented
456
465
457
466
458 def test_function_pretty():
467 def test_function_pretty():
459 "Test pretty print of function"
468 "Test pretty print of function"
460 # posixpath is a pure python module, its interface is consistent
469 # posixpath is a pure python module, its interface is consistent
461 # across Python distributions
470 # across Python distributions
462 import posixpath
471 import posixpath
463 nt.assert_equal(pretty.pretty(posixpath.join), '<function posixpath.join(a, *p)>')
472
464
473 assert pretty.pretty(posixpath.join) == "<function posixpath.join(a, *p)>"
474
465 # custom function
475 # custom function
466 def meaning_of_life(question=None):
476 def meaning_of_life(question=None):
467 if question:
477 if question:
468 return 42
478 return 42
469 return "Don't panic"
479 return "Don't panic"
470
480
471 nt.assert_in('meaning_of_life(question=None)', pretty.pretty(meaning_of_life))
481 nt.assert_in('meaning_of_life(question=None)', pretty.pretty(meaning_of_life))
472
482
473
483
474 class OrderedCounter(Counter, OrderedDict):
484 class OrderedCounter(Counter, OrderedDict):
475 'Counter that remembers the order elements are first encountered'
485 'Counter that remembers the order elements are first encountered'
476
486
477 def __repr__(self):
487 def __repr__(self):
478 return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
488 return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
479
489
480 def __reduce__(self):
490 def __reduce__(self):
481 return self.__class__, (OrderedDict(self),)
491 return self.__class__, (OrderedDict(self),)
482
492
483 class MySet(set): # Override repr of a basic type
493 class MySet(set): # Override repr of a basic type
484 def __repr__(self):
494 def __repr__(self):
485 return 'mine'
495 return 'mine'
486
496
487 def test_custom_repr():
497 def test_custom_repr():
488 """A custom repr should override a pretty printer for a parent type"""
498 """A custom repr should override a pretty printer for a parent type"""
489 oc = OrderedCounter("abracadabra")
499 oc = OrderedCounter("abracadabra")
490 nt.assert_in("OrderedCounter(OrderedDict", pretty.pretty(oc))
500 nt.assert_in("OrderedCounter(OrderedDict", pretty.pretty(oc))
491
501
492 nt.assert_equal(pretty.pretty(MySet()), 'mine')
502 assert pretty.pretty(MySet()) == "mine"
@@ -1,26 +1,27 b''
1 # coding: utf-8
1 # coding: utf-8
2 from IPython.lib import passwd
2 from IPython.lib import passwd
3 from IPython.lib.security import passwd_check, salt_len
3 from IPython.lib.security import passwd_check, salt_len
4 import nose.tools as nt
5
4
6 def test_passwd_structure():
5 def test_passwd_structure():
7 p = passwd('passphrase')
6 p = passwd("passphrase")
8 algorithm, salt, hashed = p.split(':')
7 algorithm, salt, hashed = p.split(":")
9 nt.assert_equal(algorithm, 'sha1')
8 assert algorithm == "sha1"
10 nt.assert_equal(len(salt), salt_len)
9 assert len(salt) == salt_len
11 nt.assert_equal(len(hashed), 40)
10 assert len(hashed) == 40
12
11
13 def test_roundtrip():
12 def test_roundtrip():
14 p = passwd('passphrase')
13 p = passwd("passphrase")
15 nt.assert_equal(passwd_check(p, 'passphrase'), True)
14 assert passwd_check(p, "passphrase") is True
15
16
16
17 def test_bad():
17 def test_bad():
18 p = passwd('passphrase')
18 p = passwd('passphrase')
19 nt.assert_equal(passwd_check(p, p), False)
19 assert passwd_check(p, p) is False
20 nt.assert_equal(passwd_check(p, 'a:b:c:d'), False)
20 assert passwd_check(p, "a:b:c:d") is False
21 nt.assert_equal(passwd_check(p, 'a:b'), False)
21 assert passwd_check(p, "a:b") is False
22
22
23
23 def test_passwd_check_unicode():
24 def test_passwd_check_unicode():
24 # GH issue #4524
25 # GH issue #4524
25 phash = u'sha1:23862bc21dd3:7a415a95ae4580582e314072143d9c382c491e4f'
26 phash = u'sha1:23862bc21dd3:7a415a95ae4580582e314072143d9c382c491e4f'
26 assert passwd_check(phash, u"Ε‚e¢ŧ←↓→") No newline at end of file
27 assert passwd_check(phash, u"Ε‚e¢ŧ←↓→")
@@ -1,172 +1,171 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.capture"""
2 """Tests for IPython.utils.capture"""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2013 The IPython Development Team
5 # Copyright (C) 2013 The IPython Development Team
6 #
6 #
7 # Distributed under the terms of the BSD License. The full license is in
7 # Distributed under the terms of the BSD License. The full license is in
8 # the file COPYING, distributed as part of this software.
8 # the file COPYING, distributed as part of this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15
15
16 import sys
16 import sys
17
17
18 import nose.tools as nt
19 import pytest
18 import pytest
20
19
21 from IPython.testing.decorators import skip_iptest_but_not_pytest
20 from IPython.testing.decorators import skip_iptest_but_not_pytest
22
21
23 from IPython.utils import capture
22 from IPython.utils import capture
24
23
25 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
26 # Globals
25 # Globals
27 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
28
27
29 _mime_map = dict(
28 _mime_map = dict(
30 _repr_png_="image/png",
29 _repr_png_="image/png",
31 _repr_jpeg_="image/jpeg",
30 _repr_jpeg_="image/jpeg",
32 _repr_svg_="image/svg+xml",
31 _repr_svg_="image/svg+xml",
33 _repr_html_="text/html",
32 _repr_html_="text/html",
34 _repr_json_="application/json",
33 _repr_json_="application/json",
35 _repr_javascript_="application/javascript",
34 _repr_javascript_="application/javascript",
36 )
35 )
37
36
38 basic_data = {
37 basic_data = {
39 'image/png' : b'binarydata',
38 'image/png' : b'binarydata',
40 'text/html' : "<b>bold</b>",
39 'text/html' : "<b>bold</b>",
41 }
40 }
42 basic_metadata = {
41 basic_metadata = {
43 'image/png' : {
42 'image/png' : {
44 'width' : 10,
43 'width' : 10,
45 'height' : 20,
44 'height' : 20,
46 },
45 },
47 }
46 }
48
47
49 full_data = {
48 full_data = {
50 'image/png' : b'binarydata',
49 'image/png' : b'binarydata',
51 'image/jpeg' : b'binarydata',
50 'image/jpeg' : b'binarydata',
52 'image/svg+xml' : "<svg>",
51 'image/svg+xml' : "<svg>",
53 'text/html' : "<b>bold</b>",
52 'text/html' : "<b>bold</b>",
54 'application/javascript' : "alert();",
53 'application/javascript' : "alert();",
55 'application/json' : "{}",
54 'application/json' : "{}",
56 }
55 }
57 full_metadata = {
56 full_metadata = {
58 'image/png' : {"png" : "exists"},
57 'image/png' : {"png" : "exists"},
59 'image/jpeg' : {"jpeg" : "exists"},
58 'image/jpeg' : {"jpeg" : "exists"},
60 'image/svg+xml' : {"svg" : "exists"},
59 'image/svg+xml' : {"svg" : "exists"},
61 'text/html' : {"html" : "exists"},
60 'text/html' : {"html" : "exists"},
62 'application/javascript' : {"js" : "exists"},
61 'application/javascript' : {"js" : "exists"},
63 'application/json' : {"json" : "exists"},
62 'application/json' : {"json" : "exists"},
64 }
63 }
65
64
66 hello_stdout = "hello, stdout"
65 hello_stdout = "hello, stdout"
67 hello_stderr = "hello, stderr"
66 hello_stderr = "hello, stderr"
68
67
69 #-----------------------------------------------------------------------------
68 #-----------------------------------------------------------------------------
70 # Test Functions
69 # Test Functions
71 #-----------------------------------------------------------------------------
70 #-----------------------------------------------------------------------------
72 @pytest.mark.parametrize("method_mime", _mime_map.items())
71 @pytest.mark.parametrize("method_mime", _mime_map.items())
73 @skip_iptest_but_not_pytest
72 @skip_iptest_but_not_pytest
74 def test_rich_output_empty(method_mime):
73 def test_rich_output_empty(method_mime):
75 """RichOutput with no args"""
74 """RichOutput with no args"""
76 rich = capture.RichOutput()
75 rich = capture.RichOutput()
77 method, mime = method_mime
76 method, mime = method_mime
78 nt.assert_equal(getattr(rich, method)(), None)
77 assert getattr(rich, method)() is None
79
78
80 def test_rich_output():
79 def test_rich_output():
81 """test RichOutput basics"""
80 """test RichOutput basics"""
82 data = basic_data
81 data = basic_data
83 metadata = basic_metadata
82 metadata = basic_metadata
84 rich = capture.RichOutput(data=data, metadata=metadata)
83 rich = capture.RichOutput(data=data, metadata=metadata)
85 nt.assert_equal(rich._repr_html_(), data["text/html"])
84 assert rich._repr_html_() == data["text/html"]
86 nt.assert_equal(rich._repr_png_(), (data["image/png"], metadata["image/png"]))
85 assert rich._repr_png_() == (data["image/png"], metadata["image/png"])
87 nt.assert_equal(rich._repr_latex_(), None)
86 assert rich._repr_latex_() is None
88 nt.assert_equal(rich._repr_javascript_(), None)
87 assert rich._repr_javascript_() is None
89 nt.assert_equal(rich._repr_svg_(), None)
88 assert rich._repr_svg_() is None
90
89
91
90
92 @skip_iptest_but_not_pytest
91 @skip_iptest_but_not_pytest
93 @pytest.mark.parametrize("method_mime", _mime_map.items())
92 @pytest.mark.parametrize("method_mime", _mime_map.items())
94 def test_rich_output_no_metadata(method_mime):
93 def test_rich_output_no_metadata(method_mime):
95 """test RichOutput with no metadata"""
94 """test RichOutput with no metadata"""
96 data = full_data
95 data = full_data
97 rich = capture.RichOutput(data=data)
96 rich = capture.RichOutput(data=data)
98 method, mime = method_mime
97 method, mime = method_mime
99 nt.assert_equal(getattr(rich, method)(), data[mime])
98 assert getattr(rich, method)() == data[mime]
100
99
101
100
102 @skip_iptest_but_not_pytest
101 @skip_iptest_but_not_pytest
103 @pytest.mark.parametrize("method_mime", _mime_map.items())
102 @pytest.mark.parametrize("method_mime", _mime_map.items())
104 def test_rich_output_metadata(method_mime):
103 def test_rich_output_metadata(method_mime):
105 """test RichOutput with metadata"""
104 """test RichOutput with metadata"""
106 data = full_data
105 data = full_data
107 metadata = full_metadata
106 metadata = full_metadata
108 rich = capture.RichOutput(data=data, metadata=metadata)
107 rich = capture.RichOutput(data=data, metadata=metadata)
109 method, mime = method_mime
108 method, mime = method_mime
110 nt.assert_equal(getattr(rich, method)(), (data[mime], metadata[mime]))
109 assert getattr(rich, method)() == (data[mime], metadata[mime])
111
110
112 def test_rich_output_display():
111 def test_rich_output_display():
113 """test RichOutput.display
112 """test RichOutput.display
114
113
115 This is a bit circular, because we are actually using the capture code we are testing
114 This is a bit circular, because we are actually using the capture code we are testing
116 to test itself.
115 to test itself.
117 """
116 """
118 data = full_data
117 data = full_data
119 rich = capture.RichOutput(data=data)
118 rich = capture.RichOutput(data=data)
120 with capture.capture_output() as cap:
119 with capture.capture_output() as cap:
121 rich.display()
120 rich.display()
122 nt.assert_equal(len(cap.outputs), 1)
121 assert len(cap.outputs) == 1
123 rich2 = cap.outputs[0]
122 rich2 = cap.outputs[0]
124 nt.assert_equal(rich2.data, rich.data)
123 assert rich2.data == rich.data
125 nt.assert_equal(rich2.metadata, rich.metadata)
124 assert rich2.metadata == rich.metadata
126
125
127 def test_capture_output():
126 def test_capture_output():
128 """capture_output works"""
127 """capture_output works"""
129 rich = capture.RichOutput(data=full_data)
128 rich = capture.RichOutput(data=full_data)
130 with capture.capture_output() as cap:
129 with capture.capture_output() as cap:
131 print(hello_stdout, end="")
130 print(hello_stdout, end="")
132 print(hello_stderr, end="", file=sys.stderr)
131 print(hello_stderr, end="", file=sys.stderr)
133 rich.display()
132 rich.display()
134 nt.assert_equal(hello_stdout, cap.stdout)
133 assert hello_stdout == cap.stdout
135 nt.assert_equal(hello_stderr, cap.stderr)
134 assert hello_stderr == cap.stderr
136
135
137
136
138 def test_capture_output_no_stdout():
137 def test_capture_output_no_stdout():
139 """test capture_output(stdout=False)"""
138 """test capture_output(stdout=False)"""
140 rich = capture.RichOutput(data=full_data)
139 rich = capture.RichOutput(data=full_data)
141 with capture.capture_output(stdout=False) as cap:
140 with capture.capture_output(stdout=False) as cap:
142 print(hello_stdout, end="")
141 print(hello_stdout, end="")
143 print(hello_stderr, end="", file=sys.stderr)
142 print(hello_stderr, end="", file=sys.stderr)
144 rich.display()
143 rich.display()
145 nt.assert_equal("", cap.stdout)
144 assert "" == cap.stdout
146 nt.assert_equal(hello_stderr, cap.stderr)
145 assert hello_stderr == cap.stderr
147 nt.assert_equal(len(cap.outputs), 1)
146 assert len(cap.outputs) == 1
148
147
149
148
150 def test_capture_output_no_stderr():
149 def test_capture_output_no_stderr():
151 """test capture_output(stderr=False)"""
150 """test capture_output(stderr=False)"""
152 rich = capture.RichOutput(data=full_data)
151 rich = capture.RichOutput(data=full_data)
153 # add nested capture_output so stderr doesn't make it to nose output
152 # add nested capture_output so stderr doesn't make it to nose output
154 with capture.capture_output(), capture.capture_output(stderr=False) as cap:
153 with capture.capture_output(), capture.capture_output(stderr=False) as cap:
155 print(hello_stdout, end="")
154 print(hello_stdout, end="")
156 print(hello_stderr, end="", file=sys.stderr)
155 print(hello_stderr, end="", file=sys.stderr)
157 rich.display()
156 rich.display()
158 nt.assert_equal(hello_stdout, cap.stdout)
157 assert hello_stdout == cap.stdout
159 nt.assert_equal("", cap.stderr)
158 assert "" == cap.stderr
160 nt.assert_equal(len(cap.outputs), 1)
159 assert len(cap.outputs) == 1
161
160
162
161
163 def test_capture_output_no_display():
162 def test_capture_output_no_display():
164 """test capture_output(display=False)"""
163 """test capture_output(display=False)"""
165 rich = capture.RichOutput(data=full_data)
164 rich = capture.RichOutput(data=full_data)
166 with capture.capture_output(display=False) as cap:
165 with capture.capture_output(display=False) as cap:
167 print(hello_stdout, end="")
166 print(hello_stdout, end="")
168 print(hello_stderr, end="", file=sys.stderr)
167 print(hello_stderr, end="", file=sys.stderr)
169 rich.display()
168 rich.display()
170 nt.assert_equal(hello_stdout, cap.stdout)
169 assert hello_stdout == cap.stdout
171 nt.assert_equal(hello_stderr, cap.stderr)
170 assert hello_stderr == cap.stderr
172 nt.assert_equal(cap.outputs, [])
171 assert cap.outputs == []
@@ -1,492 +1,494 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.path.py"""
2 """Tests for IPython.utils.path.py"""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import os
7 import os
8 import shutil
8 import shutil
9 import sys
9 import sys
10 import tempfile
10 import tempfile
11 import unittest
11 import unittest
12 from contextlib import contextmanager
12 from contextlib import contextmanager
13 from unittest.mock import patch
13 from unittest.mock import patch
14 from os.path import join, abspath
14 from os.path import join, abspath
15 from imp import reload
15 from imp import reload
16
16
17 from nose import SkipTest, with_setup
17 from nose import SkipTest, with_setup
18 import nose.tools as nt
18 import nose.tools as nt
19
19
20 import IPython
20 import IPython
21 from IPython import paths
21 from IPython import paths
22 from IPython.testing import decorators as dec
22 from IPython.testing import decorators as dec
23 from IPython.testing.decorators import (skip_if_not_win32, skip_win32,
23 from IPython.testing.decorators import (skip_if_not_win32, skip_win32,
24 onlyif_unicode_paths,
24 onlyif_unicode_paths,
25 skip_win32_py38,)
25 skip_win32_py38,)
26 from IPython.testing.tools import make_tempfile
26 from IPython.testing.tools import make_tempfile
27 from IPython.utils import path
27 from IPython.utils import path
28 from IPython.utils.tempdir import TemporaryDirectory
28 from IPython.utils.tempdir import TemporaryDirectory
29
29
30
30
31 # Platform-dependent imports
31 # Platform-dependent imports
32 try:
32 try:
33 import winreg as wreg
33 import winreg as wreg
34 except ImportError:
34 except ImportError:
35 #Fake _winreg module on non-windows platforms
35 #Fake _winreg module on non-windows platforms
36 import types
36 import types
37 wr_name = "winreg"
37 wr_name = "winreg"
38 sys.modules[wr_name] = types.ModuleType(wr_name)
38 sys.modules[wr_name] = types.ModuleType(wr_name)
39 try:
39 try:
40 import winreg as wreg
40 import winreg as wreg
41 except ImportError:
41 except ImportError:
42 import _winreg as wreg
42 import _winreg as wreg
43 #Add entries that needs to be stubbed by the testing code
43 #Add entries that needs to be stubbed by the testing code
44 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
44 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
45
45
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47 # Globals
47 # Globals
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49 env = os.environ
49 env = os.environ
50 TMP_TEST_DIR = tempfile.mkdtemp()
50 TMP_TEST_DIR = tempfile.mkdtemp()
51 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
51 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
52 #
52 #
53 # Setup/teardown functions/decorators
53 # Setup/teardown functions/decorators
54 #
54 #
55
55
56 def setup_module():
56 def setup_module():
57 """Setup testenvironment for the module:
57 """Setup testenvironment for the module:
58
58
59 - Adds dummy home dir tree
59 - Adds dummy home dir tree
60 """
60 """
61 # Do not mask exceptions here. In particular, catching WindowsError is a
61 # Do not mask exceptions here. In particular, catching WindowsError is a
62 # problem because that exception is only defined on Windows...
62 # problem because that exception is only defined on Windows...
63 os.makedirs(os.path.join(HOME_TEST_DIR, 'ipython'))
63 os.makedirs(os.path.join(HOME_TEST_DIR, 'ipython'))
64
64
65
65
66 def teardown_module():
66 def teardown_module():
67 """Teardown testenvironment for the module:
67 """Teardown testenvironment for the module:
68
68
69 - Remove dummy home dir tree
69 - Remove dummy home dir tree
70 """
70 """
71 # Note: we remove the parent test dir, which is the root of all test
71 # Note: we remove the parent test dir, which is the root of all test
72 # subdirs we may have created. Use shutil instead of os.removedirs, so
72 # subdirs we may have created. Use shutil instead of os.removedirs, so
73 # that non-empty directories are all recursively removed.
73 # that non-empty directories are all recursively removed.
74 shutil.rmtree(TMP_TEST_DIR)
74 shutil.rmtree(TMP_TEST_DIR)
75
75
76
76
77 def setup_environment():
77 def setup_environment():
78 """Setup testenvironment for some functions that are tested
78 """Setup testenvironment for some functions that are tested
79 in this module. In particular this functions stores attributes
79 in this module. In particular this functions stores attributes
80 and other things that we need to stub in some test functions.
80 and other things that we need to stub in some test functions.
81 This needs to be done on a function level and not module level because
81 This needs to be done on a function level and not module level because
82 each testfunction needs a pristine environment.
82 each testfunction needs a pristine environment.
83 """
83 """
84 global oldstuff, platformstuff
84 global oldstuff, platformstuff
85 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
85 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
86
86
87 def teardown_environment():
87 def teardown_environment():
88 """Restore things that were remembered by the setup_environment function
88 """Restore things that were remembered by the setup_environment function
89 """
89 """
90 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
90 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
91 os.chdir(old_wd)
91 os.chdir(old_wd)
92 reload(path)
92 reload(path)
93
93
94 for key in list(env):
94 for key in list(env):
95 if key not in oldenv:
95 if key not in oldenv:
96 del env[key]
96 del env[key]
97 env.update(oldenv)
97 env.update(oldenv)
98 if hasattr(sys, 'frozen'):
98 if hasattr(sys, 'frozen'):
99 del sys.frozen
99 del sys.frozen
100
100
101 # Build decorator that uses the setup_environment/setup_environment
101 # Build decorator that uses the setup_environment/setup_environment
102 with_environment = with_setup(setup_environment, teardown_environment)
102 with_environment = with_setup(setup_environment, teardown_environment)
103
103
104 @skip_if_not_win32
104 @skip_if_not_win32
105 @with_environment
105 @with_environment
106 def test_get_home_dir_1():
106 def test_get_home_dir_1():
107 """Testcase for py2exe logic, un-compressed lib
107 """Testcase for py2exe logic, un-compressed lib
108 """
108 """
109 unfrozen = path.get_home_dir()
109 unfrozen = path.get_home_dir()
110 sys.frozen = True
110 sys.frozen = True
111
111
112 #fake filename for IPython.__init__
112 #fake filename for IPython.__init__
113 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
113 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
114
114
115 home_dir = path.get_home_dir()
115 home_dir = path.get_home_dir()
116 nt.assert_equal(home_dir, unfrozen)
116 assert home_dir == unfrozen
117
117
118
118
119 @skip_if_not_win32
119 @skip_if_not_win32
120 @with_environment
120 @with_environment
121 def test_get_home_dir_2():
121 def test_get_home_dir_2():
122 """Testcase for py2exe logic, compressed lib
122 """Testcase for py2exe logic, compressed lib
123 """
123 """
124 unfrozen = path.get_home_dir()
124 unfrozen = path.get_home_dir()
125 sys.frozen = True
125 sys.frozen = True
126 #fake filename for IPython.__init__
126 #fake filename for IPython.__init__
127 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
127 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
128
128
129 home_dir = path.get_home_dir(True)
129 home_dir = path.get_home_dir(True)
130 nt.assert_equal(home_dir, unfrozen)
130 assert home_dir == unfrozen
131
131
132
132
133 @skip_win32_py38
133 @skip_win32_py38
134 @with_environment
134 @with_environment
135 def test_get_home_dir_3():
135 def test_get_home_dir_3():
136 """get_home_dir() uses $HOME if set"""
136 """get_home_dir() uses $HOME if set"""
137 env["HOME"] = HOME_TEST_DIR
137 env["HOME"] = HOME_TEST_DIR
138 home_dir = path.get_home_dir(True)
138 home_dir = path.get_home_dir(True)
139 # get_home_dir expands symlinks
139 # get_home_dir expands symlinks
140 nt.assert_equal(home_dir, os.path.realpath(env["HOME"]))
140 assert home_dir == os.path.realpath(env["HOME"])
141
141
142
142
143 @with_environment
143 @with_environment
144 def test_get_home_dir_4():
144 def test_get_home_dir_4():
145 """get_home_dir() still works if $HOME is not set"""
145 """get_home_dir() still works if $HOME is not set"""
146
146
147 if 'HOME' in env: del env['HOME']
147 if 'HOME' in env: del env['HOME']
148 # this should still succeed, but we don't care what the answer is
148 # this should still succeed, but we don't care what the answer is
149 home = path.get_home_dir(False)
149 home = path.get_home_dir(False)
150
150
151 @skip_win32_py38
151 @skip_win32_py38
152 @with_environment
152 @with_environment
153 def test_get_home_dir_5():
153 def test_get_home_dir_5():
154 """raise HomeDirError if $HOME is specified, but not a writable dir"""
154 """raise HomeDirError if $HOME is specified, but not a writable dir"""
155 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
155 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
156 # set os.name = posix, to prevent My Documents fallback on Windows
156 # set os.name = posix, to prevent My Documents fallback on Windows
157 os.name = 'posix'
157 os.name = 'posix'
158 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
158 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
159
159
160 # Should we stub wreg fully so we can run the test on all platforms?
160 # Should we stub wreg fully so we can run the test on all platforms?
161 @skip_if_not_win32
161 @skip_if_not_win32
162 @with_environment
162 @with_environment
163 def test_get_home_dir_8():
163 def test_get_home_dir_8():
164 """Using registry hack for 'My Documents', os=='nt'
164 """Using registry hack for 'My Documents', os=='nt'
165
165
166 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
166 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
167 """
167 """
168 os.name = 'nt'
168 os.name = 'nt'
169 # Remove from stub environment all keys that may be set
169 # Remove from stub environment all keys that may be set
170 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
170 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
171 env.pop(key, None)
171 env.pop(key, None)
172
172
173 class key:
173 class key:
174 def __enter__(self):
174 def __enter__(self):
175 pass
175 pass
176 def Close(self):
176 def Close(self):
177 pass
177 pass
178 def __exit__(*args, **kwargs):
178 def __exit__(*args, **kwargs):
179 pass
179 pass
180
180
181 with patch.object(wreg, 'OpenKey', return_value=key()), \
181 with patch.object(wreg, 'OpenKey', return_value=key()), \
182 patch.object(wreg, 'QueryValueEx', return_value=[abspath(HOME_TEST_DIR)]):
182 patch.object(wreg, 'QueryValueEx', return_value=[abspath(HOME_TEST_DIR)]):
183 home_dir = path.get_home_dir()
183 home_dir = path.get_home_dir()
184 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
184 assert home_dir == abspath(HOME_TEST_DIR)
185
185
186 @with_environment
186 @with_environment
187 def test_get_xdg_dir_0():
187 def test_get_xdg_dir_0():
188 """test_get_xdg_dir_0, check xdg_dir"""
188 """test_get_xdg_dir_0, check xdg_dir"""
189 reload(path)
189 reload(path)
190 path._writable_dir = lambda path: True
190 path._writable_dir = lambda path: True
191 path.get_home_dir = lambda : 'somewhere'
191 path.get_home_dir = lambda : 'somewhere'
192 os.name = "posix"
192 os.name = "posix"
193 sys.platform = "linux2"
193 sys.platform = "linux2"
194 env.pop('IPYTHON_DIR', None)
194 env.pop('IPYTHON_DIR', None)
195 env.pop('IPYTHONDIR', None)
195 env.pop('IPYTHONDIR', None)
196 env.pop('XDG_CONFIG_HOME', None)
196 env.pop('XDG_CONFIG_HOME', None)
197
197
198 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
198 assert path.get_xdg_dir() == os.path.join("somewhere", ".config")
199
199
200
200
201 @with_environment
201 @with_environment
202 def test_get_xdg_dir_1():
202 def test_get_xdg_dir_1():
203 """test_get_xdg_dir_1, check nonexistent xdg_dir"""
203 """test_get_xdg_dir_1, check nonexistent xdg_dir"""
204 reload(path)
204 reload(path)
205 path.get_home_dir = lambda : HOME_TEST_DIR
205 path.get_home_dir = lambda : HOME_TEST_DIR
206 os.name = "posix"
206 os.name = "posix"
207 sys.platform = "linux2"
207 sys.platform = "linux2"
208 env.pop('IPYTHON_DIR', None)
208 env.pop('IPYTHON_DIR', None)
209 env.pop('IPYTHONDIR', None)
209 env.pop('IPYTHONDIR', None)
210 env.pop('XDG_CONFIG_HOME', None)
210 env.pop('XDG_CONFIG_HOME', None)
211 nt.assert_equal(path.get_xdg_dir(), None)
211 assert path.get_xdg_dir() is None
212
212
213 @with_environment
213 @with_environment
214 def test_get_xdg_dir_2():
214 def test_get_xdg_dir_2():
215 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
215 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
216 reload(path)
216 reload(path)
217 path.get_home_dir = lambda : HOME_TEST_DIR
217 path.get_home_dir = lambda : HOME_TEST_DIR
218 os.name = "posix"
218 os.name = "posix"
219 sys.platform = "linux2"
219 sys.platform = "linux2"
220 env.pop('IPYTHON_DIR', None)
220 env.pop('IPYTHON_DIR', None)
221 env.pop('IPYTHONDIR', None)
221 env.pop('IPYTHONDIR', None)
222 env.pop('XDG_CONFIG_HOME', None)
222 env.pop('XDG_CONFIG_HOME', None)
223 cfgdir=os.path.join(path.get_home_dir(), '.config')
223 cfgdir=os.path.join(path.get_home_dir(), '.config')
224 if not os.path.exists(cfgdir):
224 if not os.path.exists(cfgdir):
225 os.makedirs(cfgdir)
225 os.makedirs(cfgdir)
226
226
227 nt.assert_equal(path.get_xdg_dir(), cfgdir)
227 assert path.get_xdg_dir() == cfgdir
228
228
229 @with_environment
229 @with_environment
230 def test_get_xdg_dir_3():
230 def test_get_xdg_dir_3():
231 """test_get_xdg_dir_3, check xdg_dir not used on OS X"""
231 """test_get_xdg_dir_3, check xdg_dir not used on OS X"""
232 reload(path)
232 reload(path)
233 path.get_home_dir = lambda : HOME_TEST_DIR
233 path.get_home_dir = lambda : HOME_TEST_DIR
234 os.name = "posix"
234 os.name = "posix"
235 sys.platform = "darwin"
235 sys.platform = "darwin"
236 env.pop('IPYTHON_DIR', None)
236 env.pop('IPYTHON_DIR', None)
237 env.pop('IPYTHONDIR', None)
237 env.pop('IPYTHONDIR', None)
238 env.pop('XDG_CONFIG_HOME', None)
238 env.pop('XDG_CONFIG_HOME', None)
239 cfgdir=os.path.join(path.get_home_dir(), '.config')
239 cfgdir=os.path.join(path.get_home_dir(), '.config')
240 if not os.path.exists(cfgdir):
240 if not os.path.exists(cfgdir):
241 os.makedirs(cfgdir)
241 os.makedirs(cfgdir)
242
242
243 nt.assert_equal(path.get_xdg_dir(), None)
243 assert path.get_xdg_dir() is None
244
244
245 def test_filefind():
245 def test_filefind():
246 """Various tests for filefind"""
246 """Various tests for filefind"""
247 f = tempfile.NamedTemporaryFile()
247 f = tempfile.NamedTemporaryFile()
248 # print 'fname:',f.name
248 # print 'fname:',f.name
249 alt_dirs = paths.get_ipython_dir()
249 alt_dirs = paths.get_ipython_dir()
250 t = path.filefind(f.name, alt_dirs)
250 t = path.filefind(f.name, alt_dirs)
251 # print 'found:',t
251 # print 'found:',t
252
252
253
253
254 @dec.skip_if_not_win32
254 @dec.skip_if_not_win32
255 def test_get_long_path_name_win32():
255 def test_get_long_path_name_win32():
256 with TemporaryDirectory() as tmpdir:
256 with TemporaryDirectory() as tmpdir:
257
257
258 # Make a long path. Expands the path of tmpdir prematurely as it may already have a long
258 # Make a long path. Expands the path of tmpdir prematurely as it may already have a long
259 # path component, so ensure we include the long form of it
259 # path component, so ensure we include the long form of it
260 long_path = os.path.join(path.get_long_path_name(tmpdir), 'this is my long path name')
260 long_path = os.path.join(path.get_long_path_name(tmpdir), 'this is my long path name')
261 os.makedirs(long_path)
261 os.makedirs(long_path)
262
262
263 # Test to see if the short path evaluates correctly.
263 # Test to see if the short path evaluates correctly.
264 short_path = os.path.join(tmpdir, 'THISIS~1')
264 short_path = os.path.join(tmpdir, 'THISIS~1')
265 evaluated_path = path.get_long_path_name(short_path)
265 evaluated_path = path.get_long_path_name(short_path)
266 nt.assert_equal(evaluated_path.lower(), long_path.lower())
266 assert evaluated_path.lower() == long_path.lower()
267
267
268
268
269 @dec.skip_win32
269 @dec.skip_win32
270 def test_get_long_path_name():
270 def test_get_long_path_name():
271 p = path.get_long_path_name('/usr/local')
271 p = path.get_long_path_name("/usr/local")
272 nt.assert_equal(p,'/usr/local')
272 assert p == "/usr/local"
273
273
274
274
275 class TestRaiseDeprecation(unittest.TestCase):
275 class TestRaiseDeprecation(unittest.TestCase):
276
276
277 @dec.skip_win32 # can't create not-user-writable dir on win
277 @dec.skip_win32 # can't create not-user-writable dir on win
278 @with_environment
278 @with_environment
279 def test_not_writable_ipdir(self):
279 def test_not_writable_ipdir(self):
280 tmpdir = tempfile.mkdtemp()
280 tmpdir = tempfile.mkdtemp()
281 os.name = "posix"
281 os.name = "posix"
282 env.pop('IPYTHON_DIR', None)
282 env.pop('IPYTHON_DIR', None)
283 env.pop('IPYTHONDIR', None)
283 env.pop('IPYTHONDIR', None)
284 env.pop('XDG_CONFIG_HOME', None)
284 env.pop('XDG_CONFIG_HOME', None)
285 env['HOME'] = tmpdir
285 env['HOME'] = tmpdir
286 ipdir = os.path.join(tmpdir, '.ipython')
286 ipdir = os.path.join(tmpdir, '.ipython')
287 os.mkdir(ipdir, 0o555)
287 os.mkdir(ipdir, 0o555)
288 try:
288 try:
289 open(os.path.join(ipdir, "_foo_"), 'w').close()
289 open(os.path.join(ipdir, "_foo_"), 'w').close()
290 except IOError:
290 except IOError:
291 pass
291 pass
292 else:
292 else:
293 # I can still write to an unwritable dir,
293 # I can still write to an unwritable dir,
294 # assume I'm root and skip the test
294 # assume I'm root and skip the test
295 raise SkipTest("I can't create directories that I can't write to")
295 raise SkipTest("I can't create directories that I can't write to")
296 with self.assertWarnsRegex(UserWarning, 'is not a writable location'):
296 with self.assertWarnsRegex(UserWarning, 'is not a writable location'):
297 ipdir = paths.get_ipython_dir()
297 ipdir = paths.get_ipython_dir()
298 env.pop('IPYTHON_DIR', None)
298 env.pop('IPYTHON_DIR', None)
299
299
300 @with_environment
300 @with_environment
301 def test_get_py_filename():
301 def test_get_py_filename():
302 os.chdir(TMP_TEST_DIR)
302 os.chdir(TMP_TEST_DIR)
303 with make_tempfile('foo.py'):
303 with make_tempfile("foo.py"):
304 nt.assert_equal(path.get_py_filename('foo.py'), 'foo.py')
304 assert path.get_py_filename("foo.py") == "foo.py"
305 nt.assert_equal(path.get_py_filename('foo'), 'foo.py')
305 assert path.get_py_filename("foo") == "foo.py"
306 with make_tempfile('foo'):
306 with make_tempfile("foo"):
307 nt.assert_equal(path.get_py_filename('foo'), 'foo')
307 assert path.get_py_filename("foo") == "foo"
308 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
308 nt.assert_raises(IOError, path.get_py_filename, "foo.py")
309 nt.assert_raises(IOError, path.get_py_filename, 'foo')
309 nt.assert_raises(IOError, path.get_py_filename, "foo")
310 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
310 nt.assert_raises(IOError, path.get_py_filename, "foo.py")
311 true_fn = 'foo with spaces.py'
311 true_fn = "foo with spaces.py"
312 with make_tempfile(true_fn):
312 with make_tempfile(true_fn):
313 nt.assert_equal(path.get_py_filename('foo with spaces'), true_fn)
313 assert path.get_py_filename("foo with spaces") == true_fn
314 nt.assert_equal(path.get_py_filename('foo with spaces.py'), true_fn)
314 assert path.get_py_filename("foo with spaces.py") == true_fn
315 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"')
315 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"')
316 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'")
316 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'")
317
317
318 @onlyif_unicode_paths
318 @onlyif_unicode_paths
319 def test_unicode_in_filename():
319 def test_unicode_in_filename():
320 """When a file doesn't exist, the exception raised should be safe to call
320 """When a file doesn't exist, the exception raised should be safe to call
321 str() on - i.e. in Python 2 it must only have ASCII characters.
321 str() on - i.e. in Python 2 it must only have ASCII characters.
322
322
323 https://github.com/ipython/ipython/issues/875
323 https://github.com/ipython/ipython/issues/875
324 """
324 """
325 try:
325 try:
326 # these calls should not throw unicode encode exceptions
326 # these calls should not throw unicode encode exceptions
327 path.get_py_filename('fooéè.py')
327 path.get_py_filename('fooéè.py')
328 except IOError as ex:
328 except IOError as ex:
329 str(ex)
329 str(ex)
330
330
331
331
332 class TestShellGlob(unittest.TestCase):
332 class TestShellGlob(unittest.TestCase):
333
333
334 @classmethod
334 @classmethod
335 def setUpClass(cls):
335 def setUpClass(cls):
336 cls.filenames_start_with_a = ['a0', 'a1', 'a2']
336 cls.filenames_start_with_a = ['a0', 'a1', 'a2']
337 cls.filenames_end_with_b = ['0b', '1b', '2b']
337 cls.filenames_end_with_b = ['0b', '1b', '2b']
338 cls.filenames = cls.filenames_start_with_a + cls.filenames_end_with_b
338 cls.filenames = cls.filenames_start_with_a + cls.filenames_end_with_b
339 cls.tempdir = TemporaryDirectory()
339 cls.tempdir = TemporaryDirectory()
340 td = cls.tempdir.name
340 td = cls.tempdir.name
341
341
342 with cls.in_tempdir():
342 with cls.in_tempdir():
343 # Create empty files
343 # Create empty files
344 for fname in cls.filenames:
344 for fname in cls.filenames:
345 open(os.path.join(td, fname), 'w').close()
345 open(os.path.join(td, fname), 'w').close()
346
346
347 @classmethod
347 @classmethod
348 def tearDownClass(cls):
348 def tearDownClass(cls):
349 cls.tempdir.cleanup()
349 cls.tempdir.cleanup()
350
350
351 @classmethod
351 @classmethod
352 @contextmanager
352 @contextmanager
353 def in_tempdir(cls):
353 def in_tempdir(cls):
354 save = os.getcwd()
354 save = os.getcwd()
355 try:
355 try:
356 os.chdir(cls.tempdir.name)
356 os.chdir(cls.tempdir.name)
357 yield
357 yield
358 finally:
358 finally:
359 os.chdir(save)
359 os.chdir(save)
360
360
361 def check_match(self, patterns, matches):
361 def check_match(self, patterns, matches):
362 with self.in_tempdir():
362 with self.in_tempdir():
363 # glob returns unordered list. that's why sorted is required.
363 # glob returns unordered list. that's why sorted is required.
364 nt.assert_equal(sorted(path.shellglob(patterns)),
364 assert sorted(path.shellglob(patterns)) == sorted(matches)
365 sorted(matches))
366
365
367 def common_cases(self):
366 def common_cases(self):
368 return [
367 return [
369 (['*'], self.filenames),
368 (['*'], self.filenames),
370 (['a*'], self.filenames_start_with_a),
369 (['a*'], self.filenames_start_with_a),
371 (['*c'], ['*c']),
370 (['*c'], ['*c']),
372 (['*', 'a*', '*b', '*c'], self.filenames
371 (['*', 'a*', '*b', '*c'], self.filenames
373 + self.filenames_start_with_a
372 + self.filenames_start_with_a
374 + self.filenames_end_with_b
373 + self.filenames_end_with_b
375 + ['*c']),
374 + ['*c']),
376 (['a[012]'], self.filenames_start_with_a),
375 (['a[012]'], self.filenames_start_with_a),
377 ]
376 ]
378
377
379 @skip_win32
378 @skip_win32
380 def test_match_posix(self):
379 def test_match_posix(self):
381 for (patterns, matches) in self.common_cases() + [
380 for (patterns, matches) in self.common_cases() + [
382 ([r'\*'], ['*']),
381 ([r'\*'], ['*']),
383 ([r'a\*', 'a*'], ['a*'] + self.filenames_start_with_a),
382 ([r'a\*', 'a*'], ['a*'] + self.filenames_start_with_a),
384 ([r'a\[012]'], ['a[012]']),
383 ([r'a\[012]'], ['a[012]']),
385 ]:
384 ]:
386 yield (self.check_match, patterns, matches)
385 yield (self.check_match, patterns, matches)
387
386
388 @skip_if_not_win32
387 @skip_if_not_win32
389 def test_match_windows(self):
388 def test_match_windows(self):
390 for (patterns, matches) in self.common_cases() + [
389 for (patterns, matches) in self.common_cases() + [
391 # In windows, backslash is interpreted as path
390 # In windows, backslash is interpreted as path
392 # separator. Therefore, you can't escape glob
391 # separator. Therefore, you can't escape glob
393 # using it.
392 # using it.
394 ([r'a\*', 'a*'], [r'a\*'] + self.filenames_start_with_a),
393 ([r'a\*', 'a*'], [r'a\*'] + self.filenames_start_with_a),
395 ([r'a\[012]'], [r'a\[012]']),
394 ([r'a\[012]'], [r'a\[012]']),
396 ]:
395 ]:
397 yield (self.check_match, patterns, matches)
396 yield (self.check_match, patterns, matches)
398
397
399
398
399 # TODO : pytest.mark.parametrise once nose is gone.
400 def test_unescape_glob():
400 def test_unescape_glob():
401 nt.assert_equal(path.unescape_glob(r'\*\[\!\]\?'), '*[!]?')
401 assert path.unescape_glob(r"\*\[\!\]\?") == "*[!]?"
402 nt.assert_equal(path.unescape_glob(r'\\*'), r'\*')
402 assert path.unescape_glob(r"\\*") == r"\*"
403 nt.assert_equal(path.unescape_glob(r'\\\*'), r'\*')
403 assert path.unescape_glob(r"\\\*") == r"\*"
404 nt.assert_equal(path.unescape_glob(r'\\a'), r'\a')
404 assert path.unescape_glob(r"\\a") == r"\a"
405 nt.assert_equal(path.unescape_glob(r'\a'), r'\a')
405 assert path.unescape_glob(r"\a") == r"\a"
406
406
407
407
408 @onlyif_unicode_paths
408 @onlyif_unicode_paths
409 def test_ensure_dir_exists():
409 def test_ensure_dir_exists():
410 with TemporaryDirectory() as td:
410 with TemporaryDirectory() as td:
411 d = os.path.join(td, 'βˆ‚ir')
411 d = os.path.join(td, 'βˆ‚ir')
412 path.ensure_dir_exists(d) # create it
412 path.ensure_dir_exists(d) # create it
413 assert os.path.isdir(d)
413 assert os.path.isdir(d)
414 path.ensure_dir_exists(d) # no-op
414 path.ensure_dir_exists(d) # no-op
415 f = os.path.join(td, 'Ζ’ile')
415 f = os.path.join(td, 'Ζ’ile')
416 open(f, 'w').close() # touch
416 open(f, 'w').close() # touch
417 with nt.assert_raises(IOError):
417 with nt.assert_raises(IOError):
418 path.ensure_dir_exists(f)
418 path.ensure_dir_exists(f)
419
419
420 class TestLinkOrCopy(unittest.TestCase):
420 class TestLinkOrCopy(unittest.TestCase):
421 def setUp(self):
421 def setUp(self):
422 self.tempdir = TemporaryDirectory()
422 self.tempdir = TemporaryDirectory()
423 self.src = self.dst("src")
423 self.src = self.dst("src")
424 with open(self.src, "w") as f:
424 with open(self.src, "w") as f:
425 f.write("Hello, world!")
425 f.write("Hello, world!")
426
426
427 def tearDown(self):
427 def tearDown(self):
428 self.tempdir.cleanup()
428 self.tempdir.cleanup()
429
429
430 def dst(self, *args):
430 def dst(self, *args):
431 return os.path.join(self.tempdir.name, *args)
431 return os.path.join(self.tempdir.name, *args)
432
432
433 def assert_inode_not_equal(self, a, b):
433 def assert_inode_not_equal(self, a, b):
434 nt.assert_not_equal(os.stat(a).st_ino, os.stat(b).st_ino,
434 assert (
435 "%r and %r do reference the same indoes" %(a, b))
435 os.stat(a).st_ino != os.stat(b).st_ino
436 ), "%r and %r do reference the same indoes" % (a, b)
436
437
437 def assert_inode_equal(self, a, b):
438 def assert_inode_equal(self, a, b):
438 nt.assert_equal(os.stat(a).st_ino, os.stat(b).st_ino,
439 assert (
439 "%r and %r do not reference the same indoes" %(a, b))
440 os.stat(a).st_ino == os.stat(b).st_ino
441 ), "%r and %r do not reference the same indoes" % (a, b)
440
442
441 def assert_content_equal(self, a, b):
443 def assert_content_equal(self, a, b):
442 with open(a) as a_f:
444 with open(a) as a_f:
443 with open(b) as b_f:
445 with open(b) as b_f:
444 nt.assert_equal(a_f.read(), b_f.read())
446 assert a_f.read() == b_f.read()
445
447
446 @skip_win32
448 @skip_win32
447 def test_link_successful(self):
449 def test_link_successful(self):
448 dst = self.dst("target")
450 dst = self.dst("target")
449 path.link_or_copy(self.src, dst)
451 path.link_or_copy(self.src, dst)
450 self.assert_inode_equal(self.src, dst)
452 self.assert_inode_equal(self.src, dst)
451
453
452 @skip_win32
454 @skip_win32
453 def test_link_into_dir(self):
455 def test_link_into_dir(self):
454 dst = self.dst("some_dir")
456 dst = self.dst("some_dir")
455 os.mkdir(dst)
457 os.mkdir(dst)
456 path.link_or_copy(self.src, dst)
458 path.link_or_copy(self.src, dst)
457 expected_dst = self.dst("some_dir", os.path.basename(self.src))
459 expected_dst = self.dst("some_dir", os.path.basename(self.src))
458 self.assert_inode_equal(self.src, expected_dst)
460 self.assert_inode_equal(self.src, expected_dst)
459
461
460 @skip_win32
462 @skip_win32
461 def test_target_exists(self):
463 def test_target_exists(self):
462 dst = self.dst("target")
464 dst = self.dst("target")
463 open(dst, "w").close()
465 open(dst, "w").close()
464 path.link_or_copy(self.src, dst)
466 path.link_or_copy(self.src, dst)
465 self.assert_inode_equal(self.src, dst)
467 self.assert_inode_equal(self.src, dst)
466
468
467 @skip_win32
469 @skip_win32
468 def test_no_link(self):
470 def test_no_link(self):
469 real_link = os.link
471 real_link = os.link
470 try:
472 try:
471 del os.link
473 del os.link
472 dst = self.dst("target")
474 dst = self.dst("target")
473 path.link_or_copy(self.src, dst)
475 path.link_or_copy(self.src, dst)
474 self.assert_content_equal(self.src, dst)
476 self.assert_content_equal(self.src, dst)
475 self.assert_inode_not_equal(self.src, dst)
477 self.assert_inode_not_equal(self.src, dst)
476 finally:
478 finally:
477 os.link = real_link
479 os.link = real_link
478
480
479 @skip_if_not_win32
481 @skip_if_not_win32
480 def test_windows(self):
482 def test_windows(self):
481 dst = self.dst("target")
483 dst = self.dst("target")
482 path.link_or_copy(self.src, dst)
484 path.link_or_copy(self.src, dst)
483 self.assert_content_equal(self.src, dst)
485 self.assert_content_equal(self.src, dst)
484
486
485 def test_link_twice(self):
487 def test_link_twice(self):
486 # Linking the same file twice shouldn't leave duplicates around.
488 # Linking the same file twice shouldn't leave duplicates around.
487 # See https://github.com/ipython/ipython/issues/6450
489 # See https://github.com/ipython/ipython/issues/6450
488 dst = self.dst('target')
490 dst = self.dst('target')
489 path.link_or_copy(self.src, dst)
491 path.link_or_copy(self.src, dst)
490 path.link_or_copy(self.src, dst)
492 path.link_or_copy(self.src, dst)
491 self.assert_inode_equal(self.src, dst)
493 self.assert_inode_equal(self.src, dst)
492 nt.assert_equal(sorted(os.listdir(self.tempdir.name)), ['src', 'target'])
494 assert sorted(os.listdir(self.tempdir.name)) == ["src", "target"]
@@ -1,195 +1,198 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Tests for platutils.py
3 Tests for platutils.py
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 import sys
17 import sys
18 import signal
18 import signal
19 import os
19 import os
20 import time
20 import time
21 from _thread import interrupt_main # Py 3
21 from _thread import interrupt_main # Py 3
22 import threading
22 import threading
23 from unittest import SkipTest
23 from unittest import SkipTest
24
24
25 import nose.tools as nt
25 import nose.tools as nt
26
26
27 from IPython.utils.process import (find_cmd, FindCmdError, arg_split,
27 from IPython.utils.process import (find_cmd, FindCmdError, arg_split,
28 system, getoutput, getoutputerror,
28 system, getoutput, getoutputerror,
29 get_output_error_code)
29 get_output_error_code)
30 from IPython.utils.capture import capture_output
30 from IPython.utils.capture import capture_output
31 from IPython.testing import decorators as dec
31 from IPython.testing import decorators as dec
32 from IPython.testing import tools as tt
32 from IPython.testing import tools as tt
33
33
34 python = os.path.basename(sys.executable)
34 python = os.path.basename(sys.executable)
35
35
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37 # Tests
37 # Tests
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39
39
40
40
41 @dec.skip_win32
41 @dec.skip_win32
42 def test_find_cmd_ls():
42 def test_find_cmd_ls():
43 """Make sure we can find the full path to ls."""
43 """Make sure we can find the full path to ls."""
44 path = find_cmd('ls')
44 path = find_cmd('ls')
45 nt.assert_true(path.endswith('ls'))
45 nt.assert_true(path.endswith('ls'))
46
46
47
47
48 def has_pywin32():
48 def has_pywin32():
49 try:
49 try:
50 import win32api
50 import win32api
51 except ImportError:
51 except ImportError:
52 return False
52 return False
53 return True
53 return True
54
54
55
55
56 @dec.onlyif(has_pywin32, "This test requires win32api to run")
56 @dec.onlyif(has_pywin32, "This test requires win32api to run")
57 def test_find_cmd_pythonw():
57 def test_find_cmd_pythonw():
58 """Try to find pythonw on Windows."""
58 """Try to find pythonw on Windows."""
59 path = find_cmd('pythonw')
59 path = find_cmd('pythonw')
60 assert path.lower().endswith('pythonw.exe'), path
60 assert path.lower().endswith('pythonw.exe'), path
61
61
62
62
63 @dec.onlyif(lambda : sys.platform != 'win32' or has_pywin32(),
63 @dec.onlyif(lambda : sys.platform != 'win32' or has_pywin32(),
64 "This test runs on posix or in win32 with win32api installed")
64 "This test runs on posix or in win32 with win32api installed")
65 def test_find_cmd_fail():
65 def test_find_cmd_fail():
66 """Make sure that FindCmdError is raised if we can't find the cmd."""
66 """Make sure that FindCmdError is raised if we can't find the cmd."""
67 nt.assert_raises(FindCmdError,find_cmd,'asdfasdf')
67 nt.assert_raises(FindCmdError,find_cmd,'asdfasdf')
68
68
69
69
70 # TODO: move to pytest.mark.parametrize once nose gone
70 @dec.skip_win32
71 @dec.skip_win32
71 def test_arg_split():
72 def test_arg_split():
72 """Ensure that argument lines are correctly split like in a shell."""
73 """Ensure that argument lines are correctly split like in a shell."""
73 tests = [['hi', ['hi']],
74 tests = [['hi', ['hi']],
74 [u'hi', [u'hi']],
75 [u'hi', [u'hi']],
75 ['hello there', ['hello', 'there']],
76 ['hello there', ['hello', 'there']],
76 # \u01ce == \N{LATIN SMALL LETTER A WITH CARON}
77 # \u01ce == \N{LATIN SMALL LETTER A WITH CARON}
77 # Do not use \N because the tests crash with syntax error in
78 # Do not use \N because the tests crash with syntax error in
78 # some cases, for example windows python2.6.
79 # some cases, for example windows python2.6.
79 [u'h\u01cello', [u'h\u01cello']],
80 [u'h\u01cello', [u'h\u01cello']],
80 ['something "with quotes"', ['something', '"with quotes"']],
81 ['something "with quotes"', ['something', '"with quotes"']],
81 ]
82 ]
82 for argstr, argv in tests:
83 for argstr, argv in tests:
83 nt.assert_equal(arg_split(argstr), argv)
84 assert arg_split(argstr) == argv
84
85
86
87 # TODO: move to pytest.mark.parametrize once nose gone
85 @dec.skip_if_not_win32
88 @dec.skip_if_not_win32
86 def test_arg_split_win32():
89 def test_arg_split_win32():
87 """Ensure that argument lines are correctly split like in a shell."""
90 """Ensure that argument lines are correctly split like in a shell."""
88 tests = [['hi', ['hi']],
91 tests = [['hi', ['hi']],
89 [u'hi', [u'hi']],
92 [u'hi', [u'hi']],
90 ['hello there', ['hello', 'there']],
93 ['hello there', ['hello', 'there']],
91 [u'h\u01cello', [u'h\u01cello']],
94 [u'h\u01cello', [u'h\u01cello']],
92 ['something "with quotes"', ['something', 'with quotes']],
95 ['something "with quotes"', ['something', 'with quotes']],
93 ]
96 ]
94 for argstr, argv in tests:
97 for argstr, argv in tests:
95 nt.assert_equal(arg_split(argstr), argv)
98 assert arg_split(argstr) == argv
96
99
97
100
98 class SubProcessTestCase(tt.TempFileMixin):
101 class SubProcessTestCase(tt.TempFileMixin):
99 def setUp(self):
102 def setUp(self):
100 """Make a valid python temp file."""
103 """Make a valid python temp file."""
101 lines = [ "import sys",
104 lines = [ "import sys",
102 "print('on stdout', end='', file=sys.stdout)",
105 "print('on stdout', end='', file=sys.stdout)",
103 "print('on stderr', end='', file=sys.stderr)",
106 "print('on stderr', end='', file=sys.stderr)",
104 "sys.stdout.flush()",
107 "sys.stdout.flush()",
105 "sys.stderr.flush()"]
108 "sys.stderr.flush()"]
106 self.mktmp('\n'.join(lines))
109 self.mktmp('\n'.join(lines))
107
110
108 def test_system(self):
111 def test_system(self):
109 status = system('%s "%s"' % (python, self.fname))
112 status = system('%s "%s"' % (python, self.fname))
110 self.assertEqual(status, 0)
113 self.assertEqual(status, 0)
111
114
112 def test_system_quotes(self):
115 def test_system_quotes(self):
113 status = system('%s -c "import sys"' % python)
116 status = system('%s -c "import sys"' % python)
114 self.assertEqual(status, 0)
117 self.assertEqual(status, 0)
115
118
116 def assert_interrupts(self, command):
119 def assert_interrupts(self, command):
117 """
120 """
118 Interrupt a subprocess after a second.
121 Interrupt a subprocess after a second.
119 """
122 """
120 if threading.main_thread() != threading.current_thread():
123 if threading.main_thread() != threading.current_thread():
121 raise nt.SkipTest("Can't run this test if not in main thread.")
124 raise nt.SkipTest("Can't run this test if not in main thread.")
122
125
123 # Some tests can overwrite SIGINT handler (by using pdb for example),
126 # Some tests can overwrite SIGINT handler (by using pdb for example),
124 # which then breaks this test, so just make sure it's operating
127 # which then breaks this test, so just make sure it's operating
125 # normally.
128 # normally.
126 signal.signal(signal.SIGINT, signal.default_int_handler)
129 signal.signal(signal.SIGINT, signal.default_int_handler)
127
130
128 def interrupt():
131 def interrupt():
129 # Wait for subprocess to start:
132 # Wait for subprocess to start:
130 time.sleep(0.5)
133 time.sleep(0.5)
131 interrupt_main()
134 interrupt_main()
132
135
133 threading.Thread(target=interrupt).start()
136 threading.Thread(target=interrupt).start()
134 start = time.time()
137 start = time.time()
135 try:
138 try:
136 result = command()
139 result = command()
137 except KeyboardInterrupt:
140 except KeyboardInterrupt:
138 # Success!
141 # Success!
139 pass
142 pass
140 end = time.time()
143 end = time.time()
141 self.assertTrue(
144 self.assertTrue(
142 end - start < 2, "Process didn't die quickly: %s" % (end - start)
145 end - start < 2, "Process didn't die quickly: %s" % (end - start)
143 )
146 )
144 return result
147 return result
145
148
146 def test_system_interrupt(self):
149 def test_system_interrupt(self):
147 """
150 """
148 When interrupted in the way ipykernel interrupts IPython, the
151 When interrupted in the way ipykernel interrupts IPython, the
149 subprocess is interrupted.
152 subprocess is interrupted.
150 """
153 """
151 def command():
154 def command():
152 return system('%s -c "import time; time.sleep(5)"' % python)
155 return system('%s -c "import time; time.sleep(5)"' % python)
153
156
154 status = self.assert_interrupts(command)
157 status = self.assert_interrupts(command)
155 self.assertNotEqual(
158 self.assertNotEqual(
156 status, 0, "The process wasn't interrupted. Status: %s" % (status,)
159 status, 0, "The process wasn't interrupted. Status: %s" % (status,)
157 )
160 )
158
161
159 def test_getoutput(self):
162 def test_getoutput(self):
160 out = getoutput('%s "%s"' % (python, self.fname))
163 out = getoutput('%s "%s"' % (python, self.fname))
161 # we can't rely on the order the line buffered streams are flushed
164 # we can't rely on the order the line buffered streams are flushed
162 try:
165 try:
163 self.assertEqual(out, 'on stderron stdout')
166 self.assertEqual(out, 'on stderron stdout')
164 except AssertionError:
167 except AssertionError:
165 self.assertEqual(out, 'on stdouton stderr')
168 self.assertEqual(out, 'on stdouton stderr')
166
169
167 def test_getoutput_quoted(self):
170 def test_getoutput_quoted(self):
168 out = getoutput('%s -c "print (1)"' % python)
171 out = getoutput('%s -c "print (1)"' % python)
169 self.assertEqual(out.strip(), '1')
172 self.assertEqual(out.strip(), '1')
170
173
171 #Invalid quoting on windows
174 #Invalid quoting on windows
172 @dec.skip_win32
175 @dec.skip_win32
173 def test_getoutput_quoted2(self):
176 def test_getoutput_quoted2(self):
174 out = getoutput("%s -c 'print (1)'" % python)
177 out = getoutput("%s -c 'print (1)'" % python)
175 self.assertEqual(out.strip(), '1')
178 self.assertEqual(out.strip(), '1')
176 out = getoutput("%s -c 'print (\"1\")'" % python)
179 out = getoutput("%s -c 'print (\"1\")'" % python)
177 self.assertEqual(out.strip(), '1')
180 self.assertEqual(out.strip(), '1')
178
181
179 def test_getoutput_error(self):
182 def test_getoutput_error(self):
180 out, err = getoutputerror('%s "%s"' % (python, self.fname))
183 out, err = getoutputerror('%s "%s"' % (python, self.fname))
181 self.assertEqual(out, 'on stdout')
184 self.assertEqual(out, 'on stdout')
182 self.assertEqual(err, 'on stderr')
185 self.assertEqual(err, 'on stderr')
183
186
184 def test_get_output_error_code(self):
187 def test_get_output_error_code(self):
185 quiet_exit = '%s -c "import sys; sys.exit(1)"' % python
188 quiet_exit = '%s -c "import sys; sys.exit(1)"' % python
186 out, err, code = get_output_error_code(quiet_exit)
189 out, err, code = get_output_error_code(quiet_exit)
187 self.assertEqual(out, '')
190 self.assertEqual(out, '')
188 self.assertEqual(err, '')
191 self.assertEqual(err, '')
189 self.assertEqual(code, 1)
192 self.assertEqual(code, 1)
190 out, err, code = get_output_error_code('%s "%s"' % (python, self.fname))
193 out, err, code = get_output_error_code('%s "%s"' % (python, self.fname))
191 self.assertEqual(out, 'on stdout')
194 self.assertEqual(out, 'on stdout')
192 self.assertEqual(err, 'on stderr')
195 self.assertEqual(err, 'on stderr')
193 self.assertEqual(code, 0)
196 self.assertEqual(code, 0)
194
197
195
198
@@ -1,200 +1,205 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.text"""
2 """Tests for IPython.utils.text"""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2011 The IPython Development Team
5 # Copyright (C) 2011 The IPython Development Team
6 #
6 #
7 # Distributed under the terms of the BSD License. The full license is in
7 # Distributed under the terms of the BSD License. The full license is in
8 # the file COPYING, distributed as part of this software.
8 # the file COPYING, distributed as part of this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 import os
15 import os
16 import math
16 import math
17 import random
17 import random
18 import sys
18 import sys
19
19
20 import nose.tools as nt
20 import nose.tools as nt
21 from pathlib import Path
21 from pathlib import Path
22
22
23 from IPython.utils import text
23 from IPython.utils import text
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Globals
26 # Globals
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 def test_columnize():
29 def test_columnize():
30 """Basic columnize tests."""
30 """Basic columnize tests."""
31 size = 5
31 size = 5
32 items = [l*size for l in 'abcd']
32 items = [l*size for l in 'abcd']
33
33
34 out = text.columnize(items, displaywidth=80)
34 out = text.columnize(items, displaywidth=80)
35 nt.assert_equal(out, 'aaaaa bbbbb ccccc ddddd\n')
35 assert out == "aaaaa bbbbb ccccc ddddd\n"
36 out = text.columnize(items, displaywidth=25)
36 out = text.columnize(items, displaywidth=25)
37 nt.assert_equal(out, 'aaaaa ccccc\nbbbbb ddddd\n')
37 assert out == "aaaaa ccccc\nbbbbb ddddd\n"
38 out = text.columnize(items, displaywidth=12)
38 out = text.columnize(items, displaywidth=12)
39 nt.assert_equal(out, 'aaaaa ccccc\nbbbbb ddddd\n')
39 assert out == "aaaaa ccccc\nbbbbb ddddd\n"
40 out = text.columnize(items, displaywidth=10)
40 out = text.columnize(items, displaywidth=10)
41 nt.assert_equal(out, 'aaaaa\nbbbbb\nccccc\nddddd\n')
41 assert out == "aaaaa\nbbbbb\nccccc\nddddd\n"
42
42
43 out = text.columnize(items, row_first=True, displaywidth=80)
43 out = text.columnize(items, row_first=True, displaywidth=80)
44 nt.assert_equal(out, 'aaaaa bbbbb ccccc ddddd\n')
44 assert out == "aaaaa bbbbb ccccc ddddd\n"
45 out = text.columnize(items, row_first=True, displaywidth=25)
45 out = text.columnize(items, row_first=True, displaywidth=25)
46 nt.assert_equal(out, 'aaaaa bbbbb\nccccc ddddd\n')
46 assert out == "aaaaa bbbbb\nccccc ddddd\n"
47 out = text.columnize(items, row_first=True, displaywidth=12)
47 out = text.columnize(items, row_first=True, displaywidth=12)
48 nt.assert_equal(out, 'aaaaa bbbbb\nccccc ddddd\n')
48 assert out == "aaaaa bbbbb\nccccc ddddd\n"
49 out = text.columnize(items, row_first=True, displaywidth=10)
49 out = text.columnize(items, row_first=True, displaywidth=10)
50 nt.assert_equal(out, 'aaaaa\nbbbbb\nccccc\nddddd\n')
50 assert out == "aaaaa\nbbbbb\nccccc\nddddd\n"
51
51
52 out = text.columnize(items, displaywidth=40, spread=True)
52 out = text.columnize(items, displaywidth=40, spread=True)
53 nt.assert_equal(out, 'aaaaa bbbbb ccccc ddddd\n')
53 assert out == "aaaaa bbbbb ccccc ddddd\n"
54 out = text.columnize(items, displaywidth=20, spread=True)
54 out = text.columnize(items, displaywidth=20, spread=True)
55 nt.assert_equal(out, 'aaaaa ccccc\nbbbbb ddddd\n')
55 assert out == "aaaaa ccccc\nbbbbb ddddd\n"
56 out = text.columnize(items, displaywidth=12, spread=True)
56 out = text.columnize(items, displaywidth=12, spread=True)
57 nt.assert_equal(out, 'aaaaa ccccc\nbbbbb ddddd\n')
57 assert out == "aaaaa ccccc\nbbbbb ddddd\n"
58 out = text.columnize(items, displaywidth=10, spread=True)
58 out = text.columnize(items, displaywidth=10, spread=True)
59 nt.assert_equal(out, 'aaaaa\nbbbbb\nccccc\nddddd\n')
59 assert out == "aaaaa\nbbbbb\nccccc\nddddd\n"
60
60
61
61
62 def test_columnize_random():
62 def test_columnize_random():
63 """Test with random input to hopefully catch edge case """
63 """Test with random input to hopefully catch edge case """
64 for row_first in [True, False]:
64 for row_first in [True, False]:
65 for nitems in [random.randint(2,70) for i in range(2,20)]:
65 for nitems in [random.randint(2,70) for i in range(2,20)]:
66 displaywidth = random.randint(20,200)
66 displaywidth = random.randint(20,200)
67 rand_len = [random.randint(2,displaywidth) for i in range(nitems)]
67 rand_len = [random.randint(2,displaywidth) for i in range(nitems)]
68 items = ['x'*l for l in rand_len]
68 items = ['x'*l for l in rand_len]
69 out = text.columnize(items, row_first=row_first, displaywidth=displaywidth)
69 out = text.columnize(items, row_first=row_first, displaywidth=displaywidth)
70 longer_line = max([len(x) for x in out.split('\n')])
70 longer_line = max([len(x) for x in out.split('\n')])
71 longer_element = max(rand_len)
71 longer_element = max(rand_len)
72 if longer_line > displaywidth:
72 if longer_line > displaywidth:
73 print("Columnize displayed something lager than displaywidth : %s " % longer_line)
73 print("Columnize displayed something lager than displaywidth : %s " % longer_line)
74 print("longer element : %s " % longer_element)
74 print("longer element : %s " % longer_element)
75 print("displaywidth : %s " % displaywidth)
75 print("displaywidth : %s " % displaywidth)
76 print("number of element : %s " % nitems)
76 print("number of element : %s " % nitems)
77 print("size of each element :\n %s" % rand_len)
77 print("size of each element :\n %s" % rand_len)
78 assert False, "row_first={0}".format(row_first)
78 assert False, "row_first={0}".format(row_first)
79
79
80
81 # TODO: pytest mark.parametrize once nose removed.
80 def test_columnize_medium():
82 def test_columnize_medium():
81 """Test with inputs than shouldn't be wider than 80"""
83 """Test with inputs than shouldn't be wider than 80"""
82 size = 40
84 size = 40
83 items = [l*size for l in 'abc']
85 items = [l*size for l in 'abc']
84 for row_first in [True, False]:
86 for row_first in [True, False]:
85 out = text.columnize(items, row_first=row_first, displaywidth=80)
87 out = text.columnize(items, row_first=row_first, displaywidth=80)
86 nt.assert_equal(out, '\n'.join(items+['']), "row_first={0}".format(row_first))
88 assert out == "\n".join(items + [""]), "row_first={0}".format(row_first)
89
87
90
91 # TODO: pytest mark.parametrize once nose removed.
88 def test_columnize_long():
92 def test_columnize_long():
89 """Test columnize with inputs longer than the display window"""
93 """Test columnize with inputs longer than the display window"""
90 size = 11
94 size = 11
91 items = [l*size for l in 'abc']
95 items = [l*size for l in 'abc']
92 for row_first in [True, False]:
96 for row_first in [True, False]:
93 out = text.columnize(items, row_first=row_first, displaywidth=size-1)
97 out = text.columnize(items, row_first=row_first, displaywidth=size - 1)
94 nt.assert_equal(out, '\n'.join(items+['']), "row_first={0}".format(row_first))
98 assert out == "\n".join(items + [""]), "row_first={0}".format(row_first)
99
95
100
96 def eval_formatter_check(f):
101 def eval_formatter_check(f):
97 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os, u=u"cafΓ©", b="cafΓ©")
102 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os, u=u"cafΓ©", b="cafΓ©")
98 s = f.format("{n} {n//4} {stuff.split()[0]}", **ns)
103 s = f.format("{n} {n//4} {stuff.split()[0]}", **ns)
99 nt.assert_equal(s, "12 3 hello")
104 assert s == "12 3 hello"
100 s = f.format(' '.join(['{n//%i}'%i for i in range(1,8)]), **ns)
105 s = f.format(' '.join(['{n//%i}'%i for i in range(1,8)]), **ns)
101 nt.assert_equal(s, "12 6 4 3 2 2 1")
106 assert s == "12 6 4 3 2 2 1"
102 s = f.format('{[n//i for i in range(1,8)]}', **ns)
107 s = f.format('{[n//i for i in range(1,8)]}', **ns)
103 nt.assert_equal(s, "[12, 6, 4, 3, 2, 2, 1]")
108 assert s == "[12, 6, 4, 3, 2, 2, 1]"
104 s = f.format("{stuff!s}", **ns)
109 s = f.format("{stuff!s}", **ns)
105 nt.assert_equal(s, ns['stuff'])
110 assert s == ns["stuff"]
106 s = f.format("{stuff!r}", **ns)
111 s = f.format("{stuff!r}", **ns)
107 nt.assert_equal(s, repr(ns['stuff']))
112 assert s == repr(ns["stuff"])
108
113
109 # Check with unicode:
114 # Check with unicode:
110 s = f.format("{u}", **ns)
115 s = f.format("{u}", **ns)
111 nt.assert_equal(s, ns['u'])
116 assert s == ns["u"]
112 # This decodes in a platform dependent manner, but it shouldn't error out
117 # This decodes in a platform dependent manner, but it shouldn't error out
113 s = f.format("{b}", **ns)
118 s = f.format("{b}", **ns)
114
119
115 nt.assert_raises(NameError, f.format, '{dne}', **ns)
120 nt.assert_raises(NameError, f.format, '{dne}', **ns)
116
121
117 def eval_formatter_slicing_check(f):
122 def eval_formatter_slicing_check(f):
118 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os)
123 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os)
119 s = f.format(" {stuff.split()[:]} ", **ns)
124 s = f.format(" {stuff.split()[:]} ", **ns)
120 nt.assert_equal(s, " ['hello', 'there'] ")
125 assert s == " ['hello', 'there'] "
121 s = f.format(" {stuff.split()[::-1]} ", **ns)
126 s = f.format(" {stuff.split()[::-1]} ", **ns)
122 nt.assert_equal(s, " ['there', 'hello'] ")
127 assert s == " ['there', 'hello'] "
123 s = f.format("{stuff[::2]}", **ns)
128 s = f.format("{stuff[::2]}", **ns)
124 nt.assert_equal(s, ns['stuff'][::2])
129 assert s == ns["stuff"][::2]
125
130
126 nt.assert_raises(SyntaxError, f.format, "{n:x}", **ns)
131 nt.assert_raises(SyntaxError, f.format, "{n:x}", **ns)
127
132
128 def eval_formatter_no_slicing_check(f):
133 def eval_formatter_no_slicing_check(f):
129 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os)
134 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os)
130
135
131 s = f.format('{n:x} {pi**2:+f}', **ns)
136 s = f.format('{n:x} {pi**2:+f}', **ns)
132 nt.assert_equal(s, "c +9.869604")
137 assert s == "c +9.869604"
133
138
134 s = f.format('{stuff[slice(1,4)]}', **ns)
139 s = f.format("{stuff[slice(1,4)]}", **ns)
135 nt.assert_equal(s, 'ell')
140 assert s == "ell"
136
141
137 s = f.format("{a[:]}", a=[1, 2])
142 s = f.format("{a[:]}", a=[1, 2])
138 nt.assert_equal(s, "[1, 2]")
143 assert s == "[1, 2]"
139
144
140 def test_eval_formatter():
145 def test_eval_formatter():
141 f = text.EvalFormatter()
146 f = text.EvalFormatter()
142 eval_formatter_check(f)
147 eval_formatter_check(f)
143 eval_formatter_no_slicing_check(f)
148 eval_formatter_no_slicing_check(f)
144
149
145 def test_full_eval_formatter():
150 def test_full_eval_formatter():
146 f = text.FullEvalFormatter()
151 f = text.FullEvalFormatter()
147 eval_formatter_check(f)
152 eval_formatter_check(f)
148 eval_formatter_slicing_check(f)
153 eval_formatter_slicing_check(f)
149
154
150 def test_dollar_formatter():
155 def test_dollar_formatter():
151 f = text.DollarFormatter()
156 f = text.DollarFormatter()
152 eval_formatter_check(f)
157 eval_formatter_check(f)
153 eval_formatter_slicing_check(f)
158 eval_formatter_slicing_check(f)
154
159
155 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os)
160 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os)
156 s = f.format("$n", **ns)
161 s = f.format("$n", **ns)
157 nt.assert_equal(s, "12")
162 assert s == "12"
158 s = f.format("$n.real", **ns)
163 s = f.format("$n.real", **ns)
159 nt.assert_equal(s, "12")
164 assert s == "12"
160 s = f.format("$n/{stuff[:5]}", **ns)
165 s = f.format("$n/{stuff[:5]}", **ns)
161 nt.assert_equal(s, "12/hello")
166 assert s == "12/hello"
162 s = f.format("$n $$HOME", **ns)
167 s = f.format("$n $$HOME", **ns)
163 nt.assert_equal(s, "12 $HOME")
168 assert s == "12 $HOME"
164 s = f.format("${foo}", foo="HOME")
169 s = f.format("${foo}", foo="HOME")
165 nt.assert_equal(s, "$HOME")
170 assert s == "$HOME"
166
171
167
172
168 def test_strip_email():
173 def test_strip_email():
169 src = """\
174 src = """\
170 >> >>> def f(x):
175 >> >>> def f(x):
171 >> ... return x+1
176 >> ... return x+1
172 >> ...
177 >> ...
173 >> >>> zz = f(2.5)"""
178 >> >>> zz = f(2.5)"""
174 cln = """\
179 cln = """\
175 >>> def f(x):
180 >>> def f(x):
176 ... return x+1
181 ... return x+1
177 ...
182 ...
178 >>> zz = f(2.5)"""
183 >>> zz = f(2.5)"""
179 nt.assert_equal(text.strip_email_quotes(src), cln)
184 assert text.strip_email_quotes(src) == cln
180
185
181
186
182 def test_strip_email2():
187 def test_strip_email2():
183 src = '> > > list()'
188 src = '> > > list()'
184 cln = 'list()'
189 cln = 'list()'
185 nt.assert_equal(text.strip_email_quotes(src), cln)
190 assert text.strip_email_quotes(src) == cln
186
191
187 def test_LSString():
192 def test_LSString():
188 lss = text.LSString("abc\ndef")
193 lss = text.LSString("abc\ndef")
189 nt.assert_equal(lss.l, ['abc', 'def'])
194 assert lss.l == ["abc", "def"]
190 nt.assert_equal(lss.s, 'abc def')
195 assert lss.s == "abc def"
191 lss = text.LSString(os.getcwd())
196 lss = text.LSString(os.getcwd())
192 nt.assert_is_instance(lss.p[0], Path)
197 nt.assert_is_instance(lss.p[0], Path)
193
198
194 def test_SList():
199 def test_SList():
195 sl = text.SList(['a 11', 'b 1', 'a 2'])
200 sl = text.SList(["a 11", "b 1", "a 2"])
196 nt.assert_equal(sl.n, 'a 11\nb 1\na 2')
201 assert sl.n == "a 11\nb 1\na 2"
197 nt.assert_equal(sl.s, 'a 11 b 1 a 2')
202 assert sl.s == "a 11 b 1 a 2"
198 nt.assert_equal(sl.grep(lambda x: x.startswith('a')), text.SList(['a 11', 'a 2']))
203 assert sl.grep(lambda x: x.startswith("a")) == text.SList(["a 11", "a 2"])
199 nt.assert_equal(sl.fields(0), text.SList(['a', 'b', 'a']))
204 assert sl.fields(0) == text.SList(["a", "b", "a"])
200 nt.assert_equal(sl.sort(field=1, nums=True), text.SList(['b 1', 'a 2', 'a 11']))
205 assert sl.sort(field=1, nums=True) == text.SList(["b 1", "a 2", "a 11"])
General Comments 0
You need to be logged in to leave comments. Login now