|
1 #!/usr/bin/env python |
|
2 # -*- coding: utf-8 -*- |
|
3 |
|
4 # Copyright (c) 2003 - 2009 Detlev Offenbach <detlev@die-offenbachs.de> |
|
5 # |
|
6 |
|
7 """ |
|
8 Eric4 Documentation Generator |
|
9 |
|
10 This is the main Python script of the documentation generator. It is |
|
11 this script that gets called via the source documentation interface. |
|
12 This script can be used via the commandline as well. |
|
13 """ |
|
14 |
|
15 import glob |
|
16 import os |
|
17 import sys |
|
18 import shutil |
|
19 import fnmatch |
|
20 |
|
21 import Utilities.ModuleParser |
|
22 from DocumentationTools.ModuleDocumentor import ModuleDocument |
|
23 from DocumentationTools.IndexGenerator import IndexGenerator |
|
24 from DocumentationTools.QtHelpGenerator import QtHelpGenerator |
|
25 from DocumentationTools.Config import eric4docDefaultColors |
|
26 from UI.Info import Version |
|
27 import Utilities |
|
28 import Preferences |
|
29 |
|
30 # list of supported filename extensions |
|
31 supportedExtensions = [".py", ".pyw", ".ptl", ".rb"] |
|
32 |
|
33 def usage(): |
|
34 """ |
|
35 Function to print some usage information. |
|
36 |
|
37 It prints a reference of all commandline parameters that may |
|
38 be used and ends the application. |
|
39 """ |
|
40 print "eric4-doc" |
|
41 print |
|
42 print "Copyright (c) 2003 - 2009 Detlev Offenbach <detlev@die-offenbachs.de>." |
|
43 print |
|
44 print "Usage:" |
|
45 print |
|
46 print " eric4-doc [options] files..." |
|
47 print |
|
48 print "where files can be either python modules, package" |
|
49 print "directories or ordinary directories." |
|
50 print |
|
51 print "Options:" |
|
52 print |
|
53 print " -c filename or --style-sheet=filename" |
|
54 print " Specify a CSS style sheet file to be used." |
|
55 print " -e or --noempty" |
|
56 print " Don't include empty modules." |
|
57 print " -h or --help" |
|
58 print " Show this help and exit." |
|
59 print " -i or --noindex" |
|
60 print " Don't generate index files." |
|
61 print " -o directory or --outdir=directory" |
|
62 print " Generate files in the named directory." |
|
63 print " -R, -r or --recursive" |
|
64 print " Perform a recursive search for Python files." |
|
65 print " -t ext or --extension=ext" |
|
66 print " Add the given extension to the list of file extensions." |
|
67 print " This option may be given multiple times." |
|
68 print " -V or --version" |
|
69 print " Show version information and exit." |
|
70 print " -x directory or --exclude=directory" |
|
71 print " Specify a directory basename to be excluded." |
|
72 print " This option may be repeated multiple times." |
|
73 print " --exclude-file=pattern" |
|
74 print " Specify a filename pattern of files to be excluded." |
|
75 print " This option may be repeated multiple times." |
|
76 print |
|
77 print " --body-color=color" |
|
78 print " Specify the text color." |
|
79 print " --body-background-color=color" |
|
80 print " Specify the text background color." |
|
81 print " --l1header-color=color" |
|
82 print " Specify the text color of level 1 headers." |
|
83 print " --l1header-background-color=color" |
|
84 print " Specify the text background color of level 1 headers." |
|
85 print " --l2header-color=color" |
|
86 print " Specify the text color of level 2 headers." |
|
87 print " --l2header-background-color=color" |
|
88 print " Specify the text background color of level 2 headers." |
|
89 print " --cfheader-color=color" |
|
90 print " Specify the text color of class and function headers." |
|
91 print " --cfheader-background-color=color" |
|
92 print " Specify the text background color of class and function headers." |
|
93 print " --link-color=color" |
|
94 print " Specify the text color of hyperlinks." |
|
95 print |
|
96 print " --create-qhp" |
|
97 print " Enable generation of QtHelp files." |
|
98 print " --qhp-outdir=directory" |
|
99 print " Generate QtHelp files in the named directory." |
|
100 print " --qhp-namespace=namespace" |
|
101 print " Use the given namespace (mandatory)." |
|
102 print " --qhp-virtualfolder=folder" |
|
103 print " Use the given virtual folder (mandatory)." |
|
104 print " The virtual folder must not contain '/'." |
|
105 print " --qhp-filtername=name" |
|
106 print " Use the given name for the custom filter." |
|
107 print " --qhp-filterattribs=attributes" |
|
108 print " Add the given attributes to the filter list." |
|
109 print " Attributes must be separated by ':'." |
|
110 print " --qhp-title=title" |
|
111 print " Use this as the title for the generated help (mandatory)." |
|
112 print " --create-qhc" |
|
113 print " Enable generation of QtHelp Collection files." |
|
114 sys.exit(1) |
|
115 |
|
116 def version(): |
|
117 """ |
|
118 Function to show the version information. |
|
119 """ |
|
120 print \ |
|
121 """eric4-doc %s |
|
122 |
|
123 Eric4 API documentation generator. |
|
124 |
|
125 Copyright (c) 2003-2009 Detlev Offenbach <detlev@die-offenbachs.de> |
|
126 This is free software; see the LICENSE.GPL3 for copying conditions. |
|
127 There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A |
|
128 PARTICULAR PURPOSE.""" % Version |
|
129 sys.exit(1) |
|
130 |
|
131 def main(): |
|
132 """ |
|
133 Main entry point into the application. |
|
134 """ |
|
135 |
|
136 import getopt |
|
137 |
|
138 try: |
|
139 opts, args = getopt.getopt(sys.argv[1:], "c:ehio:Rrt:Vx:", |
|
140 ["exclude=", "extension=", "help", "noindex", "noempty", "outdir=", |
|
141 "recursive", "style-sheet=", "version", |
|
142 "exclude-file=", |
|
143 "body-color=", "body-background-color=", |
|
144 "l1header-color=", "l1header-background-color=", |
|
145 "l2header-color=", "l2header-background-color=", |
|
146 "cfheader-color=", "cfheader-background-color=", |
|
147 "link-color=", |
|
148 "create-qhp", "qhp-outdir=", "qhp-namespace=", |
|
149 "qhp-virtualfolder=", "qhp-filtername=", "qhp-filterattribs=", |
|
150 "qhp-title=", "create-qhc", |
|
151 ]) |
|
152 except getopt.error, e: |
|
153 usage() |
|
154 |
|
155 excludeDirs = ["CVS", ".svn", "_svn", ".ropeproject", "_ropeproject", |
|
156 ".eric4project", "_eric4project", "dist", "build", "doc", "docs"] |
|
157 excludePatterns = [] |
|
158 outputDir = "doc" |
|
159 recursive = False |
|
160 doIndex = True |
|
161 noempty = False |
|
162 stylesheetFile = "" |
|
163 colors = eric4docDefaultColors.copy() |
|
164 |
|
165 qtHelpCreation = False |
|
166 qtHelpOutputDir = "help" |
|
167 qtHelpNamespace = "" |
|
168 qtHelpFolder = "source" |
|
169 qtHelpFilterName = "unknown" |
|
170 qtHelpFilterAttribs = "" |
|
171 qtHelpTitle = "" |
|
172 qtHelpCreateCollection = False |
|
173 |
|
174 # Set the applications string encoding |
|
175 try: |
|
176 sys.setappdefaultencoding(str(Preferences.getSystem("StringEncoding"))) |
|
177 except AttributeError: |
|
178 pass |
|
179 |
|
180 for k, v in opts: |
|
181 if k in ["-o", "--outdir"]: |
|
182 outputDir = v |
|
183 elif k in ["-R", "-r", "--recursive"]: |
|
184 recursive = True |
|
185 elif k in ["-x", "--exclude"]: |
|
186 excludeDirs.append(v) |
|
187 elif k == "--exclude-file": |
|
188 excludePatterns.append(v) |
|
189 elif k in ["-i", "--noindex"]: |
|
190 doIndex = False |
|
191 elif k in ["-e", "--noempty"]: |
|
192 noempty = True |
|
193 elif k in ["-h", "--help"]: |
|
194 usage() |
|
195 elif k in ["-V", "--version"]: |
|
196 version() |
|
197 elif k in ["-c", "--style-sheet"]: |
|
198 stylesheetFile = v |
|
199 elif k in ["-t", "--extension"]: |
|
200 if not v.startswith("."): |
|
201 v = ".%s" % v |
|
202 supportedExtensions.append(v) |
|
203 |
|
204 elif k == "--body-color": |
|
205 colors['BodyColor'] = v |
|
206 elif k == "--body-background-color": |
|
207 colors['BodyBgColor'] = v |
|
208 elif k == "--l1header-color": |
|
209 colors['Level1HeaderColor'] = v |
|
210 elif k == "--l1header-background-color": |
|
211 colors['Level1HeaderBgColor'] = v |
|
212 elif k == "--l2header-color": |
|
213 colors['Level2HeaderColor'] = v |
|
214 elif k == "--l2header-background-color": |
|
215 colors['Level2HeaderBgColor'] = v |
|
216 elif k == "--cfheader-color": |
|
217 colors['CFColor'] = v |
|
218 elif k == "--cfheader-background-color": |
|
219 colors['CFBgColor'] = v |
|
220 elif k == "--link-color": |
|
221 colors['LinkColor'] = v |
|
222 |
|
223 elif k == "--create-qhp": |
|
224 qtHelpCreation = True |
|
225 elif k == "--qhp-outdir": |
|
226 qtHelpOutputDir = v |
|
227 elif k == "--qhp-namespace": |
|
228 qtHelpNamespace = v |
|
229 elif k == "--qhp-virtualfolder": |
|
230 qtHelpFolder = v |
|
231 elif k == "--qhp-filtername": |
|
232 qtHelpFilterName = v |
|
233 elif k == "--qhp-filterattribs": |
|
234 qtHelpFilterAttribs = v |
|
235 elif k == "--qhp-title": |
|
236 qtHelpTitle = v |
|
237 elif k == "--create-qhc": |
|
238 qtHelpCreateCollection = True |
|
239 |
|
240 if not args: |
|
241 usage() |
|
242 |
|
243 if qtHelpCreation and \ |
|
244 (qtHelpNamespace == "" or \ |
|
245 qtHelpFolder == "" or '/' in qtHelpFolder or \ |
|
246 qtHelpTitle == ""): |
|
247 usage() |
|
248 |
|
249 input = output = 0 |
|
250 basename = "" |
|
251 |
|
252 if outputDir: |
|
253 if not os.path.isdir(outputDir): |
|
254 try: |
|
255 os.makedirs(outputDir) |
|
256 except EnvironmentError: |
|
257 sys.stderr.write("Could not create output directory %s." % outputDir) |
|
258 sys.exit(2) |
|
259 else: |
|
260 outputDir = os.getcwd() |
|
261 outputDir = os.path.abspath(outputDir) |
|
262 |
|
263 if stylesheetFile: |
|
264 try: |
|
265 sf = open(stylesheetFile, "rb") |
|
266 stylesheet = sf.read() |
|
267 sf.close() |
|
268 except IOError: |
|
269 sys.stderr.write("The CSS stylesheet '%s' does not exist\n" % stylesheetFile) |
|
270 sys.stderr.write("Disabling CSS usage.\n") |
|
271 stylesheet = None |
|
272 else: |
|
273 stylesheet = None |
|
274 |
|
275 indexGenerator = IndexGenerator(outputDir, colors, stylesheet) |
|
276 |
|
277 if qtHelpCreation: |
|
278 if qtHelpOutputDir: |
|
279 if not os.path.isdir(qtHelpOutputDir): |
|
280 try: |
|
281 os.makedirs(qtHelpOutputDir) |
|
282 except EnvironmentError: |
|
283 sys.stderr.write("Could not create QtHelp output directory %s." % \ |
|
284 qtHelpOutputDir) |
|
285 sys.exit(2) |
|
286 else: |
|
287 qtHelpOutputDir = os.getcwd() |
|
288 qtHelpOutputDir = os.path.abspath(qtHelpOutputDir) |
|
289 |
|
290 qtHelpGenerator = QtHelpGenerator(outputDir, |
|
291 qtHelpOutputDir, qtHelpNamespace, qtHelpFolder, |
|
292 qtHelpFilterName, qtHelpFilterAttribs, |
|
293 qtHelpTitle, qtHelpCreateCollection) |
|
294 |
|
295 for arg in args: |
|
296 if os.path.isdir(arg): |
|
297 if os.path.exists(os.path.join(arg, Utilities.joinext("__init__", ".py"))): |
|
298 basename = os.path.dirname(arg) |
|
299 if arg == '.': |
|
300 sys.stderr.write("The directory '.' is a package.\n") |
|
301 sys.stderr.write("Please repeat the call giving its real name.\n") |
|
302 sys.stderr.write("Ignoring the directory.\n") |
|
303 continue |
|
304 else: |
|
305 basename = arg |
|
306 if basename: |
|
307 basename = "%s%s" % (basename, os.sep) |
|
308 |
|
309 if recursive and not os.path.islink(arg): |
|
310 names = [arg] + Utilities.getDirs(arg, excludeDirs) |
|
311 else: |
|
312 names = [arg] |
|
313 else: |
|
314 basename = "" |
|
315 names = [arg] |
|
316 |
|
317 for filename in names: |
|
318 inpackage = False |
|
319 if os.path.isdir(filename): |
|
320 files = [] |
|
321 for ext in supportedExtensions: |
|
322 files.extend(glob.glob(os.path.join(filename, |
|
323 Utilities.joinext("*", ext)))) |
|
324 initFile = os.path.join(filename, Utilities.joinext("__init__", ext)) |
|
325 if initFile in files: |
|
326 inpackage = True |
|
327 files.remove(initFile) |
|
328 files.insert(0, initFile) |
|
329 else: |
|
330 if Utilities.isWindowsPlatform() and glob.has_magic(filename): |
|
331 files = glob.glob(filename) |
|
332 else: |
|
333 files = [filename] |
|
334 |
|
335 for file in files: |
|
336 skipIt = False |
|
337 for pattern in excludePatterns: |
|
338 if fnmatch.fnmatch(os.path.basename(file), pattern): |
|
339 skipIt = True |
|
340 break |
|
341 if skipIt: |
|
342 continue |
|
343 |
|
344 try: |
|
345 module = Utilities.ModuleParser.readModule(file, basename = basename, |
|
346 inpackage = inpackage, extensions = supportedExtensions) |
|
347 moduleDocument = ModuleDocument(module, colors, stylesheet) |
|
348 doc = moduleDocument.genDocument() |
|
349 except IOError, v: |
|
350 sys.stderr.write("%s error: %s\n" % (file, v[1])) |
|
351 continue |
|
352 except ImportError, v: |
|
353 sys.stderr.write("%s error: %s\n" % (file, v)) |
|
354 continue |
|
355 |
|
356 input = input + 1 |
|
357 |
|
358 f = Utilities.joinext(os.path.join(outputDir, moduleDocument.name()), |
|
359 ".html") |
|
360 |
|
361 # remember for index file generation |
|
362 indexGenerator.remember(file, moduleDocument, basename) |
|
363 |
|
364 # remember for QtHelp generation |
|
365 if qtHelpCreation: |
|
366 qtHelpGenerator.remember(file, moduleDocument, basename) |
|
367 |
|
368 if (noempty or file.endswith('__init__.py')) \ |
|
369 and moduleDocument.isEmpty(): |
|
370 continue |
|
371 |
|
372 # generate output |
|
373 try: |
|
374 out = open(f, "wb") |
|
375 out.write(doc) |
|
376 out.close() |
|
377 except IOError, v: |
|
378 sys.stderr.write("%s error: %s\n" % (file, v[1])) |
|
379 else: |
|
380 sys.stdout.write("%s ok\n" % f) |
|
381 |
|
382 output = output + 1 |
|
383 sys.stdout.flush() |
|
384 sys.stderr.flush() |
|
385 |
|
386 # write index files |
|
387 if doIndex: |
|
388 indexGenerator.writeIndices(basename) |
|
389 |
|
390 # generate the QtHelp files |
|
391 if qtHelpCreation: |
|
392 qtHelpGenerator.generateFiles() |
|
393 |
|
394 sys.exit(0) |
|
395 |
|
396 if __name__ == '__main__': |
|
397 main() |