eric6_doc.py

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

eric ide

mercurial