2000-02-04 23:39:30 +08:00
|
|
|
"""Generic output formatting.
|
|
|
|
|
|
|
|
Formatter objects transform an abstract flow of formatting events into
|
|
|
|
specific output events on writer objects. Formatters manage several stack
|
|
|
|
structures to allow various properties of a writer object to be changed and
|
|
|
|
restored; writers need not be able to handle relative changes nor any sort
|
|
|
|
of ``change back'' operation. Specific writer properties which may be
|
|
|
|
controlled via formatter objects are horizontal alignment, font, and left
|
|
|
|
margin indentations. A mechanism is provided which supports providing
|
|
|
|
arbitrary, non-exclusive style settings to a writer as well. Additional
|
|
|
|
interfaces facilitate formatting events which are not reversible, such as
|
2001-01-15 07:36:06 +08:00
|
|
|
paragraph separation.
|
2000-02-04 23:39:30 +08:00
|
|
|
|
|
|
|
Writer objects encapsulate device interfaces. Abstract devices, such as
|
|
|
|
file formats, are supported as well as physical devices. The provided
|
|
|
|
implementations all work with abstract devices. The interface makes
|
|
|
|
available mechanisms for setting the properties which formatter objects
|
2001-01-15 07:36:06 +08:00
|
|
|
manage and inserting data into the output.
|
2000-02-04 23:39:30 +08:00
|
|
|
"""
|
|
|
|
|
1995-08-08 04:07:36 +08:00
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
|
|
AS_IS = None
|
|
|
|
|
|
|
|
|
1995-10-06 23:31:30 +08:00
|
|
|
class NullFormatter:
|
2002-05-30 00:18:42 +08:00
|
|
|
"""A formatter which does nothing.
|
|
|
|
|
|
|
|
If the writer parameter is omitted, a NullWriter instance is created.
|
|
|
|
No methods of the writer are called by NullFormatter instances.
|
|
|
|
|
|
|
|
Implementations should inherit from this class if implementing a writer
|
|
|
|
interface but don't need to inherit any implementation.
|
|
|
|
|
|
|
|
"""
|
1995-10-06 23:31:30 +08:00
|
|
|
|
1996-10-08 05:29:49 +08:00
|
|
|
def __init__(self, writer=None):
|
2002-06-01 09:29:16 +08:00
|
|
|
if writer is None:
|
1998-03-27 05:13:24 +08:00
|
|
|
writer = NullWriter()
|
|
|
|
self.writer = writer
|
1995-10-06 23:31:30 +08:00
|
|
|
def end_paragraph(self, blankline): pass
|
|
|
|
def add_line_break(self): pass
|
1996-10-09 05:57:47 +08:00
|
|
|
def add_hor_rule(self, *args, **kw): pass
|
|
|
|
def add_label_data(self, format, counter, blankline=None): pass
|
1995-10-06 23:31:30 +08:00
|
|
|
def add_flowing_data(self, data): pass
|
|
|
|
def add_literal_data(self, data): pass
|
|
|
|
def flush_softspace(self): pass
|
1996-05-29 07:50:49 +08:00
|
|
|
def push_alignment(self, align): pass
|
|
|
|
def pop_alignment(self): pass
|
1995-10-06 23:31:30 +08:00
|
|
|
def push_font(self, x): pass
|
|
|
|
def pop_font(self): pass
|
|
|
|
def push_margin(self, margin): pass
|
|
|
|
def pop_margin(self): pass
|
|
|
|
def set_spacing(self, spacing): pass
|
1996-05-29 07:50:49 +08:00
|
|
|
def push_style(self, *styles): pass
|
|
|
|
def pop_style(self, n=1): pass
|
|
|
|
def assert_line_data(self, flag=1): pass
|
1995-10-06 23:31:30 +08:00
|
|
|
|
|
|
|
|
1995-08-08 04:07:36 +08:00
|
|
|
class AbstractFormatter:
|
2002-05-30 00:18:42 +08:00
|
|
|
"""The standard formatter.
|
|
|
|
|
|
|
|
This implementation has demonstrated wide applicability to many writers,
|
|
|
|
and may be used directly in most circumstances. It has been used to
|
|
|
|
implement a full-featured World Wide Web browser.
|
|
|
|
|
|
|
|
"""
|
1995-08-08 04:07:36 +08:00
|
|
|
|
1996-08-27 00:19:23 +08:00
|
|
|
# Space handling policy: blank spaces at the boundary between elements
|
|
|
|
# are handled by the outermost context. "Literal" data is not checked
|
|
|
|
# to determine context, so spaces in literal data are handled directly
|
|
|
|
# in all circumstances.
|
|
|
|
|
1995-08-08 04:07:36 +08:00
|
|
|
def __init__(self, writer):
|
1998-03-27 05:13:24 +08:00
|
|
|
self.writer = writer # Output device
|
|
|
|
self.align = None # Current alignment
|
|
|
|
self.align_stack = [] # Alignment stack
|
|
|
|
self.font_stack = [] # Font state
|
|
|
|
self.margin_stack = [] # Margin state
|
|
|
|
self.spacing = None # Vertical spacing state
|
|
|
|
self.style_stack = [] # Other state, e.g. color
|
|
|
|
self.nospace = 1 # Should leading space be suppressed
|
|
|
|
self.softspace = 0 # Should a space be inserted
|
|
|
|
self.para_end = 1 # Just ended a paragraph
|
|
|
|
self.parskip = 0 # Skipped space between paragraphs?
|
|
|
|
self.hard_break = 1 # Have a hard break
|
|
|
|
self.have_label = 0
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def end_paragraph(self, blankline):
|
1998-03-27 05:13:24 +08:00
|
|
|
if not self.hard_break:
|
|
|
|
self.writer.send_line_break()
|
|
|
|
self.have_label = 0
|
|
|
|
if self.parskip < blankline and not self.have_label:
|
|
|
|
self.writer.send_paragraph(blankline - self.parskip)
|
|
|
|
self.parskip = blankline
|
|
|
|
self.have_label = 0
|
|
|
|
self.hard_break = self.nospace = self.para_end = 1
|
|
|
|
self.softspace = 0
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def add_line_break(self):
|
1998-03-27 05:13:24 +08:00
|
|
|
if not (self.hard_break or self.para_end):
|
|
|
|
self.writer.send_line_break()
|
|
|
|
self.have_label = self.parskip = 0
|
|
|
|
self.hard_break = self.nospace = 1
|
|
|
|
self.softspace = 0
|
1995-08-08 04:07:36 +08:00
|
|
|
|
1996-05-29 07:50:49 +08:00
|
|
|
def add_hor_rule(self, *args, **kw):
|
1998-03-27 05:13:24 +08:00
|
|
|
if not self.hard_break:
|
|
|
|
self.writer.send_line_break()
|
2003-02-28 04:14:51 +08:00
|
|
|
self.writer.send_hor_rule(*args, **kw)
|
1998-03-27 05:13:24 +08:00
|
|
|
self.hard_break = self.nospace = 1
|
|
|
|
self.have_label = self.para_end = self.softspace = self.parskip = 0
|
1996-05-29 07:50:49 +08:00
|
|
|
|
|
|
|
def add_label_data(self, format, counter, blankline = None):
|
1998-03-27 05:13:24 +08:00
|
|
|
if self.have_label or not self.hard_break:
|
|
|
|
self.writer.send_line_break()
|
|
|
|
if not self.para_end:
|
|
|
|
self.writer.send_paragraph((blankline and 1) or 0)
|
Remove uses of the string and types modules:
x in string.whitespace => x.isspace()
type(x) in types.StringTypes => isinstance(x, basestring)
isinstance(x, types.StringTypes) => isinstance(x, basestring)
type(x) is types.StringType => isinstance(x, str)
type(x) == types.StringType => isinstance(x, str)
string.split(x, ...) => x.split(...)
string.join(x, y) => y.join(x)
string.zfill(x, ...) => x.zfill(...)
string.count(x, ...) => x.count(...)
hasattr(types, "UnicodeType") => try: unicode except NameError:
type(x) != types.TupleTuple => not isinstance(x, tuple)
isinstance(x, types.TupleType) => isinstance(x, tuple)
type(x) is types.IntType => isinstance(x, int)
Do not mention the string module in the rlcompleter docstring.
This partially applies SF patch http://www.python.org/sf/562373
(with basestring instead of string). (It excludes the changes to
unittest.py and does not change the os.stat stuff.)
2002-06-03 23:58:32 +08:00
|
|
|
if isinstance(format, str):
|
1998-03-27 05:13:24 +08:00
|
|
|
self.writer.send_label_data(self.format_counter(format, counter))
|
|
|
|
else:
|
|
|
|
self.writer.send_label_data(format)
|
|
|
|
self.nospace = self.have_label = self.hard_break = self.para_end = 1
|
|
|
|
self.softspace = self.parskip = 0
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def format_counter(self, format, counter):
|
|
|
|
label = ''
|
|
|
|
for c in format:
|
2001-05-12 03:25:08 +08:00
|
|
|
if c == '1':
|
|
|
|
label = label + ('%d' % counter)
|
|
|
|
elif c in 'aA':
|
|
|
|
if counter > 0:
|
|
|
|
label = label + self.format_letter(c, counter)
|
|
|
|
elif c in 'iI':
|
|
|
|
if counter > 0:
|
|
|
|
label = label + self.format_roman(c, counter)
|
|
|
|
else:
|
1996-05-29 07:50:49 +08:00
|
|
|
label = label + c
|
1995-08-08 04:07:36 +08:00
|
|
|
return label
|
|
|
|
|
|
|
|
def format_letter(self, case, counter):
|
1998-03-27 05:13:24 +08:00
|
|
|
label = ''
|
|
|
|
while counter > 0:
|
|
|
|
counter, x = divmod(counter-1, 26)
|
2001-05-12 03:25:08 +08:00
|
|
|
# This makes a strong assumption that lowercase letters
|
|
|
|
# and uppercase letters form two contiguous blocks, with
|
|
|
|
# letters in order!
|
1998-03-27 05:13:24 +08:00
|
|
|
s = chr(ord(case) + x)
|
|
|
|
label = s + label
|
|
|
|
return label
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def format_roman(self, case, counter):
|
|
|
|
ones = ['i', 'x', 'c', 'm']
|
|
|
|
fives = ['v', 'l', 'd']
|
1996-05-29 07:50:49 +08:00
|
|
|
label, index = '', 0
|
1998-03-27 05:13:24 +08:00
|
|
|
# This will die of IndexError when counter is too big
|
1995-08-08 04:07:36 +08:00
|
|
|
while counter > 0:
|
|
|
|
counter, x = divmod(counter, 10)
|
|
|
|
if x == 9:
|
1996-05-29 07:50:49 +08:00
|
|
|
label = ones[index] + ones[index+1] + label
|
1995-08-08 04:07:36 +08:00
|
|
|
elif x == 4:
|
1996-05-29 07:50:49 +08:00
|
|
|
label = ones[index] + fives[index] + label
|
1995-08-08 04:07:36 +08:00
|
|
|
else:
|
|
|
|
if x >= 5:
|
|
|
|
s = fives[index]
|
|
|
|
x = x-5
|
|
|
|
else:
|
|
|
|
s = ''
|
|
|
|
s = s + ones[index]*x
|
1998-03-27 05:13:24 +08:00
|
|
|
label = s + label
|
1995-08-08 04:07:36 +08:00
|
|
|
index = index + 1
|
1996-05-29 07:50:49 +08:00
|
|
|
if case == 'I':
|
2001-02-09 19:10:16 +08:00
|
|
|
return label.upper()
|
1995-08-08 04:07:36 +08:00
|
|
|
return label
|
|
|
|
|
Remove uses of the string and types modules:
x in string.whitespace => x.isspace()
type(x) in types.StringTypes => isinstance(x, basestring)
isinstance(x, types.StringTypes) => isinstance(x, basestring)
type(x) is types.StringType => isinstance(x, str)
type(x) == types.StringType => isinstance(x, str)
string.split(x, ...) => x.split(...)
string.join(x, y) => y.join(x)
string.zfill(x, ...) => x.zfill(...)
string.count(x, ...) => x.count(...)
hasattr(types, "UnicodeType") => try: unicode except NameError:
type(x) != types.TupleTuple => not isinstance(x, tuple)
isinstance(x, types.TupleType) => isinstance(x, tuple)
type(x) is types.IntType => isinstance(x, int)
Do not mention the string module in the rlcompleter docstring.
This partially applies SF patch http://www.python.org/sf/562373
(with basestring instead of string). (It excludes the changes to
unittest.py and does not change the os.stat stuff.)
2002-06-03 23:58:32 +08:00
|
|
|
def add_flowing_data(self, data):
|
1998-03-27 05:13:24 +08:00
|
|
|
if not data: return
|
Remove uses of the string and types modules:
x in string.whitespace => x.isspace()
type(x) in types.StringTypes => isinstance(x, basestring)
isinstance(x, types.StringTypes) => isinstance(x, basestring)
type(x) is types.StringType => isinstance(x, str)
type(x) == types.StringType => isinstance(x, str)
string.split(x, ...) => x.split(...)
string.join(x, y) => y.join(x)
string.zfill(x, ...) => x.zfill(...)
string.count(x, ...) => x.count(...)
hasattr(types, "UnicodeType") => try: unicode except NameError:
type(x) != types.TupleTuple => not isinstance(x, tuple)
isinstance(x, types.TupleType) => isinstance(x, tuple)
type(x) is types.IntType => isinstance(x, int)
Do not mention the string module in the rlcompleter docstring.
This partially applies SF patch http://www.python.org/sf/562373
(with basestring instead of string). (It excludes the changes to
unittest.py and does not change the os.stat stuff.)
2002-06-03 23:58:32 +08:00
|
|
|
prespace = data[:1].isspace()
|
|
|
|
postspace = data[-1:].isspace()
|
|
|
|
data = " ".join(data.split())
|
1998-03-27 05:13:24 +08:00
|
|
|
if self.nospace and not data:
|
|
|
|
return
|
|
|
|
elif prespace or self.softspace:
|
|
|
|
if not data:
|
|
|
|
if not self.nospace:
|
|
|
|
self.softspace = 1
|
|
|
|
self.parskip = 0
|
|
|
|
return
|
|
|
|
if not self.nospace:
|
|
|
|
data = ' ' + data
|
|
|
|
self.hard_break = self.nospace = self.para_end = \
|
|
|
|
self.parskip = self.have_label = 0
|
|
|
|
self.softspace = postspace
|
|
|
|
self.writer.send_flowing_data(data)
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def add_literal_data(self, data):
|
1998-03-27 05:13:24 +08:00
|
|
|
if not data: return
|
|
|
|
if self.softspace:
|
|
|
|
self.writer.send_flowing_data(" ")
|
|
|
|
self.hard_break = data[-1:] == '\n'
|
|
|
|
self.nospace = self.para_end = self.softspace = \
|
|
|
|
self.parskip = self.have_label = 0
|
|
|
|
self.writer.send_literal_data(data)
|
1995-08-08 04:07:36 +08:00
|
|
|
|
1995-10-01 00:49:58 +08:00
|
|
|
def flush_softspace(self):
|
1998-03-27 05:13:24 +08:00
|
|
|
if self.softspace:
|
|
|
|
self.hard_break = self.para_end = self.parskip = \
|
|
|
|
self.have_label = self.softspace = 0
|
|
|
|
self.nospace = 1
|
|
|
|
self.writer.send_flowing_data(' ')
|
1995-10-01 00:49:58 +08:00
|
|
|
|
1996-05-29 07:50:49 +08:00
|
|
|
def push_alignment(self, align):
|
1998-03-27 05:13:24 +08:00
|
|
|
if align and align != self.align:
|
|
|
|
self.writer.new_alignment(align)
|
|
|
|
self.align = align
|
|
|
|
self.align_stack.append(align)
|
|
|
|
else:
|
|
|
|
self.align_stack.append(self.align)
|
1996-05-29 07:50:49 +08:00
|
|
|
|
|
|
|
def pop_alignment(self):
|
1998-03-27 05:13:24 +08:00
|
|
|
if self.align_stack:
|
|
|
|
del self.align_stack[-1]
|
|
|
|
if self.align_stack:
|
|
|
|
self.align = align = self.align_stack[-1]
|
|
|
|
self.writer.new_alignment(align)
|
|
|
|
else:
|
|
|
|
self.align = None
|
|
|
|
self.writer.new_alignment(None)
|
1996-05-29 07:50:49 +08:00
|
|
|
|
2007-05-16 02:46:22 +08:00
|
|
|
def push_font(self, font):
|
|
|
|
size, i, b, tt = font
|
1998-03-27 05:13:24 +08:00
|
|
|
if self.softspace:
|
|
|
|
self.hard_break = self.para_end = self.softspace = 0
|
|
|
|
self.nospace = 1
|
|
|
|
self.writer.send_flowing_data(' ')
|
|
|
|
if self.font_stack:
|
|
|
|
csize, ci, cb, ctt = self.font_stack[-1]
|
|
|
|
if size is AS_IS: size = csize
|
|
|
|
if i is AS_IS: i = ci
|
|
|
|
if b is AS_IS: b = cb
|
|
|
|
if tt is AS_IS: tt = ctt
|
|
|
|
font = (size, i, b, tt)
|
|
|
|
self.font_stack.append(font)
|
|
|
|
self.writer.new_font(font)
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def pop_font(self):
|
1998-03-27 05:13:24 +08:00
|
|
|
if self.font_stack:
|
|
|
|
del self.font_stack[-1]
|
|
|
|
if self.font_stack:
|
|
|
|
font = self.font_stack[-1]
|
|
|
|
else:
|
|
|
|
font = None
|
|
|
|
self.writer.new_font(font)
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def push_margin(self, margin):
|
1998-03-27 05:13:24 +08:00
|
|
|
self.margin_stack.append(margin)
|
|
|
|
fstack = filter(None, self.margin_stack)
|
|
|
|
if not margin and fstack:
|
|
|
|
margin = fstack[-1]
|
|
|
|
self.writer.new_margin(margin, len(fstack))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def pop_margin(self):
|
1998-03-27 05:13:24 +08:00
|
|
|
if self.margin_stack:
|
|
|
|
del self.margin_stack[-1]
|
|
|
|
fstack = filter(None, self.margin_stack)
|
|
|
|
if fstack:
|
|
|
|
margin = fstack[-1]
|
|
|
|
else:
|
|
|
|
margin = None
|
|
|
|
self.writer.new_margin(margin, len(fstack))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def set_spacing(self, spacing):
|
1998-03-27 05:13:24 +08:00
|
|
|
self.spacing = spacing
|
|
|
|
self.writer.new_spacing(spacing)
|
1995-08-08 04:07:36 +08:00
|
|
|
|
1996-05-29 07:50:49 +08:00
|
|
|
def push_style(self, *styles):
|
1998-03-27 05:13:24 +08:00
|
|
|
if self.softspace:
|
|
|
|
self.hard_break = self.para_end = self.softspace = 0
|
|
|
|
self.nospace = 1
|
|
|
|
self.writer.send_flowing_data(' ')
|
|
|
|
for style in styles:
|
|
|
|
self.style_stack.append(style)
|
|
|
|
self.writer.new_styles(tuple(self.style_stack))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
1996-05-29 07:50:49 +08:00
|
|
|
def pop_style(self, n=1):
|
1998-03-27 05:13:24 +08:00
|
|
|
del self.style_stack[-n:]
|
|
|
|
self.writer.new_styles(tuple(self.style_stack))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
1996-05-29 07:50:49 +08:00
|
|
|
def assert_line_data(self, flag=1):
|
1998-03-27 05:13:24 +08:00
|
|
|
self.nospace = self.hard_break = not flag
|
|
|
|
self.para_end = self.parskip = self.have_label = 0
|
1996-05-29 07:50:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
class NullWriter:
|
2002-05-30 00:18:42 +08:00
|
|
|
"""Minimal writer interface to use in testing & inheritance.
|
|
|
|
|
|
|
|
A writer which only provides the interface definition; no actions are
|
|
|
|
taken on any methods. This should be the base class for all writers
|
|
|
|
which do not need to inherit any implementation methods.
|
|
|
|
|
|
|
|
"""
|
1996-05-29 08:02:30 +08:00
|
|
|
def __init__(self): pass
|
1997-01-01 04:50:51 +08:00
|
|
|
def flush(self): pass
|
1996-05-29 07:50:49 +08:00
|
|
|
def new_alignment(self, align): pass
|
|
|
|
def new_font(self, font): pass
|
|
|
|
def new_margin(self, margin, level): pass
|
|
|
|
def new_spacing(self, spacing): pass
|
|
|
|
def new_styles(self, styles): pass
|
|
|
|
def send_paragraph(self, blankline): pass
|
|
|
|
def send_line_break(self): pass
|
|
|
|
def send_hor_rule(self, *args, **kw): pass
|
|
|
|
def send_label_data(self, data): pass
|
|
|
|
def send_flowing_data(self, data): pass
|
|
|
|
def send_literal_data(self, data): pass
|
|
|
|
|
1995-08-08 04:07:36 +08:00
|
|
|
|
1996-05-29 08:02:30 +08:00
|
|
|
class AbstractWriter(NullWriter):
|
2002-05-30 00:18:42 +08:00
|
|
|
"""A writer which can be used in debugging formatters, but not much else.
|
|
|
|
|
|
|
|
Each method simply announces itself by printing its name and
|
|
|
|
arguments on standard output.
|
|
|
|
|
|
|
|
"""
|
1995-08-08 04:07:36 +08:00
|
|
|
|
1996-05-29 07:50:49 +08:00
|
|
|
def new_alignment(self, align):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("new_alignment(%r)" % (align,))
|
1996-05-29 07:50:49 +08:00
|
|
|
|
1995-08-08 04:07:36 +08:00
|
|
|
def new_font(self, font):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("new_font(%r)" % (font,))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def new_margin(self, margin, level):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("new_margin(%r, %d)" % (margin, level))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def new_spacing(self, spacing):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("new_spacing(%r)" % (spacing,))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def new_styles(self, styles):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("new_styles(%r)" % (styles,))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def send_paragraph(self, blankline):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("send_paragraph(%r)" % (blankline,))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def send_line_break(self):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("send_line_break()")
|
1995-08-08 04:07:36 +08:00
|
|
|
|
1996-05-29 07:50:49 +08:00
|
|
|
def send_hor_rule(self, *args, **kw):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("send_hor_rule()")
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def send_label_data(self, data):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("send_label_data(%r)" % (data,))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def send_flowing_data(self, data):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("send_flowing_data(%r)" % (data,))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def send_literal_data(self, data):
|
2007-02-09 13:37:30 +08:00
|
|
|
print("send_literal_data(%r)" % (data,))
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
|
1996-05-29 08:02:30 +08:00
|
|
|
class DumbWriter(NullWriter):
|
2002-05-30 00:18:42 +08:00
|
|
|
"""Simple writer class which writes output on the file object passed in
|
|
|
|
as the file parameter or, if file is omitted, on standard output. The
|
|
|
|
output is simply word-wrapped to the number of columns specified by
|
|
|
|
the maxcol parameter. This class is suitable for reflowing a sequence
|
|
|
|
of paragraphs.
|
|
|
|
|
|
|
|
"""
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def __init__(self, file=None, maxcol=72):
|
1998-03-27 05:13:24 +08:00
|
|
|
self.file = file or sys.stdout
|
|
|
|
self.maxcol = maxcol
|
|
|
|
NullWriter.__init__(self)
|
|
|
|
self.reset()
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def reset(self):
|
1998-03-27 05:13:24 +08:00
|
|
|
self.col = 0
|
|
|
|
self.atbreak = 0
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def send_paragraph(self, blankline):
|
1999-01-13 02:13:27 +08:00
|
|
|
self.file.write('\n'*blankline)
|
1998-03-27 05:13:24 +08:00
|
|
|
self.col = 0
|
|
|
|
self.atbreak = 0
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def send_line_break(self):
|
1998-03-27 05:13:24 +08:00
|
|
|
self.file.write('\n')
|
|
|
|
self.col = 0
|
|
|
|
self.atbreak = 0
|
1995-08-08 04:07:36 +08:00
|
|
|
|
1996-05-29 07:50:49 +08:00
|
|
|
def send_hor_rule(self, *args, **kw):
|
1998-03-27 05:13:24 +08:00
|
|
|
self.file.write('\n')
|
|
|
|
self.file.write('-'*self.maxcol)
|
|
|
|
self.file.write('\n')
|
|
|
|
self.col = 0
|
|
|
|
self.atbreak = 0
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def send_literal_data(self, data):
|
1998-03-27 05:13:24 +08:00
|
|
|
self.file.write(data)
|
2001-02-09 19:10:16 +08:00
|
|
|
i = data.rfind('\n')
|
1998-03-27 05:13:24 +08:00
|
|
|
if i >= 0:
|
|
|
|
self.col = 0
|
|
|
|
data = data[i+1:]
|
2001-02-09 19:10:16 +08:00
|
|
|
data = data.expandtabs()
|
1998-03-27 05:13:24 +08:00
|
|
|
self.col = self.col + len(data)
|
|
|
|
self.atbreak = 0
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
def send_flowing_data(self, data):
|
1998-03-27 05:13:24 +08:00
|
|
|
if not data: return
|
Remove uses of the string and types modules:
x in string.whitespace => x.isspace()
type(x) in types.StringTypes => isinstance(x, basestring)
isinstance(x, types.StringTypes) => isinstance(x, basestring)
type(x) is types.StringType => isinstance(x, str)
type(x) == types.StringType => isinstance(x, str)
string.split(x, ...) => x.split(...)
string.join(x, y) => y.join(x)
string.zfill(x, ...) => x.zfill(...)
string.count(x, ...) => x.count(...)
hasattr(types, "UnicodeType") => try: unicode except NameError:
type(x) != types.TupleTuple => not isinstance(x, tuple)
isinstance(x, types.TupleType) => isinstance(x, tuple)
type(x) is types.IntType => isinstance(x, int)
Do not mention the string module in the rlcompleter docstring.
This partially applies SF patch http://www.python.org/sf/562373
(with basestring instead of string). (It excludes the changes to
unittest.py and does not change the os.stat stuff.)
2002-06-03 23:58:32 +08:00
|
|
|
atbreak = self.atbreak or data[0].isspace()
|
1998-03-27 05:13:24 +08:00
|
|
|
col = self.col
|
|
|
|
maxcol = self.maxcol
|
|
|
|
write = self.file.write
|
2001-02-09 19:10:16 +08:00
|
|
|
for word in data.split():
|
1998-03-27 05:13:24 +08:00
|
|
|
if atbreak:
|
|
|
|
if col + len(word) >= maxcol:
|
|
|
|
write('\n')
|
|
|
|
col = 0
|
|
|
|
else:
|
|
|
|
write(' ')
|
|
|
|
col = col + 1
|
|
|
|
write(word)
|
|
|
|
col = col + len(word)
|
|
|
|
atbreak = 1
|
|
|
|
self.col = col
|
Remove uses of the string and types modules:
x in string.whitespace => x.isspace()
type(x) in types.StringTypes => isinstance(x, basestring)
isinstance(x, types.StringTypes) => isinstance(x, basestring)
type(x) is types.StringType => isinstance(x, str)
type(x) == types.StringType => isinstance(x, str)
string.split(x, ...) => x.split(...)
string.join(x, y) => y.join(x)
string.zfill(x, ...) => x.zfill(...)
string.count(x, ...) => x.count(...)
hasattr(types, "UnicodeType") => try: unicode except NameError:
type(x) != types.TupleTuple => not isinstance(x, tuple)
isinstance(x, types.TupleType) => isinstance(x, tuple)
type(x) is types.IntType => isinstance(x, int)
Do not mention the string module in the rlcompleter docstring.
This partially applies SF patch http://www.python.org/sf/562373
(with basestring instead of string). (It excludes the changes to
unittest.py and does not change the os.stat stuff.)
2002-06-03 23:58:32 +08:00
|
|
|
self.atbreak = data[-1].isspace()
|
1995-08-08 04:07:36 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test(file = None):
|
|
|
|
w = DumbWriter()
|
|
|
|
f = AbstractFormatter(w)
|
2002-06-01 09:29:16 +08:00
|
|
|
if file is not None:
|
1998-03-27 05:13:24 +08:00
|
|
|
fp = open(file)
|
1995-08-08 04:07:36 +08:00
|
|
|
elif sys.argv[1:]:
|
1998-03-27 05:13:24 +08:00
|
|
|
fp = open(sys.argv[1])
|
1995-08-08 04:07:36 +08:00
|
|
|
else:
|
1998-03-27 05:13:24 +08:00
|
|
|
fp = sys.stdin
|
Merged revisions 60151-60159,60161-60168,60170,60172-60173,60175 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r60151 | christian.heimes | 2008-01-21 14:11:15 +0100 (Mon, 21 Jan 2008) | 1 line
A bunch of header files were not listed as dependencies for object files. Changes to files like Parser/parser.h weren't picked up by make.
........
r60152 | georg.brandl | 2008-01-21 15:16:46 +0100 (Mon, 21 Jan 2008) | 3 lines
#1087741: make mmap.mmap the type of mmap objects, not a
factory function. Allow it to be subclassed.
........
r60153 | georg.brandl | 2008-01-21 15:18:14 +0100 (Mon, 21 Jan 2008) | 2 lines
mmap is an extension module.
........
r60154 | georg.brandl | 2008-01-21 17:28:13 +0100 (Mon, 21 Jan 2008) | 2 lines
Fix example.
........
r60155 | georg.brandl | 2008-01-21 17:34:07 +0100 (Mon, 21 Jan 2008) | 2 lines
#1555501: document plistlib and move it to the general library.
........
r60156 | georg.brandl | 2008-01-21 17:36:00 +0100 (Mon, 21 Jan 2008) | 2 lines
Add a stub for bundlebuilder documentation.
........
r60157 | georg.brandl | 2008-01-21 17:46:58 +0100 (Mon, 21 Jan 2008) | 2 lines
Removing bundlebuilder docs again -- it's not to be used anymore (see #779825).
........
r60158 | georg.brandl | 2008-01-21 17:51:51 +0100 (Mon, 21 Jan 2008) | 2 lines
#997912: acknowledge nested scopes in tutorial.
........
r60159 | vinay.sajip | 2008-01-21 18:02:26 +0100 (Mon, 21 Jan 2008) | 1 line
Fix: #1836: Off-by-one bug in TimedRotatingFileHandler rollover calculation. Patch thanks to Kathryn M. Kowalski.
........
r60161 | georg.brandl | 2008-01-21 18:13:03 +0100 (Mon, 21 Jan 2008) | 2 lines
Adapt pydoc to new doc URLs.
........
r60162 | georg.brandl | 2008-01-21 18:17:00 +0100 (Mon, 21 Jan 2008) | 2 lines
Fix old link.
........
r60163 | georg.brandl | 2008-01-21 18:22:06 +0100 (Mon, 21 Jan 2008) | 2 lines
#1726198: replace while 1: fp.readline() with file iteration.
........
r60164 | georg.brandl | 2008-01-21 18:29:23 +0100 (Mon, 21 Jan 2008) | 2 lines
Clarify $ behavior in re docstring. #1631394.
........
r60165 | vinay.sajip | 2008-01-21 18:39:22 +0100 (Mon, 21 Jan 2008) | 1 line
Minor documentation change - hyperlink tidied up.
........
r60166 | georg.brandl | 2008-01-21 18:42:40 +0100 (Mon, 21 Jan 2008) | 2 lines
#1530959: change distutils build dir for --with-pydebug python builds.
........
r60167 | vinay.sajip | 2008-01-21 19:16:05 +0100 (Mon, 21 Jan 2008) | 1 line
Updated to include news on recent logging fixes and documentation changes.
........
r60168 | georg.brandl | 2008-01-21 19:35:49 +0100 (Mon, 21 Jan 2008) | 3 lines
Issue #1882: when compiling code from a string, encoding cookies in the
second line of code were not always recognized correctly.
........
r60170 | georg.brandl | 2008-01-21 19:36:51 +0100 (Mon, 21 Jan 2008) | 2 lines
Add NEWS entry for #1882.
........
r60172 | georg.brandl | 2008-01-21 19:41:24 +0100 (Mon, 21 Jan 2008) | 2 lines
Use original location of document, which has translations.
........
r60173 | walter.doerwald | 2008-01-21 21:18:04 +0100 (Mon, 21 Jan 2008) | 2 lines
Follow PEP 8 in module docstring.
........
r60175 | georg.brandl | 2008-01-21 21:20:53 +0100 (Mon, 21 Jan 2008) | 2 lines
Adapt to latest doctools refactoring.
........
2008-01-22 04:36:10 +08:00
|
|
|
for line in fp:
|
1998-03-27 05:13:24 +08:00
|
|
|
if line == '\n':
|
|
|
|
f.end_paragraph(1)
|
|
|
|
else:
|
|
|
|
f.add_flowing_data(line)
|
1995-08-08 04:07:36 +08:00
|
|
|
f.end_paragraph(0)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
test()
|