root / pycommunity / pycommunity / package.py

Revision 78:b5dabe9762d1, 9.0 kB (checked in by Tarek Ziad?? <tarek@…>, 13 months ago)

rupy slides, starting up

Line 
1#!/usr/bin/python
2# -*- coding: UTF-8 -*-
3#
4# Copyright (c) 2006 Tarek Ziadé <tarek@ziade.org>
5#
6# This program is free software; you can redistribute it and/or
7# modify it under the terms of the GNU General Public License
8# as published by the Free Software Foundation; either version 2
9# of the License, or (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19# $Id: $
20""" package doc builder
21"""
22import os
23import logging
24
25from Cheetah.Template import Template
26try:
27    from epydoc.cli import write_html
28    from epydoc.docbuilder import build_doc_index
29    epydoc = True
30except ImportError:
31    epydoc = False
32
33try:
34    from cheesecake.cheesecake_index import Cheesecake
35    cheese = True
36except ImportError:
37    cheese = False
38
39from generator import registerTask
40from resttask import TaskView
41from utils import extractHtmlContent
42from utils import rest2Web
43
44class PackageIndexView(object):
45    """renders the package index"""
46    def __init__(self, templatefile, folder, options):
47        indexdoc, otherdocs = self._computeDocList(folder)
48
49        self._template = Template(open(templatefile).read(),
50                                  searchList=[{'docs': otherdocs,
51                                               'main': indexdoc[1],
52                                               'title': indexdoc[0],
53                                               'options': options}])
54
55    def _computeDocList(self, folder):
56        """gathers a list of all docs
57
58        and a reST render of README.txt if founded
59        """
60        docs = []
61        indexdoc = None, None
62        for element in os.listdir(folder):
63            fullpath = os.path.join(folder, element)
64            fullpath = os.path.realpath(fullpath)
65            if os.path.isfile(fullpath):
66                if element.lower() == 'index.html':
67                    # we don't want it listed
68                    pass
69                elif element.lower() == 'readme.html':
70                    # let's grab its content, to inject it in
71                    # the index
72                    indexdoc = extractHtmlContent(fullpath)
73                else:
74                    title, body = extractHtmlContent(fullpath)
75                    webpath = './%s' % element
76                    docs.append((title, webpath))
77        return indexdoc, docs
78
79    def render(self):
80        """renders the html"""
81        return str(self._template)
82    __call__ = render
83
84class PackagesIndexView(object):
85    """renders the global index"""
86    def __init__(self, templatefile, folder, options):
87        packages = self._computePackageList(folder)
88        title, content = rest2Web(options['packages'])
89        self._template = Template(open(templatefile).read(),
90                                  searchList=[{'packages': packages,
91                                               'options': options,
92                                               'title': title,
93                                               'content': content}])
94
95    def _computePackageList(self, folder):
96        """gathers a list of all subfolders"""
97        dirs = []
98        for element in os.listdir(folder):
99            fullpath = os.path.join(folder, element)
100            if os.path.isdir(fullpath):
101                webpath = './%s' % element
102                dirs.append((element, webpath))
103        return dirs
104
105    def render(self):
106        """renders the html"""
107        return str(self._template)
108    __call__ = render
109
110class PackageTask(object):
111    """creates the documentation for packages"""
112
113    def _writeFile(self, name, content):
114        """write a file"""
115        f = open(name, 'w')
116        logging.info('writing %s' % name)
117        try:
118            f.write(content)
119        finally:
120            f.close()
121
122    def _getName(self):
123        return 'package'
124   
125    def _makeDirectory(self, path):
126        """check that the given directory exists"""
127        if os.path.exists(path):
128            return
129        os.makedirs(path)
130
131    def _getFiles(self, folder, extension):
132        """lists all files, given an extension"""
133        ffiles = []
134        for root, dirs, files in os.walk(folder):
135            for file_ in files:
136                if not file_.endswith('.%s' % extension):
137                    continue
138                file_ = os.path.join(root, file_)
139                ffiles.append(os.path.realpath(file_))
140        return ffiles
141
142    def _listSources(self, folder):
143        """lists all python files, given a folder, recursive"""
144        return self._getFiles(folder, 'py')
145
146    def _getRestFiles(self, folder):
147        """lists all rest file, given a folder recursive"""
148        return self._getFiles(folder, 'txt')
149
150    def _run(self, configuration):
151        """generates packages"""
152        targets = configuration.targets.values()
153        packages = configuration.packages.values()
154        self._rest_template = configuration.templates['packagedoc']
155        self._stats_template = configuration.templates['packagestats']
156        self._index_template = configuration.templates['packageindex']
157        self._global_index_template = configuration.templates['packagesindex']
158        self._glossary_file = configuration.glossary
159        self._options = configuration.options
160        self._tutorials = configuration.tutorials
161        self._recipes = configuration.recipes
162
163        for target in targets:
164            root = os.path.join(target, 'packages')
165            root = os.path.realpath(root)
166
167            # making the top directory if needed
168            self._makeDirectory(root)
169
170            for package in packages:
171
172                basename = os.path.split(package)[-1]
173                package_root = os.path.join(root, basename)
174
175                # making the directory if needed
176                self._makeDirectory(package_root)
177
178                # collecting the reST files and generating them
179                restfiles = self._getRestFiles(package)
180                self._makeRestFiles(restfiles, package_root)
181 
182                # generating APIs with epydoc
183                self._makeAPIs(package, package_root)
184
185                # generating stats page
186                self._makeStats(package, package_root)
187               
188                # making the package index
189                self._makeIndex(package_root)
190
191            # making the packages index
192            self._makeGlobalIndex(root)
193
194    def _getHTMLName(self, filename):
195        """compute html file"""
196        base = os.path.split(filename)[-1].split('.')[0]
197        return '%s.html' % base
198
199    def _makeRestFiles(self, files, folder):
200        """generates rest files into the given folder"""
201        template = self._rest_template
202        glossary = self._glossary_file
203        tutorials = self._tutorials
204        recipes = self._recipes
205
206        for file_ in files:
207            view = TaskView(template, file_, glossary, tutorials, recipes)
208            filename = os.path.join(folder, self._getHTMLName(file_))
209            self._writeFile(filename, view()[1])
210
211    def _makeAPIs(self, package, folder):
212        """generates epydoc docs"""
213        if not epydoc:
214            return
215        class EpyDocOptions(object):
216            def __init__(self, target):
217                self.target = target
218                self.verbose = False
219
220        target = os.path.join(folder, 'epydoc')
221        options = EpyDocOptions(target)
222        names = self._listSources(package)
223        try:
224            docindex = build_doc_index(names, True, True,
225                                       add_submodules=True)
226        except (AttributeError, ValueError):
227            # a zope package ?
228            return 
229        if docindex is None:
230            # nothing to build
231            return
232        write_html(docindex, options)
233
234    def _makeStats(self, package, folder):
235        """generates stat page
236
237        Using:
238            - cheesecake
239            - trace2html
240        """
241        return
242        if cheese:
243            # cheesecacke wants an egg or a tarball..
244            indexer = Cheesecake(path=path)
245            indexer.compute_cheesecake_index()
246            indexer.cleanup()
247
248    def _makeIndex(self, folder):
249        """generates package index page
250
251        wich contains a list of documents and
252        display README.txt's content in the main view
253        """
254        template = self._index_template
255        view = PackageIndexView(template, folder, self._options)
256        filename = os.path.join(folder, 'index.html')
257        self._writeFile(filename, view())
258
259    def _makeGlobalIndex(self, folder):
260        """generates global package index page"""
261        template = self._global_index_template
262        view = PackagesIndexView(template, folder, self._options)
263        filename = os.path.join(folder, 'index.html')
264        self._writeFile(filename, view())
265
266registerTask(PackageTask)
Note: See TracBrowser for help on using the browser.