root/tags/0.8a6/docgen.py

Revision 51, 9.4 kB (checked in by kevin, 3 years ago)

Sebastian Jansson's redesign for the site.

Line 
1 import os
2 import sys
3 import shutil
4 import time
5 from setuptools import Command
6 import pkg_resources
7 pkg_resources.require("Kid >= 0.6.4")
8 import kid
9 import re
10 from distutils import log
11
12 class GenSite(Command):
13     "setuptools command to generate the TurboGears website"
14    
15     user_options = [
16         ("srcdirs=", "s", "directories containing the source files (default: docs)"),
17         ("destdir=", "d", "destination output directory (default: dist/site)"),
18         ("encoding=", "e", "encoding for output (default: utf8)"),
19         ("force", "f", "regenerate all files"),
20         ("ignoredirs=", "i", "directories to ignore (default: ['.svn', '.cvs'])"),
21         ("ignorefiles=", "x", "files to ignore (default: ['.*\\.pyc', '.DS_Store'])"),
22         ("templates=", "t", "mapping of templates to load (format: name=templatefile,name=templatefile)"),
23         ("copydirs=", "c", "copy files from these directories without template proc. (destdir=srcdir,...)")
24     ]
25    
26     boolean_options=["force"]
27    
28     srcdirs = None
29     destdir = "dist/site"
30     encoding = "utf8"
31     force = False
32     ignoredirs = None
33     ignorefiles = None
34     templates = None
35     copydirs = None
36    
37     def initialize_options(self):
38         pass
39        
40     def finalize_options(self):
41         if self.srcdirs is None:
42             self.srcdirs = ["docs"]
43         self.ensure_string_list("srcdirs")
44         self.ensure_string("destdir", "dist/site")
45         self.ensure_string("encoding", "utf8")
46         if self.ignoredirs is None:
47             self.ignoredirs = [".svn", ".cvs"]
48         self.ensure_string_list("ignoredirs")
49         if self.ignorefiles is None:
50             self.ignorefiles = ['.*\\.pyc', '.DS_Store']
51         self.ensure_string_list("ignorefiles")
52        
53         regexes = []
54         for pat in self.ignorefiles:
55             regexes.append(re.compile(pat))
56         self.ignorepatterns = regexes
57        
58         self.templates = self._split_mapping(self.templates)
59         self.copydirs = self._split_mapping(self.copydirs)
60            
61     def _split_mapping(self, valToSplit):
62         mapping = {}
63         if valToSplit and isinstance(valToSplit, basestring):
64             pairs = re.split(",\s*", valToSplit)
65             for pair in pairs:
66                 name, filename = re.split("\s*=\s*", pair)
67                 mapping[name] = os.path.abspath(filename)
68         return mapping
69        
70     def check_if_newer(self, src, dest):
71         srcmtime = os.path.getmtime(src)
72         if os.path.exists(dest):
73             destmtime = os.path.getmtime(dest)
74         else:
75             destmtime = 0
76         return srcmtime > destmtime
77        
78     def copy_if_newer(self, src, dest):
79         if self.force or self.check_if_newer(src, dest):
80             d = os.path.dirname(dest)
81             if not os.path.exists(d):
82                 os.makedirs(d)
83             self.copy_file(src, dest)
84            
85     def render_template(self, src, dest, depth):
86         if not self.force and not self.check_if_newer(src, dest):
87             return
88         if not self.dry_run:
89             log.info("rendering %s" % dest)
90         else:
91             log.info("skipping rendering %s" % dest)
92             return
93        
94         template = kid.load_template(src, cache=False)
95         template.Template.serializer = self.serializer
96         toroot = "../" * depth
97         destfile = dest[len(self.destdir)+1:]
98         updated = time.strftime("%b %d, %Y", time.localtime(os.path.getmtime(src)))
99         output = template.serialize(encoding=self.encoding, root=toroot, updated=updated,
100             destfile=destfile)
101         output = output.replace("$$", "$")
102         destfile = open(dest, "w")
103         destfile.write(output)
104         destfile.close()
105        
106     def update_site_files(self, srcdir, processTemplates = True, destroot=None):
107         if not destroot:
108             destroot = self.destdir
109         for root, dirs, files in os.walk(srcdir):
110             if root != srcdir:
111                 fromroot = root[len(srcdir)+1:]
112                 segments = fromroot.split(os.sep)
113                 if set(segments).intersection(self.ignoredirs):
114                     continue
115                 depth = len(segments)
116             else:
117                 fromroot = ""
118                 depth = 0
119             destdir = os.path.join(destroot, fromroot)
120             if not os.path.exists(destdir):
121                 if not self.dry_run:
122                     log.info("creating directory %s" % (destdir))
123                     os.makedirs(destdir)
124                 else:
125                     log.info("skipping creating directory %s" % (destdir))
126                
127             for file in files:
128                 ignore = False
129                 abs = os.path.abspath(file)
130                 for pat in self.ignorepatterns:
131                     if pat.match(file):
132                         ignore = True
133                         break
134                 if ignore:
135                     continue
136                
137                 for tempfile in self.templates.values():
138                     if tempfile == abs:
139                         ignore = True
140                         break
141                 if ignore:
142                     continue
143                
144                 ext = os.path.splitext(file)[1]
145                 dest = os.path.join(destdir, file)
146                 self.currentfiles.add(dest)
147                 if not processTemplates or ext != ".html":
148                     self.copy_if_newer(os.path.join(root, file),
149                         dest)
150                 else:
151                     self.render_template(os.path.join(root, file),
152                         dest, depth)
153
154     def delete_excess_files(self):
155         for root, dirs, files in os.walk(self.destdir):
156             for file in files:
157                 dest = os.path.join(root, file)
158                 if dest not in self.currentfiles:
159                     if not self.dry_run:
160                         log.info("deleting %s" % dest)
161                         os.unlink(dest)
162                     else:
163                         log.info("skipping deleting %s" % dest)
164
165     def run(self):
166         destdir = self.destdir
167         log.info("generating website to %s" % destdir)
168
169         if not os.path.exists(destdir):
170             log.info("creating %s" % destdir)
171             os.mkdir(destdir)
172            
173         for name, filename in self.templates.items():
174             log.info("template %s loaded as %s" % (filename, name))
175             kid.load_template(filename, name=name)
176
177         self.currentfiles = set()
178
179         self.serializer = kid.HTMLSerializer(encoding=self.encoding)
180
181         for d in self.srcdirs:
182             self.update_site_files(d)
183         for dest, src in self.copydirs.items():
184             if os.path.isdir(src):
185                 self.update_site_files(src, processTemplates=False,
186                                    destroot=os.path.join(self.destdir, dest))
187             else:
188                 destfile = os.path.join(self.destdir, os.path.normpath(dest))
189                 self.copy_if_newer(src, destfile)
190                 self.currentfiles.add(destfile)
191         self.printable_tutorial()
192         self.delete_excess_files()
193        
194     def printable_tutorial(self):
195         import cElementTree as elementtree
196         tutdir = os.path.join("docs", "docs", "wiki20")
197         masterdoc = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
198 <?python import printable ?>
199 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#" py:extends="printable">
200 <head>
201  <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
202  <link rel="stylesheet" type="text/css" href="../../default.css" py:attrs="href=root+'default.css'"/>
203  <link type="text/css" rel="stylesheet" href="../../sh/SyntaxHighlighter.css" py:attrs="href=root+'sh/SyntaxHighlighter.css'"></link>
204  <title>TurboGears: 20 Minute Wiki Tutorial</title>
205 </head>
206 <body>
207 """
208         docs = os.listdir(tutdir)
209         docs.sort()
210         for doc in docs:
211             if not doc.endswith(".html"):
212                 continue
213             log.info("combining %s" % doc)
214             tree = elementtree.parse(os.path.join(tutdir, doc))
215             body = tree.find("{http://www.w3.org/1999/xhtml}body")
216             map(body.remove, body.findall("{http://www.w3.org/1999/xhtml}script"))
217             bodytext = elementtree.tostring(body)
218             bodytext = bodytext.replace("</html:body>", "")
219             bodytext = bodytext.replace('<html:body xmlns:html="http://www.w3.org/1999/xhtml">', "")
220             masterdoc += bodytext
221            
222         masterdoc += """<script src="../../sh/shCore.js" py:attrs="src=root+'sh/shCore.js'"></script>
223 <script src="../../sh/shBrushPython.js" py:attrs="src=root+'sh/shBrushPython.js'"></script>
224 <script src="../../sh/shBrushXml.js" py:attrs="src=root+'sh/shBrushXml.js'"></script>
225 <script src="../../sh/shBrushJScript.js" py:attrs="src=root+'sh/shBrushJScript.js'"></script>
226 <script language="javascript">
227         dp.SyntaxHighlighter.HighlightAll('code');
228 </script>
229 </body></html>"""
230         masterdoc = masterdoc.replace("html:", "")
231         template = kid.Template(source=masterdoc, root="../../")
232         template.serializer = self.serializer
233         outfn = os.path.join("dist", "site", "docs", "wiki20",
234                              "printable.html")
235         outfile = open(outfn, "w")
236         masterdoc = template.serialize(encoding=self.encoding)
237         masterdoc = masterdoc.replace("$${", "${")
238         outfile.write(masterdoc)
239         outfile.close()
240         self.currentfiles.add(outfn)
241        
Note: See TracBrowser for help on using the browser.