summaryrefslogtreecommitdiff
path: root/paste/docsupport/gensite.py
blob: a5f44594f3ac801ab462d5f169b6115c96825c2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php

#!/usr/bin/env python
"""
This is a very basic script to generate a site from a set of ReST
documents.
"""

import os
import re
import shutil
import optparse
from Cheetah.Template import Template
from paste import pyconfig

__version__ = '0.1'

parser = optparse.OptionParser(
    version=__version__,
    usage="%prog [OPTIONS]")

parser.add_option(
    '-f', '--config-file',
    dest='config_file',
    metavar='FILENAME',
    default='doc.conf',
    help="The configuration file to load (default doc.conf)")

def main():
    options, args = parser.parse_args()
    assert not args, (
        "No arguments are allowed")
    conf = pyconfig.Config(with_default=True)
    conf.load_dict({'dirs': {},
                    'dest_base': os.getcwd()})
    conf.load(options.config_file)
    dirs = conf['dirs']
    base = conf['dest_base']
    for source, dest in dirs.items():
        dirs[source] = os.path.join(base, dest)
    gen_site(conf)
    
def gen_site(conf):
    template = make_template(conf)
    files = find_files(conf)
    for source, dest in files.items():
        if not source.endswith('.html'):
            shutil.copyfile(source, dest)
            continue
        f = RestFile(source)
        template.ns.clear()
        f.update_ns(template.ns)
        content = str(template)
        print 'Writing %s (%i bytes)' % (os.path.basename(source), len(content))
        dest_dir = os.path.dirname(dest)
        if not os.path.exists(dest_dir):
            print 'Creating %s' % dest_dir
            os.makedirs(dest_dir)
        f = open(dest, 'w')
        f.write(content)
        f.close()

def find_files(conf):
    files = {}
    for source, dest in conf['dirs'].items():
        find_files_dir(source, dest, conf, files)
    return files

def find_files_dir(source, dest, conf, files):
    for name in os.listdir(source):
        source_fn = os.path.join(source, name)
        if os.path.isdir(source_fn):
            continue
        files[source_fn] = os.path.join(os.path.join(dest, name))

def make_template(conf):
    template_fn = os.path.join(os.getcwd(), conf['template'])
    ns = {}
    template = Template(
        file=template_fn, searchList=[ns])
    template.ns = ns
    return template
    
class RestFile(object):

    def __init__(self, fn):
        self.filename = fn
        f = open(fn)
        self.html = f.read()
        f.close()
        self.read_properties()
        self.read_content()

    def update_ns(self, ns):
        ns['file'] = self
        ns['content'] = self.content
        ns.update(self.properties)

    _title_re = re.compile(r'<title>(.*?)</title>')
    def read_properties(self):
        props = self.properties = {}
        m = self._title_re.search(self.html)
        if m:
            props['title'] = m.group(1)
        else:
            print 'No title in %s' % self.filename
            props['title'] = ''

    #_start_re = re.compile(r'<div class=".*?" id="contents">')
    _start_re = re.compile(r'<body>[ \n]*(?:<div.*?>[ \n]*)?<h1.*?>.*?</h1>')
    _end_re = re.compile(r'(?:</div>[ \n]*)?</div>[ \n]*</body>[\n\r ]*</html>[\n\r ]*$')
    _bad_res = [
        (re.compile(r'<link rel="stylesheet".*?>'), ''),
        (re.compile(r'<h1 class="title">.*?</h1>'), ''),
        (re.compile(r'(<p class=".*?"><a name="contents">.*?</p>)[ \n]*'
                    r'(<ul class="simple">)'),
         '<div><ul class="simple contents">\n'
         '<li class="header">Contents</li>\n'),
        (re.compile(r'(<th class="docinfo-name">Date:</th>[ \n]*)'
                    r'(<td>).*?\((.*?)\)'),
         r'\1\2\3'),
    ]
    
    def read_content(self):
        c = self.html
        m = self._start_re.search(c)
        if m:
            c = c[m.end():]
        else:
            print 'Bad beginning in %s' % self.filename
        m = self._end_re.search(c)
        if m:
            c = c[:m.start()]
        else:
            print 'Bad ending in %s' % self.filename
        for regex, sub in self._bad_res:
            c = regex.sub(sub, c)
        self.content = c

    def __repr__(self):
        return '<%s %s>' % (self.__class__.__name__, self.filename)

if __name__ == '__main__':
    main()