]> git.proxmox.com Git - mirror_edk2.git/blobdiff - AppPkg/Applications/Python/Python-2.7.10/Lib/formatter.py
AppPkg/Applications/Python/Python-2.7.10: Initial Checkin part 4/5.
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / Lib / formatter.py
diff --git a/AppPkg/Applications/Python/Python-2.7.10/Lib/formatter.py b/AppPkg/Applications/Python/Python-2.7.10/Lib/formatter.py
new file mode 100644 (file)
index 0000000..8413f8c
--- /dev/null
@@ -0,0 +1,445 @@
+"""Generic output formatting.\r
+\r
+Formatter objects transform an abstract flow of formatting events into\r
+specific output events on writer objects. Formatters manage several stack\r
+structures to allow various properties of a writer object to be changed and\r
+restored; writers need not be able to handle relative changes nor any sort\r
+of ``change back'' operation. Specific writer properties which may be\r
+controlled via formatter objects are horizontal alignment, font, and left\r
+margin indentations. A mechanism is provided which supports providing\r
+arbitrary, non-exclusive style settings to a writer as well. Additional\r
+interfaces facilitate formatting events which are not reversible, such as\r
+paragraph separation.\r
+\r
+Writer objects encapsulate device interfaces. Abstract devices, such as\r
+file formats, are supported as well as physical devices. The provided\r
+implementations all work with abstract devices. The interface makes\r
+available mechanisms for setting the properties which formatter objects\r
+manage and inserting data into the output.\r
+"""\r
+\r
+import sys\r
+\r
+\r
+AS_IS = None\r
+\r
+\r
+class NullFormatter:\r
+    """A formatter which does nothing.\r
+\r
+    If the writer parameter is omitted, a NullWriter instance is created.\r
+    No methods of the writer are called by NullFormatter instances.\r
+\r
+    Implementations should inherit from this class if implementing a writer\r
+    interface but don't need to inherit any implementation.\r
+\r
+    """\r
+\r
+    def __init__(self, writer=None):\r
+        if writer is None:\r
+            writer = NullWriter()\r
+        self.writer = writer\r
+    def end_paragraph(self, blankline): pass\r
+    def add_line_break(self): pass\r
+    def add_hor_rule(self, *args, **kw): pass\r
+    def add_label_data(self, format, counter, blankline=None): pass\r
+    def add_flowing_data(self, data): pass\r
+    def add_literal_data(self, data): pass\r
+    def flush_softspace(self): pass\r
+    def push_alignment(self, align): pass\r
+    def pop_alignment(self): pass\r
+    def push_font(self, x): pass\r
+    def pop_font(self): pass\r
+    def push_margin(self, margin): pass\r
+    def pop_margin(self): pass\r
+    def set_spacing(self, spacing): pass\r
+    def push_style(self, *styles): pass\r
+    def pop_style(self, n=1): pass\r
+    def assert_line_data(self, flag=1): pass\r
+\r
+\r
+class AbstractFormatter:\r
+    """The standard formatter.\r
+\r
+    This implementation has demonstrated wide applicability to many writers,\r
+    and may be used directly in most circumstances.  It has been used to\r
+    implement a full-featured World Wide Web browser.\r
+\r
+    """\r
+\r
+    #  Space handling policy:  blank spaces at the boundary between elements\r
+    #  are handled by the outermost context.  "Literal" data is not checked\r
+    #  to determine context, so spaces in literal data are handled directly\r
+    #  in all circumstances.\r
+\r
+    def __init__(self, writer):\r
+        self.writer = writer            # Output device\r
+        self.align = None               # Current alignment\r
+        self.align_stack = []           # Alignment stack\r
+        self.font_stack = []            # Font state\r
+        self.margin_stack = []          # Margin state\r
+        self.spacing = None             # Vertical spacing state\r
+        self.style_stack = []           # Other state, e.g. color\r
+        self.nospace = 1                # Should leading space be suppressed\r
+        self.softspace = 0              # Should a space be inserted\r
+        self.para_end = 1               # Just ended a paragraph\r
+        self.parskip = 0                # Skipped space between paragraphs?\r
+        self.hard_break = 1             # Have a hard break\r
+        self.have_label = 0\r
+\r
+    def end_paragraph(self, blankline):\r
+        if not self.hard_break:\r
+            self.writer.send_line_break()\r
+            self.have_label = 0\r
+        if self.parskip < blankline and not self.have_label:\r
+            self.writer.send_paragraph(blankline - self.parskip)\r
+            self.parskip = blankline\r
+            self.have_label = 0\r
+        self.hard_break = self.nospace = self.para_end = 1\r
+        self.softspace = 0\r
+\r
+    def add_line_break(self):\r
+        if not (self.hard_break or self.para_end):\r
+            self.writer.send_line_break()\r
+            self.have_label = self.parskip = 0\r
+        self.hard_break = self.nospace = 1\r
+        self.softspace = 0\r
+\r
+    def add_hor_rule(self, *args, **kw):\r
+        if not self.hard_break:\r
+            self.writer.send_line_break()\r
+        self.writer.send_hor_rule(*args, **kw)\r
+        self.hard_break = self.nospace = 1\r
+        self.have_label = self.para_end = self.softspace = self.parskip = 0\r
+\r
+    def add_label_data(self, format, counter, blankline = None):\r
+        if self.have_label or not self.hard_break:\r
+            self.writer.send_line_break()\r
+        if not self.para_end:\r
+            self.writer.send_paragraph((blankline and 1) or 0)\r
+        if isinstance(format, str):\r
+            self.writer.send_label_data(self.format_counter(format, counter))\r
+        else:\r
+            self.writer.send_label_data(format)\r
+        self.nospace = self.have_label = self.hard_break = self.para_end = 1\r
+        self.softspace = self.parskip = 0\r
+\r
+    def format_counter(self, format, counter):\r
+        label = ''\r
+        for c in format:\r
+            if c == '1':\r
+                label = label + ('%d' % counter)\r
+            elif c in 'aA':\r
+                if counter > 0:\r
+                    label = label + self.format_letter(c, counter)\r
+            elif c in 'iI':\r
+                if counter > 0:\r
+                    label = label + self.format_roman(c, counter)\r
+            else:\r
+                label = label + c\r
+        return label\r
+\r
+    def format_letter(self, case, counter):\r
+        label = ''\r
+        while counter > 0:\r
+            counter, x = divmod(counter-1, 26)\r
+            # This makes a strong assumption that lowercase letters\r
+            # and uppercase letters form two contiguous blocks, with\r
+            # letters in order!\r
+            s = chr(ord(case) + x)\r
+            label = s + label\r
+        return label\r
+\r
+    def format_roman(self, case, counter):\r
+        ones = ['i', 'x', 'c', 'm']\r
+        fives = ['v', 'l', 'd']\r
+        label, index = '', 0\r
+        # This will die of IndexError when counter is too big\r
+        while counter > 0:\r
+            counter, x = divmod(counter, 10)\r
+            if x == 9:\r
+                label = ones[index] + ones[index+1] + label\r
+            elif x == 4:\r
+                label = ones[index] + fives[index] + label\r
+            else:\r
+                if x >= 5:\r
+                    s = fives[index]\r
+                    x = x-5\r
+                else:\r
+                    s = ''\r
+                s = s + ones[index]*x\r
+                label = s + label\r
+            index = index + 1\r
+        if case == 'I':\r
+            return label.upper()\r
+        return label\r
+\r
+    def add_flowing_data(self, data):\r
+        if not data: return\r
+        prespace = data[:1].isspace()\r
+        postspace = data[-1:].isspace()\r
+        data = " ".join(data.split())\r
+        if self.nospace and not data:\r
+            return\r
+        elif prespace or self.softspace:\r
+            if not data:\r
+                if not self.nospace:\r
+                    self.softspace = 1\r
+                    self.parskip = 0\r
+                return\r
+            if not self.nospace:\r
+                data = ' ' + data\r
+        self.hard_break = self.nospace = self.para_end = \\r
+                          self.parskip = self.have_label = 0\r
+        self.softspace = postspace\r
+        self.writer.send_flowing_data(data)\r
+\r
+    def add_literal_data(self, data):\r
+        if not data: return\r
+        if self.softspace:\r
+            self.writer.send_flowing_data(" ")\r
+        self.hard_break = data[-1:] == '\n'\r
+        self.nospace = self.para_end = self.softspace = \\r
+                       self.parskip = self.have_label = 0\r
+        self.writer.send_literal_data(data)\r
+\r
+    def flush_softspace(self):\r
+        if self.softspace:\r
+            self.hard_break = self.para_end = self.parskip = \\r
+                              self.have_label = self.softspace = 0\r
+            self.nospace = 1\r
+            self.writer.send_flowing_data(' ')\r
+\r
+    def push_alignment(self, align):\r
+        if align and align != self.align:\r
+            self.writer.new_alignment(align)\r
+            self.align = align\r
+            self.align_stack.append(align)\r
+        else:\r
+            self.align_stack.append(self.align)\r
+\r
+    def pop_alignment(self):\r
+        if self.align_stack:\r
+            del self.align_stack[-1]\r
+        if self.align_stack:\r
+            self.align = align = self.align_stack[-1]\r
+            self.writer.new_alignment(align)\r
+        else:\r
+            self.align = None\r
+            self.writer.new_alignment(None)\r
+\r
+    def push_font(self, font):\r
+        size, i, b, tt = font\r
+        if self.softspace:\r
+            self.hard_break = self.para_end = self.softspace = 0\r
+            self.nospace = 1\r
+            self.writer.send_flowing_data(' ')\r
+        if self.font_stack:\r
+            csize, ci, cb, ctt = self.font_stack[-1]\r
+            if size is AS_IS: size = csize\r
+            if i is AS_IS: i = ci\r
+            if b is AS_IS: b = cb\r
+            if tt is AS_IS: tt = ctt\r
+        font = (size, i, b, tt)\r
+        self.font_stack.append(font)\r
+        self.writer.new_font(font)\r
+\r
+    def pop_font(self):\r
+        if self.font_stack:\r
+            del self.font_stack[-1]\r
+        if self.font_stack:\r
+            font = self.font_stack[-1]\r
+        else:\r
+            font = None\r
+        self.writer.new_font(font)\r
+\r
+    def push_margin(self, margin):\r
+        self.margin_stack.append(margin)\r
+        fstack = filter(None, self.margin_stack)\r
+        if not margin and fstack:\r
+            margin = fstack[-1]\r
+        self.writer.new_margin(margin, len(fstack))\r
+\r
+    def pop_margin(self):\r
+        if self.margin_stack:\r
+            del self.margin_stack[-1]\r
+        fstack = filter(None, self.margin_stack)\r
+        if fstack:\r
+            margin = fstack[-1]\r
+        else:\r
+            margin = None\r
+        self.writer.new_margin(margin, len(fstack))\r
+\r
+    def set_spacing(self, spacing):\r
+        self.spacing = spacing\r
+        self.writer.new_spacing(spacing)\r
+\r
+    def push_style(self, *styles):\r
+        if self.softspace:\r
+            self.hard_break = self.para_end = self.softspace = 0\r
+            self.nospace = 1\r
+            self.writer.send_flowing_data(' ')\r
+        for style in styles:\r
+            self.style_stack.append(style)\r
+        self.writer.new_styles(tuple(self.style_stack))\r
+\r
+    def pop_style(self, n=1):\r
+        del self.style_stack[-n:]\r
+        self.writer.new_styles(tuple(self.style_stack))\r
+\r
+    def assert_line_data(self, flag=1):\r
+        self.nospace = self.hard_break = not flag\r
+        self.para_end = self.parskip = self.have_label = 0\r
+\r
+\r
+class NullWriter:\r
+    """Minimal writer interface to use in testing & inheritance.\r
+\r
+    A writer which only provides the interface definition; no actions are\r
+    taken on any methods.  This should be the base class for all writers\r
+    which do not need to inherit any implementation methods.\r
+\r
+    """\r
+    def __init__(self): pass\r
+    def flush(self): pass\r
+    def new_alignment(self, align): pass\r
+    def new_font(self, font): pass\r
+    def new_margin(self, margin, level): pass\r
+    def new_spacing(self, spacing): pass\r
+    def new_styles(self, styles): pass\r
+    def send_paragraph(self, blankline): pass\r
+    def send_line_break(self): pass\r
+    def send_hor_rule(self, *args, **kw): pass\r
+    def send_label_data(self, data): pass\r
+    def send_flowing_data(self, data): pass\r
+    def send_literal_data(self, data): pass\r
+\r
+\r
+class AbstractWriter(NullWriter):\r
+    """A writer which can be used in debugging formatters, but not much else.\r
+\r
+    Each method simply announces itself by printing its name and\r
+    arguments on standard output.\r
+\r
+    """\r
+\r
+    def new_alignment(self, align):\r
+        print "new_alignment(%r)" % (align,)\r
+\r
+    def new_font(self, font):\r
+        print "new_font(%r)" % (font,)\r
+\r
+    def new_margin(self, margin, level):\r
+        print "new_margin(%r, %d)" % (margin, level)\r
+\r
+    def new_spacing(self, spacing):\r
+        print "new_spacing(%r)" % (spacing,)\r
+\r
+    def new_styles(self, styles):\r
+        print "new_styles(%r)" % (styles,)\r
+\r
+    def send_paragraph(self, blankline):\r
+        print "send_paragraph(%r)" % (blankline,)\r
+\r
+    def send_line_break(self):\r
+        print "send_line_break()"\r
+\r
+    def send_hor_rule(self, *args, **kw):\r
+        print "send_hor_rule()"\r
+\r
+    def send_label_data(self, data):\r
+        print "send_label_data(%r)" % (data,)\r
+\r
+    def send_flowing_data(self, data):\r
+        print "send_flowing_data(%r)" % (data,)\r
+\r
+    def send_literal_data(self, data):\r
+        print "send_literal_data(%r)" % (data,)\r
+\r
+\r
+class DumbWriter(NullWriter):\r
+    """Simple writer class which writes output on the file object passed in\r
+    as the file parameter or, if file is omitted, on standard output.  The\r
+    output is simply word-wrapped to the number of columns specified by\r
+    the maxcol parameter.  This class is suitable for reflowing a sequence\r
+    of paragraphs.\r
+\r
+    """\r
+\r
+    def __init__(self, file=None, maxcol=72):\r
+        self.file = file or sys.stdout\r
+        self.maxcol = maxcol\r
+        NullWriter.__init__(self)\r
+        self.reset()\r
+\r
+    def reset(self):\r
+        self.col = 0\r
+        self.atbreak = 0\r
+\r
+    def send_paragraph(self, blankline):\r
+        self.file.write('\n'*blankline)\r
+        self.col = 0\r
+        self.atbreak = 0\r
+\r
+    def send_line_break(self):\r
+        self.file.write('\n')\r
+        self.col = 0\r
+        self.atbreak = 0\r
+\r
+    def send_hor_rule(self, *args, **kw):\r
+        self.file.write('\n')\r
+        self.file.write('-'*self.maxcol)\r
+        self.file.write('\n')\r
+        self.col = 0\r
+        self.atbreak = 0\r
+\r
+    def send_literal_data(self, data):\r
+        self.file.write(data)\r
+        i = data.rfind('\n')\r
+        if i >= 0:\r
+            self.col = 0\r
+            data = data[i+1:]\r
+        data = data.expandtabs()\r
+        self.col = self.col + len(data)\r
+        self.atbreak = 0\r
+\r
+    def send_flowing_data(self, data):\r
+        if not data: return\r
+        atbreak = self.atbreak or data[0].isspace()\r
+        col = self.col\r
+        maxcol = self.maxcol\r
+        write = self.file.write\r
+        for word in data.split():\r
+            if atbreak:\r
+                if col + len(word) >= maxcol:\r
+                    write('\n')\r
+                    col = 0\r
+                else:\r
+                    write(' ')\r
+                    col = col + 1\r
+            write(word)\r
+            col = col + len(word)\r
+            atbreak = 1\r
+        self.col = col\r
+        self.atbreak = data[-1].isspace()\r
+\r
+\r
+def test(file = None):\r
+    w = DumbWriter()\r
+    f = AbstractFormatter(w)\r
+    if file is not None:\r
+        fp = open(file)\r
+    elif sys.argv[1:]:\r
+        fp = open(sys.argv[1])\r
+    else:\r
+        fp = sys.stdin\r
+    for line in fp:\r
+        if line == '\n':\r
+            f.end_paragraph(1)\r
+        else:\r
+            f.add_flowing_data(line)\r
+    f.end_paragraph(0)\r
+\r
+\r
+if __name__ == '__main__':\r
+    test()\r