docs/tools/yaml.py
author rgbecker
Wed, 25 Oct 2000 08:57:46 +0000
changeset 494 54257447cfe9
parent 344 dd6e41c2b0ed
permissions -rw-r--r--
Changed to indirect copyright
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
494
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 344
diff changeset
     1
#copyright ReportLab Inc. 2000
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 344
diff changeset
     2
#see license.txt for license details
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 344
diff changeset
     3
#history http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/docs/tools/yaml.py?cvsroot=reportlab
54257447cfe9 Changed to indirect copyright
rgbecker
parents: 344
diff changeset
     4
#$Header: /tmp/reportlab/docs/tools/yaml.py,v 1.9 2000/10/25 08:57:45 rgbecker Exp $
256
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
     5
# parses "Yet Another Markup Language" into a list of tuples.
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
     6
# Each tuple says what the data is e.g.
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
     7
# ('Paragraph', 'Heading1', 'Why Reportlab Rules')
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
     8
# and the pattern depends on type.
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
     9
"""
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    10
Parser for "Aaron's Markup Language" - a markup language
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    11
which is easier to type in than XML, yet gives us a
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    12
reasonable selection of formats.
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    13
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    14
The general rule is that if a line begins with a '.',
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    15
it requires special processing. Otherwise lines
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    16
are concatenated to paragraphs, and blank lines
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    17
separate paragraphs. 
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    18
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    19
If the line ".foo bar bletch" is encountered,
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    20
it immediately ends and writes out any current
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    21
paragraph.
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    22
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    23
It then looks for a parser method called 'foo';
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    24
if found, it is called with arguments (bar, bletch).
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    25
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    26
If this is not found, it assumes that 'foo' is a
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    27
paragraph style, and the text for the first line
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    28
of the paragraph is 'bar bletch'.  It would be
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    29
up to the formatter to decide whether on not 'foo'
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    30
was a valid paragraph.
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    31
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    32
Special commands understood at present are:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    33
.image filename
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    34
- adds the image to the document
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    35
.beginPre Code
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    36
- begins a Preformatted object in style 'Code'
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    37
.endPre
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    38
- ends a preformatted object.
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    39
"""
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    40
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    41
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    42
import sys
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    43
import string
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    44
import imp
281
ed379b28de00 Changes to imports again sigh mumble
rgbecker
parents: 271
diff changeset
    45
import codegrab
256
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    46
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    47
#modes:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    48
PLAIN = 1
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    49
PREFORMATTED = 2
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    50
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    51
BULLETCHAR = '\267'  # assumes font Symbol, but works on all platforms
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    52
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    53
class Parser:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    54
    def __init__(self):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    55
        self.reset()
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    56
        
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    57
    def reset(self):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    58
        self._lineNo = 0
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    59
        self._style = 'Normal'  # the default
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    60
        self._results = []
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    61
        self._buf = []
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    62
        self._mode = PLAIN
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    63
        
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    64
    def parseFile(self, filename):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    65
        #returns list of objects
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    66
        data = open(filename, 'r').readlines()
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    67
        
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    68
        for line in data:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    69
            #strip trailing newlines
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    70
            self.readLine(line[:-1])
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    71
        self.endPara()
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    72
        return self._results
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    73
        
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    74
    def readLine(self, line):    
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    75
        #this is the inner loop
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    76
        self._lineNo = self._lineNo + 1
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    77
        stripped = string.lstrip(line)
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    78
        if len(stripped) == 0:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    79
            if self._mode == PLAIN:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    80
                self.endPara()
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    81
            else:  #preformatted, append it
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    82
                self._buf.append(line)
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    83
        elif line[0]=='.':
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    84
            # we have a command of some kind
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    85
            self.endPara()
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    86
            words = string.split(stripped[1:])
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    87
            cmd, args = words[0], words[1:]
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    88
    
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    89
            #is it a parser method?
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    90
            if hasattr(self.__class__, cmd):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    91
                method = eval('self.'+cmd)
287
bbd0eb35aee8 Python 1.5.1 compatibility fixes
rgbecker
parents: 281
diff changeset
    92
                #this was very bad; any type error in the method was hidden
bbd0eb35aee8 Python 1.5.1 compatibility fixes
rgbecker
parents: 281
diff changeset
    93
                #we have to hack the traceback
256
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    94
                try:
287
bbd0eb35aee8 Python 1.5.1 compatibility fixes
rgbecker
parents: 281
diff changeset
    95
                    apply(method, tuple(args))
bbd0eb35aee8 Python 1.5.1 compatibility fixes
rgbecker
parents: 281
diff changeset
    96
                except TypeError, err:
bbd0eb35aee8 Python 1.5.1 compatibility fixes
rgbecker
parents: 281
diff changeset
    97
                    sys.stderr.write("Parser method: apply(%s,%s) %s at line %d\n" % (cmd, tuple(args), err, self._lineNo))
bbd0eb35aee8 Python 1.5.1 compatibility fixes
rgbecker
parents: 281
diff changeset
    98
                    raise
