text: # coding: utf-8
  """Tests for IPython.lib.pretty."""
  
  # Copyright (c) IPython Development Team.
  # Distributed under the terms of the Modified BSD License.
  
  from __future__ import print_function
  
  from collections import Counter, defaultdict, deque, OrderedDict
  import types, string, ctypes
  
  import nose.tools as nt
  
  from IPython.lib import pretty
  from IPython.testing.decorators import (skip_without, py2_only, py3_only,
                                          cpython2_only)
  from IPython.utils.py3compat import PY3, unicode_to_str
  
  if PY3:
      from io import StringIO
  else:
      from StringIO import StringIO
  
  
  class MyList(object):
      def __init__(self, content):
          self.content = content
      def _repr_pretty_(self, p, cycle):
          if cycle:
              p.text("MyList(...)")
          else:
              with p.group(3, "MyList(", ")"):
                  for (i, child) in enumerate(self.content):
                      if i:
                          p.text(",")
                          p.breakable()
                      else:
                          p.breakable("")
                      p.pretty(child)
  
  
  class MyDict(dict):
      def _repr_pretty_(self, p, cycle):
          p.text("MyDict(...)")
  
  class MyObj(object):
      def somemethod(self):
          pass
  
  
  class Dummy1(object):
      def _repr_pretty_(self, p, cycle):
          p.text("Dummy1(...)")
  
  class Dummy2(Dummy1):
      _repr_pretty_ = None
  
  class NoModule(object):
      pass
  
  NoModule.__module__ = None
  
  class Breaking(object):
      def _repr_pretty_(self, p, cycle):
          with p.group(4,"TG: ",":"):
              p.text("Breaking(")
              p.break_()
              p.text(")")
  
  class BreakingRepr(object):
      def __repr__(self):
          return "Breaking(\n)"
  
  class BreakingReprParent(object):
      def _repr_pretty_(self, p, cycle):
          with p.group(4,"TG: ",":"):
              p.pretty(BreakingRepr())
  
  class BadRepr(object):
      
      def __repr__(self):
          return 1/0
  
  
  def test_indentation():
      """Test correct indentation in groups"""
      count = 40
      gotoutput = pretty.pretty(MyList(range(count)))
      expectedoutput = "MyList(\n" + ",\n".join("   %d" % i for i in range(count)) + ")"
  
      nt.assert_equal(gotoutput, expectedoutput)
  
  
  def test_dispatch():
      """
      Test correct dispatching: The _repr_pretty_ method for MyDict
      must be found before the registered printer for dict.
      """
      gotoutput = pretty.pretty(MyDict())
      expectedoutput = "MyDict(...)"
  
      nt.assert_equal(gotoutput, expectedoutput)
  
  
  def test_callability_checking():
      """
      Test that the _repr_pretty_ method is tested for callability and skipped if
      not.
      """
      gotoutput = pretty.pretty(Dummy2())
      expectedoutput = "Dummy1(...)"
  
      nt.assert_equal(gotoutput, expectedoutput)
  
  
  def test_sets():
      """
      Test that set and frozenset use Python 3 formatting.
      """
      objects = [set(), frozenset(), set([1]), frozenset([1]), set([1, 2]),
          frozenset([1, 2]), set([-1, -2, -3])]
      expected = ['set()', 'frozenset()', '{1}', 'frozenset({1})', '{1, 2}',
          'frozenset({1, 2})', '{-3, -2, -1}']
      for obj, expected_output in zip(objects, expected):
          got_output = pretty.pretty(obj)
          yield nt.assert_equal, got_output, expected_output
  
  
  @skip_without('xxlimited')
  def test_pprint_heap_allocated_type():
      """
      Test that pprint works for heap allocated types.
      """
      import xxlimited
      output = pretty.pretty(xxlimited.Null)
      nt.assert_equal(output, 'xxlimited.Null')
  
  def test_pprint_nomod():
      """
      Test that pprint works for classes with no __module__.
      """
      output = pretty.pretty(NoModule)
      nt.assert_equal(output, 'NoModule')
      
  def test_pprint_break():
      """
      Test that p.break_ produces expected output
      """
      output = pretty.pretty(Breaking())
      expected = "TG: Breaking(\n    ):"
      nt.assert_equal(output, expected)
  
  def test_pprint_break_repr():
      """
      Test that p.break_ is used in repr
      """
      output = pretty.pretty(BreakingReprParent())
      expected = "TG: Breaking(\n    ):"
      nt.assert_equal(output, expected)
  
  def test_bad_repr():
      """Don't catch bad repr errors"""
      with nt.assert_raises(ZeroDivisionError):
          output = pretty.pretty(BadRepr())
  
  class BadException(Exception):
      def __str__(self):
          return -1
  
  class ReallyBadRepr(object):
      __module__ = 1
      @property
      def __class__(self):
          raise ValueError("I am horrible")
      
      def __repr__(self):
          raise BadException()
  
  def test_really_bad_repr():
      with nt.assert_raises(BadException):
          output = pretty.pretty(ReallyBadRepr())
  
  
  class SA(object):
      pass
  
  class SB(SA):
      pass
  
  def test_super_repr():
      # "<super: module_name.SA, None>"
      output = pretty.pretty(super(SA))
      nt.assert_regexp_matches(output, r"<super: \S+.SA, None>")
  
      # "<super: module_name.SA, <module_name.SB at 0x...>>"
      sb = SB()
      output = pretty.pretty(super(SA, sb))
      nt.assert_regexp_matches(output, r"<super: \S+.SA,\s+<\S+.SB at 0x\S+>>")
  
  
  def test_long_list():
      lis = list(range(10000))
      p = pretty.pretty(lis)
      last2 = p.rsplit('\n', 2)[-2:]
      nt.assert_equal(last2, [' 999,', ' ...]'])
  
  def test_long_set():
      s = set(range(10000))
      p = pretty.pretty(s)
      last2 = p.rsplit('\n', 2)[-2:]
      nt.assert_equal(last2, [' 999,', ' ...}'])
  
  def test_long_tuple():
      tup = tuple(range(10000))
      p = pretty.pretty(tup)
      last2 = p.rsplit('\n', 2)[-2:]
      nt.assert_equal(last2, [' 999,', ' ...)'])
  
  def test_long_dict():
      d = { n:n for n in range(10000) }
      p = pretty.pretty(d)
      last2 = p.rsplit('\n', 2)[-2:]
      nt.assert_equal(last2, [' 999: 999,', ' ...}'])
  
  def test_unbound_method():
      output = pretty.pretty(MyObj.somemethod)
      nt.assert_in('MyObj.somemethod', output)
  
  
  class MetaClass(type):
      def __new__(cls, name):
          return type.__new__(cls, name, (object,), {'name': name})
  
      def __repr__(self):
          return "[CUSTOM REPR FOR CLASS %s]" % self.name
  
  
  ClassWithMeta = MetaClass('ClassWithMeta')
  
  
  def test_metaclass_repr():
      output = pretty.pretty(ClassWithMeta)
      nt.assert_equal(output, "[CUSTOM REPR FOR CLASS ClassWithMeta]")
  
  
  def test_unicode_repr():
      u = u"üniçodé"
      ustr = unicode_to_str(u)
      
      class C(object):
          def __repr__(self):
              return ustr
      
      c = C()
      p = pretty.pretty(c)
      nt.assert_equal(p, u)
      p = pretty.pretty([c])
      nt.assert_equal(p, u'[%s]' % u)
  
  
  def test_basic_class():
      def type_pprint_wrapper(obj, p, cycle):
          if obj is MyObj:
              type_pprint_wrapper.called = True
          return pretty._type_pprint(obj, p, cycle)
      type_pprint_wrapper.called = False
  
      stream = StringIO()
      printer = pretty.RepresentationPrinter(stream)
      printer.type_pprinters[type] = type_pprint_wrapper
      printer.pretty(MyObj)
      printer.flush()
      output = stream.getvalue()
  
      nt.assert_equal(output, '%s.MyObj' % __name__)
      nt.assert_true(type_pprint_wrapper.called)
  
  
  # This is only run on Python 2 because in Python 3 the language prevents you
  # from setting a non-unicode value for __qualname__ on a metaclass, and it
  # doesn't respect the descriptor protocol if you subclass unicode and implement
  # __get__.
  @py2_only
  def test_fallback_to__name__on_type():
      # Test that we correctly repr types that have non-string values for
      # __qualname__ by falling back to __name__
  
      class Type(object):
          __qualname__ = 5
  
      # Test repring of the type.
      stream = StringIO()
      printer = pretty.RepresentationPrinter(stream)
  
      printer.pretty(Type)
      printer.flush()
      output = stream.getvalue()
  
      # If __qualname__ is malformed, we should fall back to __name__.
      expected = '.'.join([__name__, Type.__name__])
      nt.assert_equal(output, expected)
  
      # Clear stream buffer.
      stream.buf = ''
  
      # Test repring of an instance of the type.
      instance = Type()
      printer.pretty(instance)
      printer.flush()
      output = stream.getvalue()
  
      # Should look like:
      # <IPython.lib.tests.test_pretty.Type at 0x7f7658ae07d0>
      prefix = '<' + '.'.join([__name__, Type.__name__]) + ' at 0x'
      nt.assert_true(output.startswith(prefix))
  
  
  @py2_only
  def test_fail_gracefully_on_bogus__qualname__and__name__():
      # Test that we correctly repr types that have non-string values for both
      # __qualname__ and __name__
  
      class Meta(type):
          __name__ = 5
  
      class Type(object):
          __metaclass__ = Meta
          __qualname__ = 5
  
      stream = StringIO()
      printer = pretty.RepresentationPrinter(stream)
  
      printer.pretty(Type)
      printer.flush()
      output = stream.getvalue()
  
      # If we can't find __name__ or __qualname__ just use a sentinel string.
      expected = '.'.join([__name__, '<unknown type>'])
      nt.assert_equal(output, expected)
  
      # Clear stream buffer.
      stream.buf = ''
  
      # Test repring of an instance of the type.
      instance = Type()
      printer.pretty(instance)
      printer.flush()
      output = stream.getvalue()
  
      # Should look like:
      # <IPython.lib.tests.test_pretty.<unknown type> at 0x7f7658ae07d0>
      prefix = '<' + '.'.join([__name__, '<unknown type>']) + ' at 0x'
      nt.assert_true(output.startswith(prefix))
  
  
  def test_collections_defaultdict():
      # Create defaultdicts with cycles
      a = defaultdict()
      a.default_factory = a
      b = defaultdict(list)
      b['key'] = b
  
      # Dictionary order cannot be relied on, test against single keys.
      cases = [
          (defaultdict(list), 'defaultdict(list, {})'),
          (defaultdict(list, {'key': '-' * 50}),
           "defaultdict(list,\n"
           "            {'key': '--------------------------------------------------'})"),
          (a, 'defaultdict(defaultdict(...), {})'),
          (b, "defaultdict(list, {'key': defaultdict(...)})"),
      ]
      for obj, expected in cases:
          nt.assert_equal(pretty.pretty(obj), expected)
  
  
  def test_collections_ordereddict():
      # Create OrderedDict with cycle
      a = OrderedDict()
      a['key'] = a
  
      cases = [
          (OrderedDict(), 'OrderedDict()'),
          (OrderedDict((i, i) for i in range(1000, 1010)),
           'OrderedDict([(1000, 1000),\n'
           '             (1001, 1001),\n'
           '             (1002, 1002),\n'
           '             (1003, 1003),\n'
           '             (1004, 1004),\n'
           '             (1005, 1005),\n'
           '             (1006, 1006),\n'
           '             (1007, 1007),\n'
           '             (1008, 1008),\n'
           '             (1009, 1009)])'),
          (a, "OrderedDict([('key', OrderedDict(...))])"),
      ]
      for obj, expected in cases:
          nt.assert_equal(pretty.pretty(obj), expected)
  
  
  def test_collections_deque():
      # Create deque with cycle
      a = deque()
      a.append(a)
  
      cases = [
          (deque(), 'deque([])'),
          (deque(i for i in range(1000, 1020)),
           'deque([1000,\n'
           '       1001,\n'
           '       1002,\n'
           '       1003,\n'
           '       1004,\n'
           '       1005,\n'
           '       1006,\n'
           '       1007,\n'
           '       1008,\n'
           '       1009,\n'
           '       1010,\n'
           '       1011,\n'
           '       1012,\n'
           '       1013,\n'
           '       1014,\n'
           '       1015,\n'
           '       1016,\n'
           '       1017,\n'
           '       1018,\n'
           '       1019])'),
          (a, 'deque([deque(...)])'),
      ]
      for obj, expected in cases:
          nt.assert_equal(pretty.pretty(obj), expected)
  
  def test_collections_counter():
      class MyCounter(Counter):
          pass
      cases = [
          (Counter(), 'Counter()'),
          (Counter(a=1), "Counter({'a': 1})"),
          (MyCounter(a=1), "MyCounter({'a': 1})"),
      ]
      for obj, expected in cases:
          nt.assert_equal(pretty.pretty(obj), expected)
  
  @py3_only
  def test_mappingproxy():
      MP = types.MappingProxyType
      underlying_dict = {}
      mp_recursive = MP(underlying_dict)
      underlying_dict[2] = mp_recursive
      underlying_dict[3] = underlying_dict
  
      cases = [
          (MP({}), "mappingproxy({})"),
          (MP({None: MP({})}), "mappingproxy({None: mappingproxy({})})"),
          (MP({k: k.upper() for k in string.ascii_lowercase}),
           "mappingproxy({'a': 'A',\n"
           "              'b': 'B',\n"
           "              'c': 'C',\n"
           "              'd': 'D',\n"
           "              'e': 'E',\n"
           "              'f': 'F',\n"
           "              'g': 'G',\n"
           "              'h': 'H',\n"
           "              'i': 'I',\n"
           "              'j': 'J',\n"
           "              'k': 'K',\n"
           "              'l': 'L',\n"
           "              'm': 'M',\n"
           "              'n': 'N',\n"
           "              'o': 'O',\n"
           "              'p': 'P',\n"
           "              'q': 'Q',\n"
           "              'r': 'R',\n"
           "              's': 'S',\n"
           "              't': 'T',\n"
           "              'u': 'U',\n"
           "              'v': 'V',\n"
           "              'w': 'W',\n"
           "              'x': 'X',\n"
           "              'y': 'Y',\n"
           "              'z': 'Z'})"),
          (mp_recursive, "mappingproxy({2: {...}, 3: {2: {...}, 3: {...}}})"),
          (underlying_dict,
           "{2: mappingproxy({2: {...}, 3: {...}}), 3: {...}}"),
      ]
      for obj, expected in cases:
          nt.assert_equal(pretty.pretty(obj), expected)
  
  @cpython2_only # In PyPy, types.DictProxyType is dict
  def test_dictproxy():
      # This is the dictproxy constructor itself from the Python API,
      DP = ctypes.pythonapi.PyDictProxy_New
      DP.argtypes, DP.restype = (ctypes.py_object,), ctypes.py_object
  
      underlying_dict = {}
      mp_recursive = DP(underlying_dict)
      underlying_dict[0] = mp_recursive
      underlying_dict[-3] = underlying_dict
  
      cases = [
          (DP({}), "dict_proxy({})"),
          (DP({None: DP({})}), "dict_proxy({None: dict_proxy({})})"),
          (DP({k: k.lower() for k in string.ascii_uppercase}),
           "dict_proxy({'A': 'a',\n"
           "            'B': 'b',\n"
           "            'C': 'c',\n"
           "            'D': 'd',\n"
           "            'E': 'e',\n"
           "            'F': 'f',\n"
           "            'G': 'g',\n"
           "            'H': 'h',\n"
           "            'I': 'i',\n"
           "            'J': 'j',\n"
           "            'K': 'k',\n"
           "            'L': 'l',\n"
           "            'M': 'm',\n"
           "            'N': 'n',\n"
           "            'O': 'o',\n"
           "            'P': 'p',\n"
           "            'Q': 'q',\n"
           "            'R': 'r',\n"
           "            'S': 's',\n"
           "            'T': 't',\n"
           "            'U': 'u',\n"
           "            'V': 'v',\n"
           "            'W': 'w',\n"
           "            'X': 'x',\n"
           "            'Y': 'y',\n"
           "            'Z': 'z'})"),
          (mp_recursive, "dict_proxy({-3: {-3: {...}, 0: {...}}, 0: {...}})"),
      ]
      for obj, expected in cases:
          nt.assert_is_instance(obj, types.DictProxyType) # Meta-test
          nt.assert_equal(pretty.pretty(obj), expected)
      nt.assert_equal(pretty.pretty(underlying_dict),
                      "{-3: {...}, 0: dict_proxy({-3: {...}, 0: {...}})}")
  