]> Savannah Git Hosting - gnulib.git/commitdiff
config: aggregate all options
authorDmitry Selyutin <ghostmansd@gmail.com>
Fri, 20 Oct 2017 17:24:17 +0000 (20:24 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Fri, 20 Oct 2017 19:46:49 +0000 (22:46 +0300)
pygnulib.py
pygnulib/config.py
pygnulib/module.py

index 75f8f303e37dc4c2887f3e67178cabb42153e0d7..3cec4b10a6d8c222c9ce5cd51ffc44cc7d15bb77 100755 (executable)
@@ -62,13 +62,22 @@ def extract_hook(program, gnulib, mode, namespace, *args, **kwargs):
 
 
 def import_hook(script, gnulib, namespace, verbosity, options, *args, **kwargs):
+    keywords = frozenset({
+        "tests",
+        "obsolete",
+        "cxx_tests",
+        "longrunning_tests",
+        "privileged_tests",
+        "unportable_tests",
+    })
     (_, _) = (args, kwargs)
     config = BaseConfig(**namespace)
     cache = CacheConfig(configure=None)
     for key in {"ac_version", "files"}:
         if key not in namespace:
             config[key] = cache[key]
-    (base, full, main, final, tests) = transitive_closure(gnulib.module, config.modules, config.options)
+    options = {key:config[key] for key in keywords}
+    (base, full, main, final, tests) = transitive_closure(gnulib.module, config.modules, **options)
 
     # Print some information about modules.
     print("Module list with included dependencies (indented):", file=sys.stdout)
index 4da66eac5b2f49fd0778c97e95f55823f29351dd..7adaf23c6fa37bc74d977d9b042221b7ad3d0f62 100644 (file)
@@ -37,17 +37,6 @@ OTHER_LICENSES = frozenset({
 })
 
 
-class Option:
-    """gnulib configuration options"""
-    Obsolete = (1 << 0)
-    Tests = (1 << 1)
-    CXX = (1 << 2)
-    Longrunning = (1 << 3)
-    Privileged = (1 << 4)
-    Unportable = (1 << 5)
-    All = (Obsolete | Tests | CXX | Longrunning | Privileged | Unportable)
-
-
 
 class Base:
     """gnulib generic configuration"""
@@ -66,13 +55,6 @@ class Base:
         "po_domain"         : "",
         "witness_c_macro"   : "",
         "licenses"          : set(),
-        "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,
@@ -81,10 +63,29 @@ class Base:
         "avoid"             : set(),
         "files"             : set(),
     }
+    _OPTIONS_ = frozenset({
+        "tests",
+        "obsolete",
+        "cxx_tests",
+        "longrunning_tests",
+        "privileged_tests",
+        "unportable_tests",
+    })
+
+
+    class _Option_:
+        """gnulib configuration options"""
+        Obsolete = (1 << 0)
+        Tests = (1 << 1)
+        CXX = (1 << 2)
+        Longrunning = (1 << 3)
+        Privileged = (1 << 4)
+        Unportable = (1 << 5)
+        AllTests = (Obsolete | Tests | CXX | Longrunning | Privileged | Unportable)
 
 
     def __init__(self, **kwargs):
-        self.__table = {}
+        self.__table = {"options": 0}
         for (key, value) in Base._TABLE_.items():
             self[key] = kwargs.get(key, value)
 
@@ -286,105 +287,98 @@ class Base:
     @property
     def tests(self):
         """include unit tests for the included modules"""
-        return self.__table["tests"]
+        return bool(self.__table["options"] & Base._Option_.Tests)
 
     @tests.setter
     def tests(self, value):
         _type_assert_("tests", value, bool)
-        self.__table["tests"] = value
+        if value:
+            self.__table["options"] |= Base._Option_.Tests
+        else:
+            self.__table["options"] &= ~Base._Option_.Tests
 
 
     @property
     def obsolete(self):
         """include obsolete modules when they occur among the modules"""
-        return self.__table["obsolete"]
+        return bool(self.__table["options"] & Base._Option_.Tests)
 
     @obsolete.setter
     def obsolete(self, value):
         _type_assert_("obsolete", value, bool)
-        self.__table["obsolete"] = value
+        if value:
+            self.__table["options"] |= Base._Option_.Obsolete
+        else:
+            self.__table["options"] &= ~Base._Option_.Obsolete
 
 
     @property
     def cxx_tests(self):
         """include even unit tests for C++ interoperability"""
-        return self.__table["cxx_tests"]
+        return bool(self.__table["options"] & Base._Option_.CXX)
 
     @cxx_tests.setter
     def cxx_tests(self, value):
         _type_assert_("cxx_tests", value, bool)
-        self.__table["cxx_tests"] = value
+        if value:
+            self.__table["options"] |= Base._Option_.CXX
+        else:
+            self.__table["options"] &= ~Base._Option_.CXX
 
 
     @property
     def longrunning_tests(self):
         """include even unit tests that are long-runners"""
-        return self.__table["longrunning_tests"]
+        return bool(self.__table["options"] & Base._Option_.Longrunning)
 
     @longrunning_tests.setter
     def longrunning_tests(self, value):
         _type_assert_("longrunning_tests", value, bool)
-        self.__table["longrunning_tests"] = value
+        if value:
+            self.__table["options"] |= Base._Option_.Longrunning
+        else:
+            self.__table["options"] &= ~Base._Option_.Longrunning
 
 
     @property
     def privileged_tests(self):
         """include even unit tests that require root privileges"""
-        return self.__table["privileged_tests"]
+        return bool(self.__table["options"] & Base._Option_.Privileged)
 
     @privileged_tests.setter
     def privileged_tests(self, value):
         _type_assert_("privileged_tests", value, bool)
