Simple Genshi static site generator

11 August 2008
13:58

By cmlenz as Python

Expects templates in a "pages" subdir, and static files (images etc) in a "resources" subdir

1 #!/usr/bin/env python
2
3 import os
4 import posixpath
5 import shutil
6 import sys
7
8 from genshi.core import Markup, Stream, START
9 from genshi.input import HTMLParser
10 from genshi.output import DocType
11 from genshi.template import TemplateLoader
12
13 basedir = os.path.dirname(os.path.abspath(sys.argv[0]))
14 templates = TemplateLoader([os.path.join(basedir, 'templates')])
15
16 def copyfile(src, dst):
17 print 'Copying %s' % os.path.basename(src)
18 shutil.copy2(src, dst)
19
20 def copytree(src, dst, symlinks=False, skip=()):
21 """Recursively copy a directory tree using copy2() (from shutil.copytree.)
22
23 Added a `skip` parameter consisting of absolute paths
24 which we don't want to copy.
25 """
26 names = os.listdir(src)
27 os.mkdir(dst)
28 errors = []
29 for name in names:
30 if name in skip:
31 continue
32 srcname = os.path.join(src, name)
33 dstname = os.path.join(dst, name)
34 try:
35 if symlinks and os.path.islink(srcname):
36 linkto = os.readlink(srcname)
37 os.symlink(linkto, dstname)
38 elif os.path.isdir(srcname):
39 copytree(srcname, dstname, symlinks, skip)
40 else:
41 copyfile(srcname, dstname)
42 except (IOError, os.error), why:
43 errors.append((srcname, dstname, why))
44 if errors:
45 raise shutil.Error, errors
46
47 def make_relatify(base):
48 def relatify(link):
49 base_parts = filter(None, base.split('/'))[:-1]
50 dest = filter(None, link.split('/'))
51 dest_parts = dest[:-1]
52 dest_file = dest[-1]
53 idx = 0
54 for part in base_parts:
55 if idx < len(dest_parts) and part == dest_parts[idx]:
56 del dest_parts[idx]
57 else:
58 dest_parts[idx:idx] = ['..']
59 idx += 1
60 return '/'.join(dest_parts + [dest_file])
61 return relatify
62
63 def make_document(base, relatify):
64 def document(path):
65 return Stream(HTMLParser(open(os.path.join(base, path))))
66 return document
67
68
69 if __name__ == '__main__':
70 destdir = os.path.join(basedir, 'dist')
71
72 if os.path.exists(destdir):
73 shutil.rmtree(destdir)
74
75 copytree(os.path.join(basedir, 'resources'), destdir,
76 skip=('.DS_Store', '.svn', 'Thumbs.db'))
77
78 pagesdir = os.path.join(basedir, 'pages')
79 for root, dirs, files in os.walk(pagesdir):
80 if '.svn' in dirs:
81 dirs.remove('.svn')
82 if '.DS_Store' in files:
83 files.remove('.DS_Store')
84 if 'Thumbs.db' in files:
85 files.remove('Thumbs.db')
86 basepath = root[len(pagesdir):].lstrip('/')
87 for dirname in dirs:
88 os.mkdir(os.path.join(destdir, basepath, dirname))
89 for filename in files:
90 dirname = root[len(pagesdir):].lstrip('/')
91 filepath = os.path.join(root, filename)
92 outfile = open(os.path.join(destdir, dirname, filename), 'w')
93 try:
94 template = templates.load(filepath)
95 relpath = posixpath.join(dirname, filename)
96 relatify = make_relatify(relpath)
97 document = make_document(os.path.join(basedir, 'fragments'),
98 relatify)
99 print 'Generating %s' % relpath
100 stream = template.generate(path=relpath, dirname=dirname,
101 filename=filename, Markup=Markup,
102 relatify=relatify,
103 document=document)
104 output = stream.render('html', doctype=DocType.HTML_STRICT,
105 strip_whitespace=False)
106 outfile.write(output)
107 finally:
108 outfile.close()
109
110 copyfile(os.path.join(basedir, 'README.txt'), destdir)
111

Download Raw Source

Comments

No comments so far.