src/eric7/eric7_doc.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9211
99eb1cb030a5
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3
4 # Copyright (c) 2003 - 2022 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 fnmatch
16 import glob
17 import os
18 import shutil
19 import sys
20
21 sys.path.insert(1, os.path.dirname(__file__))
22
23 import Utilities.ModuleParser
24
25 from DocumentationTools.ModuleDocumentor import ModuleDocument
26 from DocumentationTools.IndexGenerator import IndexGenerator
27 from DocumentationTools.QtHelpGenerator import QtHelpGenerator
28 from DocumentationTools.Config import eric7docDefaultColors
29 from DocumentationTools import TemplatesListsStyleCSS
30
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("eric7_doc")
46 print()
47 print("Copyright (c) 2003 - 2022 Detlev Offenbach"
48 " <detlev@die-offenbachs.de>.")
49 print()
50 print("Usage:")
51 print()
52 print(" eric7_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 """eric7_doc {0}\n"""
133 """\n"""
134 """eric API documentation generator.\n"""
135 """\n"""
136 """Copyright (c) 2003-2022 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 = [".svn", ".hg", ".git", ".ropeproject", ".eric7project",
171 "dist", "build", "doc", "docs"]
172 excludePatterns = []
173 outputDir = "doc"
174 recursive = False
175 doIndex = True
176 noempty = False
177 newline = None
178
179 stylesheetFile = ""
180 colors = eric7docDefaultColors.copy()
181
182 qtHelpCreation = False
183 qtHelpOutputDir = "help"
184 qtHelpNamespace = ""
185 qtHelpFolder = "source"
186 qtHelpFilterName = "unknown"
187 qtHelpFilterAttribs = ""
188 qtHelpTitle = ""
189 qtHelpCreateCollection = False
190
191 for k, v in opts:
192 if k in ["-o", "--outdir"]:
193 outputDir = v
194 elif k in ["-R", "-r", "--recursive"]:
195 recursive = True
196 elif k in ["-x", "--exclude"]:
197 excludeDirs.append(v)
198 elif k == "--exclude-file":
199 excludePatterns.append(v)
200 elif k in ["-i", "--noindex"]:
201 doIndex = False
202 elif k in ["-e", "--noempty"]:
203 noempty = True
204 elif k in ["-h", "--help"]:
205 usage()
206 elif k in ["-V", "--version"]:
207 version()
208 elif k in ["-c", "--style-sheet"]:
209 stylesheetFile = v
210 elif k in ["-t", "--extension"]:
211 if v.strip() and not v.startswith("."):
212 v = ".{0}".format(v)
213 supportedExtensions.append(v)
214 elif k == "--eol":
215 if v.lower() == "cr":
216 newline = '\r'
217 elif v.lower() == "lf":
218 newline = '\n'
219 elif v.lower() == "crlf":
220 newline = '\r\n'
221
222 elif k == "--body-color":
223 colors['BodyColor'] = v
224 elif k == "--body-background-color":
225 colors['BodyBgColor'] = v
226 elif k == "--l1header-color":
227 colors['Level1HeaderColor'] = v
228 elif k == "--l1header-background-color":
229 colors['Level1HeaderBgColor'] = v
230 elif k == "--l2header-color":
231 colors['Level2HeaderColor'] = v
232 elif k == "--l2header-background-color":
233 colors['Level2HeaderBgColor'] = v
234 elif k == "--cfheader-color":
235 colors['CFColor'] = v
236 elif k == "--cfheader-background-color":
237 colors['CFBgColor'] = v
238 elif k == "--link-color":
239 colors['LinkColor'] = v
240
241 elif k == "--create-qhp":
242 qtHelpCreation = True
243 elif k == "--qhp-outdir":
244 qtHelpOutputDir = v
245 elif k == "--qhp-namespace":
246 qtHelpNamespace = v
247 elif k == "--qhp-virtualfolder":
248 qtHelpFolder = v
249 elif k == "--qhp-filtername":
250 qtHelpFilterName = v
251 elif k == "--qhp-filterattribs":
252 qtHelpFilterAttribs = v
253 elif k == "--qhp-title":
254 qtHelpTitle = v
255 elif k == "--create-qhc":
256 qtHelpCreateCollection = True
257
258 if not args:
259 usage()
260
261 if (
262 qtHelpCreation and
263 (qtHelpNamespace == "" or
264 qtHelpFolder == "" or
265 '/' in qtHelpFolder or
266 qtHelpTitle == "")
267 ):
268 usage()
269
270 basename = ""
271
272 if outputDir:
273 if not os.path.isdir(outputDir):
274 try:
275 os.makedirs(outputDir)
276 except OSError:
277 sys.stderr.write(
278 "Could not create output directory {0}.".format(outputDir))
279 sys.exit(2)
280 else:
281 outputDir = os.getcwd()
282 outputDir = os.path.abspath(outputDir)
283
284 if stylesheetFile:
285 try:
286 shutil.copy(stylesheetFile, os.path.join(outputDir, "styles.css"))
287 except OSError:
288 sys.stderr.write(
289 "The CSS stylesheet '{0}' does not exist\n".format(
290 stylesheetFile))
291 sys.exit(2)
292 else:
293 try:
294 with open(os.path.join(outputDir, "styles.css"), "w") as sf:
295 sf.write(TemplatesListsStyleCSS.cssTemplate.format(**colors))
296 except OSError:
297 sys.stderr.write(
298 "The CSS stylesheet '{0}' could not be created\n".format(
299 stylesheetFile))
300 sys.exit(2)
301
302 indexGenerator = IndexGenerator(outputDir)
303
304 if qtHelpCreation:
305 if qtHelpOutputDir:
306 if not os.path.isdir(qtHelpOutputDir):
307 try:
308 os.makedirs(qtHelpOutputDir)
309 except OSError:
310 sys.stderr.write(
311 "Could not create QtHelp output directory {0}.".format(
312 qtHelpOutputDir))
313 sys.exit(2)
314 else:
315 qtHelpOutputDir = os.getcwd()
316 qtHelpOutputDir = os.path.abspath(qtHelpOutputDir)
317
318 qtHelpGenerator = QtHelpGenerator(outputDir,
319 qtHelpOutputDir, qtHelpNamespace,
320 qtHelpFolder, qtHelpFilterName,
321 qtHelpFilterAttribs, qtHelpTitle,
322 qtHelpCreateCollection)
323
324 for arg in args:
325 if os.path.isdir(arg):
326 if os.path.exists(os.path.join(
327 arg, Utilities.joinext("__init__", ".py"))):
328 basename = os.path.dirname(arg)
329 if arg == '.':
330 sys.stderr.write("The directory '.' is a package.\n")
331 sys.stderr.write(
332 "Please repeat the call giving its real name.\n")
333 sys.stderr.write("Ignoring the directory.\n")
334 continue
335 else:
336 basename = arg
337 if basename:
338 basename = "{0}{1}".format(basename, os.sep)
339
340 if recursive and not os.path.islink(arg):
341 names = [arg] + Utilities.getDirs(arg, excludeDirs)
342 else:
343 names = [arg]
344 else:
345 basename = ""
346 names = [arg]
347
348 for filename in names:
349 inpackage = False
350 if os.path.isdir(filename):
351 files = []
352 for ext in supportedExtensions:
353 files.extend(glob.glob(os.path.join(
354 filename, Utilities.joinext("*", ext))))
355 initFile = os.path.join(
356 filename, Utilities.joinext("__init__", ext))
357 if initFile in files:
358 inpackage = True
359 files.remove(initFile)
360 files.insert(0, initFile)
361 else:
362 if Utilities.isWindowsPlatform() and glob.has_magic(filename):
363 files = glob.glob(filename)
364 else:
365 files = [filename]
366
367 for file in files:
368 skipIt = False
369 for pattern in excludePatterns:
370 if fnmatch.fnmatch(os.path.basename(file), pattern):
371 skipIt = True
372 break
373 if skipIt:
374 continue
375
376 try:
377 module = Utilities.ModuleParser.readModule(
378 file, basename=basename,
379 inpackage=inpackage, extensions=supportedExtensions)
380 moduleDocument = ModuleDocument(module)
381 doc = moduleDocument.genDocument()
382 except OSError as v:
383 sys.stderr.write("{0} error: {1}\n".format(file, v[1]))
384 continue
385 except ImportError as v:
386 sys.stderr.write("{0} error: {1}\n".format(file, v))
387 continue
388
389 f = Utilities.joinext(os.path.join(
390 outputDir, moduleDocument.name()), ".html")
391
392 # remember for index file generation
393 indexGenerator.remember(file, moduleDocument, basename)
394
395 # remember for QtHelp generation
396 if qtHelpCreation:
397 qtHelpGenerator.remember(file, moduleDocument, basename)
398
399 if (
400 (noempty or file.endswith('__init__.py')) and
401 moduleDocument.isEmpty()
402 ):
403 continue
404
405 # generate output
406 try:
407 with open(f, "w", encoding="utf-8",
408 newline=newline) as out:
409 out.write(doc)
410 except OSError as v:
411 sys.stderr.write("{0} error: {1}\n".format(file, v[1]))
412 else:
413 sys.stdout.write("{0} ok\n".format(f))
414
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()
430
431 #
432 # eflag: noqa = M801

eric ide

mercurial