-        self.__table["privileged_tests"] = value
+        if value:
+            self.__table["options"] |= Base._Option_.Privileged
+        else:
+            self.__table["options"] &= ~Base._Option_.Privileged
 
 
     @property
     def unportable_tests(self):
         """include even unit tests that fail on some platforms"""
-        return self.__table["unportable_tests"]
+        return bool(self.__table["options"] & Base._Option_.Unportable)
 
     @unportable_tests.setter
     def unportable_tests(self, value):
         _type_assert_("unportable_tests", value, bool)
-        self.__table["unportable_tests"] = value
+        if value:
+            self.__table["options"] |= Base._Option_.Unportable
+        else:
+            self.__table["options"] &= ~Base._Option_.Unportable
 
 
     @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
+        return (self.__table["options"] & Base._Option_.AllTests) == Base._Option_.AllTests
 
     @all_tests.setter
     def all_tests(self, value):
-        self.__table["tests"] = value
-        self.__table["cxx_tests"] = value
-        self.__table["privileged_tests"] = value
-        self.__table["unportable_tests"] = value
-        self.__table["longrunning_tests"] = value
-
-    @property
-    def options(self):
-        """bitmask of active options"""
-        result = 0
-        if self.obsolete:
-            result |= Option.Obsolete
-        if self.tests:
-            result |= Option.Tests
-        if self.cxx_tests:
-            result |= Option.CXX
-        if self.longrunning_tests:
-            result |= Option.Longrunning
-        if self.privileged_tests:
-            result |= Option.Privileged
-        if self.unportable_tests:
-            result |= Option.Unportable
-        return result
+        if value:
+            self.__table["options"] |= Base._Option_.AllTests
+        else:
+            self.__table["options"] &= Base._Option_.AllTests
 
 
     @property
@@ -489,17 +483,19 @@ class Base:
 
 
     def __getitem__(self, key):
-        if key not in Base._TABLE_:
+        table = (set(Base._TABLE_.keys()) | Base._OPTIONS_)
+        if key not in table:
             key = key.replace("-", "_")
-            if key not in Base._TABLE_:
+            if key not in table:
                 raise KeyError("unsupported option: {0}".format(key))
         return getattr(self, key)
 
 
     def __setitem__(self, key, value):
-        if key not in Base._TABLE_:
+        table = (set(Base._TABLE_.keys()) | Base._OPTIONS_)
+        if key not in table:
             key = key.replace("_", "-")
-            if key not in Base._TABLE_:
+            if key not in table:
                 raise KeyError("unsupported option: {0}".format(key))
         return setattr(self, key, value)
 
index fc9951ab74b252df7e10aa6782e1b94908112f8a..8a9faeb080737677a5f67088e6e50a42e68124ca 100644 (file)
@@ -13,7 +13,6 @@ import re as _re_
 
 from .error import type_assert as _type_assert_
 from .error import UnknownModuleError as _UnknownModuleError_
-from .config import Option as _ConfigOption_
 
 
 
@@ -450,7 +449,7 @@ class File(Base):
 
 
 
-def transitive_closure(lookup, modules, options):
+def transitive_closure(lookup, modules, **options):
     """
     Perform a transitive closure, generating a set of module dependencies.
     Each iteration over the table yields a tuple of (module, demander, condition).
@@ -462,27 +461,29 @@ def transitive_closure(lookup, modules, options):
     modules is an iterable, yielding a module (either name or instance).
     options may be any combination of gnulib configuration options.
     """
+    keywords = frozenset({
+        "tests",
+        "obsolete",
+        "cxx_tests",
+        "longrunning_tests",
+        "privileged_tests",
+        "unportable_tests",
+    })
     if not callable(lookup):
         raise TypeError("lookup must be a callable")
-    _type_assert_("options", options, int)
-    if options & ~_ConfigOption_.All:
-        raise ValueError("unknown configuration options")
-
-    obsolete = bool(options & _ConfigOption_.Obsolete)
-    tests = bool(options & _ConfigOption_.Tests)
-    cxx_tests = bool(options & _ConfigOption_.CXX)
-    longrunning_tests = bool(options & _ConfigOption_.Longrunning)
-    privileged_tests = bool(options & _ConfigOption_.Privileged)
-    unportable_tests = bool(options & _ConfigOption_.Unportable)
+    for (key, value) in options.items():
+        if key not in keywords:
+            return KeyError(key)
+        _type_assert_("option", value, bool)
     modules = set(lookup(module) for module in modules)
 
     def _exclude_(module):
         return any((
-            (not obsolete and module.obsolete),
-            (not cxx_tests and module.cxx_test),
-            (not longrunning_tests and module.longrunning_test),
-            (not privileged_tests and module.privileged_test),
-            (not unportable_tests and module.unportable_test),
+            (not options.get("obsolete", False) and module.obsolete),
+            (not options.get("cxx_tests", False) and module.cxx_test),
+            (not options.get("longrunning_tests", False) and module.longrunning_test),
+            (not options.get("privileged_tests", False) and module.privileged_test),
+            (not options.get("unportable_tests", False) and module.unportable_test),
         ))
 
     def _transitive_closure_(tests):
@@ -513,9 +514,9 @@ def transitive_closure(lookup, modules, options):
 
     base = _transitive_closure_(False)
     full = _transitive_closure_(True)
-    ignore = {"main"} if tests else {"main", "all"}
     main = {module for (module, _, _) in base}
-    final = {module for (module, _, _) in full} if tests else set(main)
+    final = {module for (module, _, _) in full} if options.get("tests", False) else set(main)
+    ignore = frozenset({"main"} if options.get("tests", False) else {"main", "all"})
     tests = (final - {module for module in main if module.applicability in ignore})
     return (base, full, main, final, tests)