Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ExeBy/smexe_ro.../lib64/python2....
File: formatter.py
"""Generic output formatting.
[0] Fix | Delete
[1] Fix | Delete
Formatter objects transform an abstract flow of formatting events into
[2] Fix | Delete
specific output events on writer objects. Formatters manage several stack
[3] Fix | Delete
structures to allow various properties of a writer object to be changed and
[4] Fix | Delete
restored; writers need not be able to handle relative changes nor any sort
[5] Fix | Delete
of ``change back'' operation. Specific writer properties which may be
[6] Fix | Delete
controlled via formatter objects are horizontal alignment, font, and left
[7] Fix | Delete
margin indentations. A mechanism is provided which supports providing
[8] Fix | Delete
arbitrary, non-exclusive style settings to a writer as well. Additional
[9] Fix | Delete
interfaces facilitate formatting events which are not reversible, such as
[10] Fix | Delete
paragraph separation.
[11] Fix | Delete
[12] Fix | Delete
Writer objects encapsulate device interfaces. Abstract devices, such as
[13] Fix | Delete
file formats, are supported as well as physical devices. The provided
[14] Fix | Delete
implementations all work with abstract devices. The interface makes
[15] Fix | Delete
available mechanisms for setting the properties which formatter objects
[16] Fix | Delete
manage and inserting data into the output.
[17] Fix | Delete
"""
[18] Fix | Delete
[19] Fix | Delete
import sys
[20] Fix | Delete
[21] Fix | Delete
[22] Fix | Delete
AS_IS = None
[23] Fix | Delete
[24] Fix | Delete
[25] Fix | Delete
class NullFormatter:
[26] Fix | Delete
"""A formatter which does nothing.
[27] Fix | Delete
[28] Fix | Delete
If the writer parameter is omitted, a NullWriter instance is created.
[29] Fix | Delete
No methods of the writer are called by NullFormatter instances.
[30] Fix | Delete
[31] Fix | Delete
Implementations should inherit from this class if implementing a writer
[32] Fix | Delete
interface but don't need to inherit any implementation.
[33] Fix | Delete
[34] Fix | Delete
"""
[35] Fix | Delete
[36] Fix | Delete
def __init__(self, writer=None):
[37] Fix | Delete
if writer is None:
[38] Fix | Delete
writer = NullWriter()
[39] Fix | Delete
self.writer = writer
[40] Fix | Delete
def end_paragraph(self, blankline): pass
[41] Fix | Delete
def add_line_break(self): pass
[42] Fix | Delete
def add_hor_rule(self, *args, **kw): pass
[43] Fix | Delete
def add_label_data(self, format, counter, blankline=None): pass
[44] Fix | Delete
def add_flowing_data(self, data): pass
[45] Fix | Delete
def add_literal_data(self, data): pass
[46] Fix | Delete
def flush_softspace(self): pass
[47] Fix | Delete
def push_alignment(self, align): pass
[48] Fix | Delete
def pop_alignment(self): pass
[49] Fix | Delete
def push_font(self, x): pass
[50] Fix | Delete
def pop_font(self): pass
[51] Fix | Delete
def push_margin(self, margin): pass
[52] Fix | Delete
def pop_margin(self): pass
[53] Fix | Delete
def set_spacing(self, spacing): pass
[54] Fix | Delete
def push_style(self, *styles): pass
[55] Fix | Delete
def pop_style(self, n=1): pass
[56] Fix | Delete
def assert_line_data(self, flag=1): pass
[57] Fix | Delete
[58] Fix | Delete
[59] Fix | Delete
class AbstractFormatter:
[60] Fix | Delete
"""The standard formatter.
[61] Fix | Delete
[62] Fix | Delete
This implementation has demonstrated wide applicability to many writers,
[63] Fix | Delete
and may be used directly in most circumstances. It has been used to
[64] Fix | Delete
implement a full-featured World Wide Web browser.
[65] Fix | Delete
[66] Fix | Delete
"""
[67] Fix | Delete
[68] Fix | Delete
# Space handling policy: blank spaces at the boundary between elements
[69] Fix | Delete
# are handled by the outermost context. "Literal" data is not checked
[70] Fix | Delete
# to determine context, so spaces in literal data are handled directly
[71] Fix | Delete
# in all circumstances.
[72] Fix | Delete
[73] Fix | Delete
def __init__(self, writer):
[74] Fix | Delete
self.writer = writer # Output device
[75] Fix | Delete
self.align = None # Current alignment
[76] Fix | Delete
self.align_stack = [] # Alignment stack
[77] Fix | Delete
self.font_stack = [] # Font state
[78] Fix | Delete
self.margin_stack = [] # Margin state
[79] Fix | Delete
self.spacing = None # Vertical spacing state
[80] Fix | Delete
self.style_stack = [] # Other state, e.g. color
[81] Fix | Delete
self.nospace = 1 # Should leading space be suppressed
[82] Fix | Delete
self.softspace = 0 # Should a space be inserted
[83] Fix | Delete
self.para_end = 1 # Just ended a paragraph
[84] Fix | Delete
self.parskip = 0 # Skipped space between paragraphs?
[85] Fix | Delete
self.hard_break = 1 # Have a hard break
[86] Fix | Delete
self.have_label = 0
[87] Fix | Delete
[88] Fix | Delete
def end_paragraph(self, blankline):
[89] Fix | Delete
if not self.hard_break:
[90] Fix | Delete
self.writer.send_line_break()
[91] Fix | Delete
self.have_label = 0
[92] Fix | Delete
if self.parskip < blankline and not self.have_label:
[93] Fix | Delete
self.writer.send_paragraph(blankline - self.parskip)
[94] Fix | Delete
self.parskip = blankline
[95] Fix | Delete
self.have_label = 0
[96] Fix | Delete
self.hard_break = self.nospace = self.para_end = 1
[97] Fix | Delete
self.softspace = 0
[98] Fix | Delete
[99] Fix | Delete
def add_line_break(self):
[100] Fix | Delete
if not (self.hard_break or self.para_end):
[101] Fix | Delete
self.writer.send_line_break()
[102] Fix | Delete
self.have_label = self.parskip = 0
[103] Fix | Delete
self.hard_break = self.nospace = 1
[104] Fix | Delete
self.softspace = 0
[105] Fix | Delete
[106] Fix | Delete
def add_hor_rule(self, *args, **kw):
[107] Fix | Delete
if not self.hard_break:
[108] Fix | Delete
self.writer.send_line_break()
[109] Fix | Delete
self.writer.send_hor_rule(*args, **kw)
[110] Fix | Delete
self.hard_break = self.nospace = 1
[111] Fix | Delete
self.have_label = self.para_end = self.softspace = self.parskip = 0
[112] Fix | Delete
[113] Fix | Delete
def add_label_data(self, format, counter, blankline = None):
[114] Fix | Delete
if self.have_label or not self.hard_break:
[115] Fix | Delete
self.writer.send_line_break()
[116] Fix | Delete
if not self.para_end:
[117] Fix | Delete
self.writer.send_paragraph((blankline and 1) or 0)
[118] Fix | Delete
if isinstance(format, str):
[119] Fix | Delete
self.writer.send_label_data(self.format_counter(format, counter))
[120] Fix | Delete
else:
[121] Fix | Delete
self.writer.send_label_data(format)
[122] Fix | Delete
self.nospace = self.have_label = self.hard_break = self.para_end = 1
[123] Fix | Delete
self.softspace = self.parskip = 0
[124] Fix | Delete
[125] Fix | Delete
def format_counter(self, format, counter):
[126] Fix | Delete
label = ''
[127] Fix | Delete
for c in format:
[128] Fix | Delete
if c == '1':
[129] Fix | Delete
label = label + ('%d' % counter)
[130] Fix | Delete
elif c in 'aA':
[131] Fix | Delete
if counter > 0:
[132] Fix | Delete
label = label + self.format_letter(c, counter)
[133] Fix | Delete
elif c in 'iI':
[134] Fix | Delete
if counter > 0:
[135] Fix | Delete
label = label + self.format_roman(c, counter)
[136] Fix | Delete
else:
[137] Fix | Delete
label = label + c
[138] Fix | Delete
return label
[139] Fix | Delete
[140] Fix | Delete
def format_letter(self, case, counter):
[141] Fix | Delete
label = ''
[142] Fix | Delete
while counter > 0:
[143] Fix | Delete
counter, x = divmod(counter-1, 26)
[144] Fix | Delete
# This makes a strong assumption that lowercase letters
[145] Fix | Delete
# and uppercase letters form two contiguous blocks, with
[146] Fix | Delete
# letters in order!
[147] Fix | Delete
s = chr(ord(case) + x)
[148] Fix | Delete
label = s + label
[149] Fix | Delete
return label
[150] Fix | Delete
[151] Fix | Delete
def format_roman(self, case, counter):
[152] Fix | Delete
ones = ['i', 'x', 'c', 'm']
[153] Fix | Delete
fives = ['v', 'l', 'd']
[154] Fix | Delete
label, index = '', 0
[155] Fix | Delete
# This will die of IndexError when counter is too big
[156] Fix | Delete
while counter > 0:
[157] Fix | Delete
counter, x = divmod(counter, 10)
[158] Fix | Delete
if x == 9:
[159] Fix | Delete
label = ones[index] + ones[index+1] + label
[160] Fix | Delete
elif x == 4:
[161] Fix | Delete
label = ones[index] + fives[index] + label
[162] Fix | Delete
else:
[163] Fix | Delete
if x >= 5:
[164] Fix | Delete
s = fives[index]
[165] Fix | Delete
x = x-5
[166] Fix | Delete
else:
[167] Fix | Delete
s = ''
[168] Fix | Delete
s = s + ones[index]*x
[169] Fix | Delete
label = s + label
[170] Fix | Delete
index = index + 1
[171] Fix | Delete
if case == 'I':
[172] Fix | Delete
return label.upper()
[173] Fix | Delete
return label
[174] Fix | Delete
[175] Fix | Delete
def add_flowing_data(self, data):
[176] Fix | Delete
if not data: return
[177] Fix | Delete
prespace = data[:1].isspace()
[178] Fix | Delete
postspace = data[-1:].isspace()
[179] Fix | Delete
data = " ".join(data.split())
[180] Fix | Delete
if self.nospace and not data:
[181] Fix | Delete
return
[182] Fix | Delete
elif prespace or self.softspace:
[183] Fix | Delete
if not data:
[184] Fix | Delete
if not self.nospace:
[185] Fix | Delete
self.softspace = 1
[186] Fix | Delete
self.parskip = 0
[187] Fix | Delete
return
[188] Fix | Delete
if not self.nospace:
[189] Fix | Delete
data = ' ' + data
[190] Fix | Delete
self.hard_break = self.nospace = self.para_end = \
[191] Fix | Delete
self.parskip = self.have_label = 0
[192] Fix | Delete
self.softspace = postspace
[193] Fix | Delete
self.writer.send_flowing_data(data)
[194] Fix | Delete
[195] Fix | Delete
def add_literal_data(self, data):
[196] Fix | Delete
if not data: return
[197] Fix | Delete
if self.softspace:
[198] Fix | Delete
self.writer.send_flowing_data(" ")
[199] Fix | Delete
self.hard_break = data[-1:] == '\n'
[200] Fix | Delete
self.nospace = self.para_end = self.softspace = \
[201] Fix | Delete
self.parskip = self.have_label = 0
[202] Fix | Delete
self.writer.send_literal_data(data)
[203] Fix | Delete
[204] Fix | Delete
def flush_softspace(self):
[205] Fix | Delete
if self.softspace:
[206] Fix | Delete
self.hard_break = self.para_end = self.parskip = \
[207] Fix | Delete
self.have_label = self.softspace = 0
[208] Fix | Delete
self.nospace = 1
[209] Fix | Delete
self.writer.send_flowing_data(' ')
[210] Fix | Delete
[211] Fix | Delete
def push_alignment(self, align):
[212] Fix | Delete
if align and align != self.align:
[213] Fix | Delete
self.writer.new_alignment(align)
[214] Fix | Delete
self.align = align
[215] Fix | Delete
self.align_stack.append(align)
[216] Fix | Delete
else:
[217] Fix | Delete
self.align_stack.append(self.align)
[218] Fix | Delete
[219] Fix | Delete
def pop_alignment(self):
[220] Fix | Delete
if self.align_stack:
[221] Fix | Delete
del self.align_stack[-1]
[222] Fix | Delete
if self.align_stack:
[223] Fix | Delete
self.align = align = self.align_stack[-1]
[224] Fix | Delete
self.writer.new_alignment(align)
[225] Fix | Delete
else:
[226] Fix | Delete
self.align = None
[227] Fix | Delete
self.writer.new_alignment(None)
[228] Fix | Delete
[229] Fix | Delete
def push_font(self, font):
[230] Fix | Delete
size, i, b, tt = font
[231] Fix | Delete
if self.softspace:
[232] Fix | Delete
self.hard_break = self.para_end = self.softspace = 0
[233] Fix | Delete
self.nospace = 1
[234] Fix | Delete
self.writer.send_flowing_data(' ')
[235] Fix | Delete
if self.font_stack:
[236] Fix | Delete
csize, ci, cb, ctt = self.font_stack[-1]
[237] Fix | Delete
if size is AS_IS: size = csize
[238] Fix | Delete
if i is AS_IS: i = ci
[239] Fix | Delete
if b is AS_IS: b = cb
[240] Fix | Delete
if tt is AS_IS: tt = ctt
[241] Fix | Delete
font = (size, i, b, tt)
[242] Fix | Delete
self.font_stack.append(font)
[243] Fix | Delete
self.writer.new_font(font)
[244] Fix | Delete
[245] Fix | Delete
def pop_font(self):
[246] Fix | Delete
if self.font_stack:
[247] Fix | Delete
del self.font_stack[-1]
[248] Fix | Delete
if self.font_stack:
[249] Fix | Delete
font = self.font_stack[-1]
[250] Fix | Delete
else:
[251] Fix | Delete
font = None
[252] Fix | Delete
self.writer.new_font(font)
[253] Fix | Delete
[254] Fix | Delete
def push_margin(self, margin):
[255] Fix | Delete
self.margin_stack.append(margin)
[256] Fix | Delete
fstack = filter(None, self.margin_stack)
[257] Fix | Delete
if not margin and fstack:
[258] Fix | Delete
margin = fstack[-1]
[259] Fix | Delete
self.writer.new_margin(margin, len(fstack))
[260] Fix | Delete
[261] Fix | Delete
def pop_margin(self):
[262] Fix | Delete
if self.margin_stack:
[263] Fix | Delete
del self.margin_stack[-1]
[264] Fix | Delete
fstack = filter(None, self.margin_stack)
[265] Fix | Delete
if fstack:
[266] Fix | Delete
margin = fstack[-1]
[267] Fix | Delete
else:
[268] Fix | Delete
margin = None
[269] Fix | Delete
self.writer.new_margin(margin, len(fstack))
[270] Fix | Delete
[271] Fix | Delete
def set_spacing(self, spacing):
[272] Fix | Delete
self.spacing = spacing
[273] Fix | Delete
self.writer.new_spacing(spacing)
[274] Fix | Delete
[275] Fix | Delete
def push_style(self, *styles):
[276] Fix | Delete
if self.softspace:
[277] Fix | Delete
self.hard_break = self.para_end = self.softspace = 0
[278] Fix | Delete
self.nospace = 1
[279] Fix | Delete
self.writer.send_flowing_data(' ')
[280] Fix | Delete
for style in styles:
[281] Fix | Delete
self.style_stack.append(style)
[282] Fix | Delete
self.writer.new_styles(tuple(self.style_stack))
[283] Fix | Delete
[284] Fix | Delete
def pop_style(self, n=1):
[285] Fix | Delete
del self.style_stack[-n:]
[286] Fix | Delete
self.writer.new_styles(tuple(self.style_stack))
[287] Fix | Delete
[288] Fix | Delete
def assert_line_data(self, flag=1):
[289] Fix | Delete
self.nospace = self.hard_break = not flag
[290] Fix | Delete
self.para_end = self.parskip = self.have_label = 0
[291] Fix | Delete
[292] Fix | Delete
[293] Fix | Delete
class NullWriter:
[294] Fix | Delete
"""Minimal writer interface to use in testing & inheritance.
[295] Fix | Delete
[296] Fix | Delete
A writer which only provides the interface definition; no actions are
[297] Fix | Delete
taken on any methods. This should be the base class for all writers
[298] Fix | Delete
which do not need to inherit any implementation methods.
[299] Fix | Delete
[300] Fix | Delete
"""
[301] Fix | Delete
def __init__(self): pass
[302] Fix | Delete
def flush(self): pass
[303] Fix | Delete
def new_alignment(self, align): pass
[304] Fix | Delete
def new_font(self, font): pass
[305] Fix | Delete
def new_margin(self, margin, level): pass
[306] Fix | Delete
def new_spacing(self, spacing): pass
[307] Fix | Delete
def new_styles(self, styles): pass
[308] Fix | Delete
def send_paragraph(self, blankline): pass
[309] Fix | Delete
def send_line_break(self): pass
[310] Fix | Delete
def send_hor_rule(self, *args, **kw): pass
[311] Fix | Delete
def send_label_data(self, data): pass
[312] Fix | Delete
def send_flowing_data(self, data): pass
[313] Fix | Delete
def send_literal_data(self, data): pass
[314] Fix | Delete
[315] Fix | Delete
[316] Fix | Delete
class AbstractWriter(NullWriter):
[317] Fix | Delete
"""A writer which can be used in debugging formatters, but not much else.
[318] Fix | Delete
[319] Fix | Delete
Each method simply announces itself by printing its name and
[320] Fix | Delete
arguments on standard output.
[321] Fix | Delete
[322] Fix | Delete
"""
[323] Fix | Delete
[324] Fix | Delete
def new_alignment(self, align):
[325] Fix | Delete
print "new_alignment(%r)" % (align,)
[326] Fix | Delete
[327] Fix | Delete
def new_font(self, font):
[328] Fix | Delete
print "new_font(%r)" % (font,)
[329] Fix | Delete
[330] Fix | Delete
def new_margin(self, margin, level):
[331] Fix | Delete
print "new_margin(%r, %d)" % (margin, level)
[332] Fix | Delete
[333] Fix | Delete
def new_spacing(self, spacing):
[334] Fix | Delete
print "new_spacing(%r)" % (spacing,)
[335] Fix | Delete
[336] Fix | Delete
def new_styles(self, styles):
[337] Fix | Delete
print "new_styles(%r)" % (styles,)
[338] Fix | Delete
[339] Fix | Delete
def send_paragraph(self, blankline):
[340] Fix | Delete
print "send_paragraph(%r)" % (blankline,)
[341] Fix | Delete
[342] Fix | Delete
def send_line_break(self):
[343] Fix | Delete
print "send_line_break()"
[344] Fix | Delete
[345] Fix | Delete
def send_hor_rule(self, *args, **kw):
[346] Fix | Delete
print "send_hor_rule()"
[347] Fix | Delete
[348] Fix | Delete
def send_label_data(self, data):
[349] Fix | Delete
print "send_label_data(%r)" % (data,)
[350] Fix | Delete
[351] Fix | Delete
def send_flowing_data(self, data):
[352] Fix | Delete
print "send_flowing_data(%r)" % (data,)
[353] Fix | Delete
[354] Fix | Delete
def send_literal_data(self, data):
[355] Fix | Delete
print "send_literal_data(%r)" % (data,)
[356] Fix | Delete
[357] Fix | Delete
[358] Fix | Delete
class DumbWriter(NullWriter):
[359] Fix | Delete
"""Simple writer class which writes output on the file object passed in
[360] Fix | Delete
as the file parameter or, if file is omitted, on standard output. The
[361] Fix | Delete
output is simply word-wrapped to the number of columns specified by
[362] Fix | Delete
the maxcol parameter. This class is suitable for reflowing a sequence
[363] Fix | Delete
of paragraphs.
[364] Fix | Delete
[365] Fix | Delete
"""
[366] Fix | Delete
[367] Fix | Delete
def __init__(self, file=None, maxcol=72):
[368] Fix | Delete
self.file = file or sys.stdout
[369] Fix | Delete
self.maxcol = maxcol
[370] Fix | Delete
NullWriter.__init__(self)
[371] Fix | Delete
self.reset()
[372] Fix | Delete
[373] Fix | Delete
def reset(self):
[374] Fix | Delete
self.col = 0
[375] Fix | Delete
self.atbreak = 0
[376] Fix | Delete
[377] Fix | Delete
def send_paragraph(self, blankline):
[378] Fix | Delete
self.file.write('\n'*blankline)
[379] Fix | Delete
self.col = 0
[380] Fix | Delete
self.atbreak = 0
[381] Fix | Delete
[382] Fix | Delete
def send_line_break(self):
[383] Fix | Delete
self.file.write('\n')
[384] Fix | Delete
self.col = 0
[385] Fix | Delete
self.atbreak = 0
[386] Fix | Delete
[387] Fix | Delete
def send_hor_rule(self, *args, **kw):
[388] Fix | Delete
self.file.write('\n')
[389] Fix | Delete
self.file.write('-'*self.maxcol)
[390] Fix | Delete
self.file.write('\n')
[391] Fix | Delete
self.col = 0
[392] Fix | Delete
self.atbreak = 0
[393] Fix | Delete
[394] Fix | Delete
def send_literal_data(self, data):
[395] Fix | Delete
self.file.write(data)
[396] Fix | Delete
i = data.rfind('\n')
[397] Fix | Delete
if i >= 0:
[398] Fix | Delete
self.col = 0
[399] Fix | Delete
data = data[i+1:]
[400] Fix | Delete
data = data.expandtabs()
[401] Fix | Delete
self.col = self.col + len(data)
[402] Fix | Delete
self.atbreak = 0
[403] Fix | Delete
[404] Fix | Delete
def send_flowing_data(self, data):
[405] Fix | Delete
if not data: return
[406] Fix | Delete
atbreak = self.atbreak or data[0].isspace()
[407] Fix | Delete
col = self.col
[408] Fix | Delete
maxcol = self.maxcol
[409] Fix | Delete
write = self.file.write
[410] Fix | Delete
for word in data.split():
[411] Fix | Delete
if atbreak:
[412] Fix | Delete
if col + len(word) >= maxcol:
[413] Fix | Delete
write('\n')
[414] Fix | Delete
col = 0
[415] Fix | Delete
else:
[416] Fix | Delete
write(' ')
[417] Fix | Delete
col = col + 1
[418] Fix | Delete
write(word)
[419] Fix | Delete
col = col + len(word)
[420] Fix | Delete
atbreak = 1
[421] Fix | Delete
self.col = col
[422] Fix | Delete
self.atbreak = data[-1].isspace()
[423] Fix | Delete
[424] Fix | Delete
[425] Fix | Delete
def test(file = None):
[426] Fix | Delete
w = DumbWriter()
[427] Fix | Delete
f = AbstractFormatter(w)
[428] Fix | Delete
if file is not None:
[429] Fix | Delete
fp = open(file)
[430] Fix | Delete
elif sys.argv[1:]:
[431] Fix | Delete
fp = open(sys.argv[1])
[432] Fix | Delete
else:
[433] Fix | Delete
fp = sys.stdin
[434] Fix | Delete
for line in fp:
[435] Fix | Delete
if line == '\n':
[436] Fix | Delete
f.end_paragraph(1)
[437] Fix | Delete
else:
[438] Fix | Delete
f.add_flowing_data(line)
[439] Fix | Delete
f.end_paragraph(0)
[440] Fix | Delete
[441] Fix | Delete
[442] Fix | Delete
if __name__ == '__main__':
[443] Fix | Delete
test()
[444] Fix | Delete
[445] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function