3 from optparse import OptionParser
5 from urllib import urlencode
8 from jinja2 import Environment, FileSystemLoader
10 from dirtag import Dirtag, Tree, dir_tree
14 """The web interface to Dirtag.
16 def __init__(self, dirtag, template_dir, repository_name='Dirtag'):
17 """Initialize the bug repository for this web interface."""
19 self.env = Environment(loader=FileSystemLoader(template_dir))
20 self.repository_name = repository_name
21 self.rdf_root = 'http://dirtag.com/'
25 template = self.env.get_template('dirtag.xul')
26 cherrypy.response.headers['Content-Type'] = \
27 'application/vnd.mozilla.xul+xml'
28 return template.render(repository_name=self.repository_name)
32 return self.tree_rdf(self.dirtag.raw_dir, 'raw')
36 return self.tree_rdf(self.dirtag.tag_dir, 'tag', with_files=False)
38 def tree_rdf(self, root_dir, name, with_files=True):
39 cherrypy.response.headers['Content-Type'] = \
41 tree = dir_tree(root_dir)
43 '<?xml version="1.0"?>',
45 '<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"',
46 ' xmlns:FILES="%srdf#">' % self.rdf_root,
48 if with_files == True:
49 nodes = tree.traverse(depth=1, dirtag=self.dirtag)
51 nodes = tree.traverse(depth=1, type='dirs', dirtag=self.dirtag)
54 ' <RDF:Description RDF:about="%s%s">'
55 % (self.rdf_root, '/'.join([name]+node)),
56 ' <FILES:name>%s</FILES:name>' % node[-1],
58 if node.type == 'file':
59 lines.append(' <FILES:tags>%s</FILES:tags>'
60 % ','.join(['/'.join(t) for t in node.tags]))
61 lines.append(' </RDF:Description>')
63 lines.append(' <RDF:Seq RDF:about="%s%s/files">'
64 % (self.rdf_root, name))
66 for node in tree.traverse(depth=1,):
67 while (len(stack) > 0 and
68 not self.list_startswith(stack[-1], node[:-1])):
70 ' '*(4*len(stack)+2) + '</RDF:Seq>',
71 ' '*(4*len(stack)) + '</RDF:li>',
74 assert len(node) == len(stack)+1, (
75 'Floating %s -> %s (%d -> %d)'
76 % (stack[-1], node, len(stack), len(node)))
78 if node.type == 'file':
79 raw_node = self.dirtag.raw_node(node)
80 lines.append(' '*(4*len(stack))
81 + '<RDF:li RDF:resource="%s%s"/>'
82 % (self.rdf_root, '/'.join(['raw']+raw_node)))
86 ' '*(4*len(stack)) + '<RDF:li>',
87 ' '*(4*len(stack)+2) + '<RDF:Seq RDF:about="%s%s">'
88 % (self.rdf_root, '/'.join([name]+node)),
92 ' '*(4*len(stack)+2) + '</RDF:Seq>',
93 ' '*(4*len(stack)) + '</RDF:li>',
102 return '\n'.join(lines)
104 def list_startswith(self, a, b):
106 >>> x = WebInterface(None, 'template')
107 >>> x.list_startswith([1, 2, 3], [1, 2, 3, 4])
109 >>> x.list_startswith([1, 2, 3], [1, 2, 3])
111 >>> x.list_startswith([1, 2, 3], [1, 2])
113 >>> x.list_startswith([1, 2, 3], [2, 2, 3])
116 return len([x for x,y in zip(a,b) if x==y]) == len(a)
119 def new_tag(self, tag):
120 self.dirtag.new_tag(tag.split('/'))
121 return '<p>New tag %s added</p>' % tag
124 def add_tag(self, path, tag):
125 self.dirtag.add_tag(path.split('/'), tag.split('/'))
126 return '<p>Added tag %s to %s</p>' % (tag, path)
129 def remove_tag(self, path, tag):
130 self.dirtag.remove_tag(path.split('/'), tag.split('/'))
131 return '<p>Removed tag %s from %s</p>' % (tag, path)
134 if __name__ == '__main__':
135 parser = OptionParser('%prog [options]', epilog=WebInterface.__doc__)
136 parser.add_option('-r', '--raw-dir', dest='raw_dir', metavar='DIR',
138 help='Location of raw files (%default)')
139 parser.add_option('-t', '--tag-dir', dest='tag_dir', metavar='DIR',
141 help='Location of tag links (%default)')
142 parser.add_option('-T', '--template-dir', dest='template_dir',
143 metavar='DIR', default='template',
144 help='Location of template files (%default)')
145 parser.add_option('-s', '--static-dir', dest='static_dir', metavar='DIR',
147 help='Location of static files (%default)')
148 parser.add_option('-n', '--name', dest='name', metavar='STRING',
150 help='Name of the dirtag repository')
151 parser.add_option('--test', dest='test', default=False,
153 help='Run unittests and exit')
154 options,args = parser.parse_args()
161 d = Dirtag(raw_dir=options.raw_dir, tag_dir=options.tag_dir)
163 d, template_dir=options.template_dir, repository_name=options.name)
164 cherrypy.config.update({
165 'tools.encode.on': True,
166 'tools.encode.encoding': 'utf8',
170 'tools.staticdir.on': True,
171 'tools.staticdir.dir': path.abspath(options.static_dir),
174 cherrypy.quickstart(w, '/', app_config)