Show More
@@ -85,7 +85,7 b' import re' | |||
|
85 | 85 | import datetime |
|
86 | 86 | from collections import deque |
|
87 | 87 | |
|
88 | from IPython.utils.py3compat import PY3, cast_unicode | |
|
88 | from IPython.utils.py3compat import PY3, cast_unicode, string_types | |
|
89 | 89 | from IPython.utils.encoding import get_stream_enc |
|
90 | 90 | |
|
91 | 91 | from io import StringIO |
@@ -671,7 +671,16 b' def _type_pprint(obj, p, cycle):' | |||
|
671 | 671 | return |
|
672 | 672 | |
|
673 | 673 | mod = _safe_getattr(obj, '__module__', None) |
|
674 | name = _safe_getattr(obj, '__qualname__', obj.__name__) | |
|
674 | try: | |
|
675 | name = obj.__qualname__ | |
|
676 | if not isinstance(name, string_types): | |
|
677 | # This can happen if the type implements __qualname__ as a property | |
|
678 | # or other descriptor in Python 2. | |
|
679 | raise Exception("Try __name__") | |
|
680 | except Exception: | |
|
681 | name = obj.__name__ | |
|
682 | if not isinstance(name, string_types): | |
|
683 | name = '<unknown type>' | |
|
675 | 684 | |
|
676 | 685 | if mod in (None, '__builtin__', 'builtins', 'exceptions'): |
|
677 | 686 | p.text(name) |
@@ -11,7 +11,7 b' from collections import Counter, defaultdict, deque, OrderedDict' | |||
|
11 | 11 | import nose.tools as nt |
|
12 | 12 | |
|
13 | 13 | from IPython.lib import pretty |
|
14 | from IPython.testing.decorators import skip_without | |
|
14 | from IPython.testing.decorators import skip_without, py2_only | |
|
15 | 15 | from IPython.utils.py3compat import PY3, unicode_to_str |
|
16 | 16 | |
|
17 | 17 | if PY3: |
@@ -272,6 +272,83 b' def test_basic_class():' | |||
|
272 | 272 | nt.assert_true(type_pprint_wrapper.called) |
|
273 | 273 | |
|
274 | 274 | |
|
275 | # This is only run on Python 2 because in Python 3 the language prevents you | |
|
276 | # from setting a non-unicode value for __qualname__ on a metaclass, and it | |
|
277 | # doesn't respect the descriptor protocol if you subclass unicode and implement | |
|
278 | # __get__. | |
|
279 | @py2_only | |
|
280 | def test_fallback_to__name__on_type(): | |
|
281 | # Test that we correctly repr types that have non-string values for | |
|
282 | # __qualname__ by falling back to __name__ | |
|
283 | ||
|
284 | class Type(object): | |
|
285 | __qualname__ = 5 | |
|
286 | ||
|
287 | # Test repring of the type. | |
|
288 | stream = StringIO() | |
|
289 | printer = pretty.RepresentationPrinter(stream) | |
|
290 | ||
|
291 | printer.pretty(Type) | |
|
292 | printer.flush() | |
|
293 | output = stream.getvalue() | |
|
294 | ||
|
295 | # If __qualname__ is malformed, we should fall back to __name__. | |
|
296 | expected = '.'.join([__name__, Type.__name__]) | |
|
297 | nt.assert_equal(output, expected) | |
|
298 | ||
|
299 | # Clear stream buffer. | |
|
300 | stream.buf = '' | |
|
301 | ||
|
302 | # Test repring of an instance of the type. | |
|
303 | instance = Type() | |
|
304 | printer.pretty(instance) | |
|
305 | printer.flush() | |
|
306 | output = stream.getvalue() | |
|
307 | ||
|
308 | # Should look like: | |
|
309 | # <IPython.lib.tests.test_pretty.Type at 0x7f7658ae07d0> | |
|
310 | prefix = '<' + '.'.join([__name__, Type.__name__]) + ' at 0x' | |
|
311 | nt.assert_true(output.startswith(prefix)) | |
|
312 | ||
|
313 | ||
|
314 | @py2_only | |
|
315 | def test_fail_gracefully_on_bogus__qualname__and__name__(): | |
|
316 | # Test that we correctly repr types that have non-string values for both | |
|
317 | # __qualname__ and __name__ | |
|
318 | ||
|
319 | class Meta(type): | |
|
320 | __name__ = 5 | |
|
321 | ||
|
322 | class Type(object): | |
|
323 | __metaclass__ = Meta | |
|
324 | __qualname__ = 5 | |
|
325 | ||
|
326 | stream = StringIO() | |
|
327 | printer = pretty.RepresentationPrinter(stream) | |
|
328 | ||
|
329 | printer.pretty(Type) | |
|
330 | printer.flush() | |
|
331 | output = stream.getvalue() | |
|
332 | ||
|
333 | # If we can't find __name__ or __qualname__ just use a sentinel string. | |
|
334 | expected = '.'.join([__name__, '<unknown type>']) | |
|
335 | nt.assert_equal(output, expected) | |
|
336 | ||
|
337 | # Clear stream buffer. | |
|
338 | stream.buf = '' | |
|
339 | ||
|
340 | # Test repring of an instance of the type. | |
|
341 | instance = Type() | |
|
342 | printer.pretty(instance) | |
|
343 | printer.flush() | |
|
344 | output = stream.getvalue() | |
|
345 | ||
|
346 | # Should look like: | |
|
347 | # <IPython.lib.tests.test_pretty.<unknown type> at 0x7f7658ae07d0> | |
|
348 | prefix = '<' + '.'.join([__name__, '<unknown type>']) + ' at 0x' | |
|
349 | nt.assert_true(output.startswith(prefix)) | |
|
350 | ||
|
351 | ||
|
275 | 352 | def test_collections_defaultdict(): |
|
276 | 353 | # Create defaultdicts with cycles |
|
277 | 354 | a = defaultdict() |
@@ -48,7 +48,7 b' from .ipunittest import ipdoctest, ipdocstring' | |||
|
48 | 48 | from IPython.external.decorators import * |
|
49 | 49 | |
|
50 | 50 | # For onlyif_cmd_exists decorator |
|
51 | from IPython.utils.py3compat import string_types, which | |
|
51 | from IPython.utils.py3compat import string_types, which, PY2, PY3 | |
|
52 | 52 | |
|
53 | 53 | #----------------------------------------------------------------------------- |
|
54 | 54 | # Classes and functions |
@@ -336,6 +336,9 b" skip_known_failure = knownfailureif(True,'This test is known to fail')" | |||
|
336 | 336 | known_failure_py3 = knownfailureif(sys.version_info[0] >= 3, |
|
337 | 337 | 'This test is known to fail on Python 3.') |
|
338 | 338 | |
|
339 | py2_only = skipif(PY3, "This test only runs on Python 2.") | |
|
340 | py3_only = skipif(PY2, "This test only runs on Python 3.") | |
|
341 | ||
|
339 | 342 | # A null 'decorator', useful to make more readable code that needs to pick |
|
340 | 343 | # between different decorators based on OS or other conditions |
|
341 | 344 | null_deco = lambda f: f |
General Comments 0
You need to be logged in to leave comments.
Login now