src/reportlab/lib/yaml.py
author damian
Mon, 08 Feb 2010 18:17:33 +0000
changeset 3326 ce725978d11c
parent 2964 32352db0d71e
child 3617 ae5744e97c42
permissions -rw-r--r--
Initial Python3 compatibility fixes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 1683
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2004
682
andy_robinson
parents:
diff changeset
     2
#see license.txt for license details
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 1683
diff changeset
     3
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/lib/yaml.py
682
andy_robinson
parents:
diff changeset
     4
# parses "Yet Another Markup Language" into a list of tuples.
andy_robinson
parents:
diff changeset
     5
# Each tuple says what the data is e.g.
andy_robinson
parents:
diff changeset
     6
# ('Paragraph', 'Heading1', 'Why Reportlab Rules')
andy_robinson
parents:
diff changeset
     7
# and the pattern depends on type.
andy_robinson
parents:
diff changeset
     8
"""
andy_robinson
parents:
diff changeset
     9
.h1 Welcome to YAML!
andy_robinson
parents:
diff changeset
    10
YAML is "Yet Another Markup Language" - a markup language
andy_robinson
parents:
diff changeset
    11
which is easier to type in than XML, yet gives us a
andy_robinson
parents:
diff changeset
    12
reasonable selection of formats.
andy_robinson
parents:
diff changeset
    13
andy_robinson
parents:
diff changeset
    14
The general rule is that if a line begins with a '.',
andy_robinson
parents:
diff changeset
    15
it requires special processing. Otherwise lines
andy_robinson
parents:
diff changeset
    16
are concatenated to paragraphs, and blank lines
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    17
separate paragraphs.
682
andy_robinson
parents:
diff changeset
    18
andy_robinson
parents:
diff changeset
    19
If the line ".foo bar bletch" is encountered,
andy_robinson
parents:
diff changeset
    20
it immediately ends and writes out any current
andy_robinson
parents:
diff changeset
    21
paragraph.
andy_robinson
parents:
diff changeset
    22
andy_robinson
parents:
diff changeset
    23
It then looks for a parser method called 'foo';
andy_robinson
parents:
diff changeset
    24
if found, it is called with arguments (bar, bletch).
andy_robinson
parents:
diff changeset
    25
andy_robinson
parents:
diff changeset
    26
If this is not found, it assumes that 'foo' is a
andy_robinson
parents:
diff changeset
    27
paragraph style, and the text for the first line
andy_robinson
parents:
diff changeset
    28
of the paragraph is 'bar bletch'.  It would be
andy_robinson
parents:
diff changeset
    29
up to the formatter to decide whether on not 'foo'
andy_robinson
parents:
diff changeset
    30
was a valid paragraph.
andy_robinson
parents:
diff changeset
    31
andy_robinson
parents:
diff changeset
    32
Special commands understood at present are:
andy_robinson
parents:
diff changeset
    33
dot image filename
andy_robinson
parents:
diff changeset
    34
- adds the image to the document
andy_robinson
parents:
diff changeset
    35
dot beginPre Code
andy_robinson
parents:
diff changeset
    36
- begins a Preformatted object in style 'Code'
andy_robinson
parents:
diff changeset
    37
dot endPre
andy_robinson
parents:
diff changeset
    38
- ends a preformatted object.
andy_robinson
parents:
diff changeset
    39
"""
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 1683
diff changeset
    40
__version__=''' $Id$ '''
682
andy_robinson
parents:
diff changeset
    41
andy_robinson
parents:
diff changeset
    42
andy_robinson
parents:
diff changeset
    43
import sys
andy_robinson
parents:
diff changeset
    44
import string
andy_robinson
parents:
diff changeset
    45
andy_robinson
parents:
diff changeset
    46
#modes:
andy_robinson
parents:
diff changeset
    47
PLAIN = 1
andy_robinson
parents:
diff changeset
    48
PREFORMATTED = 2
andy_robinson
parents:
diff changeset
    49
andy_robinson
parents:
diff changeset
    50
BULLETCHAR = '\267'  # assumes font Symbol, but works on all platforms
andy_robinson
parents:
diff changeset
    51
andy_robinson
parents:
diff changeset
    52
class BaseParser:
andy_robinson
parents:
diff changeset
    53
    """"Simplest possible parser with only the most basic options.
andy_robinson
parents:
diff changeset
    54
andy_robinson
parents:
diff changeset
    55
    This defines the line-handling abilities and basic mechanism.
andy_robinson
parents:
diff changeset
    56
    The class YAMLParser includes capabilities for a fairly rich
andy_robinson
parents:
diff changeset
    57
    story."""
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    58
682
andy_robinson
parents:
diff changeset
    59
    def __init__(self):
