On 4/10/24 7:17 AM, Bruno Haible wrote:
> Pretty good. The only thing that's missing is the type check for 
> module_filter.
> Is it
>   module_filter is function                            Nope!
>   module_filter is Callable                            Nope!
>   module_filter is callable                            Nope!

Yes, I tried to add it but was confused since:

>>> print(type(lambda x: True).__name__)
function

But 'is function' does not work.

> The previous knowledge summarization engine told me how to write it:
>   callable(module_filter)

Ah, it was correct this time. I guess that makes sense because you can
create classes with the '__call__' method. Then use objects in a
similar way to functions.

> What I considered is write 3 constants:
>   ALL_MODULES_FILTER = lambda module: True
>   NON_TESTS_MODULES_FILTER = lambda module: module.isNonTests()
>   TESTS_MODULES_FILTER = lambda module: module.isTests()
> but that's probably not worth it either.

Yeah, now that I think about it the lambda's are fine. That way we
don't have to deal with importing those across multiple files.

> This is a problem with gcc's warnings as well. Such tools don't make
> the distinction between a function that is only meant to be called
> directly and a function which needs to adhere to a certain signature.

True. Sometimes I forget about those and use -Wall + -Wextra and get
greeted with the unused variable/function spam.

I attached the patch with the callable(module_filter) check.

Collin
From ff1164711c1397f0f76f6919b395ff132312864f Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Wed, 10 Apr 2024 08:24:58 -0700
Subject: [PATCH] gnulib-tool.py: Use function arguments instead of magic
 numbers.

* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippets): Remove the
'verifier' integer flag argument. Add the 'module_filter' function
argument. Use it to determine if Autoconf snippets should be printed for
each module.
* pygnulib/GLImport.py (GLImport.gnulib_comp): Update call to use a
lambda function.
* pygnulib/GLTestDir.py (GLTestDir.execute): Likewise.
---
 ChangeLog             | 11 ++++++++
 pygnulib/GLEmiter.py  | 65 +++++++++----------------------------------
 pygnulib/GLImport.py  |  4 +--
 pygnulib/GLTestDir.py | 21 ++++++++------
 4 files changed, 38 insertions(+), 63 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 7de60dfead..f8fcd38de7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2024-04-10  Collin Funk  <collin.fu...@gmail.com>
+
+	gnulib-tool.py: Use function arguments instead of magic numbers.
+	* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippets): Remove the
+	'verifier' integer flag argument. Add the 'module_filter' function
+	argument. Use it to determine if Autoconf snippets should be printed for
+	each module.
+	* pygnulib/GLImport.py (GLImport.gnulib_comp): Update call to use a
+	lambda function.
+	* pygnulib/GLTestDir.py (GLTestDir.execute): Likewise.
+
 2024-04-10  Collin Funk  <collin.fu...@gmail.com>
 
 	gnulib-tool: Fix a typo.
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index e6143645be..6d82657e7c 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -22,6 +22,7 @@ import os
 import re
 import codecs
 import subprocess as sp
+from collections.abc import Callable
 from . import constants
 from .GLInfo import GLInfo
 from .GLConfig import GLConfig