256
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
    99
            else:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   100
                # assume it is a paragraph style -
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   101
                # becomes the formatter's problem
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   102
                self.endPara()  #end the last one
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   103
                words = string.split(stripped, ' ', 1)
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   104
                assert len(words)==2, "Style %s but no data at line %d" % (words[0], self._lineNo)
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   105
                (styletag, data) = words
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   106
                self._style = styletag[1:]
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   107
                self._buf.append(data)
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   108
        else:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   109
            #we have data, add to para
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   110
            self._buf.append(line)            
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   111
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   112
    def endPara(self):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   113
        #ends the current paragraph, or preformatted block
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   114
            
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   115
        text = string.join(self._buf, ' ')
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   116
        if text:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   117
            if self._mode == PREFORMATTED:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   118
                #item 3 is list of lines
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   119
                self._results.append(('Preformatted', self._style,
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   120
                                 string.join(self._buf,'\n')))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   121
            else:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   122
                self._results.append(('Paragraph', self._style, text))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   123
        self._buf = []
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   124
        self._style = 'Normal'
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   125
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   126
    def beginPre(self, stylename):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   127
        self._mode = PREFORMATTED
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   128
        self._style = stylename
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   129
        
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   130
    def endPre(self):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   131
        self.endPara()
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   132
        self._mode = PLAIN
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   133
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   134
    def image(self, filename):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   135
        self.endPara()
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   136
        self._results.append(('Image', filename))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   137
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   138
    def vSpace(self, points):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   139
        """Inserts a vertical spacer"""
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   140
        self._results.append(('VSpace', points))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   141
        
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   142
    def pageBreak(self):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   143
        """Inserts a frame break"""
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   144
        self._results.append(('PageBreak','blah'))  # must be a tuple
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   145
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   146
    def custom(self, moduleName, funcName):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   147
        """Goes and gets the Python object and adds it to the story"""
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   148
        self.endPara()
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   149
        self._results.append(('Custom',moduleName, funcName))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   150
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   151
    
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   152
        
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   153
    def getModuleDoc(self, modulename, pathname=None):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   154
        """Documents the entire module at this point by making
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   155
        paragraphs and preformatted objects"""
281
ed379b28de00 Changes to imports again sigh mumble
rgbecker
parents: 271
diff changeset
   156
        docco = codegrab.getObjectsDefinedIn(modulename, pathname)
271
574511abf998 Added docs for library
andy_robinson
parents: 269
diff changeset
   157
        if docco.doc <> None:
574511abf998 Added docs for library
andy_robinson
parents: 269
diff changeset
   158
            self._results.append(('Paragraph', 'DocString', docco.doc))
256
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   159
        if len(docco.functions) > 0:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   160
            for fn in docco.functions:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   161
                if fn.status == 'official':
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   162
                    self._results.append(('Preformatted','FunctionHeader', fn.proto))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   163
                    self._results.append(('Preformatted','DocString', fn.doc))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   164
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   165
        if len(docco.classes) > 0:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   166
            for cls in docco.classes:
271
574511abf998 Added docs for library
andy_robinson
parents: 269
diff changeset
   167
                if cls.status == 'official':
574511abf998 Added docs for library
andy_robinson
parents: 269
diff changeset
   168
                    self._results.append(('Preformatted','FunctionHeader', 'Class %s:' % cls.name))
574511abf998 Added docs for library
andy_robinson
parents: 269
diff changeset
   169
                    self._results.append(('Preformatted','DocString', cls.doc))
574511abf998 Added docs for library
andy_robinson
parents: 269
diff changeset
   170
                    for mth in cls.methods:
574511abf998 Added docs for library
andy_robinson
parents: 269
diff changeset
   171
                        if mth.status == 'official':
574511abf998 Added docs for library
andy_robinson
parents: 269
diff changeset
   172
                            self._results.append(('Preformatted','FunctionHeader', mth.proto))
574511abf998 Added docs for library
andy_robinson
parents: 269
diff changeset
   173
                            self._results.append(('Preformatted','DocStringIndent', mth.doc))
256
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   174
                    
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   175
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   176
    def getClassDoc(self, modulename, classname, pathname=None):
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   177
        """Documents the class and its public methods"""
281
ed379b28de00 Changes to imports again sigh mumble
rgbecker
parents: 271
diff changeset
   178
        docco = codegrab.getObjectsDefinedIn(modulename, pathname)
256
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   179
        found = 0
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   180
        for cls in docco.classes:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   181
            if cls.name == classname:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   182
                found = 1
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   183
                self._results.append(('Preformatted','FunctionHeader', 'Class %s:' % cls.name))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   184
                self._results.append(('Preformatted','DocString', cls.doc))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   185
                for mth in cls.methods:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   186
                    if mth.status == 'official':
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   187
                        self._results.append(('Preformatted','FunctionHeader', mth.proto))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   188
                        self._results.append(('Preformatted','DocStringIndent', mth.doc))
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   189
                break
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   190
        assert found, 'No Classes Defined in ' + modulename
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   191
344
dd6e41c2b0ed Paragraphs chapter pretty much complete. Fancy cover.
andy_robinson
parents: 316
diff changeset
   192
    def nextPageTemplate(self, templateName):
dd6e41c2b0ed Paragraphs chapter pretty much complete. Fancy cover.
andy_robinson
parents: 316
diff changeset
   193
        self._results.append(('NextPageTemplate',templateName))
256
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   194
        
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   195
if __name__=='__main__': #NORUNTESTS
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   196
    if len(sys.argv) <> 2:
315
21835616ec56 Fix usage message
rgbecker
parents: 287
diff changeset
   197
        print 'usage: yaml.py source.txt'
256
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   198
    else:
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   199
        p = Parser()
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   200
        results = p.parseFile(sys.argv[1])
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   201
        import pprint
0dedfa161b21 Initial revision
andy_robinson
parents:
diff changeset
   202
        pprint.pprint(results)