andy_robinson
parents:
diff changeset
    60
        self.reset()
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    61
682
andy_robinson
parents:
diff changeset
    62
    def reset(self):
andy_robinson
parents:
diff changeset
    63
        self._lineNo = 0
andy_robinson
parents:
diff changeset
    64
        self._style = 'Normal'  # the default
andy_robinson
parents:
diff changeset
    65
        self._results = []
andy_robinson
parents:
diff changeset
    66
        self._buf = []
andy_robinson
parents:
diff changeset
    67
        self._mode = PLAIN
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    68
682
andy_robinson
parents:
diff changeset
    69
    def parseFile(self, filename):
andy_robinson
parents:
diff changeset
    70
        #returns list of objects
andy_robinson
parents:
diff changeset
    71
        data = open(filename, 'r').readlines()
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    72
682
andy_robinson
parents:
diff changeset
    73
        for line in data:
andy_robinson
parents:
diff changeset
    74
            #strip trailing newlines
andy_robinson
parents:
diff changeset
    75
            self.readLine(line[:-1])
andy_robinson
parents:
diff changeset
    76
        self.endPara()
andy_robinson
parents:
diff changeset
    77
        return self._results
andy_robinson
parents:
diff changeset
    78
andy_robinson
parents:
diff changeset
    79
    def parseText(self, textBlock):
andy_robinson
parents:
diff changeset
    80
        "Parses the a possible multi-line text block"
andy_robinson
parents:
diff changeset
    81
        lines = string.split(textBlock, '\n')
andy_robinson
parents:
diff changeset
    82
        for line in lines:
andy_robinson
parents:
diff changeset
    83
            self.readLine(line)
andy_robinson
parents:
diff changeset
    84
        self.endPara()
andy_robinson
parents:
diff changeset
    85
        return self._results
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    86
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    87
    def readLine(self, line):
682
andy_robinson
parents:
diff changeset
    88
        #this is the inner loop
andy_robinson
parents:
diff changeset
    89
        self._lineNo = self._lineNo + 1
andy_robinson
parents:
diff changeset
    90
        stripped = string.lstrip(line)
andy_robinson
parents:
diff changeset
    91
        if len(stripped) == 0:
andy_robinson
parents:
diff changeset
    92
            if self._mode == PLAIN:
andy_robinson
parents:
diff changeset
    93
                self.endPara()
andy_robinson
parents:
diff changeset
    94
            else:  #preformatted, append it
andy_robinson
parents:
diff changeset
    95
                self._buf.append(line)
andy_robinson
parents:
diff changeset
    96
        elif line[0]=='.':
andy_robinson
parents:
diff changeset
    97
            # we have a command of some kind
andy_robinson
parents:
diff changeset
    98
            self.endPara()
andy_robinson
parents:
diff changeset
    99
            words = string.split(stripped[1:])
andy_robinson
parents:
diff changeset
   100
            cmd, args = words[0], words[1:]
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   101
682
andy_robinson
parents:
diff changeset
   102
            #is it a parser method?
andy_robinson
parents:
diff changeset
   103
            if hasattr(self.__class__, cmd):
andy_robinson
parents:
diff changeset
   104
                #this was very bad; any type error in the method was hidden
andy_robinson
parents:
diff changeset
   105
                #we have to hack the traceback
andy_robinson
parents:
diff changeset
   106
                try:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 2964
diff changeset
   107
                    getattr(self,cmd)(*args)
682
andy_robinson
parents:
diff changeset
   108
                except TypeError, err:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 2964
diff changeset
   109
                    sys.stderr.write("Parser method: %s(*%s) %s at line %d\n" % (cmd, args, err, self._lineNo))
682
andy_robinson
parents:
diff changeset
   110
                    raise
andy_robinson
parents:
diff changeset
   111
            else:
andy_robinson
parents:
diff changeset
   112
                # assume it is a paragraph style -
andy_robinson
parents:
diff changeset
   113
                # becomes the formatter's problem
andy_robinson
parents:
diff changeset
   114
                self.endPara()  #end the last one
andy_robinson
parents:
diff changeset
   115
                words = string.split(stripped, ' ', 1)
andy_robinson
parents:
diff changeset
   116
                assert len(words)==2, "Style %s but no data at line %d" % (words[0], self._lineNo)
andy_robinson
parents:
diff changeset
   117
                (styletag, data) = words
andy_robinson
parents:
diff changeset
   118
                self._style = styletag[1:]
andy_robinson
parents:
diff changeset
   119
                self._buf.append(data)
andy_robinson
parents:
diff changeset
   120
        else:
andy_robinson
parents:
diff changeset
   121
            #we have data, add to para
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   122
            self._buf.append(line)
682
andy_robinson
parents:
diff changeset
   123