@@ -257,7 +258,7 @@ class GLEmiter:
         return emit
 
     def autoconfSnippets(self, modules: list[GLModule], referenceable_modules: list[GLModule],
-                         moduletable: GLModuleTable, verifier: int, toplevel: bool,
+                         moduletable: GLModuleTable, module_filter: Callable[[GLModule], bool], toplevel: bool,
                          disable_libtool: bool, disable_gettext: bool, replace_auxdir: bool) -> str:
         '''Collect and emit the autoconf snippets of a set of modules.
         GLConfig: conddeps.
@@ -271,10 +272,8 @@ class GLEmiter:
           dependencies.
         moduletable is a GLModuleTable instance, which contains necessary
           information about dependencies of the modules.
-        verifier is an integer, which can be 0, 1 or 2.
-          if verifier == 0, then process every module;
-          if verifier == 1, then process only non-tests modules;
-          if verifier == 2, then process only tests modules.
+        module_filter is a function that accepts a GLModule and returns a bool describing
+          whether or not Autoconf snippets should be emitted for it.
         toplevel is a bool variable, False means a subordinate use of pygnulib.
         disable_libtool is a bool variable; it tells whether to disable libtool
           handling even if it has been specified through the GLConfig class.
@@ -291,11 +290,9 @@ class GLEmiter:
         if type(moduletable) is not GLModuleTable:
             raise TypeError('moduletable must be a GLModuleTable, not %s'
                             % type(moduletable).__name__)
-        if type(verifier) is not int:
-            raise TypeError('verifier must be an int, not %s'
-                            % type(verifier).__name__)
-        if not (0 <= verifier <= 2):
-            raise ValueError('verifier must be 0, 1 or 2, not %d' % verifier)
+        if not callable(module_filter):
+            raise TypeError('module_filter must be a function, not %s'
+                            % type(module_filter).__name__)
         if type(toplevel) is not bool:
             raise TypeError('toplevel must be a bool, not %s'
                             % type(toplevel).__name__)
@@ -314,37 +311,19 @@ class GLEmiter:
         if not conddeps:
             # Ignore the conditions, and enable all modules unconditionally.
             for module in modules:
-                if verifier == 0:
-                    solution = True
-                elif verifier == 1:
-                    solution = module.isNonTests()
-                elif verifier == 2:
-                    solution = module.isTests()
-                if solution:
+                if module_filter(module):
                     emit += self.autoconfSnippet(module, toplevel,
                                                  disable_libtool, disable_gettext, replace_auxdir, '  ')
         else:  # if conddeps
             # Emit the autoconf code for the unconditional modules.
             for module in modules:
-                if verifier == 0:
-                    solution = True
-                elif verifier == 1:
-                    solution = module.isNonTests()
-                elif verifier == 2:
-                    solution = module.isTests()
-                if solution:
+                if module_filter(module):
                     if not moduletable.isConditional(module):
                         emit += self.autoconfSnippet(module, toplevel,
                                                      disable_libtool, disable_gettext, replace_auxdir, '  ')
             # Initialize the shell variables indicating that the modules are enabled.
             for module in modules:
-                if verifier == 0:
-                    solution = True
-                elif verifier == 1:
-                    solution = module.isNonTests()
-                elif verifier == 2:
-                    solution = module.isTests()
-                if solution:
+                if module_filter(module):
                     if moduletable.isConditional(module):
                         shellvar = module.getShellVar()
                         emit += '  %s=false\n' % module.getShellVar()
@@ -352,13 +331,7 @@ class GLEmiter:
             # function. This makes it possible to support cycles among conditional
             # modules.
             for module in modules:
-                if verifier == 0:
-                    solution = True
-                elif verifier == 1:
-                    solution = module.isNonTests()
-                elif verifier == 2:
-                    solution = module.isTests()
-                if solution:
+                if module_filter(module):
                     if moduletable.isConditional(module):
                         shellfunc = module.getShellFunc()
                         shellvar = module.getShellVar()
@@ -390,13 +363,7 @@ class GLEmiter:
                         emit += '  }\n'
             # Emit the dependencies from the unconditional to the conditional modules.
             for module in modules:
-                if verifier == 0:
-                    solution = True
-                elif verifier == 1:
-                    solution = module.isNonTests()
-                elif verifier == 2:
-                    solution = module.isTests()
-                if solution:
+                if module_filter(module):
                     if not moduletable.isConditional(module):
                         depmodules = module.getDependenciesWithoutConditions()
                         # Intersect dependencies with the modules list.
@@ -419,13 +386,7 @@ class GLEmiter:
             # Define the Automake conditionals.
             emit += '  m4_pattern_allow([^%s_GNULIB_ENABLED_])\n' % macro_prefix
             for module in modules:
-                if verifier == 0:
-                    solution = True
-                elif verifier == 1:
-                    solution = module.isNonTests()
-                elif verifier == 2:
-                    solution = module.isTests()
-                if solution:
+                if module_filter(module):
                     if moduletable.isConditional(module):
                         condname = module.getConditionalName()
                         shellvar = module.getShellVar()
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index 4a6f7c48b8..66d8eb922c 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -678,7 +678,7 @@ AC_DEFUN([%s_INIT],
             emit += '  m4_pushdef([gl_MODULE_INDICATOR_CONDITION], [%s])\n' % witness_c_macro
         # Emit main autoconf snippets.
         emit += self.emitter.autoconfSnippets(moduletable.getMainModules(), moduletable.getMainModules(),
-                                              moduletable, 0, True, False, True, replace_auxdir)
+                                              moduletable, lambda module: True, True, False, True, replace_auxdir)
         if witness_c_macro:
             emit += '  m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n'
         emit += '  # End of code from modules\n'
@@ -702,7 +702,7 @@ AC_DEFUN([%s_INIT],
         # Emit tests autoconf snippets.
         emit += self.emitter.autoconfSnippets(moduletable.getTestsModules(),
                                               moduletable.getMainModules() + moduletable.getTestsModules(),
-                                              moduletable, 0, True, True, True, replace_auxdir)
+                                              moduletable, lambda module: True, True, True, True, replace_auxdir)
         emit += '  m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n'
         emit += self.emitter.initmacro_end('%stests' % macro_prefix, gentests)
         emit += '  AC_REQUIRE([gl_CC_GNULIB_WARNINGS])\n'
diff --git a/pygnulib/GLTestDir.py b/pygnulib/GLTestDir.py
index e8c8f63faf..f6ab4f9d2e 100644
--- a/pygnulib/GLTestDir.py
+++ b/pygnulib/GLTestDir.py
@@ -497,13 +497,13 @@ class GLTestDir:
                 # autoconf snippets. It's cleanest to put those of the library before
                 # those of the tests.
                 emit += self.emitter.shellvars_init(True, f'../{sourcebase}')
-                emit += self.emitter.autoconfSnippets(modules, modules,
-                                                      moduletable, 1, False, False, False,
-                                                      replace_auxdir)
+                emit += self.emitter.autoconfSnippets(modules, modules, moduletable,
+                                                      lambda module: module.isNonTests(),
+                                                      False, False, False, replace_auxdir)
                 emit += self.emitter.shellvars_init(True, '.')
-                emit += self.emitter.autoconfSnippets(modules, modules,
-                                                      moduletable, 2, False, False, False,
-                                                      replace_auxdir)
+                emit += self.emitter.autoconfSnippets(modules, modules, moduletable,
+                                                      lambda module: module.isTests(),
+                                                      False, False, False, replace_auxdir)
                 emit += self.emitter.initmacro_end(macro_prefix, True)
                 # _LIBDEPS and _LTLIBDEPS variables are not needed if this library is
                 # created using libtool, because libtool already handles the
@@ -613,10 +613,12 @@ class GLTestDir:
         emit += self.emitter.shellvars_init(False, sourcebase)
         if single_configure:
             emit += self.emitter.autoconfSnippets(main_modules, main_modules, moduletable,
-                                                  0, True, False, False, replace_auxdir)
+                                                  lambda module: True,
+                                                  True, False, False, replace_auxdir)
         else:  # if not single_configure
             emit += self.emitter.autoconfSnippets(modules, modules, moduletable,
-                                                  1, True, False, False, replace_auxdir)
+                                                  lambda module: module.isNonTests(),
+                                                  True, False, False, replace_auxdir)
         emit += self.emitter.initmacro_end(macro_prefix, False)
         if single_configure:
             emit += '  gltests_libdeps=\n'
@@ -630,7 +632,8 @@ class GLTestDir:
             emit += '  m4_pushdef([gl_MODULE_INDICATOR_CONDITION], '
             emit += '[$gl_module_indicator_condition])\n'
             snippets = self.emitter.autoconfSnippets(tests_modules, main_modules + tests_modules,
-                                                     moduletable, 0, True, False, False, replace_auxdir)
+                                                     moduletable, lambda module: True,
+                                                     True, False, False, replace_auxdir)
             emit += snippets
             emit += '  m4_popdef([gl_MODULE_INDICATOR_CONDITION])\n'
             emit += self.emitter.initmacro_end('%stests' % macro_prefix, True)
-- 
2.44.0

Reply via email to