Hi Bruno,

On 4/9/24 12:04 PM, Bruno Haible wrote:
> A better fix would be revisit this 'verifier'. Either an enum with 3 possible
> values, or (better) a function  GLModule -> bool. And call it 'moduleFilter'
> rather than 'verifier'.

How does this patch look?

This method seems much clearer to me than passing 0, 1, or 2 which
have no meaning unless you have previously read the docstring.

I've type hinted it and double checked that it works with Python 3.7
and Python 3.12 on my machine. The type hinting looks something like
this [1]:

    from collections.abc import Callable

    def autoconfSnippets(self, ..., module_filter: Callable[[GLModule], bool]) 
-> str:

Meaning that 'module_filter' is a function that accepts a GLModule
object and returns a bool.

This removes a lot of repetitive lines which is nice. The conditionals
can be refactored to remove a level of nesting in a few places. I
didn't do that now since it would make the patch harder to follow.

I've just used lambda functions since these functions are just
wrappers around GLModule methods. I'm not sure if it is better to
define them in GLModuleSystem.py or something. Since you are the
lisp expert, I will trust your judgment here.

Also, now I see an annoying warning:

      lambda module: True  # warning under 'module'

because pyright thinks it is unused [2]. I tried omitting the 'module'
in hopes that Python would just deal with it. But it gives this:

Traceback (most recent call last):
[...]
  File "/home/collin/.local/src/gnulib/pygnulib/GLEmiter.py", line 311, in 
autoconfSnippets
    if module_filter(module):
       ^^^^^^^^^^^^^^^^^^^^^
TypeError: GLImport.gnulib_comp.<locals>.<lambda>() takes 0 positional 
arguments but 1 was given

Maybe I will use fixing that as an excuse to add to the HACKING file.
I meant to add information there earlier but got lazy...

[1] https://docs.python.org/3/library/typing.html#annotating-callable-objects
[2] https://github.com/microsoft/pyright

Collin
From 45a750586980579c44c14e5d95ac4434f2d61313 Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Wed, 10 Apr 2024 05:05:52 -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  | 62 +++++++------------------------------------
 pygnulib/GLImport.py  |  4 +--
 pygnulib/GLTestDir.py | 21 ++++++++-------
 4 files changed, 35 insertions(+), 63 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 033eb5dc92..f6aaab6b05 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-09  Collin Funk  <collin.fu...@gmail.com>
 
 	gnulib-tool.py: Change the avoid list to a set for lookups.
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index e6143645be..247e791e6b 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,6 @@ 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 type(toplevel) is not bool:
             raise TypeError('toplevel must be a bool, not %s'
                             % type(toplevel).__name__)
@@ -314,37 +308,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 +328,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 +360,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 +383,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