Package turbogears :: Module docgen
[hide private]

Source Code for Module turbogears.docgen

  1  import os 
  2  import sys 
  3  import shutil 
  4  import time 
  5  from glob import glob 
  6  from setuptools import Command 
  7  import pkg_resources 
  8  pkg_resources.require("Kid >= 0.6.4") 
  9  import kid 
 10  import re 
 11  from distutils import log 
 12   
13 -class GenSite(Command):
14 "setuptools command to generate the TurboGears website" 15 16 user_options = [ 17 ("srcdirs=", "s", "directories containing the source files (default: docs)"), 18 ("destdir=", "d", "destination output directory (default: dist/site)"), 19 ("encoding=", "e", "encoding for output (default: utf8)"), 20 ("force", "f", "regenerate all files"), 21 ("ignoredirs=", "i", "directories to ignore (default: ['.svn', '.cvs'])"), 22 ("ignorefiles=", "x", "files to ignore (default: ['.*\\.pyc', '.DS_Store'])"), 23 ("nodelete=", "l", "directories to leave alone rather than delete"), 24 ("templates=", "t", "mapping of templates to load (format: name=templatefile,name=templatefile)"), 25 ("copydirs=", "c", "copy files from these directories without template proc. (destdir=srcdir,...)"), 26 ("noprintable", "N", "don't make printable version of tutorials"), 27 ("eggdir=", "g", "which directory has the eggs in it (default: '../thirdparty/eggs')") 28 ] 29 30 boolean_options=["force"] 31 32 srcdirs = None 33 destdir = "dist/site" 34 encoding = "utf8" 35 force = False 36 ignoredirs = None 37 ignorefiles = None 38 nodelete = None 39 templates = None 40 copydirs = None 41 eggdir = "../thirdparty/eggs" 42 noprintable = False 43
44 - def initialize_options(self):
45 pass
46
47 - def finalize_options(self):
48 if self.srcdirs is None: 49 self.srcdirs = ["docs"] 50 if self.srcdirs == "": 51 self.srcdirs = [] 52 self.ensure_string_list("srcdirs") 53 self.ensure_string("destdir", "dist/site") 54 self.ensure_string("encoding", "utf8") 55 if self.ignoredirs is None: 56 self.ignoredirs = [".svn", ".cvs"] 57 self.ensure_string_list("ignoredirs") 58 if self.ignorefiles is None: 59 self.ignorefiles = ['.*\\.pyc', '.DS_Store'] 60 if self.nodelete is None: 61 self.nodelete = ["dist/site/preview"] 62 self.ensure_string_list("nodelete") 63 self.ensure_string_list("ignorefiles") 64 65 regexes = [] 66 for pat in self.ignorefiles: 67 regexes.append(re.compile(pat)) 68 self.ignorepatterns = regexes 69 70 self.templates, self.templates_order = self._split_mapping(self.templates, True) 71 self.copydirs = self._split_mapping(self.copydirs)
72
73 - def _split_mapping(self, valToSplit, preserve_order=False):
74 mapping = {} 75 order = [] 76 if valToSplit and isinstance(valToSplit, basestring): 77 pairs = re.split(",\s*", valToSplit) 78 for pair in pairs: 79 name, filename = re.split("\s*=\s*", pair) 80 mapping[name] = os.path.abspath(filename) 81 order.append(name) 82 if preserve_order: 83 return mapping, order 84 return mapping
85
86 - def check_if_newer(self, src, dest):
87 srcmtime = os.path.getmtime(src) 88 if os.path.exists(dest): 89 destmtime = os.path.getmtime(dest) 90 else: 91 destmtime = 0 92 return srcmtime > destmtime
93
94 - def copy_if_newer(self, src, dest):
95 if self.force or self.check_if_newer(src, dest): 96 d = os.path.dirname(dest) 97 if not os.path.exists(d): 98 os.makedirs(d) 99 self.copy_file(src, dest)
100
101 - def render_template(self, src, dest, depth):
102 if not self.force and not self.check_if_newer(src, dest): 103 return 104 if not self.dry_run: 105 log.info("rendering %s" % dest) 106 else: 107 log.info("skipping rendering %s" % dest) 108 return 109 110 template = kid.load_template(src, cache=False) 111 template.Template.serializer = self.serializer 112 toroot = "../" * depth 113 destfile = dest[len(self.destdir)+1:] 114 updated = time.strftime("%b %d, %Y", time.localtime(os.path.getmtime(src))) 115 output = template.serialize(encoding=self.encoding, root=toroot, updated=updated, 116 destfile=destfile, eggs=self.eggs) 117 output = output.replace("$$", "$") 118 destfile = open(dest, "w") 119 destfile.write(output) 120 destfile.close()
121
122 - def update_site_files(self, srcdir, processTemplates = True, destroot=None):
123 if not destroot: 124 destroot = self.destdir 125 for root, dirs, files in os.walk(srcdir): 126 if root != srcdir: 127 fromroot = root[len(srcdir)+1:] 128 segments = fromroot.split(os.sep) 129 if set(segments).intersection(self.ignoredirs): 130 continue 131 depth = len(segments) 132 else: 133 fromroot = "" 134 depth = 0 135 destdir = os.path.join(destroot, fromroot) 136 if not os.path.exists(destdir): 137 if not self.dry_run: 138 log.info("creating directory %s" % (destdir)) 139 os.makedirs(destdir) 140 else: 141 log.info("skipping creating directory %s" % (destdir)) 142 143 for file in files: 144 ignore = False 145 abs = os.path.abspath(file) 146 for pat in self.ignorepatterns: 147 if pat.match(file): 148 ignore = True 149 break 150 if ignore: 151 continue 152 153 for tempfile in self.templates.values(): 154 if tempfile == abs: 155 ignore = True 156 break 157 if ignore: 158 continue 159 160 ext = os.path.splitext(file)[1] 161 dest = os.path.join(destdir, file) 162 self.currentfiles.add(dest) 163 if not processTemplates or ext != ".html": 164 self.copy_if_newer(os.path.join(root, file), 165 dest) 166 else: 167 self.render_template(os.path.join(root, file), 168 dest, depth)
169
170 - def delete_excess_files(self):
171 for root, dirs, files in os.walk(self.destdir): 172 leavealone = False 173 for dirname in self.nodelete: 174 if root.startswith(dirname): 175 leavealone = True 176 break 177 if leavealone: 178 continue 179 for file in files: 180 dest = os.path.join(root, file) 181 if dest not in self.currentfiles: 182 if not self.dry_run: 183 log.info("deleting %s" % dest) 184 os.unlink(dest) 185 else: 186 log.info("skipping deleting %s" % dest)
187
188 - def run(self):
189 destdir = self.destdir 190 log.info("generating website to %s" % destdir) 191 192 if not os.path.exists(destdir): 193 log.info("creating %s" % destdir) 194 os.makedirs(destdir) 195 196 for name in self.templates_order: 197 filename = self.templates[name] 198 log.info("template %s loaded as %s" % (filename, name)) 199 kid.load_template(filename, name=name) 200 201 if self.eggdir: 202 if not self.eggdir.endswith("/"): 203 self.eggdir += "/" 204 choplen = len(self.eggdir) 205 self.eggs = [fn[choplen:] for fn in glob(self.eggdir + "*")] 206 self.eggs.