Mercurial > gnulib
view pygnulib/config.py @ 38940:b790ffde5faa
private import even for standard modules
author | Dmitry Selyutin <ghostmansd@gmail.com> |
---|---|
date | Sat, 09 Sep 2017 23:01:51 +0300 |
parents | 3db083b5486c |
children | 8efa9010ba8a |
line wrap: on
line source
#!/usr/bin/python # encoding: UTF-8 import argparse as _argparse_ import codecs as _codecs_ import collections as _collections_ import os as _os_ import re as _re_ import sys as _sys_ from .error import type_assert as _type_assert_ from .error import AutoconfVersionError as _AutoconfVersionError_ class Base: """gnulib generic configuration""" _TABLE_ = { "root" : "", "local" : "", "source_base" : "lib", "m4_base" : "m4", "po_base" : "po", "doc_base" : "doc", "tests_base" : "tests", "auxdir" : "", "lib" : "libgnu", "makefile_name" : "Makefile.am", "macro_prefix" : "gl", "po_domain" : "", "witness_c_macro" : "", "lgpl" : 0, "tests" : False, "obsolete" : False, "cxx_tests" : False, "longrunning_tests" : False, "privileged_tests" : False, "unportable_tests" : False, "all_tests" : False, "libtool" : False, "conddeps" : False, "vc_files" : False, "autoconf" : 2.59, "modules" : [], "avoid" : [], "files" : [], } def __init__(self, **kwargs): self.__table = dict() for key in Base._TABLE_: self.__table[key] = Base._TABLE_[key] for key, value in kwargs.items(): self[key] = value def __repr__(self): return repr(self.__table) def __iter__(self): for key in Base._TABLE_: value = self[key] yield key, value @property def source_base(self): """directory relative to ROOT where source code is placed; defaults to 'lib'""" return self["source_base"] @source_base.setter def source_base(self, value): self["source_base"] = value @property def m4_base(self): """directory relative to ROOT where *.m4 macros are placed; defaults to 'm4'""" return self["m4_base"] @m4_base.setter def m4_base(self, value): self["m4_base"] = value @property def po_base(self): """directory relative to ROOT where *.po files are placed; defaults to 'po'""" return self["po_base"] @po_base.setter def po_base(self, value): self["po_base"] = value @property def doc_base(self): """directory relative to ROOT where doc files are placed; defaults to 'doc'""" return self["doc_base"] @doc_base.setter def doc_base(self, value): self["doc_base"] = value @property def tests_base(self): """directory relative to ROOT where unit tests are placed; defaults to 'tests'""" return self["tests_base"] @tests_base.setter def tests_base(self, value): self["tests_base"] = value @property def auxdir(self): """directory relative to ROOT where auxiliary build tools are placed""" return self["auxdir"] @auxdir.setter def auxdir(self, value): self["auxdir"] = value @property def lib(self): """library name; defaults to 'libgnu'""" return self["lib"] @lib.setter def lib(self, value): self["lib"] = value @property def makefile_name(self): """name of makefile in automake syntax in the source-base and tests-base directories""" return self["makefile_name"] @makefile_name.setter def makefile_name(self, value): self["makefile_name"] = value @property def macro_prefix(self): """ the prefix of the macros 'gl_EARLY' and 'gl_INIT' (default is 'gl'); the change of this parameter also affects include_guard_prefix parameter """ return self["macro_prefix"] @macro_prefix.setter def macro_prefix(self, value): self["macro_prefix"] = value @property def po_domain(self): """the prefix of the i18n domain""" return self["po_domain"] @po_domain.setter def po_domain(self, value): self["po_domain"] = value @property def witness_c_macro(self): """the C macro that is defined when the sources are compiled or used""" return self["witness_c_macro"] @witness_c_macro.setter def witness_c_macro(self, value): self["witness_c_macro"] = value @property def lgpl(self): """abort if modules aren't available under the LGPL; also modify license template""" return self["lgpl"] @lgpl.setter def lgpl(self, value): self["lgpl"] = value @property def tests(self): """include unit tests for the included modules""" return self["tests"] @tests.setter def tests(self, value): self["tests"] = value @property def obsolete(self): """include obsolete modules when they occur among the modules""" return self["obsolete"] @obsolete.setter def obsolete(self, value): self["obsolete"] = value @property def cxx_tests(self): """include even unit tests for C++ interoperability""" return self["cxx_tests"] @cxx_tests.setter def cxx_tests(self, value): self["cxx_tests"] = value @property def longrunning_tests(self): """include even unit tests that are long-runners""" return self["longrunning_tests"] @longrunning_tests.setter def longrunning_tests(self, value): self["longrunning_tests"] = value @property def privileged_tests(self): """include even unit tests that require root privileges""" return self["privileged_tests"] @privileged_tests.setter def privileged_tests(self, value): self["privileged_tests"] = value @property def unportable_tests(self): """include even unit tests that fail on some platforms""" return self["unportable_tests"] @unportable_tests.setter def unportable_tests(self, value): self["unportable_tests"] = value @property def all_tests(self): """include all kinds of problematic unit tests""" result = True result &= self.tests result &= self.cxx_tests result &= self.privileged_tests result &= self.unportable_tests result &= self.longrunning_tests return result @all_tests.setter def all_tests(self, value): self.tests = value self.cxx_tests = value self.privileged_tests = value self.unportable_tests = value self.longrunning_tests = value @property def libtool(self): """use libtool rules""" return self["libtool"] @libtool.setter def libtool(self, value): self["libtool"] = value @property def conddeps(self): """support conditional dependencies (may save configure time and object code)""" return self["conddeps"] @conddeps.setter def conddeps(self, value): self["conddeps"] = value @property def vc_files(self): """update version control related files""" return self["vc_files"] @vc_files.setter def vc_files(self, value): self["vc_files"] = value @property def autoconf(self): """autoconf version""" return self["autoconf"] @autoconf.setter def autoconf(self, value): self["autoconf"] = value @property def modules(self): """list of modules""" return self["modules"] @modules.setter def modules(self, value): self["modules"] = tuple(value) @property def avoid(self): """list of modules to avoid""" return self["avoid"] @avoid.setter def avoid(self, value): self["avoid"] = tuple(value) @property def files(self): """list of files to be processed""" return self["files"] @files.setter def files(self, value): self["files"] = list(value) @property def include_guard_prefix(self): """include guard prefix""" prefix = self["macro_prefix"].upper() default = Base._TABLE_["macro_prefix"] return "GL_%s" % prefix if prefix == default else "GL" def __getitem__(self, key): if key not in Base._TABLE_: key = key.replace("-", "_") if key not in Base._TABLE_: raise KeyError("unsupported option: %r" % key) if key == "all_tests": return self.all_tests return self.__table[key] def __setitem__(self, key, value): if key not in Base._TABLE_: key = key.replace("_", "-") if key not in Base._TABLE_: raise KeyError("unsupported option: %r" % key) key = key.replace("-", "_") if key == "all_tests": self.all_tests = value return typeid = type(Base._TABLE_[key]) if key == "lgpl" and value is None: value = 0 _type_assert_(key, value, typeid) if key == "lgpl" and value not in (0, 2, 3): raise ValueError("lgpl: None, 2 or 3 expected") if key == "autoconf" and value < 2.59: raise _AutoconfVersionError_(2.59) self.__table[key] = value def items(self): """a set-like object providing a view on configuration items""" return self.__table.items() def keys(self): """a set-like object providing a view on configuration keys""" return self.__table.keys() def values(self): """a set-like object providing a view on configuration values""" return self.__table.values() class Cache(Base): """gnulib cached configuration""" _AUTOCONF_ = { "autoconf" : _re_.compile(".*AC_PREREQ\\(\\[(.*?)\\]\\)", _re_.S | _re_.M), "auxdir" : _re_.compile("^AC_CONFIG_AUX_DIR\\(\\[(.*?)\\]\\)$", _re_.S | _re_.M), "libtool" : _re_.compile("A[CM]_PROG_LIBTOOL", _re_.S | _re_.M) } _GNULIB_CACHE_ = { "local" : (str, "gl_LOCAL_DIR"), "libtool" : (bool, "gl_LIBTOOL"), "conddeps" : (bool, "gl_CONDITIONAL_DEPENDENCIES"), "vc_files" : (bool, "gl_VC_FILES"), "tests" : (bool, "gl_WITH_TESTS"), "obsolete" : (bool, "gl_WITH_OBSOLETE"), "cxx_tests" : (bool, "gl_WITH_CXX_TESTS"), "longrunning_tests" : (bool, "gl_WITH_LONGRUNNING_TESTS"), "privileged_tests" : (bool, "gl_WITH_PRIVILEGED_TESTS"), "unportable_tests" : (bool, "gl_WITH_UNPORTABLE_TESTS"), "all_tests" : (bool, "gl_WITH_ALL_TESTS"), "source_base" : (str, "gl_SOURCE_BASE"), "m4_base" : (str, "gl_M4_BASE"), "po_base" : (str, "gl_PO_BASE"), "doc_base" : (str, "gl_DOC_BASE"), "tests_base" : (str, "gl_TESTS_BASE"), "makefile_name" : (str, "gl_MAKEFILE_NAME"), "macro_prefix" : (str, "gl_MACRO_PREFIX"), "po_domain" : (str, "gl_PO_DOMAIN"), "witness_c_macro" : (str, "gl_WITNESS_C_MACRO"), "lib" : (str, "gl_LIB"), "modules" : (list, "gl_MODULES"), "avoid" : (list, "gl_AVOID"), "lgpl" : (str, "gl_LGPL"), } _GNULIB_CACHE_BOOL_ = [] _GNULIB_CACHE_STR_ = [] _GNULIB_CACHE_LIST_ = [] for _key_, (_typeid_, _) in _GNULIB_CACHE_.items(): if _typeid_ is bool: _GNULIB_CACHE_BOOL_ += [_key_] elif _typeid_ is str: _GNULIB_CACHE_STR_ += [_key_] else: _GNULIB_CACHE_LIST_ += [_key_] _GNULIB_CACHE_PATTERN_ = _re_.compile("^(gl_.*?)\\(\\[(.*?)\\]\\)$", _re_.S | _re_.M) def __init__(self, root, m4_base, autoconf=None, **kwargs): super().__init__(root=root, m4_base=m4_base, **kwargs) self.__autoconf(root, autoconf) self.__gnulib_cache(root) self.__gnulib_comp(root) def __autoconf(self, root, autoconf): if not autoconf: autoconf = _os_.path.join(root, "configure.ac") if not _os_.path.exists(autoconf): autoconf = _os_.path.join(root, "configure.in") if not _os_.path.isabs(autoconf): autoconf = _os_.path.join(root, autoconf) autoconf = _os_.path.normpath(autoconf) with _codecs_.open(autoconf, "rb", "UTF-8") as stream: data = stream.read() for key, pattern in Cache._AUTOCONF_.items(): match = pattern.findall(data) if not match: continue if key == "autoconf": self[key] = float([_ for _ in match if match][-1]) else: self[key] = match[-1] def __gnulib_cache(self, root): m4base = self.m4_base gnulib_cache = _os_.path.join(root, m4base, "gnulib-cache.m4") if _os_.path.exists(gnulib_cache): with _codecs_.open(gnulib_cache, "rb", "UTF-8") as stream: data = stream.read() for key in Cache._GNULIB_CACHE_BOOL_: (_, macro) = Cache._GNULIB_CACHE_[key] if key in data: self[key] = True match = dict(Cache._GNULIB_CACHE_PATTERN_.findall(data)) for key in Cache._GNULIB_CACHE_STR_: (_, macro) = Cache._GNULIB_CACHE_[key] if macro in match: self[key] = match[macro].strip() for key in Cache._GNULIB_CACHE_LIST_: (_, macro) = Cache._GNULIB_CACHE_[key] if macro in match: self[key] = [_.strip() for _ in match[macro].split("\n") if _.strip()] def __gnulib_comp(self, root): m4base = self.m4_base gnulib_comp = _os_.path.join(root, m4base, "gnulib-comp.m4") if _os_.path.exists(gnulib_comp): with _codecs_.open(gnulib_comp, "rb", "UTF-8") as stream: data = stream.read() regex = "AC_DEFUN\\(\\[%s_FILE_LIST\\], \\[(.*?)\\]\\)" % self["macro-prefix"] pattern = _re_.compile(regex, _re_.S | _re_.M) match = pattern.findall(data) if match: self.files = [_.strip() for _ in match[-1].split("\n") if _.strip()] class CommandLine(Base): """gnulib-tool command line configuration""" _LIST_ = (1 << 0) _FIND_ = (1 << 1) _IMPORT_ = (1 << 2) _ADD_IMPORT_ = (1 << 3) _REMOVE_IMPORT_ = (1 << 4) _UPDATE_ = (1 << 5) _TEST_DIRECTORY_ = (1 << 6) _MEGA_TEST_DIRECTORY_ = (1 << 7) _TEST_ = (1 << 8) _MEGA_TEST_ = (1 << 9) _COPY_FILE_ = (1 << 10) _EXTRACT_DESCRIPTION_ = (1 << 11) _EXTRACT_COMMENT_ = (1 << 12) _EXTRACT_STATUS_ = (1 << 13) _EXTRACT_NOTICE_ = (1 << 14) _EXTRACT_APPLICABILITY_ = (1 << 15) _EXTRACT_FILELIST_ = (1 << 16) _EXTRACT_DEPENDENCIES_ = (1 << 17) _EXTRACT_AUTOCONF_SNIPPET_ = (1 << 18) _EXTRACT_AUTOMAKE_SNIPPET_ = (1 << 19) _EXTRACT_INCLUDE_DIRECTIVE_ = (1 << 20) _EXTRACT_LINK_DIRECTIVE_ = (1 << 21) _EXTRACT_LICENSE_ = (1 << 22) _EXTRACT_MAINTAINER_ = (1 << 23) _EXTRACT_TESTS_MODULE_ = (1 << 24) _ANY_IMPORT_ = _IMPORT_ | _ADD_IMPORT_ | _REMOVE_IMPORT_ | _UPDATE_ _ANY_TEST_ = _TEST_ | _MEGA_TEST_ | _TEST_DIRECTORY_ | _MEGA_TEST_DIRECTORY_ _ALL_ = _LIST_ | _FIND_ | _ANY_IMPORT_ | _ANY_TEST_ _MODES_ = ( (_LIST_, "list", ""), (_FIND_, "find", "filename"), (_IMPORT_, "import", "[module1 ... moduleN]"), (_ADD_IMPORT_, "add-import", "[module1 ... moduleN]"), (_REMOVE_IMPORT_, "remove-import", "[module1 ... moduleN]"), (_UPDATE_, "update", ""), (_TEST_DIRECTORY_, "testdir", "--dir=directory [module1 ... moduleN]"), (_MEGA_TEST_DIRECTORY_, "megatestdir", "--dir=directory [module1 ... moduleN]"), (_TEST_, "test", "--dir=directory [module1 ... moduleN]"), (_MEGA_TEST_, "megatest", "--dir=directory [module1 ... moduleN]"), (_EXTRACT_DESCRIPTION_, "extract-description", "module"), (_EXTRACT_COMMENT_, "extract-comment", "module"), (_EXTRACT_STATUS_, "extract-status", "module"), (_EXTRACT_NOTICE_, "extract-notice", "module"), (_EXTRACT_APPLICABILITY_, "extract-applicability", "module"), (_EXTRACT_FILELIST_, "extract-filelist", "module"), (_EXTRACT_DEPENDENCIES_, "extract-dependencies", "module"), (_EXTRACT_AUTOCONF_SNIPPET_, "extract-autoconf-snippet", "module"), (_EXTRACT_AUTOMAKE_SNIPPET_, "extract-automake-snippet", "module"), (_EXTRACT_INCLUDE_DIRECTIVE_, "extract-include-directive", "module"), (_EXTRACT_LINK_DIRECTIVE_, "extract-link-directive", "module"), (_EXTRACT_LICENSE_, "extract-license", "module"), (_EXTRACT_MAINTAINER_, "extract-maintainer", "module"), (_EXTRACT_TESTS_MODULE_, "extract-tests-module", "module"), (_COPY_FILE_, "copy", "file [destination]"), ) _LINK_SYMBOLIC_ = (1 << 0) _LINK_HARD_ = (1 << 1) _LINK_LOCAL_ = (1 << 2) _LINK_NOTICE_ = (1 << 3) class _ModeAction_(_argparse_.Action): def __init__(self, *args, **kwargs): mode = kwargs["const"] kwargs["dest"] = "mode" kwargs["nargs"] = 0 if mode & CommandLine._ANY_IMPORT_ or mode & CommandLine._ANY_TEST_: kwargs["nargs"] = "+" kwargs["metavar"] = "module0 ... moduleN" elif mode & CommandLine._FIND_: kwargs.pop("nargs") kwargs["metavar"] = "FILE" elif mode & CommandLine._COPY_FILE_: kwargs["nargs"] = "+" kwargs["metavar"] = "SRC [DST]" super().__init__(*args, **kwargs) def __call__(self, parser, namespace, value, option=None): old_option = "" new_option = option new_mode = None old_mode = getattr(namespace, self.dest) for (mode, name, _) in CommandLine._MODES_: option = ("--" + name) if mode == old_mode: old_option = option if option == new_option: new_mode = mode if old_option and new_mode: break if old_mode != new_mode: if not old_mode is None: fmt = "argument {0}: not allowed with {1}" parser.error(fmt.format(new_option, old_option)) setattr(namespace, "modules", list(value)) setattr(namespace, self.dest, new_mode) class _AvoidAction_(_argparse_.Action): def __call__(self, parser, namespace, value, option=None): values = getattr(namespace, self.dest) values += value class _VerboseAction_(_argparse_.Action): def __call__(self, parser, namespace, value, option=None): value = getattr(namespace, self.dest) verbose = option in ("-v", "--verbose") value += +1 if verbose else -1 setattr(namespace, self.dest, value) class _LinkAction_(_argparse_.Action): def __call__(self, parser, namespace, value, option=None): flags = getattr(namespace, self.dest) symlink = ("-s", "--symlink", "--local-symlink", "-S", "--more-symlink") hardlink = ("-h", "--hardlink", "--local-hardlink", "-H", "--more-hardlink") local = ("--local-symlink", "--local-hardlink") disable_notice = ("-S", "--more-symlink", "-H", "--more-hardlink") if option in symlink: if flags & CommandLine._LINK_HARD_: parser.error("conflicting --symlink and --hardlink options") flags |= CommandLine._LINK_SYMBOLIC_ if option in hardlink: if flags & CommandLine._LINK_SYMBOLIC_: parser.error("conflicting --symlink and --hardlink options") flags |= CommandLine._LINK_HARD_ if option in local: flags |= CommandLine._LINK_LOCAL_ if option in disable_notice: flags &= ~CommandLine._LINK_NOTICE_ setattr(namespace, self.dest, flags) # section0: (section0_modes, (([section0_option0, section0_optionN], **section0_kwargs))) # sectionN: (sectionN_modes, (([sectionN_option0, sectionN_optionN], **sectionN_kwargs))) # # for (name, flags, arguments) in sections: # for argument in arguments: # (options, kwargs) = argument _SECTIONS_ = ( ( "Operation modes", None, ( (["-l", "--list"], { "help": ( "print the available module names", ), "action": _ModeAction_, "const": _LIST_, }), (["-f", "--find"], { "help": ( "find the modules which contain the specified file", ), "action": _ModeAction_, "const": _FIND_, }), (["-i", "--import"], { "help": ( "import the given modules into the current package", ), "action": _ModeAction_, "const": _IMPORT_, }), (["-a", "--add-import"], { "help": ( "augment the list of imports from gnulib into the", "current package, by adding the given modules;", "if no modules are specified, update the current", "package from the current gnulib", ), "action": _ModeAction_, "const": _ADD_IMPORT_, }), (["-r", "--remove-import"], { "help": ( "reduce the list of imports from gnulib into the", "current package, by removing the given modules", ), "action": _ModeAction_, "const": _REMOVE_IMPORT_, }), (["-u", "--update"], { "help": ( "update the current package, restore files omitted", "from version control", ), "action": _ModeAction_, "const": _UPDATE_, }), (["--extract-description"], { "help": ( "extract the description", ), "action": _ModeAction_, "const": _EXTRACT_DESCRIPTION_, }), (["--extract-comment"], { "help": ( "extract the comment", ), "action": _ModeAction_, "const": _EXTRACT_COMMENT_, }), (["--extract-status"], { "help": ( "extract the status (obsolete etc.)", ), "action": _ModeAction_, "const": _EXTRACT_STATUS_, }), (["--extract-notice"], { "help": ( "extract the notice or banner", ), "action": _ModeAction_, "const": _EXTRACT_NOTICE_, }), (["--extract-applicability"], { "help": ( "extract the applicability", ), "action": _ModeAction_, "const": _EXTRACT_APPLICABILITY_, }), (["--extract-filelist"], { "help": ( "extract the list of files", ), "action": _ModeAction_, "const": _EXTRACT_FILELIST_, }), (["--extract-dependencies"], { "help": ( "extract the dependencies", ), "action": _ModeAction_, "const": _EXTRACT_DEPENDENCIES_, }), (["--extract-autoconf-snippet"], { "help": ( "extract the snippet for configure.ac", ), "action": _ModeAction_, "const": _EXTRACT_AUTOCONF_SNIPPET_, }), (["--extract-automake-snippet"], { "help": ( "extract the snippet for library makefile", ), "action": _ModeAction_, "const": _EXTRACT_AUTOMAKE_SNIPPET_, }), (["--extract-include-directive"], { "help": ( "extract the #include directive", ), "action": _ModeAction_, "const": _EXTRACT_INCLUDE_DIRECTIVE_, }), (["--extract-link-directive"], { "help": ( "extract the linker directive", ), "action": _ModeAction_, "const": _EXTRACT_LINK_DIRECTIVE_, }), (["--extract-license"], { "help": ( "report the license terms of the source files", "under lib/", ), "action": _ModeAction_, "const": _EXTRACT_LICENSE_, }), (["--extract-maintainer"], { "help": ( "report the maintainer(s) inside gnulib", ), "action": _ModeAction_, "const": _EXTRACT_MAINTAINER_, }), (["--extract-tests-module"], { "help": ( "report the unit test module, if it exists", ), "action": _ModeAction_, "const": _EXTRACT_TESTS_MODULE_, }), (["--copy-file"], { "help": ( "copy a file that is not part of any module", ), "action": _ModeAction_, "const": _COPY_FILE_, }), ), ), ( "General options", _ALL_, ( (["--dir"], { "help": ( "specify the target directory; on --import,", "this specifies where your configure.ac", "can be found; defaults to current directory", ), "dest": "root", "default": ".", "metavar": "DIRECTORY", }), (["--local-dir"], { "help": ( "pecify a local override directory where to look", "up files before looking in gnulib's directory", ), "dest": "local", "default": "", "nargs": 1, "metavar": "DIRECTORY", }), (["-v", "--verbose"], { "help": ( "increase verbosity; may be repeated", ), "dest": "verbosity", "action": _VerboseAction_, "default": 0, "nargs": 0, }), (["-q", "--quiet"], { "help": ( "decrease verbosity; may be repeated", ), "dest": "verbosity", "action": _VerboseAction_, "default": 0, "nargs": 0, }), ), ), ( "Options for --import, --add/remove-import, --update", _ANY_IMPORT_, ( (["--dry-run"], { "help": ( "only print what would have been done", ), "dest": "dry_run", "action": "store_true", "default": False, }), ), ), ( "Options for --import, --add/remove-import", (_IMPORT_ | _ADD_IMPORT_ | _REMOVE_IMPORT_), ( (["--with-tests"], { "help": ( "include unit tests for the included modules", ), "dest": "tests", "action": "store_true", "default": False, }), (["--single-configure"], { "help": ( "generate a single configure file, not a separate", "configure file for the tests directory", ), "dest": "single_configure", "action": "store_true", "default": False, }), ), ), ( "Options for --create-[mega]testdir, --[mega]test", _ANY_TEST_, ( (["--without-tests"], { "help": ( "don't include unit tests for the included modules", ), "dest": "tests", "action": "store_false", "default": False, }), ), ), ( "Options for --import, --add/remove-import," "\n" " --create-[mega]testdir, --[mega]test", (_ANY_IMPORT_ & ~_UPDATE_) | _ANY_TEST_, ( (["--with-obsolete"], { "help": ( "include obsolete modules when they occur among the", "dependencies; by default, dependencies to obsolete", "modules are ignored", ), "dest": "obsolete", "action": "store_true", "default": False, }), (["--with-c++-tests"], { "help": ( "include even unit tests for C++ interoperability", ), "dest": "cxx_tests", "action": "store_true", "default": False, }), (["--without-c++-tests"], { "help": ( "exclude unit tests for C++ interoperability", ), "dest": "cxx_tests", "action": "store_false", "default": False, }), (["--with-longrunning-tests"], { "help": ( "include even unit tests that are long-runners", ), "dest": "longrunning_tests", "action": "store_true", "default": False, }), (["--without-longrunning-tests"], { "help": ( "exclude unit tests that are long-runners", ), "dest": "longrunning_tests", "action": "store_false", "default": False, }), (["--with-privileged-tests"], { "help": ( "include even unit tests that require root privileges", ), "dest": "privileged_tests", "action": "store_true", "default": False, }), (["--without-privileged-tests"], { "help": ( "exclude unit tests that require root privileges", ), "dest": "privileged_tests", "action": "store_false", "default": False, }), (["--with-unportable-tests"], { "help": ( "include even unit tests that fail on some platforms", ), "dest": "unportable_tests", "action": "store_true", "default": False, }), (["--without-unportable-tests"], { "help": ( "exclude unit tests that fail on some platforms", ), "dest": "unportable_tests", "action": "store_false", "default": False, }), (["--with-all-tests"], { "help": ( "include all kinds of problematic unit tests", ), "dest": "all_tests", "action": "store_true", "default": False, }), (["--avoid"], { "help": ( "avoid including the given MODULE; useful if you", "have code that provides equivalent functionality;", "this option can be repeated", ), "action": _AvoidAction_, "nargs": 1, "default": [], "metavar": "MODULE", }), (["--conditional-dependencies"], { "help": ( "support conditional dependencies (may save configure", "time and object code)", ), "action": "store_true", "default": False, "dest": "conddeps", }), (["--no-conditional-dependencies"], { "help": ( "don't use conditional dependencies", ), "action": "store_false", "default": False, "dest": "conddeps", }), (["--libtool"], { "help": ( "use libtool rules", ), "action": "store_true", "default": False, "dest": "libtool", }), (["--no-libtool"], { "help": ( "don't use libtool rules", ), "action": "store_false", "default": False, "dest": "libtool", }), ), ), ( "Options for --import, --add/remove-import", (_ANY_IMPORT_ & ~_UPDATE_), ( (["--lib"], { "help": ( "specify the library name; defaults to 'libgnu'", ), "default": "libgnu", "metavar": "LIBRARY", }), (["--source-base"], { "help": ( "directory relative to --dir where source code is", "placed (default \"lib\")", ), "default": "lib", "metavar": "DIRECTORY", }), (["--m4-base"], { "help": ( "directory relative to --dir where *.m4 macros are", "placed (default \"m4\")", ), "default": "m4", "metavar": "DIRECTORY", }), (["--po-base"], { "help": ( "directory relative to --dir where *.po files are", "placed (default \"po\")", ), "default": "po", "metavar": "DIRECTORY", }), (["--doc-base"], { "help": ( "directory relative to --dir where doc files are", "placed (default \"doc\")", ), "default": "doc", "metavar": "DIRECTORY", }), (["--tests-base"], { "help": ( "directory relative to --dir where unit tests are", "placed (default \"tests\")", ), "default": "tests", "metavar": "DIRECTORY", }), (["--aux-dir"], { "help": ( "directory relative to --dir where auxiliary build", "tools are placed (default comes from configure.ac);", ), "dest": "auxdir", "default": "", "metavar": "DIRECTORY", }), (["--lgpl"], { "help": ( "abort if modules aren't available under the LGPL;", "also modify license template from GPL to LGPL;", "the version number of the LGPL can be specified;", "the default is currently LGPLv3.", ), "choices": (2, 3), "type": int, "metavar": "[=2|=3]", }), (["--makefile-name"], { "help": ( "name of makefile in automake syntax in the", "source-base and tests-base directories", "(default \"Makefile.am\")", ), "default": "Makefile.am", "metavar": "NAME", }), (["--macro-prefix"], { "help": ( "specify the prefix of the macros 'gl_EARLY' and", "'gl_INIT'; default is 'gl'", ), "default": "gl", "metavar": "PREFIX", }), (["--po-domain"], { "help": ( "specify the prefix of the i18n domain; usually use", "the package name; a suffix '-gnulib' is appended", ), "default": "", "metavar": "NAME", }), (["--witness-c-macro"], { "help": ( "specify the C macro that is defined when the", "sources in this directory are compiled or used", ), "default": "", "metavar": "NAME", }), (["--vc-files"], { "help": ( "update version control related files", "(.gitignore and/or .cvsignore)", ), "action": "store_true", "default": False, "dest": "vc_files", }), (["--no-vc-files"], { "help": ( "don't update version control related files", "(.gitignore and/or .cvsignore)", ), "action": "store_false", "default": False, "dest": "libtool", }), (["--no-changelog"], { "help": ( "don't update or create ChangeLog files;", "this option is currently deprecated", ), "default": None, "action": "store_const", "const": None, }), ), ), ( "Options for --import, --add/remove-import, --update" "\n" " --create-[mega]testdir, --[mega]test", _ANY_IMPORT_ | _ANY_TEST_, ( (["-s", "--symlink"], { "help": ( "make symbolic links instead of copying files", ), "dest": "link", "action": _LinkAction_, "nargs": 0, "default": _LINK_NOTICE_, }), (["--local-symlink"], { "help": ( "make symbolic links instead of copying files, only", "for files from the local override directory" ), "dest": "link", "action": _LinkAction_, "nargs": 0, "default": _LINK_NOTICE_, }), (["-h", "--hardlink"], { "help": ( "make hard links instead of copying files", ), "dest": "link", "action": _LinkAction_, "nargs": 0, "default": _LINK_NOTICE_, }), (["--local-hardlink"], { "help": ( "make hard links instead of copying files, only", "for files from the local override directory" ), "dest": "link", "action": _LinkAction_, "nargs": 0, "default": _LINK_NOTICE_, }), ), ), ( "Options for --import, --add/remove-import, --update", _ANY_IMPORT_, ( (["-S", "--more-symlink"], { "help": ( "make symbolic links instead of copying files and", "don't replace copyright notices", ), "dest": "link", "action": _LinkAction_, "nargs": 0, "default": _LINK_NOTICE_, }), (["-H", "--more-hardlink"], { "help": ( "make symbolic links instead of copying files and", "don't replace copyright notices", ), "dest": "link", "action": _LinkAction_, "nargs": 0, "default": _LINK_NOTICE_, }), ), ), ) def __usage(self): iterable = iter(CommandLine._MODES_) (_, cmd, args) = next(iterable) fmt = (" --{cmd}" + (" {args}" if args else "")) lines = ["usage: {program}" + fmt.format(cmd=cmd, args=args)] for (_, cmd, args) in iterable: fmt = (" --{cmd}" + (" {args}" if args else "")) lines += [" {program}" + fmt.format(cmd=cmd, args=args)] lines += ["", ""] return "\n".join(lines).format(program=self.__program) def __help(self): lines = [""] for (name, _, args) in CommandLine._SECTIONS_: offset = -1 lines += ["", "%s:" % name, ""] for arg in args: (options, kwargs) = arg options = ", ".join(options) if "metavar" in kwargs: options += (" " + kwargs["metavar"]) length = len(options) if length > offset: offset = length fmt1 = " %-{0}s %s".format(offset) fmt2 = " " + " " * offset + " %s" for arg in args: (options, kwargs) = arg options = ", ".join(options) if "metavar" in kwargs: sep = "" if "choices" in kwargs else "=" options += ("%s%s" % (sep, kwargs["metavar"])) description = iter(kwargs["help"]) line = next(description) lines += [fmt1 % (options, line)] for line in description: lines += [fmt2 % line] lines += [""] return self.__usage()[:-1] + "\n".join(lines) def __init__(self, program, argv, **kwargs): _type_assert_("program", program, str) _type_assert_("argv", argv, _collections_.Iterable) super().__init__(**kwargs) parser = _argparse_.ArgumentParser(prog=program, add_help=False, allow_abbrev=False) for (_, _, args) in CommandLine._SECTIONS_: for arg in args: (options, kwargs) = arg parser.add_argument(*options, **kwargs) self.__program = _os_.path.basename(program) parser.format_usage = self.__usage parser.format_help = self.__help if "--help" in argv: parser.print_help() _sys_.exit(0) namespace = parser.parse_args(argv) namespace = vars(namespace) self.__mode = namespace.pop("mode") if self.__mode is None: parser.error("no operating mode selected") self.__dry_run = namespace.pop("dry_run") self.__link = namespace.pop("link", None) self.__single_configure = namespace.pop("single_configure") self.__verbosity = namespace.pop("verbosity") namespace.pop("no_changelog", None) for (key, value) in namespace.items(): self[key] = value @property def mode(self): """operating mode""" for (flag, cmd, _) in CommandLine._MODES_: if flag == self.__mode: return cmd return "" @property def dry_run(self): """running in dry-run mode?""" return self.__dry_run @property def verbosity(self): """verbosity level""" return self.__verbosity @property def single_configure(self): """generate a single configure file?""" return self.__single_configure @property def symlink(self): """make symbolic links instead of copying files?""" return bool(self.__link & CommandLine._LINK_SYMBOLIC_) def hardlink(self): """make hard links instead of copying files?""" return bool(self.__link & CommandLine._LINK_HARD_) @property def only_local_links(self): """make links only for files from the local override directory?""" return bool(self.__link & CommandLine._LINK_LOCAL_) @property def allow_license_update(self): """allow to update license notice?""" return bool(self.__link & CommandLine._LINK_NOTICE_)