test_saferepr.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import pytest
  2. import re
  3. from decimal import Decimal
  4. from pprint import pprint
  5. from celery.utils.saferepr import saferepr
  6. D_NUMBERS = {
  7. b'integer': 1,
  8. b'float': 1.3,
  9. b'decimal': Decimal('1.3'),
  10. b'complex': complex(13.3),
  11. }
  12. D_INT_KEYS = {v: k for k, v in D_NUMBERS.items()}
  13. QUICK_BROWN_FOX = 'The quick brown fox jumps over the lazy dog.'
  14. B_QUICK_BROWN_FOX = b'The quick brown fox jumps over the lazy dog.'
  15. D_TEXT = {
  16. b'foo': QUICK_BROWN_FOX,
  17. b'bar': B_QUICK_BROWN_FOX,
  18. b'baz': B_QUICK_BROWN_FOX,
  19. b'xuzzy': B_QUICK_BROWN_FOX,
  20. }
  21. L_NUMBERS = list(D_NUMBERS.values())
  22. D_TEXT_LARGE = {
  23. b'bazxuzzyfoobarlongverylonglong': QUICK_BROWN_FOX * 30,
  24. }
  25. D_ALL = {
  26. b'numbers': D_NUMBERS,
  27. b'intkeys': D_INT_KEYS,
  28. b'text': D_TEXT,
  29. b'largetext': D_TEXT_LARGE,
  30. }
  31. D_D_TEXT = {b'rest': D_TEXT}
  32. RE_OLD_SET_REPR = re.compile(r'(?<!frozen)set\([\[|\{](.+?)[\}\]]\)')
  33. RE_OLD_SET_REPR_REPLACE = r'{\1}'
  34. RE_OLD_SET_CUSTOM_REPR = re.compile(r'((?:frozen)?set\d?\()\[(.+?)\](\))')
  35. RE_OLD_SET_CUSTOM_REPR_REPLACE = r'\1{\2}\3'
  36. RE_EMPTY_SET_REPR = re.compile(r'((?:frozen)?set\d?)\(\[\]\)')
  37. RE_EMPTY_SET_REPR_REPLACE = r'\1()'
  38. RE_LONG_SUFFIX = re.compile(r'(\d)+L')
  39. def old_repr(s):
  40. return str(RE_LONG_SUFFIX.sub(
  41. r'\1',
  42. RE_EMPTY_SET_REPR.sub(
  43. RE_EMPTY_SET_REPR_REPLACE,
  44. RE_OLD_SET_REPR.sub(
  45. RE_OLD_SET_REPR_REPLACE,
  46. RE_OLD_SET_CUSTOM_REPR.sub(
  47. RE_OLD_SET_CUSTOM_REPR_REPLACE, repr(s).replace("u'", "'"),
  48. )
  49. ),
  50. ),
  51. )).replace('set([])', 'set()')
  52. class list2(list):
  53. pass
  54. class list3(list):
  55. def __repr__(self):
  56. return list.__repr__(self)
  57. class tuple2(tuple):
  58. pass
  59. class tuple3(tuple):
  60. def __repr__(self):
  61. return tuple.__repr__(self)
  62. class set2(set):
  63. pass
  64. class set3(set):
  65. def __repr__(self):
  66. return set.__repr__(self)
  67. class frozenset2(frozenset):
  68. pass
  69. class frozenset3(frozenset):
  70. def __repr__(self):
  71. return frozenset.__repr__(self)
  72. class dict2(dict):
  73. pass
  74. class dict3(dict):
  75. def __repr__(self):
  76. return dict.__repr__(self)
  77. class test_saferepr:
  78. @pytest.mark.parametrize('value', list(D_NUMBERS.values()))
  79. def test_safe_types(self, value):
  80. assert saferepr(value) == old_repr(value)
  81. def test_numbers_dict(self):
  82. assert saferepr(D_NUMBERS) == old_repr(D_NUMBERS)
  83. def test_numbers_list(self):
  84. assert saferepr(L_NUMBERS) == old_repr(L_NUMBERS)
  85. def test_numbers_keys(self):
  86. assert saferepr(D_INT_KEYS) == old_repr(D_INT_KEYS)
  87. def test_text(self):
  88. assert saferepr(D_TEXT) == old_repr(D_TEXT).replace("u'", "'")
  89. def test_text_maxlen(self):
  90. assert saferepr(D_D_TEXT, 100).endswith("...', ...}}")
  91. def test_maxlevels(self):
  92. saferepr(D_ALL, maxlevels=1)
  93. def test_recursion(self):
  94. d = {1: 2, 3: {4: 5}}
  95. d[3][6] = d
  96. res = saferepr(d)
  97. assert 'Recursion on' in res
  98. @pytest.mark.parametrize('value', [
  99. 0, 0, 0 + 0j, 0.0, '', b'',
  100. (), tuple2(), tuple3(),
  101. [], list2(), list3(),
  102. set(), set2(), set3(),
  103. frozenset(), frozenset2(), frozenset3(),
  104. {}, dict2(), dict3(),
  105. test_recursion, pprint,
  106. -6, -6, -6 - 6j, -1.5, 'x', b'x', (3,), [3], {3: 6},
  107. (1, 2), [3, 4], {5: 6},
  108. tuple2((1, 2)), tuple3((1, 2)), tuple3(range(100)),
  109. [3, 4], list2([3, 4]), list3([3, 4]), list3(range(100)),
  110. {7}, set2({7}), set3({7}),
  111. frozenset({8}), frozenset2({8}), frozenset3({8}),
  112. dict2({5: 6}), dict3({5: 6}),
  113. range(10, -11, -1)
  114. ])
  115. def test_same_as_repr(self, value):
  116. # Simple objects, small containers, and classes that overwrite __repr__
  117. # For those the result should be the same as repr().
  118. # Ahem. The docs don't say anything about that -- this appears to
  119. # be testing an implementation quirk. Starting in Python 2.5, it's
  120. # not true for dicts: pprint always sorts dicts by key now; before,
  121. # it sorted a dict display if and only if the display required
  122. # multiple lines. For that reason, dicts with more than one element
  123. # aren't tested here.
  124. native = old_repr(value)
  125. assert saferepr(value) == native