summaryrefslogtreecommitdiff
path: root/Demo/parser/pprint.py
blob: c4b815800c1de3e1933f311c7754d14065ea2cd3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#  pprint.py
#
#  Author:	Fred L. Drake, Jr.
#		fdrake@vt.edu
#
#  This is a simple little module I wrote to make life easier.  I didn't
#  see anything quite like it in the library, though I may have overlooked
#  something.  I wrote this when I was trying to read some heavily nested
#  tuples with fairly non-descriptive content.  This is modelled very much
#  after Lisp/Scheme - style pretty-printing of lists.  If you find it
#  useful, thank small children who sleep at night.
#

"""Support to pretty-print lists, tuples, & dictionaries recursively.
Very simple, but at least somewhat useful, especially in debugging
data structures.

INDENT_PER_LEVEL	--  Amount of indentation to use for each new
			    recursive level.  The default is 1.  This
			    must be a non-negative integer, and may be
			    set by the caller before calling pprint().

MAX_WIDTH		--  Maximum width of the display.  This is only
			    used if the representation *can* be kept
			    less than MAX_WIDTH characters wide.  May
			    be set by the user before calling pprint().

TAB_WIDTH		--  The width represented by a single tab.  This
			    value is typically 8, but 4 is the default
			    under MacOS.  Can be changed by the user if
			    desired, but is probably not a good idea.

pprint(seq [, stream])	--  The pretty-printer.  This takes a Python
			    object (presumably a sequence, but that
			    doesn't matter) and an optional output
			    stream.  See the function documentation
			    for details.
"""


INDENT_PER_LEVEL = 1

MAX_WIDTH = 80

import os
TAB_WIDTH = (os.name == 'mac' and 4) or 8
del os



def _indentation(cols):
    "Create tabbed indentation string COLS columns wide."

    #  This is used to reduce the byte-count for the output, allowing
    #  files created using this module to use as little external storage
    #  as possible.  This is primarily intended to minimize impact on
    #  a user's quota when storing resource files, or for creating output
    #  intended for transmission.

    return ((cols / TAB_WIDTH) * '\t') + ((cols % TAB_WIDTH) * ' ')



def pprint(seq, stream = None, indent = 0, allowance = 0):
    """Pretty-print a list, tuple, or dictionary.

    pprint(seq [, stream]) ==> None

    If STREAM is provided, output is written to that stream, otherwise
    sys.stdout is used.  Indentation is done according to
    INDENT_PER_LEVEL, which may be set to any non-negative integer
    before calling this function.  The output written on the stream is
    a perfectly valid representation of the Python object passed in,
    with indentation to suite human-readable interpretation.  The
    output can be used as input without error, given readable
    representations of all sequence elements are available via repr().
    Output is restricted to MAX_WIDTH columns where possible.  The
    STREAM parameter must support the write() method with a single
    parameter, which will always be a string.  The output stream may be
    a StringIO.StringIO object if the result is needed as a string.
    """

    if stream is None:
	import sys
	stream = sys.stdout

    from types import DictType, ListType, TupleType

    rep = `seq`
    typ = type(seq)
    sepLines = len(rep) > (MAX_WIDTH - 1 - indent - allowance)

    if sepLines and (typ is ListType or typ is TupleType):
	#  Pretty-print the sequence.
	stream.write(((typ is ListType) and '[') or '(')

	length = len(seq)
	if length:
	    indent = indent + INDENT_PER_LEVEL
	    pprint(seq[0], stream, indent, allowance + 1)

	    if len(seq) > 1:
		for ent in seq[1:]:
		    stream.write(',\n' + _indentation(indent))
		    pprint(ent, stream, indent, allowance + 1)

	    indent = indent - INDENT_PER_LEVEL

	stream.write(((typ is ListType) and ']') or ')')

    elif typ is DictType and sepLines:
	stream.write('{')

	length = len(seq)
	if length:
	    indent = indent + INDENT_PER_LEVEL
	    items  = seq.items()
	    items.sort()
	    key, ent = items[0]
	    rep = `key` + ': '
	    stream.write(rep)
	    pprint(ent, stream, indent + len(rep), allowance + 1)

	    if len(items) > 1:
		for key, ent in items[1:]:
		    rep = `key` + ': '
		    stream.write(',\n' + _indentation(indent) + rep)
		    pprint(ent, stream, indent + len(rep), allowance + 1)

	    indent = indent - INDENT_PER_LEVEL

	stream.write('}')

    else:
	stream.write(rep)

    #  Terminate the 'print' if we're not a recursive invocation.
    if not indent:
	stream.write('\n')


#
#  end of pprint.py