]> Savannah Git Hosting - gnulib.git/commitdiff
module: transform transitive closure back into function
authorDmitry Selyutin <ghostmansd@gmail.com>
Tue, 26 Sep 2017 19:36:56 +0000 (22:36 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Tue, 26 Sep 2017 19:36:56 +0000 (22:36 +0300)
pygnulib.py
pygnulib/module.py

index 27235d82e9200dc807421d81da87069791677af5..677fd1e9b963c3342c569b8943aa259e67ab9488 100755 (executable)
@@ -13,7 +13,7 @@ from pygnulib.error import CommandLineError
 from pygnulib.error import UnknownModuleError
 from pygnulib.config import Base as BaseConfig
 from pygnulib.config import Cache as CacheConfig
-from pygnulib.module import Table as ModuleTable
+from pygnulib.module import transitive_closure
 from pygnulib.parser import CommandLine as CommandLineParser
 from pygnulib.filesystem import GnulibGit as GnulibGitFS
 
@@ -44,28 +44,28 @@ def extract_hook(program, gnulib, mode, namespace, *args, **kwargs):
 def import_hook(gnulib, namespace, verbosity, options, *args, **kwargs):
     (_, _) = (args, kwargs)
     config = BaseConfig(**namespace)
-    table = ModuleTable(gnulib.module, config.modules, config.options)
+    values = transitive_closure(gnulib.module, config.modules, config.options)
+    (base, full, main, final, tests) = transitive_closure(gnulib.module, config.modules, config.options)
 
+    # Print some information about modules.
     print("Module list with included dependencies (indented):", file=sys.stdout)
     BOLD_ON = BOLD_OFF = ""
     mode = os.fstat(sys.stdout.fileno()).st_mode
     if not (stat.S_ISFIFO(mode) or stat.S_ISREG(mode)):
         BOLD_ON = "\033[1m"
         BOLD_OFF = "\033[0m"
-    for module in sorted(table.final):
+    for module in sorted(final):
         manual = module.name in config.modules
         prefix = "  " if manual else "    "
         bold_on = BOLD_ON if manual else ""
         bold_off = BOLD_OFF if manual else ""
         print("{0}{1}{2}{3}".format(prefix, bold_on, module.name, bold_off), file=sys.stdout)
-
     if verbosity >= 1:
         print("Main module list:", file=sys.stdout)
-        for module in sorted(table.main):
+        for module in sorted(main):
             print("  {0}".format(module.name), file=sys.stdout)
-
         print("Tests-related module list:", file=sys.stdout)
-        for module in sorted(table.tests):
+        for module in sorted(tests):
             print("  {0}".format(module.name), file=sys.stdout)
 
     return os.EX_OK
index 780ba58d3bcf95caa17a32a1c02f86e6070d6ee1..1159ba30f49d395ec1a3b788a4a4944dc51fe3b4 100644 (file)
@@ -441,98 +441,69 @@ class File(Base):
 
 
 
-class Table:
-    """module transitive closure result"""
-    def __init__(self, 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).
-
-        If condition is None, but demander is not, there is no special condition for this module.
-        If demander is None, the module is provided unconditionally (condition is always None).
-
-        lookup must be a callable which obtains a pygnulib module by its name.
-        modules is an iterable, yielding a module (either name or instance).
-        options may be any combination of gnulib configuration options.
-        """
-        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)
-        modules = set(lookup(module) for module in modules)
-
-        def _transitive_closure_(tests):
-            queue = set()
-            previous = set()
-            current = set()
-            for module in modules:
-                current.add((module, None, None))
-            while previous != current:
-                previous.update(current)
-                for (demander, _, _) in previous:
-                    if demander in queue:
-                        continue
-                    if tests and not demander.name.endswith("-tests"):
-                        try:
-                            name = "{0}-tests".format(demander.name)
-                            current.add((lookup(name), None, None))
-                        except _UnknownModuleError_:
-                            pass # ignore non-existent tests
-                    for (dependency, condition) in demander.dependencies:
-                        module = lookup(dependency)
-                        exclude = (
-                            (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),
-                        )
-                        if not any(exclude):
-                            condition = condition if condition.strip() else None
-                            current.add((module, demander, condition))
-                    queue.add(demander)
-            return current
-
-        self.__with_tests = tests
-        self.__base = _transitive_closure_(False)
-        self.__full = _transitive_closure_(True)
-
-
-    def __iter__(self):
-        return iter(self.__full)
-
-
-    @property
-    def main(self):
-        """an iterator over main module set"""
-        return iter(set(module for (module, _, _) in self.__base))
-
-
-    @property
-    def tests(self):
-        """an iterator over tests-related module set"""
-        final = self.final
-        if not self.__with_tests:
-            final = (module for module in final if module.applicability != "all")
-        main = (module for module in self.main if module.applicability != "all")
-        return iter(set(final) ^ set(main))
-
-
-    @property
-    def final(self):
-        """an iterator over final module set"""
-        return self.all if self.__with_tests else self.main
-
-
-    @property
-    def all(self):
-        """an iterator over all modules"""
-        return iter(set(module for (module, _, _) in self.__full))
+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).
+
+    If condition is None, but demander is not, there is no special condition for this module.
+    If demander is None, the module is provided unconditionally (condition is always None).
+
+    lookup must be a callable which obtains a pygnulib module by its name.
+    modules is an iterable, yielding a module (either name or instance).
+    options may be any combination of gnulib configuration options.
+    """
+    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)
+    modules = set(lookup(module) for module in modules)
+
+    def _transitive_closure_(tests):
+        queue = set()
+        previous = set()
+        current = set()
+        for module in modules:
+            current.add((module, None, None))
+        while previous != current:
+            previous.update(current)
+            for (demander, _, _) in previous:
+                if demander in queue:
+                    continue
+                if tests and not demander.name.endswith("-tests"):
+                    try:
+                        name = "{0}-tests".format(demander.name)
+                        current.add((lookup(name), None, None))
+                    except _UnknownModuleError_:
+                        pass # ignore non-existent tests
+                for (dependency, condition) in demander.dependencies:
+                    module = lookup(dependency)
+                    exclude = (
+                        (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),
+                    )
+                    if not any(exclude):
+                        condition = condition if condition.strip() else None
+                        current.add((module, demander, condition))
+                queue.add(demander)
+        return current
+
+    base = _transitive_closure_(False)
+    full = _transitive_closure_(True)
+    main = set(module for (module, _, _) in base)
+    final = set(module for (module, _, _) in full) if tests else set(main)
+    tests_final = set(module for module in final if not tests or module.applicability != "all")
+    tests_main = set(module for module in main if module.applicability != "all")
+    tests = (tests_final ^ tests_main)
+    return (base, full, main, final, tests)