Dmitry Tyzhnenko | 2b730a0 | 2017-04-07 19:31:32 +0300 | [diff] [blame] | 1 | import six |
| 2 | |
| 3 | |
| 4 | def _simple(item): |
| 5 | """Check for nested iterations: True, if not""" |
| 6 | return not isinstance(item, (list, set, tuple, dict)) |
| 7 | |
| 8 | |
| 9 | _formatters = { |
| 10 | 'simple': "{spc:<{indent}}{val!r}".format, |
| 11 | 'text': "{spc:<{indent}}{prefix}'''{string}'''".format, |
| 12 | 'dict': "\n{spc:<{indent}}{key!r:{size}}: {val},".format, |
| 13 | } |
| 14 | |
| 15 | |
| 16 | def pretty_repr(src, indent=0, no_indent_start=False, max_indent=20): |
| 17 | """Make human readable repr of object |
| 18 | :param src: object to process |
| 19 | :type src: object |
| 20 | :param indent: start indentation, all next levels is +4 |
| 21 | :type indent: int |
| 22 | :param no_indent_start: do not indent open bracket and simple parameters |
| 23 | :type no_indent_start: bool |
| 24 | :param max_indent: maximal indent before classic repr() call |
| 25 | :type max_indent: int |
| 26 | :return: formatted string |
| 27 | """ |
| 28 | if _simple(src) or indent >= max_indent: |
| 29 | indent = 0 if no_indent_start else indent |
| 30 | if isinstance(src, (six.binary_type, six.text_type)): |
| 31 | if isinstance(src, six.binary_type): |
| 32 | string = src.decode( |
| 33 | encoding='utf-8', |
| 34 | errors='backslashreplace' |
| 35 | ) |
| 36 | prefix = 'b' |
| 37 | else: |
| 38 | string = src |
| 39 | prefix = 'u' |
| 40 | return _formatters['text']( |
| 41 | spc='', |
| 42 | indent=indent, |
| 43 | prefix=prefix, |
| 44 | string=string |
| 45 | ) |
| 46 | return _formatters['simple']( |
| 47 | spc='', |
| 48 | indent=indent, |
| 49 | val=src |
| 50 | ) |
| 51 | if isinstance(src, dict): |
| 52 | prefix, suffix = '{', '}' |
| 53 | result = '' |
| 54 | max_len = len(max([repr(key) for key in src])) if src else 0 |
| 55 | for key, val in src.items(): |
| 56 | result += _formatters['dict']( |
| 57 | spc='', |
| 58 | indent=indent + 4, |
| 59 | size=max_len, |
| 60 | key=key, |
| 61 | val=pretty_repr(val, indent + 8, no_indent_start=True) |
| 62 | ) |
| 63 | return ( |
| 64 | '\n{start:>{indent}}'.format( |
| 65 | start=prefix, |
| 66 | indent=indent + 1 |
| 67 | ) + |
| 68 | result + |
| 69 | '\n{end:>{indent}}'.format(end=suffix, indent=indent + 1) |
| 70 | ) |
| 71 | if isinstance(src, list): |
| 72 | prefix, suffix = '[', ']' |
| 73 | elif isinstance(src, tuple): |
| 74 | prefix, suffix = '(', ')' |
| 75 | else: |
| 76 | prefix, suffix = '{', '}' |
| 77 | result = '' |
| 78 | for elem in src: |
| 79 | if _simple(elem): |
| 80 | result += '\n' |
| 81 | result += pretty_repr(elem, indent + 4) + ',' |
| 82 | return ( |
| 83 | '\n{start:>{indent}}'.format( |
| 84 | start=prefix, |
| 85 | indent=indent + 1) + |
| 86 | result + |
| 87 | '\n{end:>{indent}}'.format(end=suffix, indent=indent + 1) |
| 88 | ) |