src/reportlab/lib/yaml.py
author robin
Tue, 19 Nov 2013 13:50:34 +0000
branchpy33
changeset 3794 398ea04239b5
parent 3721 0c93dd8ff567
child 4252 fe660f227cac
permissions -rw-r--r--
string module usage minimization
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3617
ae5744e97c42 reportlab: copyright date changes
robin
parents: 3326
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2012
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
import sys
andy_robinson
parents:
diff changeset
    43
andy_robinson
parents:
diff changeset
    44
#modes:
andy_robinson
parents:
diff changeset
    45
PLAIN = 1
andy_robinson
parents:
diff changeset
    46
PREFORMATTED = 2
andy_robinson
parents:
diff changeset
    47
andy_robinson
parents:
diff changeset
    48
BULLETCHAR = '\267'  # assumes font Symbol, but works on all platforms
andy_robinson
parents:
diff changeset
    49
andy_robinson
parents:
diff changeset
    50
class BaseParser:
andy_robinson
parents:
diff changeset
    51
    """"Simplest possible parser with only the most basic options.
andy_robinson
parents:
diff changeset
    52
andy_robinson
parents:
diff changeset
    53
    This defines the line-handling abilities and basic mechanism.
andy_robinson
parents:
diff changeset
    54
    The class YAMLParser includes capabilities for a fairly rich
andy_robinson
parents:
diff changeset
    55
    story."""
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    56
682
andy_robinson
parents:
diff changeset
    57
    def __init__(self):
andy_robinson
parents:
diff changeset
    58
        self.reset()
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    59
682
andy_robinson
parents:
diff changeset
    60
    def reset(self):
andy_robinson
parents:
diff changeset
    61
        self._lineNo = 0
andy_robinson
parents:
diff changeset
    62
        self._style = 'Normal'  # the default
andy_robinson
parents:
diff changeset
    63
        self._results = []
andy_robinson
parents:
diff changeset
    64
        self._buf = []
andy_robinson
parents:
diff changeset
    65
        self._mode = PLAIN
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    66
682
andy_robinson
parents:
diff changeset
    67
    def parseFile(self, filename):
andy_robinson
parents:
diff changeset
    68
        #returns list of objects
andy_robinson
parents:
diff changeset
    69
        data = open(filename, 'r').readlines()
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    70
682
andy_robinson
parents:
diff changeset
    71
        for line in data:
andy_robinson
parents:
diff changeset
    72
            #strip trailing newlines
andy_robinson
parents:
diff changeset
    73
            self.readLine(line[:-1])
andy_robinson
parents:
diff changeset
    74
        self.endPara()
andy_robinson
parents:
diff changeset
    75
        return self._results
andy_robinson
parents:
diff changeset
    76
andy_robinson
parents:
diff changeset
    77
    def parseText(self, textBlock):
andy_robinson
parents:
diff changeset
    78
        "Parses the a possible multi-line text block"
3794
398ea04239b5 string module usage minimization
robin
parents: 3721
diff changeset
    79
        lines = textBlock.split('\n')
682
andy_robinson
parents:
diff changeset
    80
        for line in lines:
andy_robinson
parents:
diff changeset
    81
            self.readLine(line)
andy_robinson
parents:
diff changeset
    82
        self.endPara()
andy_robinson
parents:
diff changeset
    83
        return self._results
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    84
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    85
    def readLine(self, line):
682
andy_robinson
parents:
diff changeset
    86
        #this is the inner loop
andy_robinson
parents:
diff changeset
    87
        self._lineNo = self._lineNo + 1
3794
398ea04239b5 string module usage minimization
robin
parents: 3721
diff changeset
    88
        stripped = line.lstrip()
682
andy_robinson
parents:
diff changeset
    89
        if len(stripped) == 0:
andy_robinson
parents:
diff changeset
    90
            if self._mode == PLAIN:
andy_robinson
parents:
diff changeset
    91
                self.endPara()
andy_robinson
parents:
diff changeset
    92
            else:  #preformatted, append it
andy_robinson
parents:
diff changeset
    93
                self._buf.append(line)
andy_robinson
parents:
diff changeset
    94
        elif line[0]=='.':
andy_robinson
parents:
diff changeset
    95
            # we have a command of some kind
andy_robinson
parents:
diff changeset
    96
            self.endPara()
3794
398ea04239b5 string module usage minimization
robin
parents: 3721
diff changeset
    97
            words = stripped[1:].split()
682
andy_robinson
parents:
diff changeset
    98
            cmd, args = words[0], words[1:]
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
    99
682
andy_robinson
parents:
diff changeset
   100
            #is it a parser method?
andy_robinson
parents:
diff changeset
   101
            if hasattr(self.__class__, cmd):
andy_robinson
parents:
diff changeset
   102
                #this was very bad; any type error in the method was hidden
andy_robinson
parents:
diff changeset
   103
                #we have to hack the traceback
andy_robinson
parents:
diff changeset
   104
                try:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 2964
diff changeset
   105
                    getattr(self,cmd)(*args)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3617
diff changeset
   106
                except TypeError as err:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 2964
diff changeset
   107
                    sys.stderr.write("Parser method: %s(*%s) %s at line %d\n" % (cmd, args, err, self._lineNo))
682
andy_robinson
parents:
diff changeset
   108
                    raise
andy_robinson
parents:
diff changeset
   109
            else:
andy_robinson
parents:
diff changeset
   110
                # assume it is a paragraph style -
andy_robinson
parents:
diff changeset
   111
                # becomes the formatter's problem
andy_robinson
parents:
diff changeset
   112
                self.endPara()  #end the last one
