src/eric7/eric7_api.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
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 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("eric7_api")
37 print()
38 print("Copyright (c) 2004 - 2022 Detlev Offenbach"
39 " <detlev@die-offenbachs.de>.")
40 print()
41 print("Usage:")
42 print()
43 print(" eric7_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 """eric7_api {0}\n"""
96 """\n"""
97 """eric API generator.\n"""
98 """\n"""
99 """Copyright (c) 2004 - 2022 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", ".eric7project",
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
197 if not outputFileName.endswith(".api"):
198 # append the .api extension, if not given by the user
199 outputFileName += ".api"
200 if "%L" in outputFileName:
201 outputFile = outputFileName.replace("%L", progLanguage)
202 else:
203 if len(progLanguages) == 1:
204 outputFile = outputFileName
205 else:
206 root, ext = os.path.splitext(outputFileName)
207 outputFile = "{0}-{1}{2}".format(root, progLanguage.lower(),
208 ext)
209 basesFile = os.path.splitext(outputFile)[0] + '.bas'
210
211 for arg in args:
212 if os.path.isdir(arg):
213 if os.path.exists(os.path.join(
214 arg, Utilities.joinext("__init__", ".py"))):
215 basename = os.path.dirname(arg)
216 if arg == '.':
217 sys.stderr.write("The directory '.' is a package.\n")
218 sys.stderr.write(
219 "Please repeat the call giving its real name.\n")
220 sys.stderr.write("Ignoring the directory.\n")
221 continue
222 else:
223 basename = arg
224 if basename:
225 basename = "{0}{1}".format(basename, os.sep)
226
227 if recursive and not os.path.islink(arg):
228 names = [arg] + Utilities.getDirs(arg, excludeDirs)
229 else:
230 names = [arg]
231 else:
232 basename = ""
233 names = [arg]
234
235 for filename in sorted(names):
236 inpackage = False
237 if os.path.isdir(filename):
238 files = []
239 for ext in supportedExtensions:
240 files.extend(glob.glob(os.path.join(
241 filename, Utilities.joinext("*", ext))))
242 initFile = os.path.join(
243 filename, Utilities.joinext("__init__", ext))
244 if initFile in files:
245 inpackage = True
246 files.remove(initFile)
247 files.insert(0, initFile)
248 elif progLanguage != "Python3":
249 # assume package
250 inpackage = True
251 else:
252 if (
253 Utilities.isWindowsPlatform() and
254 glob.has_magic(filename)
255 ):
256 files = glob.glob(filename)
257 else:
258 files = [filename]
259
260 for file in files:
261 skipIt = False
262 for pattern in excludePatterns:
263 if fnmatch.fnmatch(os.path.basename(file), pattern):
264 skipIt = True
265 break
266 if skipIt:
267 continue
268
269 try:
270 module = Utilities.ModuleParser.readModule(
271 file,
272 basename=basename, inpackage=inpackage,
273 ignoreBuiltinModules=ignoreBuiltinModules)
274 apiGenerator = APIGenerator(module)
275 api = apiGenerator.genAPI(True, basePackage,
276 includePrivate)
277 bases = apiGenerator.genBases(includePrivate)
278 except OSError as v:
279 sys.stderr.write("{0} error: {1}\n".format(file, v[1]))
280 continue
281 except ImportError as v:
282 sys.stderr.write("{0} error: {1}\n".format(file, v))
283 continue
284
285 for apiEntry in api:
286 if apiEntry not in apis:
287 apis.append(apiEntry)
288 for basesEntry in bases:
289 if bases[basesEntry]:
290 basesDict[basesEntry] = bases[basesEntry][:]
291 sys.stdout.write("-- {0} -- {1} ok\n".format(
292 progLanguage, file))
293
294 outdir = os.path.dirname(outputFile)
295 if outdir and not os.path.exists(outdir):
296 os.makedirs(outdir)
297 try:
298 with open(outputFile, "w", encoding="utf-8",
299 newline=newline) as out:
300 out.write("\n".join(sorted(apis)) + "\n")
301 except OSError as v:
302 sys.stderr.write("{0} error: {1}\n".format(outputFile, v[1]))
303 sys.exit(3)
304 try:
305 with open(basesFile, "w", encoding="utf-8",
306 newline=newline) as out:
307 for baseEntry in sorted(basesDict.keys()):
308 out.write("{0} {1}\n".format(
309 baseEntry, " ".join(sorted(basesDict[baseEntry]))))
310 except OSError as v:
311 sys.stderr.write("{0} error: {1}\n".format(basesFile, v[1]))
312 sys.exit(3)
313
314 sys.stdout.write('\nDone.\n')
315 sys.exit(0)
316
317 if __name__ == '__main__':
318 main()
319
320 #
321 # eflag: noqa = M801

eric ide

mercurial