compat.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. import six
  4. from collections import OrderedDict
  5. from sure.terminal import red, green, yellow
  6. if six.PY2:
  7. def compat_repr(object_repr):
  8. # compat_repr is designed to return all reprs with leading 'u's
  9. # inserted to make all strings look like unicode strings.
  10. # This makes testing between py2 and py3 much easier.
  11. result = ''
  12. in_quote = False
  13. curr_quote = None
  14. for char in object_repr:
  15. if char in ['"', "'"] and (
  16. not curr_quote or char == curr_quote):
  17. if in_quote:
  18. # Closing quote
  19. curr_quote = None
  20. in_quote = False
  21. else:
  22. # Opening quote
  23. curr_quote = char
  24. result += 'u'
  25. in_quote = True
  26. result += char
  27. return result
  28. else:
  29. def compat_repr(object_repr):
  30. return object_repr
  31. # FIXME: move FakeOrderedDict to another module since it
  32. # does not have anything todo with compat.
  33. # The safe_repr function should already get a
  34. # FakeOrderedDict instance. Maybe the _obj_with_safe_repr
  35. # function should be part of the FakeOrderedDict
  36. # classes __repr__ method.
  37. class FakeOrderedDict(OrderedDict):
  38. """ OrderedDict that has the repr of a normal dict
  39. We must return a string whether in py2 or py3.
  40. """
  41. def __unicode__(self):
  42. if not self:
  43. return '{}'
  44. key_values = []
  45. for key, value in self.items():
  46. key, value = repr(key), repr(value)
  47. if isinstance(value, six.binary_type) and six.PY2:
  48. value = value.decode("utf-8")
  49. key_values.append("{0}: {1}".format(key, value))
  50. res = "{{{0}}}".format(", ".join(key_values))
  51. return res
  52. if six.PY2:
  53. def __repr__(self):
  54. return self.__unicode__().encode('utf-8')
  55. else:
  56. def __repr__(self):
  57. return self.__unicode__()
  58. def _obj_with_safe_repr(obj):
  59. if isinstance(obj, dict):
  60. ret = FakeOrderedDict()
  61. for key in sorted(obj.keys()):
  62. ret[_obj_with_safe_repr(key)] = _obj_with_safe_repr(obj[key])
  63. elif isinstance(obj, list):
  64. ret = []
  65. for x in obj:
  66. if isinstance(x, dict):
  67. ret.append(_obj_with_safe_repr(x))
  68. else:
  69. ret.append(x)
  70. else:
  71. ret = obj
  72. return ret
  73. def safe_repr(val):
  74. try:
  75. if isinstance(val, dict):
  76. # We special case dicts to have a sorted repr. This makes testing
  77. # significantly easier
  78. val = _obj_with_safe_repr(val)
  79. ret = repr(val)
  80. if six.PY2:
  81. ret = ret.decode('utf-8')
  82. except UnicodeEncodeError:
  83. ret = red('a %r that cannot be represented' % type(val))
  84. else:
  85. ret = green(ret)
  86. return ret
  87. text_type_name = six.text_type().__class__.__name__