eric7/eric7_api.py

branch
eric7
changeset 8312
800c432b34c8
parent 8258
82b608e352ec
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 API Generator.
9
10 This is the main Python script of the API generator. It is
11 this script that gets called via the API generation interface.
12 This script can be used via the commandline as well.
13 """
14
15 import os
16 import sys
17 import glob
18 import fnmatch
19
20 sys.path.insert(1, os.path.dirname(__file__))
21
22 import Utilities.ModuleParser
23 from DocumentationTools.APIGenerator import APIGenerator
24 from UI.Info import Version
25 import Utilities
26 import DocumentationTools
27
28
29 def usage():
30 """
31 Function to print some usage information.
32
33 It prints a reference of all commandline parameters that may
34 be used and ends the application.
35 """
36 print("eric6_api")
37 print()
38 print("Copyright (c) 2004 - 2021 Detlev Offenbach"
39 " <detlev@die-offenbachs.de>.")
40 print()
41 print("Usage:")
42 print()
43 print(" eric6_api [options] files...")
44 print()
45 print("where files can be either python modules, package")
46 print("directories or ordinary directories.")
47 print()
48 print("Options:")
49 print()
50 print(" -b name or --base=name")
51 print(" Use the given name as the name of the base package.")
52 print(" -e eol-type or --eol=eol-type")
53 print(" Use the given eol type to terminate lines.")
54 print(" Valid values are 'cr', 'lf' and 'crlf'.")
55 print(" --exclude-file=pattern")
56 print(" Specify a filename pattern of files to be excluded.")
57 print(" This option may be repeated multiple times.")
58 print(" -h or --help")
59 print(" Show this help and exit.")
60 print(" -i or --ignore")
61 print(" Ignore the set of builtin modules")
62 print(" -l language or --language=language")
63 print(" Generate an API file for the given programming language.")
64 print(" Supported programming languages are:")
65 for lang in sorted(
66 DocumentationTools.supportedExtensionsDictForApis.keys()):
67 print(" * {0}".format(lang))
68 print(" The default is 'Python3'.")
69 print(" This option may be repeated multiple times.")
70 print(" -o filename or --output=filename")
71 print(" Write the API information to the named file."
72 " A '%L' placeholder") # __IGNORE_WARNING_M601__
73 print(" is replaced by the language of the API file"
74 " (see --language).")
75 print(" -p or --private")
76 print(" Include private methods and functions.")
77 print(" -R, -r or --recursive")
78 print(" Perform a recursive search for source files.")
79 print(" -t ext or --extension=ext")
80 print(" Add the given extension to the list of file extensions.")
81 print(" This option may be given multiple times.")
82 print(" -V or --version")
83 print(" Show version information and exit.")
84 print(" -x directory or --exclude=directory")
85 print(" Specify a directory basename to be excluded.")
86 print(" This option may be repeated multiple times.")
87 sys.exit(1)
88
89
90 def version():
91 """
92 Function to show the version information.
93 """
94 print(
95 """eric6_api {0}\n"""
96 """\n"""
97 """eric API generator.\n"""
98 """\n"""
99 """Copyright (c) 2004 - 2021 Detlev Offenbach"""
100 """ <detlev@die-offenbachs.de>\n"""
101 """This is free software; see the LICENSE.GPL3 for copying"""
102 """ conditions.\n"""
103 """There is NO warranty; not even for MERCHANTABILITY or FITNESS"""
104 """ FOR A\n"""
105 """PARTICULAR PURPOSE.""".format(Version))
106 sys.exit(1)
107
108
109 def main():
110 """
111 Main entry point into the application.
112 """
113 global supportedExtensions
114
115 import getopt
116
117 try:
118 opts, args = getopt.getopt(
119 sys.argv[1:], "b:e:hil:o:pRrt:Vx:",
120 ["base=", "eol=", "exclude=", "exclude-file=", "extension=",
121 "help", "ignore", "language=", "output=", "private", "recursive",
122 "version", ])
123 except getopt.error:
124 usage()
125
126 excludeDirs = [".svn", ".hg", ".git", ".ropeproject", ".eric6project",
127 "dist", "build", "doc", "docs"]
128 excludePatterns = []
129 outputFileName = ""
130 recursive = False
131 basePackage = ""
132 includePrivate = False
133 progLanguages = []
134 extensions = []
135 newline = None
136 ignoreBuiltinModules = False
137
138 for k, v in opts:
139 if k in ["-o", "--output"]:
140 outputFileName = v
141 elif k in ["-R", "-r", "--recursive"]:
142 recursive = True
143 elif k in ["-x", "--exclude"]:
144 excludeDirs.append(v)
145 elif k == "--exclude-file":
146 excludePatterns.append(v)
147 elif k in ["-h", "--help"]:
148 usage()
149 elif k in ["-i", "--ignore"]:
150 ignoreBuiltinModules = True
151 elif k in ["-V", "--version"]:
152 version()
153 elif k in ["-t", "--extension"]:
154 if not v.startswith("."):
155 v = ".{0}".format(v)
156 extensions.append(v)
157 elif k in ["-b", "--base"]:
158 basePackage = v
159 elif k in ["-p", "--private"]:
160 includePrivate = True
161 elif k in ["-l", "--language"]:
162 if v not in progLanguages:
163 if v not in DocumentationTools.supportedExtensionsDictForApis:
164 sys.stderr.write(
165 "Wrong language given: {0}. Aborting\n".format(v))
166 sys.exit(1)
167 else:
168 progLanguages.append(v)
169 elif k in ["-e", "--eol"]:
170 if v.lower() == "cr":
171 newline = '\r'
172 elif v.lower() == "lf":
173 newline = '\n'
174 elif v.lower() == "crlf":
175 newline = '\r\n'
176
177 if not args:
178 usage()
179
180 if outputFileName == "":
181 sys.stderr.write("No output file given. Aborting\n")
182 sys.exit(1)
183
184 if len(progLanguages) == 0:
185 progLanguages = ["Python3"]
186
187 for progLanguage in sorted(progLanguages):
188 basename = ""
189 apis = []
190 basesDict = {}
191
192 supportedExtensions = (
193 DocumentationTools.supportedExtensionsDictForApis[progLanguage]
194 )
195 supportedExtensions.extend(extensions)
196 if "%L" in outputFileName:
197 outputFile = outputFileName.replace("%L", progLanguage)
198 else:
199 if len(progLanguages) == 1:
200 outputFile = outputFileName
201 else:
202 root, ext = os.path.splitext(outputFileName)
203 outputFile = "{0}-{1}{2}".format(root, progLanguage.lower(),
204 ext)
205 basesFile = os.path.splitext(outputFile)[0] + '.bas'
206
207 for arg in args:
208 if os.path.isdir(arg):
209 if os.path.exists(os.path.join(
210 arg, Utilities.joinext("__init__", ".py"))):
211 basename = os.path.dirname(arg)
212 if arg == '.':
213 sys.stderr.write("The directory '.' is a package.\n")
214 sys.stderr.write(
215 "Please repeat the call giving its real name.\n")
216 sys.stderr.write("Ignoring the directory.\n")
217 continue
218 else:
219 basename = arg
220 if basename:
221 basename = "{0}{1}".format(basename, os.sep)
222
223 if recursive and not os.path.islink(arg):
224 names = [arg] + Utilities.getDirs(arg, excludeDirs)
225 else:
226 names = [arg]
227 else:
228 basename = ""
229 names = [arg]
230
231 for filename in sorted(names):
232 inpackage = False
233 if os.path.isdir(filename):
234 files = []
235 for ext in supportedExtensions:
236 files.extend(glob.glob(os.path.join(
237 filename, Utilities.joinext("*", ext))))
238 initFile = os.path.join(
239 filename, Utilities.joinext("__init__", ext))
240 if initFile in files:
241 inpackage = True
242 files.remove(initFile)
243 files.insert(0, initFile)
244 elif progLanguage != "Python3":
245 # assume package
246 inpackage = True
247 else:
248 if (
249 Utilities.isWindowsPlatform() and
250 glob.has_magic(filename)
251 ):
252 files = glob.glob(filename)
253 else:
254 files = [filename]
255
256 for file in files:
257 skipIt = False
258 for pattern in excludePatterns:
259 if fnmatch.fnmatch(os.path.basename(file), pattern):
260 skipIt = True
261 break
262 if skipIt:
263 continue
264
265 try:
266 module = Utilities.ModuleParser.readModule(
267 file,
268 basename=basename, inpackage=inpackage,
269 ignoreBuiltinModules=ignoreBuiltinModules)
270 apiGenerator = APIGenerator(module)
271 api = apiGenerator.genAPI(True, basePackage,
272 includePrivate)
273 bases = apiGenerator.genBases(includePrivate)
274 except OSError as v:
275 sys.stderr.write("{0} error: {1}\n".format(file, v[1]))
276 continue
277 except ImportError as v:
278 sys.stderr.write("{0} error: {1}\n".format(file, v))
279 continue
280
281 for apiEntry in api:
282 if apiEntry not in apis:
283 apis.append(apiEntry)
284 for basesEntry in bases:
285 if bases[basesEntry]:
286 basesDict[basesEntry] = bases[basesEntry][:]
287 sys.stdout.write("-- {0} -- {1} ok\n".format(
288 progLanguage, file))
289
290 outdir = os.path.dirname(outputFile)
291 if outdir and not os.path.exists(outdir):
292 os.makedirs(outdir)
293 try:
294 with open(outputFile, "w", encoding="utf-8",
295 newline=newline) as out:
296 out.write("\n".join(sorted(apis)) + "\n")
297 except OSError as v:
298 sys.stderr.write("{0} error: {1}\n".format(outputFile, v[1]))
299 sys.exit(3)
300 try:
301 with open(basesFile, "w", encoding="utf-8",
302 newline=newline) as out:
303 for baseEntry in sorted(basesDict.keys()):
304 out.write("{0} {1}\n".format(
305 baseEntry, " ".join(sorted(basesDict[baseEntry]))))
306 except OSError as v:
307 sys.stderr.write("{0} error: {1}\n".format(basesFile, v[1]))
308 sys.exit(3)
309
310 sys.stdout.write('\nDone.\n')
311 sys.exit(0)
312
313 if __name__ == '__main__':
314 main()
315
316 #
317 # eflag: noqa = M801

eric ide

mercurial