eric7/eric7_doc.py

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

eric ide

mercurial