13257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel"""Generic output formatting. 23257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 33257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielFormatter objects transform an abstract flow of formatting events into 43257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielspecific output events on writer objects. Formatters manage several stack 53257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielstructures to allow various properties of a writer object to be changed and 63257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielrestored; writers need not be able to handle relative changes nor any sort 73257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielof ``change back'' operation. Specific writer properties which may be 83257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielcontrolled via formatter objects are horizontal alignment, font, and left 93257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielmargin indentations. A mechanism is provided which supports providing 103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielarbitrary, non-exclusive style settings to a writer as well. Additional 113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielinterfaces facilitate formatting events which are not reversible, such as 123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielparagraph separation. 133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielWriter objects encapsulate device interfaces. Abstract devices, such as 153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielfile formats, are supported as well as physical devices. The provided 163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimplementations all work with abstract devices. The interface makes 173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielavailable mechanisms for setting the properties which formatter objects 183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielmanage and inserting data into the output. 193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel""" 203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport sys 223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielAS_IS = None 253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass NullFormatter: 283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """A formatter which does nothing. 293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel If the writer parameter is omitted, a NullWriter instance is created. 313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel No methods of the writer are called by NullFormatter instances. 323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Implementations should inherit from this class if implementing a writer 343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel interface but don't need to inherit any implementation. 353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __init__(self, writer=None): 393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if writer is None: 403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel writer = NullWriter() 413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer = writer 423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def end_paragraph(self, blankline): pass 433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def add_line_break(self): pass 443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def add_hor_rule(self, *args, **kw): pass 453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def add_label_data(self, format, counter, blankline=None): pass 463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def add_flowing_data(self, data): pass 473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def add_literal_data(self, data): pass 483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def flush_softspace(self): pass 493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def push_alignment(self, align): pass 503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def pop_alignment(self): pass 513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def push_font(self, x): pass 523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def pop_font(self): pass 533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def push_margin(self, margin): pass 543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def pop_margin(self): pass 553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def set_spacing(self, spacing): pass 563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def push_style(self, *styles): pass 573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def pop_style(self, n=1): pass 583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def assert_line_data(self, flag=1): pass 593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass AbstractFormatter: 623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """The standard formatter. 633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel This implementation has demonstrated wide applicability to many writers, 653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel and may be used directly in most circumstances. It has been used to 663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel implement a full-featured World Wide Web browser. 673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # Space handling policy: blank spaces at the boundary between elements 713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # are handled by the outermost context. "Literal" data is not checked 723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # to determine context, so spaces in literal data are handled directly 733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # in all circumstances. 743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __init__(self, writer): 763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer = writer # Output device 773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.align = None # Current alignment 783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.align_stack = [] # Alignment stack 793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.font_stack = [] # Font state 803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.margin_stack = [] # Margin state 813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.spacing = None # Vertical spacing state 823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.style_stack = [] # Other state, e.g. color 833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.nospace = 1 # Should leading space be suppressed 843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.softspace = 0 # Should a space be inserted 853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.para_end = 1 # Just ended a paragraph 863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.parskip = 0 # Skipped space between paragraphs? 873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.hard_break = 1 # Have a hard break 883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.have_label = 0 893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def end_paragraph(self, blankline): 913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not self.hard_break: 923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_line_break() 933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.have_label = 0 943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.parskip < blankline and not self.have_label: 953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_paragraph(blankline - self.parskip) 963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.parskip = blankline 973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.have_label = 0 983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.hard_break = self.nospace = self.para_end = 1 993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.softspace = 0 1003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def add_line_break(self): 1023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not (self.hard_break or self.para_end): 1033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_line_break() 1043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.have_label = self.parskip = 0 1053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.hard_break = self.nospace = 1 1063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.softspace = 0 1073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def add_hor_rule(self, *args, **kw): 1093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not self.hard_break: 1103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_line_break() 1113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_hor_rule(*args, **kw) 1123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.hard_break = self.nospace = 1 1133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.have_label = self.para_end = self.softspace = self.parskip = 0 1143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def add_label_data(self, format, counter, blankline = None): 1163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.have_label or not self.hard_break: 1173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_line_break() 1183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not self.para_end: 1193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_paragraph((blankline and 1) or 0) 1203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if isinstance(format, str): 1213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_label_data(self.format_counter(format, counter)) 1223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_label_data(format) 1243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.nospace = self.have_label = self.hard_break = self.para_end = 1 1253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.softspace = self.parskip = 0 1263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def format_counter(self, format, counter): 1283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label = '' 1293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for c in format: 1303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if c == '1': 1313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label = label + ('%d' % counter) 1323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel elif c in 'aA': 1333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if counter > 0: 1343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label = label + self.format_letter(c, counter) 1353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel elif c in 'iI': 1363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if counter > 0: 1373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label = label + self.format_roman(c, counter) 1383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label = label + c 1403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return label 1413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def format_letter(self, case, counter): 1433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label = '' 1443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel while counter > 0: 1453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel counter, x = divmod(counter-1, 26) 1463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # This makes a strong assumption that lowercase letters 1473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # and uppercase letters form two contiguous blocks, with 1483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # letters in order! 1493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel s = chr(ord(case) + x) 1503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label = s + label 1513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return label 1523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def format_roman(self, case, counter): 1543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel ones = ['i', 'x', 'c', 'm'] 1553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel fives = ['v', 'l', 'd'] 1563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label, index = '', 0 1573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel # This will die of IndexError when counter is too big 1583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel while counter > 0: 1593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel counter, x = divmod(counter, 10) 1603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if x == 9: 1613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label = ones[index] + ones[index+1] + label 1623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel elif x == 4: 1633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label = ones[index] + fives[index] + label 1643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if x >= 5: 1663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel s = fives[index] 1673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel x = x-5 1683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 1693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel s = '' 1703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel s = s + ones[index]*x 1713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel label = s + label 1723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel index = index + 1 1733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if case == 'I': 1743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return label.upper() 1753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return label 1763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def add_flowing_data(self, data): 1783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not data: return 1793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel prespace = data[:1].isspace() 1803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel postspace = data[-1:].isspace() 1813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel data = " ".join(data.split()) 1823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.nospace and not data: 1833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return 1843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel elif prespace or self.softspace: 1853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not data: 1863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not self.nospace: 1873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.softspace = 1 1883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.parskip = 0 1893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel return 1903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not self.nospace: 1913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel data = ' ' + data 1923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.hard_break = self.nospace = self.para_end = \ 1933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.parskip = self.have_label = 0 1943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.softspace = postspace 1953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_flowing_data(data) 1963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 1973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def add_literal_data(self, data): 1983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not data: return 1993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.softspace: 2003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_flowing_data(" ") 2013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.hard_break = data[-1:] == '\n' 2023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.nospace = self.para_end = self.softspace = \ 2033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.parskip = self.have_label = 0 2043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_literal_data(data) 2053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def flush_softspace(self): 2073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.softspace: 2083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.hard_break = self.para_end = self.parskip = \ 2093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.have_label = self.softspace = 0 2103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.nospace = 1 2113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_flowing_data(' ') 2123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def push_alignment(self, align): 2143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if align and align != self.align: 2153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.new_alignment(align) 2163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.align = align 2173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.align_stack.append(align) 2183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 2193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.align_stack.append(self.align) 2203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def pop_alignment(self): 2223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.align_stack: 2233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel del self.align_stack[-1] 2243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.align_stack: 2253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.align = align = self.align_stack[-1] 2263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.new_alignment(align) 2273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 2283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.align = None 2293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.new_alignment(None) 2303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def push_font(self, font): 2323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel size, i, b, tt = font 2333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.softspace: 2343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.hard_break = self.para_end = self.softspace = 0 2353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.nospace = 1 2363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_flowing_data(' ') 2373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.font_stack: 2383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel csize, ci, cb, ctt = self.font_stack[-1] 2393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if size is AS_IS: size = csize 2403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if i is AS_IS: i = ci 2413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if b is AS_IS: b = cb 2423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if tt is AS_IS: tt = ctt 2433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel font = (size, i, b, tt) 2443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.font_stack.append(font) 2453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.new_font(font) 2463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def pop_font(self): 2483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.font_stack: 2493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel del self.font_stack[-1] 2503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.font_stack: 2513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel font = self.font_stack[-1] 2523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 2533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel font = None 2543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.new_font(font) 2553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def push_margin(self, margin): 2573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.margin_stack.append(margin) 2583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel fstack = filter(None, self.margin_stack) 2593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not margin and fstack: 2603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel margin = fstack[-1] 2613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.new_margin(margin, len(fstack)) 2623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def pop_margin(self): 2643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.margin_stack: 2653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel del self.margin_stack[-1] 2663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel fstack = filter(None, self.margin_stack) 2673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if fstack: 2683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel margin = fstack[-1] 2693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 2703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel margin = None 2713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.new_margin(margin, len(fstack)) 2723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def set_spacing(self, spacing): 2743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.spacing = spacing 2753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.new_spacing(spacing) 2763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def push_style(self, *styles): 2783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if self.softspace: 2793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.hard_break = self.para_end = self.softspace = 0 2803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.nospace = 1 2813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.send_flowing_data(' ') 2823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for style in styles: 2833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.style_stack.append(style) 2843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.new_styles(tuple(self.style_stack)) 2853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def pop_style(self, n=1): 2873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel del self.style_stack[-n:] 2883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.writer.new_styles(tuple(self.style_stack)) 2893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def assert_line_data(self, flag=1): 2913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.nospace = self.hard_break = not flag 2923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.para_end = self.parskip = self.have_label = 0 2933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass NullWriter: 2963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """Minimal writer interface to use in testing & inheritance. 2973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 2983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel A writer which only provides the interface definition; no actions are 2993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel taken on any methods. This should be the base class for all writers 3003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel which do not need to inherit any implementation methods. 3013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 3033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __init__(self): pass 3043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def flush(self): pass 3053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def new_alignment(self, align): pass 3063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def new_font(self, font): pass 3073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def new_margin(self, margin, level): pass 3083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def new_spacing(self, spacing): pass 3093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def new_styles(self, styles): pass 3103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_paragraph(self, blankline): pass 3113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_line_break(self): pass 3123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_hor_rule(self, *args, **kw): pass 3133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_label_data(self, data): pass 3143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_flowing_data(self, data): pass 3153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_literal_data(self, data): pass 3163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass AbstractWriter(NullWriter): 3193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """A writer which can be used in debugging formatters, but not much else. 3203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel Each method simply announces itself by printing its name and 3223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel arguments on standard output. 3233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 3253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def new_alignment(self, align): 3273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "new_alignment(%r)" % (align,) 3283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def new_font(self, font): 3303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "new_font(%r)" % (font,) 3313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def new_margin(self, margin, level): 3333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "new_margin(%r, %d)" % (margin, level) 3343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def new_spacing(self, spacing): 3363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "new_spacing(%r)" % (spacing,) 3373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def new_styles(self, styles): 3393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "new_styles(%r)" % (styles,) 3403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_paragraph(self, blankline): 3423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "send_paragraph(%r)" % (blankline,) 3433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_line_break(self): 3453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "send_line_break()" 3463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_hor_rule(self, *args, **kw): 3483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "send_hor_rule()" 3493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_label_data(self, data): 3513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "send_label_data(%r)" % (data,) 3523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_flowing_data(self, data): 3543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "send_flowing_data(%r)" % (data,) 3553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_literal_data(self, data): 3573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel print "send_literal_data(%r)" % (data,) 3583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass DumbWriter(NullWriter): 3613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """Simple writer class which writes output on the file object passed in 3623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel as the file parameter or, if file is omitted, on standard output. The 3633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel output is simply word-wrapped to the number of columns specified by 3643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel the maxcol parameter. This class is suitable for reflowing a sequence 3653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel of paragraphs. 3663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel """ 3683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def __init__(self, file=None, maxcol=72): 3703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.file = file or sys.stdout 3713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.maxcol = maxcol 3723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel NullWriter.__init__(self) 3733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.reset() 3743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def reset(self): 3763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.col = 0 3773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.atbreak = 0 3783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_paragraph(self, blankline): 3803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.file.write('\n'*blankline) 3813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.col = 0 3823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.atbreak = 0 3833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_line_break(self): 3853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.file.write('\n') 3863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.col = 0 3873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.atbreak = 0 3883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_hor_rule(self, *args, **kw): 3903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.file.write('\n') 3913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.file.write('-'*self.maxcol) 3923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.file.write('\n') 3933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.col = 0 3943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.atbreak = 0 3953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 3963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_literal_data(self, data): 3973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.file.write(data) 3983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel i = data.rfind('\n') 3993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if i >= 0: 4003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.col = 0 4013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel data = data[i+1:] 4023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel data = data.expandtabs() 4033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.col = self.col + len(data) 4043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.atbreak = 0 4053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 4063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel def send_flowing_data(self, data): 4073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if not data: return 4083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel atbreak = self.atbreak or data[0].isspace() 4093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel col = self.col 4103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel maxcol = self.maxcol 4113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel write = self.file.write 4123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for word in data.split(): 4133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if atbreak: 4143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if col + len(word) >= maxcol: 4153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel write('\n') 4163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel col = 0 4173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 4183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel write(' ') 4193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel col = col + 1 4203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel write(word) 4213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel col = col + len(word) 4223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel atbreak = 1 4233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.col = col 4243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel self.atbreak = data[-1].isspace() 4253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 4263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 4273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef test(file = None): 4283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel w = DumbWriter() 4293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel f = AbstractFormatter(w) 4303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if file is not None: 4313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel fp = open(file) 4323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel elif sys.argv[1:]: 4333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel fp = open(sys.argv[1]) 4343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 4353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel fp = sys.stdin 4363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel for line in fp: 4373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel if line == '\n': 4383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel f.end_paragraph(1) 4393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel else: 4403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel f.add_flowing_data(line) 4413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel f.end_paragraph(0) 4423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 4433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel 4443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielif __name__ == '__main__': 4453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel test() 446