andy_robinson
parents:
diff changeset
   124
    def endPara(self):
andy_robinson
parents:
diff changeset
   125
        #ends the current paragraph, or preformatted block
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   126
682
andy_robinson
parents:
diff changeset
   127
        text = string.join(self._buf, ' ')
andy_robinson
parents:
diff changeset
   128
        if text:
andy_robinson
parents:
diff changeset
   129
            if self._mode == PREFORMATTED:
andy_robinson
parents:
diff changeset
   130
                #item 3 is list of lines
andy_robinson
parents:
diff changeset
   131
                self._results.append(('PREFORMATTED', self._style,
andy_robinson
parents:
diff changeset
   132
                                 string.join(self._buf,'\n')))
andy_robinson
parents:
diff changeset
   133
            else:
andy_robinson
parents:
diff changeset
   134
                self._results.append(('PARAGRAPH', self._style, text))
andy_robinson
parents:
diff changeset
   135
        self._buf = []
andy_robinson
parents:
diff changeset
   136
        self._style = 'Normal'
andy_robinson
parents:
diff changeset
   137
andy_robinson
parents:
diff changeset
   138
    def beginPre(self, stylename):
andy_robinson
parents:
diff changeset
   139
        self._mode = PREFORMATTED
andy_robinson
parents:
diff changeset
   140
        self._style = stylename
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   141
682
andy_robinson
parents:
diff changeset
   142
    def endPre(self):
andy_robinson
parents:
diff changeset
   143
        self.endPara()
andy_robinson
parents:
diff changeset
   144
        self._mode = PLAIN
andy_robinson
parents:
diff changeset
   145
andy_robinson
parents:
diff changeset
   146
    def image(self, filename):
andy_robinson
parents:
diff changeset
   147
        self.endPara()
andy_robinson
parents:
diff changeset
   148
        self._results.append(('IMAGE', filename))
andy_robinson
parents:
diff changeset
   149
andy_robinson
parents:
diff changeset
   150
andy_robinson
parents:
diff changeset
   151
class Parser(BaseParser):
andy_robinson
parents:
diff changeset
   152
    """This adds a basic set of "story" components compatible with HTML & PDF.
andy_robinson
parents:
diff changeset
   153
andy_robinson
parents:
diff changeset
   154
    Images, spaces"""
andy_robinson
parents:
diff changeset
   155
andy_robinson
parents:
diff changeset
   156
    def vSpace(self, points):
andy_robinson
parents:
diff changeset
   157
        """Inserts a vertical spacer"""
andy_robinson
parents:
diff changeset
   158
        self._results.append(('VSpace', points))
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   159
682
andy_robinson
parents:
diff changeset
   160
    def pageBreak(self):
andy_robinson
parents:
diff changeset
   161
        """Inserts a frame break"""
andy_robinson
parents:
diff changeset
   162
        self._results.append(('PageBreak','blah'))  # must be a tuple
andy_robinson
parents:
diff changeset
   163
andy_robinson
parents:
diff changeset
   164
    def custom(self, moduleName, funcName):
andy_robinson
parents:
diff changeset
   165
        """Goes and gets the Python object and adds it to the story"""
andy_robinson
parents:
diff changeset
   166
        self.endPara()
andy_robinson
parents:
diff changeset
   167
        self._results.append(('Custom',moduleName, funcName))
andy_robinson
parents:
diff changeset
   168
andy_robinson
parents:
diff changeset
   169
    def nextPageTemplate(self, templateName):
andy_robinson
parents:
diff changeset
   170
        self._results.append(('NextPageTemplate',templateName))
andy_robinson
parents:
diff changeset
   171
andy_robinson
parents:
diff changeset
   172
def parseFile(filename):
andy_robinson
parents:
diff changeset
   173
    p = Parser()
andy_robinson
parents:
diff changeset
   174
    return p.parseFile(filename)
andy_robinson
parents:
diff changeset
   175
andy_robinson
parents:
diff changeset
   176
def parseText(textBlock):
andy_robinson
parents:
diff changeset
   177
    p = Parser()
andy_robinson
parents:
diff changeset
   178
    return p.parseText(textBlock)
andy_robinson
parents:
diff changeset
   179
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   180
682
andy_robinson
parents:
diff changeset
   181
if __name__=='__main__': #NORUNTESTS
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 2964
diff changeset
   182
    if len(sys.argv) != 2:
682
andy_robinson
parents:
diff changeset
   183
        results = parseText(__doc__)
andy_robinson
parents:
diff changeset
   184
    else:
andy_robinson
parents:
diff changeset
   185
        results = parseFile(sys.argv[1])
andy_robinson
parents:
diff changeset
   186
    import pprint
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 2964
diff changeset
   187
    pprint.pprint(results)