3794
398ea04239b5 string module usage minimization
robin
parents: 3721
diff changeset
   113
                words = stripped.split(' ', 1)
682
andy_robinson
parents:
diff changeset
   114
                assert len(words)==2, "Style %s but no data at line %d" % (words[0], self._lineNo)
andy_robinson
parents:
diff changeset
   115
                (styletag, data) = words
andy_robinson
parents:
diff changeset
   116
                self._style = styletag[1:]
andy_robinson
parents:
diff changeset
   117
                self._buf.append(data)
andy_robinson
parents:
diff changeset
   118
        else:
andy_robinson
parents:
diff changeset
   119
            #we have data, add to para
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   120
            self._buf.append(line)
682
andy_robinson
parents:
diff changeset
   121
andy_robinson
parents:
diff changeset
   122
    def endPara(self):
andy_robinson
parents:
diff changeset
   123
        #ends the current paragraph, or preformatted block
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   124
3794
398ea04239b5 string module usage minimization
robin
parents: 3721
diff changeset
   125
        text = ' '.join(self._buf)
682
andy_robinson
parents:
diff changeset
   126
        if text:
andy_robinson
parents:
diff changeset
   127
            if self._mode == PREFORMATTED:
andy_robinson
parents:
diff changeset
   128
                #item 3 is list of lines
andy_robinson
parents:
diff changeset
   129
                self._results.append(('PREFORMATTED', self._style,
3794
398ea04239b5 string module usage minimization
robin
parents: 3721
diff changeset
   130
                                 '\n'.join(self._buf)))
682
andy_robinson
parents:
diff changeset
   131
            else:
andy_robinson
parents:
diff changeset
   132
                self._results.append(('PARAGRAPH', self._style, text))
andy_robinson
parents:
diff changeset
   133
        self._buf = []
andy_robinson
parents:
diff changeset
   134
        self._style = 'Normal'
andy_robinson
parents:
diff changeset
   135
andy_robinson
parents:
diff changeset
   136
    def beginPre(self, stylename):
andy_robinson
parents:
diff changeset
   137
        self._mode = PREFORMATTED
andy_robinson
parents:
diff changeset
   138
        self._style = stylename
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   139
682
andy_robinson
parents:
diff changeset
   140
    def endPre(self):
andy_robinson
parents:
diff changeset
   141
        self.endPara()
andy_robinson
parents:
diff changeset
   142
        self._mode = PLAIN
andy_robinson
parents:
diff changeset
   143
andy_robinson
parents:
diff changeset
   144
    def image(self, filename):
andy_robinson
parents:
diff changeset
   145
        self.endPara()
andy_robinson
parents:
diff changeset
   146
        self._results.append(('IMAGE', filename))
andy_robinson
parents:
diff changeset
   147
andy_robinson
parents:
diff changeset
   148
andy_robinson
parents:
diff changeset
   149
class Parser(BaseParser):
andy_robinson
parents:
diff changeset
   150
    """This adds a basic set of "story" components compatible with HTML & PDF.
andy_robinson
parents:
diff changeset
   151
andy_robinson
parents:
diff changeset
   152
    Images, spaces"""
andy_robinson
parents:
diff changeset
   153
andy_robinson
parents:
diff changeset
   154
    def vSpace(self, points):
andy_robinson
parents:
diff changeset
   155
        """Inserts a vertical spacer"""
andy_robinson
parents:
diff changeset
   156
        self._results.append(('VSpace', points))
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   157
682
andy_robinson
parents:
diff changeset
   158
    def pageBreak(self):
andy_robinson
parents:
diff changeset
   159
        """Inserts a frame break"""
andy_robinson
parents:
diff changeset
   160
        self._results.append(('PageBreak','blah'))  # must be a tuple
andy_robinson
parents:
diff changeset
   161
andy_robinson
parents:
diff changeset
   162
    def custom(self, moduleName, funcName):
andy_robinson
parents:
diff changeset
   163
        """Goes and gets the Python object and adds it to the story"""
andy_robinson
parents:
diff changeset
   164
        self.endPara()
andy_robinson
parents:
diff changeset
   165
        self._results.append(('Custom',moduleName, funcName))
andy_robinson
parents:
diff changeset
   166
andy_robinson
parents:
diff changeset
   167
    def nextPageTemplate(self, templateName):
andy_robinson
parents:
diff changeset
   168
        self._results.append(('NextPageTemplate',templateName))
andy_robinson
parents:
diff changeset
   169
andy_robinson
parents:
diff changeset
   170
def parseFile(filename):
andy_robinson
parents:
diff changeset
   171
    p = Parser()
andy_robinson
parents:
diff changeset
   172
    return p.parseFile(filename)
andy_robinson
parents:
diff changeset
   173
andy_robinson
parents:
diff changeset
   174
def parseText(textBlock):
andy_robinson
parents:
diff changeset
   175
    p = Parser()
andy_robinson
parents:
diff changeset
   176
    return p.parseText(textBlock)
andy_robinson
parents:
diff changeset
   177
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1559
diff changeset
   178
682
andy_robinson
parents:
diff changeset
   179
if __name__=='__main__': #NORUNTESTS
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 2964
diff changeset
   180
    if len(sys.argv) != 2:
682
andy_robinson
parents:
diff changeset
   181
        results = parseText(__doc__)
andy_robinson
parents:
diff changeset
   182
    else:
andy_robinson
parents:
diff changeset
   183
        results = parseFile(sys.argv[1])
andy_robinson
parents:
diff changeset
   184
    import pprint
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 2964
diff changeset
   185
    pprint.pprint(results)