eric6/eric6_doc.py

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

eric ide

mercurial