diff -r 6c5585c3e543 -r a055e1b82af8 src/eric7/eric7_api.py --- a/src/eric7/eric7_api.py Tue Nov 07 16:52:08 2023 +0100 +++ b/src/eric7/eric7_api.py Wed Nov 08 10:03:23 2023 +0100 @@ -12,8 +12,8 @@ This script can be used via the commandline as well. """ +import argparse import fnmatch -import getopt import glob import os import sys @@ -25,64 +25,109 @@ from eric7.Utilities import ModuleParser -def usage(): +def createArgumentParser(): """ - Function to print some usage information. + Function to create an argument parser. - It prints a reference of all commandline parameters that may - be used and ends the application. + @return created argument parser object + @rtype argparse.ArgumentParser """ - print("eric7_api") - print() - print("Copyright (c) 2004 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>.") - print() - print("Usage:") - print() - print(" eric7_api [options] files...") - print() - print("where files can be either python modules, package") - print("directories or ordinary directories.") - print() - print("Options:") - print() - print(" -b name or --base=name") - print(" Use the given name as the name of the base package.") - print(" -e eol-type or --eol=eol-type") - print(" Use the given eol type to terminate lines.") - print(" Valid values are 'cr', 'lf' and 'crlf'.") - print(" --exclude-file=pattern") - print(" Specify a filename pattern of files to be excluded.") - print(" This option may be repeated multiple times.") - print(" -h or --help") - print(" Show this help and exit.") - print(" -i or --ignore") - print(" Ignore the set of builtin modules") - print(" -l language or --language=language") - print(" Generate an API file for the given programming language.") - print(" Supported programming languages are:") - for lang in sorted(DocumentationTools.supportedExtensionsDictForApis.keys()): - print(" * {0}".format(lang)) - print(" The default is 'Python3'.") - print(" This option may be repeated multiple times.") - print(" -o filename or --output=filename") - print( - " Write the API information to the named file." - " A '%L' placeholder" # __IGNORE_WARNING_M601__ + parser = argparse.ArgumentParser( + description=( + "Create API files to be used by 'QScintilla' or the 'eric Assistant'" + " plugin." + ), + epilog="Copyright (c) 2004 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>.", + add_help=False, + ) + + parser.add_argument( + "file", + nargs="*", + help="'file' can be either python modules, package directories or ordinary" + " directories.", + ) + parser.add_argument( + "-b", + "--base", + default="", + help="Use the given name as the name of the base package.", + ) + parser.add_argument( + "-e", + "--eol", + choices=["cr", "lf", "crlf"], + help="Use the given eol type to terminate lines.", + ) + parser.add_argument( + "--exclude-file", + action="append", + default=[], + help="Specify a filename pattern of files to be excluded. This option may be" + " repeated multiple times.", + ) + parser.add_argument( + "-h", "--help", action="store_true", help="Show this help and exit." + ) + parser.add_argument( + "-i", + "--ignore", + action="store_true", + help="Ignore the set of builtin modules.", ) - print(" is replaced by the language of the API file (see --language).") - print(" -p or --private") - print(" Include private methods and functions.") - print(" -R, -r or --recursive") - print(" Perform a recursive search for source files.") - print(" -t ext or --extension=ext") - print(" Add the given extension to the list of file extensions.") - print(" This option may be given multiple times.") - print(" -V or --version") - print(" Show version information and exit.") - print(" -x directory or --exclude=directory") - print(" Specify a directory basename to be excluded.") - print(" This option may be repeated multiple times.") - sys.exit(1) + parser.add_argument( + "-l", + "--language", + action="append", + default=[], + choices=DocumentationTools.supportedExtensionsDictForApis.keys(), + help="Generate an API file for the given programming language. The default" + " is 'Python3'. This option may be repeated multiple times.", + ) + parser.add_argument( + "-o", + "--output", + default="", + help="Write the API information to the named file. A '%%L'" # noqa: M601 + " placeholder is replaced by the language of the API file (see --language).", + ) + parser.add_argument( + "-p", + "--private", + action="store_true", + help="Include private methods and functions.", + ) + parser.add_argument( + "-R", + "-r", + "--recursive", + action="store_true", + help="Perform a recursive search for source files.", + ) + parser.add_argument( + "-t", + "--extension", + action="append", + default=[], + help="Add the given extension to the list of file extensions. This option may" + " be given multiple times.", + ) + parser.add_argument( + "-V", + "--version", + action="store_true", + help="Show version information and exit.", + ) + parser.add_argument( + "-x", + "--exclude", + action="append", + default=[], + help="Specify a directory basename to be excluded. This option may be repeated" + " multiple times.", + ) + + return parser def version(): @@ -102,7 +147,6 @@ """ FOR A\n""" """PARTICULAR PURPOSE.""".format(Version) ) - sys.exit(1) def main(): @@ -111,27 +155,24 @@ """ global supportedExtensions - try: - opts, args = getopt.getopt( - sys.argv[1:], - "b:e:hil:o:pRrt:Vx:", - [ - "base=", - "eol=", - "exclude=", - "exclude-file=", - "extension=", - "help", - "ignore", - "language=", - "output=", - "private", - "recursive", - "version", - ], + parser = createArgumentParser() + args = parser.parse_args() + + if args.help: + parser.print_help() + sys.exit(1) + elif args.version: + version() + sys.exit(1) + + if not args.file: + parser.error( + "At least one file, Python module, Python package or directory must be" + " given." ) - except getopt.error: - usage() + + if not args.output: + parser.error("No output file given.") excludeDirs = [ ".svn", @@ -143,61 +184,22 @@ "build", "doc", "docs", + ] + args.exclude + excludePatterns = args.exclude_file + outputFileName = args.output + recursive = args.recursive + basePackage = args.base + includePrivate = args.private + progLanguages = args.language + extensions = [ + ext if ext.startswith(".") else ".{0}".format(ext) for ext in args.extension ] - excludePatterns = [] - outputFileName = "" - recursive = False - basePackage = "" - includePrivate = False - progLanguages = [] - extensions = [] - newline = None - ignoreBuiltinModules = False - - for k, v in opts: - if k in ["-o", "--output"]: - outputFileName = v - elif k in ["-R", "-r", "--recursive"]: - recursive = True - elif k in ["-x", "--exclude"]: - excludeDirs.append(v) - elif k == "--exclude-file": - excludePatterns.append(v) - elif k in ["-h", "--help"]: - usage() - elif k in ["-i", "--ignore"]: - ignoreBuiltinModules = True - elif k in ["-V", "--version"]: - version() - elif k in ["-t", "--extension"]: - if not v.startswith("."): - v = ".{0}".format(v) - extensions.append(v) - elif k in ["-b", "--base"]: - basePackage = v - elif k in ["-p", "--private"]: - includePrivate = True - elif k in ["-l", "--language"]: - if v not in progLanguages: - if v not in DocumentationTools.supportedExtensionsDictForApis: - sys.stderr.write("Wrong language given: {0}. Aborting\n".format(v)) - sys.exit(1) - else: - progLanguages.append(v) - elif k in ["-e", "--eol"]: - if v.lower() == "cr": - newline = "\r" - elif v.lower() == "lf": - newline = "\n" - elif v.lower() == "crlf": - newline = "\r\n" - - if not args: - usage() - - if outputFileName == "": - sys.stderr.write("No output file given. Aborting\n") - sys.exit(1) + ignoreBuiltinModules = args.ignore + newline = { + "cr": "\r", + "lf": "\n", + "crlf": "\r\n", + }[args.eol] if len(progLanguages) == 0: progLanguages = ["Python3"] @@ -227,13 +229,15 @@ outputFile = "{0}-{1}{2}".format(root, progLanguage.lower(), ext) basesFile = os.path.splitext(outputFile)[0] + ".bas" - for arg in args: - if os.path.isdir(arg): + for argsfile in args.file: + if os.path.isdir(argsfile): if os.path.exists( - os.path.join(arg, FileSystemUtilities.joinext("__init__", ".py")) + os.path.join( + argsfile, FileSystemUtilities.joinext("__init__", ".py") + ) ): - basename = os.path.dirname(arg) - if arg == ".": + basename = os.path.dirname(argsfile) + if argsfile == ".": sys.stderr.write("The directory '.' is a package.\n") sys.stderr.write( "Please repeat the call giving its real name.\n" @@ -241,17 +245,19 @@ sys.stderr.write("Ignoring the directory.\n") continue else: - basename = arg + basename = argsfile if basename: basename = "{0}{1}".format(basename, os.sep) - if recursive and not os.path.islink(arg): - names = [arg] + FileSystemUtilities.getDirs(arg, excludeDirs) + if recursive and not os.path.islink(argsfile): + names = [argsfile] + FileSystemUtilities.getDirs( + argsfile, excludeDirs + ) else: - names = [arg] + names = [argsfile] else: basename = "" - names = [arg] + names = [argsfile] for filename in sorted(names): inpackage = False