Hi Bruno,

On 4/22/24 7:33 AM, Bruno Haible wrote:
> OK, patch welcome. I assume that when Dmitry used this style of assignments,
> the Python 2.7 / 3.0 imports were not so well developed as they are today.

Here is a patch that removes all the module-specific variables and
imports the functions directly. I haven't pushed it just incase you
want to make any style changes or something.

I ran all the tests quickly with Python 3.7 and 3.12 just to double
check that I didn't break anything in the process. PyCharm has good
warnings for missing or unused imports so I used that too.

Collin
From 96b746aca8cd77c121ffd4b4343e1b37aec1f745 Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Mon, 22 Apr 2024 17:57:52 -0700
Subject: [PATCH] gnulib-tool.py: Make better use of imports.

* pygnulib/*.py: Import functions from constants.py directly instead of
assigning them to module-specific variable. Keep the module prefix for
standard library functions.
---
 ChangeLog                   |   7 ++
 pygnulib/GLConfig.py        |  23 ++---
 pygnulib/GLEmiter.py        |  32 +++----
 pygnulib/GLError.py         |   6 --
 pygnulib/GLFileSystem.py    |  55 +++++-------
 pygnulib/GLImport.py        | 125 +++++++++++++-------------
 pygnulib/GLInfo.py          |  14 +--
 pygnulib/GLMakefileTable.py |  13 +--
 pygnulib/GLModuleSystem.py  |  36 ++++----
 pygnulib/GLTestDir.py       | 144 +++++++++++++++---------------
 pygnulib/main.py            | 170 ++++++++++++++++++------------------
 11 files changed, 290 insertions(+), 335 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 462823888d..8fda2cdbba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2024-04-22  Collin Funk  <collin.fu...@gmail.com>
+
+	gnulib-tool.py: Make better use of imports.
+	* pygnulib/*.py: Import functions from constants.py directly instead of
+	assigning them to module-specific variable. Keep the module prefix for
+	standard library functions.
+
 2024-04-22  Bruno Haible  <br...@clisp.org>
 
 	gnulib-tool: Fix trouble caused by Python's bytecode cache.
diff --git a/pygnulib/GLConfig.py b/pygnulib/GLConfig.py
index 05947e8ed3..16fa490fc6 100644
--- a/pygnulib/GLConfig.py
+++ b/pygnulib/GLConfig.py
@@ -22,23 +22,16 @@
 import copy
 import tempfile
 from typing import Any
-from . import constants
+from .constants import (
+    MODES,
+    TESTS,
+    joinpath,
+    remove_trailing_slashes,
+)
 from .GLError import GLError
 from pygnulib.enums import CopyAction
 
 
-#===============================================================================
-# Define global constants
-#===============================================================================
-MODES = constants.MODES
-TESTS = constants.TESTS
-joinpath = constants.joinpath
-relpath = constants.relativize
-remove_trailing_slashes = constants.remove_trailing_slashes
-isfile = os.path.isfile
-normpath = os.path.normpath
-
-
 #===============================================================================
 # Define GLConfig class
 #===============================================================================
@@ -1053,9 +1046,9 @@ def setAutoconfFile(self, configure_ac: str) -> None:
     def resetAutoconfFile(self) -> None:
         '''Reset path of autoconf file relative to destdir.'''
         configure_ac = ''
-        if isfile(joinpath(self.table['destdir'], 'configure.ac')):
+        if os.path.isfile(joinpath(self.table['destdir'], 'configure.ac')):
             configure_ac = joinpath(self.table['destdir'], 'configure.ac')
-        elif isfile(joinpath(self.table['destdir'], 'configure.in')):
+        elif os.path.isfile(joinpath(self.table['destdir'], 'configure.in')):
             configure_ac = joinpath(self.table['destdir'], 'configure.in')
         self.table['configure_ac'] = configure_ac
 
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index 91077a0325..ed6eae4997 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -22,7 +22,14 @@
 import re
 import subprocess as sp
 from collections.abc import Callable
-from . import constants
+from .constants import (
+    UTILS,
+    joinpath,
+    lines_to_multiline,
+    combine_lines_matching,
+    substart,
+    relinverse,
+)
 from .GLInfo import GLInfo
 from .GLConfig import GLConfig
 from .GLModuleSystem import GLModule
@@ -30,17 +37,6 @@
 from .GLMakefileTable import GLMakefileTable
 
 
-#===============================================================================
-# Define global constants
-#===============================================================================
-UTILS = constants.UTILS
-TESTS = constants.TESTS
-joinpath = constants.joinpath
-relinverse = constants.relinverse
-lines_to_multiline = constants.lines_to_multiline
-isfile = os.path.isfile
-normpath = os.path.normpath
-
 # Regular expressions used to convert Automake conditionals to GNU Make syntax.
 # Each tuple is the arguments given to re.sub in the correct order.
 _CONVERT_TO_GNU_MAKE = [
@@ -474,7 +470,7 @@ def po_POTFILES_in(self, files: list[str]) -> str:
         emit += '# List of files which contain translatable strings.\n'
         for file in files:
             if file.startswith('lib/'):
-                emit += '%s\n' % constants.substart('lib/', sourcebase, file)
+                emit += '%s\n' % substart('lib/', sourcebase, file)
         return emit
 
     def initmacro_start(self, macro_prefix_arg: str, gentests: bool) -> str:
@@ -753,8 +749,8 @@ def lib_Makefile_am(self, destfile: str, modules: list[GLModule], moduletable: G
                 if str(module) == 'alloca':
                     amsnippet1 += '%s_%s_LIBADD += @%sALLOCA@\n' % (libname, libext, perhapsLT)
                     amsnippet1 += '%s_%s_DEPENDENCIES += @%sALLOCA@\n' % (libname, libext, perhapsLT)
-                amsnippet1 = constants.combine_lines_matching(re.compile(r'%s_%s_SOURCES' % (libname, libext)),
-                                                              amsnippet1)
+                amsnippet1 = combine_lines_matching(re.compile(r'%s_%s_SOURCES' % (libname, libext)),
+                                                    amsnippet1)
 
                 # Get unconditional snippet, edit it and save to amsnippet2.
                 amsnippet2 = module.getAutomakeSnippet_Unconditional()
@@ -884,7 +880,7 @@ def lib_Makefile_am(self, destfile: str, modules: list[GLModule], moduletable: G
             # Then test if $sourcebase/Makefile.am (if it exists) specifies it.
             if makefile_name:
                 path = joinpath(sourcebase, 'Makefile.am')
-                if isfile(path):
+                if os.path.isfile(path):
                     with open(path, mode='r', newline='\n', encoding='utf-8') as file:
                         data = file.read()
                     if pattern.findall(data):
@@ -1049,8 +1045,8 @@ def tests_Makefile_am(self, destfile: str, modules: list[GLModule], moduletable:
                     amsnippet1 += 'libtests_a_LIBADD += @ALLOCA@\n'
                     amsnippet1 += 'libtests_a_DEPENDENCIES += @ALLOCA@\n'
 
-                amsnippet1 = constants.combine_lines_matching(re.compile(r'libtests_a_SOURCES'),
-                                                              amsnippet1)
+                amsnippet1 = combine_lines_matching(re.compile(r'libtests_a_SOURCES'),
+                                                    amsnippet1)
 
                 # Get unconditional snippet, edit it and save to amsnippet2.
                 amsnippet2 = module.getAutomakeSnippet_Unconditional()
diff --git a/pygnulib/GLError.py b/pygnulib/GLError.py
index 47d1e97fdc..184d65f59c 100644
--- a/pygnulib/GLError.py
+++ b/pygnulib/GLError.py
@@ -19,12 +19,6 @@
 # Define global imports
 #===============================================================================
 import os
-from . import constants
-
-
-#===============================================================================
-# Define global constants
-#===============================================================================
 
 
 #===============================================================================
diff --git a/pygnulib/GLFileSystem.py b/pygnulib/GLFileSystem.py
index 1cad7f5bad..028ba3885e 100644
--- a/pygnulib/GLFileSystem.py
+++ b/pygnulib/GLFileSystem.py
@@ -22,28 +22,21 @@
 import re
 import filecmp
 import subprocess as sp
-from . import constants
+from .constants import (
+    DIRS,
+    ensure_writable,
+    hardlink,
+    joinpath,
+    link_if_changed,
+    movefile,
+    copyfile,
+    substart,
+)
 from pygnulib.enums import CopyAction
 from .GLError import GLError
 from .GLConfig import GLConfig
 
 
-#===============================================================================
-# Define global constants
-#===============================================================================
-DIRS = constants.DIRS
-substart = constants.substart
-joinpath = constants.joinpath
-copyfile = constants.copyfile
-movefile = constants.movefile
-hardlink = constants.hardlink
-ensure_writable = constants.ensure_writable
-link_if_changed = constants.link_if_changed
-isdir = os.path.isdir
-isfile = os.path.isfile
-islink = os.path.islink
-
-
 #===============================================================================
 # Define GLFileSystem class
 #===============================================================================
@@ -84,17 +77,17 @@ def lookup(self, name: str) -> tuple[str, bool]:
         lookedupPatches = []
         for localdir in localpath:
             file_in_localdir = joinpath(localdir, name)
-            if isfile(file_in_localdir):
+            if os.path.isfile(file_in_localdir):
                 lookedupFile = file_in_localdir
                 break
             diff_in_localdir = joinpath(localdir, '%s.diff' % name)
-            if isfile(diff_in_localdir):
+            if os.path.isfile(diff_in_localdir):
                 lookedupPatches.append(diff_in_localdir)
         # Treat the gnulib dir like a lowest-priority --local-dir, except that
         # here we don't look for .diff files.
         if lookedupFile == None:
             file_in_localdir = joinpath(DIRS['root'], name)
-            if isfile(file_in_localdir):
+            if os.path.isfile(file_in_localdir):
                 lookedupFile = file_in_localdir
         if lookedupFile != None:
             if len(lookedupPatches) > 0:
@@ -104,7 +97,7 @@ def lookup(self, name: str) -> tuple[str, bool]:
                     os.makedirs(os.path.dirname(tempFile))
                 except OSError:
                     pass  # Skip errors if directory exists
-                if isfile(tempFile):
+                if os.path.isfile(tempFile):
                     os.remove(tempFile)
                 copyfile(lookedupFile, tempFile)
                 ensure_writable(tempFile)
@@ -191,7 +184,7 @@ def tmpfilename(self, path: str) -> str:
             # to guarantee that an 'mv' to "$destdir/$file" works).
             result = joinpath(self.config['destdir'], '%s.tmp' % path)
             dirname = os.path.dirname(result)
-            if dirname and not isdir(dirname):
+            if dirname and not os.path.isdir(dirname):
                 os.makedirs(dirname)
         else:  # if self.config['dryrun']
             # Put the new contents of $file in a file in a temporary directory
@@ -199,7 +192,7 @@ def tmpfilename(self, path: str) -> str:
             tempdir = self.config['tempdir']
             result = joinpath(tempdir, '%s.tmp' % os.path.basename(path))
             dirname = os.path.dirname(result)
-            if not isdir(dirname):
+            if not os.path.isdir(dirname):
                 os.makedirs(dirname)
         return result
 
@@ -284,7 +277,7 @@ def update(self, lookedup: str, tmpflag: bool, tmpfile: str, already_present: bo
                     message += '%s (non-gnulib code backed up in ' % basename
                     message += '%s) !!' % backupname
                     print(message)
-                if isfile(backuppath):
+                if os.path.isfile(backuppath):
                     os.remove(backuppath)
                 try:  # Try to replace the given file
                     movefile(basepath, backuppath)
@@ -354,16 +347,16 @@ def add_or_update(self, already_present: bool) -> None:
                 with open(tmpfile, mode='w', newline='\n', encoding='utf-8') as file:
                     file.write(re.sub(transformer[0], transformer[1], src_data))
         path = joinpath(self.config['destdir'], rewritten)
-        if isfile(path):
+        if os.path.isfile(path):
             # The file already exists.
             self.update(lookedup, tmpflag, tmpfile, already_present)
-        else:  # if not isfile(path)
+        else:  # if not os.path.isfile(path)
             # Install the file.
             # Don't protest if the file should be there but isn't: it happens
             # frequently that developers don't put autogenerated files under version control.
             self.add(lookedup, tmpflag, tmpfile)
             self.addFile(rewritten)
-        if isfile(tmpfile):
+        if os.path.isfile(tmpfile):
             os.remove(tmpfile)
 
     def super_update(self, basename: str, tmpfile: str) -> tuple[str, str, int]:
@@ -375,22 +368,22 @@ def super_update(self, basename: str, tmpfile: str) -> tuple[str, str, int]:
         backupname = '%s~' % basename
         basepath = joinpath(self.config['destdir'], basename)
         backuppath = joinpath(self.config['destdir'], backupname)
-        if isfile(basepath):
+        if os.path.isfile(basepath):
             if filecmp.cmp(basepath, tmpfile):
                 result_flag = 0
             else:  # if not filecmp.cmp(basepath, tmpfile)
                 result_flag = 1
                 if not self.config['dryrun']:
-                    if isfile(backuppath):
+                    if os.path.isfile(backuppath):
                         os.remove(backuppath)
                     movefile(basepath, backuppath)
                     movefile(tmpfile, basepath)
                 else:  # if self.config['dryrun']
                     os.remove(tmpfile)
-        else:  # if not isfile(basepath)
+        else:  # if not os.path.isfile(basepath)
             result_flag = 2
             if not self.config['dryrun']:
-                if isfile(basepath):
+                if os.path.isfile(basepath):
                     os.remove(basepath)
                 movefile(tmpfile, basepath)
             else:  # if self.config['dryrun']
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index cc7648890d..0bab7ca150 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -21,7 +21,23 @@
 import os
 import re
 import subprocess as sp
-from . import constants
+from .constants import (
+    DIRS,
+    MODES,
+    TESTS,
+    cleaner,
+    joinpath,
+    lines_to_multiline,
+    movefile,
+    copyfile,
+    copyfile2,
+    substart,
+    subend,
+    bold_escapes,
+    relconcat,
+    relativize,
+    rmtree,
+)
 from .GLError import GLError
 from .GLConfig import GLConfig
 from .GLModuleSystem import GLModuleTable
@@ -32,25 +48,6 @@
 from .GLEmiter import GLEmiter
 
 
-#===============================================================================
-# Define global constants
-#===============================================================================
-APP = constants.APP
-DIRS = constants.DIRS
-MODES = constants.MODES
-TESTS = constants.TESTS
-joinpath = constants.joinpath
-cleaner = constants.cleaner
-copyfile = constants.copyfile
-copyfile2 = constants.copyfile2
-movefile = constants.movefile
-lines_to_multiline = constants.lines_to_multiline
-isabs = os.path.isabs
-isdir = os.path.isdir
-isfile = os.path.isfile
-normpath = os.path.normpath
-
-
 #===============================================================================
 # Define GLImport class
 #===============================================================================
@@ -117,7 +114,7 @@ def __init__(self, config: GLConfig, mode: int) -> None:
 
         # Get other cached variables.
         path = joinpath(self.config['m4base'], 'gnulib-cache.m4')
-        if isfile(path):
+        if os.path.isfile(path):
             with open(path, mode='r', newline='\n', encoding='utf-8') as file:
                 data = file.read()
 
@@ -211,7 +208,7 @@ def __init__(self, config: GLConfig, mode: int) -> None:
             # Get cached filelist from gnulib-comp.m4.
             destdir, m4base = self.config.getDestDir(), self.config.getM4Base()
             path = joinpath(destdir, m4base, 'gnulib-comp.m4')
-            if isfile(path):
+            if os.path.isfile(path):
                 with open(path, mode='r', newline='\n', encoding='utf-8') as file:
                     data = file.read()
                 regex = r'AC_DEFUN\(\[%s_FILE_LIST\], \[(.*?)\]\)' % self.cache['macro_prefix']
@@ -279,7 +276,7 @@ def __init__(self, config: GLConfig, mode: int) -> None:
                     base = self.config['destdir']
                 else:
                     base = '.'
-                if isfile(joinpath(base, 'Makefile.am')):
+                if os.path.isfile(joinpath(base, 'Makefile.am')):
                     with open(joinpath(base, 'Makefile.am'), mode='r', newline='\n', encoding='utf-8') as file:
                         data = file.read()
                     pattern = re.compile(r'^AUTOMAKE_OPTIONS[\t ]*=(.*)$', re.MULTILINE)
@@ -325,19 +322,19 @@ def rewrite_old_files(self, files: list[str]) -> list[str]:
         result = []
         for file in files:
             if file.startswith('build-aux/'):
-                path = constants.substart('build-aux/', '%s/' % auxdir, file)
+                path = substart('build-aux/', '%s/' % auxdir, file)
             elif file.startswith('doc/'):
-                path = constants.substart('doc/', '%s/' % docbase, file)
+                path = substart('doc/', '%s/' % docbase, file)
             elif file.startswith('lib/'):
-                path = constants.substart('lib/', '%s/' % sourcebase, file)
+                path = substart('lib/', '%s/' % sourcebase, file)
             elif file.startswith('m4/'):
-                path = constants.substart('m4/', '%s/' % m4base, file)
+                path = substart('m4/', '%s/' % m4base, file)
             elif file.startswith('tests/'):
-                path = constants.substart('tests/', '%s/' % testsbase, file)
+                path = substart('tests/', '%s/' % testsbase, file)
             elif file.startswith('tests=lib/'):
-                path = constants.substart('tests=lib/', '%s/' % testsbase, file)
+                path = substart('tests=lib/', '%s/' % testsbase, file)
             elif file.startswith('top/'):
-                path = constants.substart('top/', '', file)
+                path = substart('top/', '', file)
             else:  # file is not a special file
                 path = file
             result.append(os.path.normpath(path))
@@ -361,19 +358,19 @@ def rewrite_new_files(self, files: list[str]) -> list[str]:
         result = []
         for file in files:
             if file.startswith('build-aux/'):
-                path = constants.substart('build-aux/', '%s/' % auxdir, file)
+                path = substart('build-aux/', '%s/' % auxdir, file)
             elif file.startswith('doc/'):
-                path = constants.substart('doc/', '%s/' % docbase, file)
+                path = substart('doc/', '%s/' % docbase, file)
             elif file.startswith('lib/'):
-                path = constants.substart('lib/', '%s/' % sourcebase, file)
+                path = substart('lib/', '%s/' % sourcebase, file)
             elif file.startswith('m4/'):
-                path = constants.substart('m4/', '%s/' % m4base, file)
+                path = substart('m4/', '%s/' % m4base, file)
             elif file.startswith('tests/'):
-                path = constants.substart('tests/', '%s/' % testsbase, file)
+                path = substart('tests/', '%s/' % testsbase, file)
             elif file.startswith('tests=lib/'):
-                path = constants.substart('tests=lib/', '%s/' % testsbase, file)
+                path = substart('tests=lib/', '%s/' % testsbase, file)
             elif file.startswith('top/'):
-                path = constants.substart('top/', '', file)
+                path = substart('top/', '', file)
             else:  # file is not a special file
                 path = file
             result.append(os.path.normpath(path))
@@ -487,7 +484,7 @@ def relative_to_destdir(self, dir: str) -> str:
                 # XXX This doesn't look right.
                 return dir
             else:
-                return constants.relativize(destdir, dir)
+                return relativize(destdir, dir)
 
     def relative_to_currdir(self, dir: str) -> str:
         '''The opposite of GLImport.relative_to_destdir:
@@ -502,7 +499,7 @@ def relative_to_currdir(self, dir: str) -> str:
                 # XXX This doesn't look right.
                 return joinpath(destdir, dir)
             else:
-                return constants.relconcat(destdir, dir)
+                return relconcat(destdir, dir)
 
     def gnulib_cache(self) -> str:
         '''Emit the contents of generated $m4base/gnulib-cache.m4 file.
@@ -737,14 +734,14 @@ def _done_dir_(self, directory: str, files_added: list[str], files_removed: list
         '''This method is used to determine ignore argument for _update_ignorelist_
         method and then call it.'''
         destdir = self.config['destdir']
-        if (isdir(joinpath(destdir, 'CVS'))
-                or isdir(joinpath(destdir, directory, 'CVS'))
-                or isfile(joinpath(destdir, directory, '.cvsignore'))):
+        if (os.path.isdir(joinpath(destdir, 'CVS'))
+                or os.path.isdir(joinpath(destdir, directory, 'CVS'))
+                or os.path.isfile(joinpath(destdir, directory, '.cvsignore'))):
             self._update_ignorelist_(directory, '.cvsignore',
                                      files_added, files_removed)
-        if (isdir(joinpath(destdir, '.git'))
-                or isfile(joinpath(destdir, '.gitignore'))
-                or isfile(joinpath(destdir, directory, '.gitignore'))):
+        if (os.path.isdir(joinpath(destdir, '.git'))
+                or os.path.isfile(joinpath(destdir, '.gitignore'))
+                or os.path.isfile(joinpath(destdir, directory, '.gitignore'))):
             self._update_ignorelist_(directory, '.gitignore',
                                      files_added, files_removed)
 
@@ -760,14 +757,14 @@ def _update_ignorelist_(self, directory: str, ignore: str, files_added: list[str
             anchor = ''
         srcpath = joinpath(directory, ignore)
         backupname = '%s~' % srcpath
-        if isfile(joinpath(destdir, srcpath)):
+        if os.path.isfile(joinpath(destdir, srcpath)):
             if files_added or files_removed:
                 with open(joinpath(destdir, srcpath), mode='r', newline='\n', encoding='utf-8') as file:
                     original_lines = file.readlines()
                 # Clean the newlines but not trailing whitespace.
                 original_lines = [ line.rstrip('\n')
                                    for line in original_lines ]
-                already_listed_filenames = { constants.substart(anchor, '', filename)
+                already_listed_filenames = { substart(anchor, '', filename)
                                              for filename in original_lines
                                              if filename.strip() }
                 filenames_to_add = set(files_added).difference(already_listed_filenames)
@@ -790,7 +787,7 @@ def _update_ignorelist_(self, directory: str, ignore: str, files_added: list[str
                             file.write(lines_to_multiline(new_lines))
                     else:  # if self.config['dryrun']
                         print('Update %s (backup in %s)' % (srcpath, backupname))
-        else:  # if not isfile(joinpath(destdir, srcpath))
+        else:  # if not os.path.isfile(joinpath(destdir, srcpath))
             if files_added:
                 if not self.config['dryrun']:
                     print('Creating %s' % srcpath)
@@ -825,7 +822,7 @@ def prepare(self) -> tuple[dict[str, list[str]], dict[str, tuple[re.Pattern, str
 
         # Show final module list.
         if verbose >= 0:
-            (bold_on, bold_off) = constants.bold_escapes()
+            (bold_on, bold_off) = bold_escapes()
             print('Module list with included dependencies (indented):')
             for module in final_modules:
                 if str(module) in self.config.getModules():
@@ -939,7 +936,7 @@ def prepare(self) -> tuple[dict[str, list[str]], dict[str, tuple[re.Pattern, str
         new_files = filelist + ['m4/gnulib-tool.m4']
         old_files = list(self.cache['files'])
         path = joinpath(destdir, m4base, 'gnulib-tool.m4')
-        if isfile(path):
+        if os.path.isfile(path):
             old_files.append(joinpath('m4', 'gnulib-tool.m4'))
         # old_files is the list of files according to the last gnulib-tool invocation.
         # new_files is the list of files after this gnulib-tool invocation.
@@ -1027,7 +1024,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
         dirs = [ os.path.join(destdir, d)
                  for d in dirs ]
         for directory in dirs:
-            if not isdir(directory):
+            if not os.path.isdir(directory):
                 print('Creating directory %s' % directory)
                 if not self.config['dryrun']:
                     try:  # Try to create directory
@@ -1056,7 +1053,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
         files = sorted(set(pair[0] for pair in pairs))
         for file in files:
             path = joinpath(destdir, file)
-            if isfile(path) or os.path.islink(path):
+            if os.path.isfile(path) or os.path.islink(path):
                 if not self.config['dryrun']:
                     backup = '%s~' % path
                     print('Removing file %s (backup in %s)' % (path, backup))
@@ -1157,7 +1154,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
                     else:  # if self.config['dryrun']:
                         print('Create %s' % filename)
                     filetable['added'].append(filename)
-                if isfile(tmpfile):
+                if os.path.isfile(tmpfile):
                     os.remove(tmpfile)
 
             # Create po makefile parameterization, part 1.
@@ -1178,7 +1175,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
                 else:  # if self.config['dryrun']:
                     print('Create %s' % filename)
                 filetable['added'].append(filename)
-            if isfile(tmpfile):
+            if os.path.isfile(tmpfile):
                 os.remove(tmpfile)
 
             # Create po makefile parameterization, part 2.
@@ -1199,7 +1196,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
                 else:  # if self.config['dryrun']:
                     print('Create %s' % filename)
                 filetable['added'].append(filename)
-            if isfile(tmpfile):
+            if os.path.isfile(tmpfile):
                 os.remove(tmpfile)
 
             # Fetch PO files.
@@ -1217,7 +1214,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
             if not self.config['dryrun']:
                 tmpfile = assistant.tmpfilename(basename)
                 data = '# Set of available languages.\n'
-                files = sorted([ constants.subend('.po', '', file)
+                files = sorted([ subend('.po', '', file)
                                  for file in os.listdir(joinpath(destdir, pobase))
                                  if file.endswith('.po') ])
                 data += lines_to_multiline(files)
@@ -1229,13 +1226,13 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
                 elif flag == 2:
                     print('Creating %s' % filename)
                     filetable['added'].append(filename)
-                if isfile(tmpfile):
+                if os.path.isfile(tmpfile):
                     os.remove(tmpfile)
             else:  # if not self.config['dryrun']
                 backupname = '%s~' % basename
-                if isfile(joinpath(destdir, basename)):
+                if os.path.isfile(joinpath(destdir, basename)):
                     print('Update %s (backup in %s)' % (basename, backupname))
-                else:  # if not isfile(joinpath(destdir, basename))
+                else:  # if not os.path.isfile(joinpath(destdir, basename))
                     print('Create %s' % basename)
 
         # Create m4/gnulib-cache.m4.
@@ -1260,7 +1257,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
                 elif emit[-1:] == '\n':
                     emit = emit[:-1]
                 print(emit)
-        if isfile(tmpfile):
+        if os.path.isfile(tmpfile):
             os.remove(tmpfile)
 
         # Create m4/gnulib-comp.m4.
@@ -1285,7 +1282,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
                 elif emit[-1:] == '\n':
                     emit = emit[:-1]
                 print(emit)
-        if isfile(tmpfile):
+        if os.path.isfile(tmpfile):
             os.remove(tmpfile)
 
         # Create library makefile.
@@ -1314,7 +1311,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
             else:  # if self.config['dryrun']:
                 print('Create %s' % filename)
             filetable['added'].append(filename)
-        if isfile(tmpfile):
+        if os.path.isfile(tmpfile):
             os.remove(tmpfile)
 
         # Create tests Makefile.
@@ -1338,7 +1335,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
                 else:  # if self.config['dryrun']:
                     print('Create %s' % filename)
                 filetable['added'].append(filename)
-            if isfile(tmpfile):
+            if os.path.isfile(tmpfile):
                 os.remove(tmpfile)
 
         if vc_files != False:
@@ -1468,4 +1465,4 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, tuple
             position_early_after = 'AC_PROG_CC'
         print('  - invoke %s_EARLY in %s, right after %s,' % (macro_prefix, configure_ac, position_early_after))
         print('  - invoke %s_INIT in %s.' % (macro_prefix, configure_ac))
-        constants.rmtree(self.config['tempdir'])
+        rmtree(self.config['tempdir'])
diff --git a/pygnulib/GLInfo.py b/pygnulib/GLInfo.py
index 37d8560af0..eac4c65071 100644
--- a/pygnulib/GLInfo.py
+++ b/pygnulib/GLInfo.py
@@ -22,15 +22,7 @@
 import re
 import subprocess as sp
 from pygnulib import __author__, __copyright__
-from . import constants
-
-
-#===============================================================================
-# Define global constants
-#===============================================================================
-DIRS = constants.DIRS
-joinpath = constants.joinpath
-isdir = os.path.isdir
+from .constants import DIRS, joinpath
 
 
 #===============================================================================
@@ -81,7 +73,7 @@ def copyright(self) -> str:
 
     def date(self) -> str:
         '''Return formatted string which contains date and time in GMT format.'''
-        if isdir(DIRS['git']):
+        if os.path.isdir(DIRS['git']):
             try:
                 sp.check_call(['git', '--version'], stdout=sp.DEVNULL)
                 have_git = True
@@ -322,7 +314,7 @@ def usage(self) -> str:
 
     def version(self) -> str:
         '''Return formatted string which contains git version.'''
-        if isdir(DIRS['git']):
+        if os.path.isdir(DIRS['git']):
             try:
                 sp.check_call(['git', '--version'], stdout=sp.DEVNULL)
                 have_git = True
diff --git a/pygnulib/GLMakefileTable.py b/pygnulib/GLMakefileTable.py
index a38276c665..16e22f914f 100644
--- a/pygnulib/GLMakefileTable.py
+++ b/pygnulib/GLMakefileTable.py
@@ -19,18 +19,9 @@
 # Define global imports
 #===============================================================================
 import os
-from . import constants
+from .constants import joinpath
 from .GLConfig import GLConfig
 
-
-#===============================================================================
-# Define global constants
-#===============================================================================
-TESTS = constants.TESTS
-isfile = os.path.isfile
-joinpath = constants.joinpath
-
-
 #===============================================================================
 # Define GLMakefileTable class
 #===============================================================================
@@ -97,7 +88,7 @@ def parent(self, gentests: bool, source_makefile_am: str, tests_makefile_am: str
         dir1 = '%s%s' % (m4base, os.path.sep)
         dir2 = ''
         while (dir1
-               and not (isfile(joinpath(self.config['destdir'], dir1, 'Makefile.am'))
+               and not (os.path.isfile(joinpath(self.config['destdir'], dir1, 'Makefile.am'))
                         or joinpath(dir1, 'Makefile.am') == joinpath(sourcebase, source_makefile_am)
                         or (gentests and joinpath(dir1, 'Makefile.am') == joinpath(testsbase, tests_makefile_am)))):
             dir2 = joinpath(os.path.basename(dir1), dir2)
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index c28f2ddd73..ba1c57eb3f 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -24,27 +24,21 @@
 import hashlib
 import subprocess as sp
 from collections import defaultdict
-from . import constants
+from .constants import (
+    DIRS,
+    ENCS,
+    TESTS,
+    combine_lines,
+    filter_filelist,
+    joinpath,
+    lines_to_multiline,
+    subend,
+)
 from .GLError import GLError
 from .GLConfig import GLConfig
 from .GLFileSystem import GLFileSystem
 
 
-#===============================================================================
-# Define global constants
-#===============================================================================
-DIRS = constants.DIRS
-ENCS = constants.ENCS
-TESTS = constants.TESTS
-joinpath = constants.joinpath
-subend = constants.subend
-lines_to_multiline = constants.lines_to_multiline
-combine_lines = constants.combine_lines
-isdir = os.path.isdir
-isfile = os.path.isfile
-filter_filelist = constants.filter_filelist
-
-
 #===============================================================================
 # Define GLModuleSystem class
 #===============================================================================
@@ -78,11 +72,11 @@ def exists(self, module: str) -> bool:
         badnames = ['ChangeLog', 'COPYING', 'README', 'TEMPLATE',
                     'TEMPLATE-EXTENDED', 'TEMPLATE-TESTS']
         if module not in badnames:
-            result = isfile(joinpath(DIRS['modules'], module))
+            result = os.path.isfile(joinpath(DIRS['modules'], module))
             if not result:
                 for localdir in localpath:
-                    if (isdir(joinpath(localdir, 'modules'))
-                            and isfile(joinpath(localdir, 'modules', module))):
+                    if (os.path.isdir(joinpath(localdir, 'modules'))
+                            and os.path.isfile(joinpath(localdir, 'modules', module))):
                         result = True
                         break
         return result
@@ -128,7 +122,7 @@ def list(self) -> list[str]:
         find_args = ['find', 'modules', '-type', 'f', '-print']
 
         # Read modules from gnulib root directory.
-        result += sp.run(find_args, cwd=constants.DIRS['root'], text=True, capture_output=True, check=False).stdout
+        result += sp.run(find_args, cwd=DIRS['root'], text=True, capture_output=True, check=False).stdout
 
         # Read modules from local directories.
         if len(localpath) > 0:
@@ -589,7 +583,7 @@ def getAutomakeSnippet_Unconditional(self) -> str:
             else:  # if not tests module
                 # Synthesize an EXTRA_DIST augmentation.
                 snippet = self.getAutomakeSnippet_Conditional()
-                snippet = constants.combine_lines(snippet)
+                snippet = combine_lines(snippet)
                 pattern = re.compile(r'^lib_SOURCES[\t ]*\+=[\t ]*(.*)$', re.MULTILINE)
                 mentioned_files = set(pattern.findall(snippet))
                 if mentioned_files:
diff --git a/pygnulib/GLTestDir.py b/pygnulib/GLTestDir.py
index 9673a5bd26..b48cf98c35 100644
--- a/pygnulib/GLTestDir.py
+++ b/pygnulib/GLTestDir.py
@@ -23,7 +23,25 @@
 import sys
 import subprocess as sp
 from pathlib import Path
-from . import constants
+from .constants import (
+    DIRS,
+    TESTS,
+    UTILS,
+    combine_lines,
+    execute,
+    ensure_writable,
+    force_output,
+    hardlink,
+    joinpath,
+    link_relative,
+    lines_to_multiline,
+    movefile,
+    copyfile,
+    substart,
+    bold_escapes,
+    relinverse,
+    rmtree,
+)
 from .enums import CopyAction
 from .GLError import GLError
 from .GLConfig import GLConfig
@@ -35,24 +53,6 @@
 from .GLEmiter import GLEmiter
 
 
-#===============================================================================
-# Define global constants
-#===============================================================================
-DIRS = constants.DIRS
-UTILS = constants.UTILS
-TESTS = constants.TESTS
-joinpath = constants.joinpath
-relinverse = constants.relinverse
-copyfile = constants.copyfile
-ensure_writable = constants.ensure_writable
-movefile = constants.movefile
-lines_to_multiline = constants.lines_to_multiline
-combine_lines = constants.combine_lines
-isdir = os.path.isdir
-isfile = os.path.isfile
-normpath = os.path.normpath
-
-
 def _patch_test_driver() -> None:
     '''Patch the test-driver script in testdirs.'''
     test_driver = joinpath('build-aux', 'test-driver')
@@ -66,17 +66,17 @@ def _patch_test_driver() -> None:
         try:
             result = sp.call(command, shell=True, stdout=sp.DEVNULL, stderr=sp.DEVNULL)
         except OSError as exc:
-            if isfile(f'{test_driver}.orig'):
+            if os.path.isfile(f'{test_driver}.orig'):
                 os.remove(f'{test_driver}.orig')
-            if isfile(f'{test_driver}.rej'):
+            if os.path.isfile(f'{test_driver}.rej'):
                 os.remove(f'{test_driver}.rej')
             raise GLError(20, None) from exc
         if result == 0:
             patched = True
             break
-        if isfile(f'{test_driver}.orig'):
+        if os.path.isfile(f'{test_driver}.orig'):
             os.remove(f'{test_driver}.orig')
-        if isfile(f'{test_driver}.rej'):
+        if os.path.isfile(f'{test_driver}.rej'):
             os.remove(f'{test_driver}.rej')
     if not patched:
         raise GLError(20, None)
@@ -139,19 +139,19 @@ def rewrite_files(self, files: list[str]) -> list[str]:
         result = []
         for file in files:
             if file.startswith('build-aux/'):
-                path = constants.substart('build-aux/', '%s/' % auxdir, file)
+                path = substart('build-aux/', '%s/' % auxdir, file)
             elif file.startswith('doc/'):
-                path = constants.substart('doc/', '%s/' % docbase, file)
+                path = substart('doc/', '%s/' % docbase, file)
             elif file.startswith('lib/'):
-                path = constants.substart('lib/', '%s/' % sourcebase, file)
+                path = substart('lib/', '%s/' % sourcebase, file)
             elif file.startswith('m4/'):
-                path = constants.substart('m4/', '%s/' % m4base, file)
+                path = substart('m4/', '%s/' % m4base, file)
             elif file.startswith('tests/'):
-                path = constants.substart('tests/', '%s/' % testsbase, file)
+                path = substart('tests/', '%s/' % testsbase, file)
             elif file.startswith('tests=lib/'):
-                path = constants.substart('tests=lib/', '%s/' % testsbase, file)
+                path = substart('tests=lib/', '%s/' % testsbase, file)
             elif file.startswith('top/'):
-                path = constants.substart('top/', '', file)
+                path = substart('top/', '', file)
             else:  # file is not a special file
                 path = file
             result.append(os.path.normpath(path))
@@ -247,7 +247,7 @@ def execute(self) -> None:
 
         # Show final module list.
         if verbose >= 0:
-            (bold_on, bold_off) = constants.bold_escapes()
+            (bold_on, bold_off) = bold_escapes()
             print('Module list with included dependencies (indented):')
             specified_modules_set = { str(module)
                                       for module in specified_modules }
@@ -344,7 +344,7 @@ def execute(self) -> None:
                         for file in self.rewrite_files(filelist) ]
         directories = sorted(set(directories))
         for directory in directories:
-            if not isdir(directory):
+            if not os.path.isdir(directory):
                 os.makedirs(directory)
 
         # Copy files or make symbolic links or hard links.
@@ -357,18 +357,18 @@ def execute(self) -> None:
             dest = row[0]
             destpath = joinpath(self.testdir, dest)
             if src.startswith('tests=lib/'):
-                src = constants.substart('tests=lib/', 'lib/', src)
+                src = substart('tests=lib/', 'lib/', src)
             lookedup, flag = self.filesystem.lookup(src)
-            if isfile(destpath):
+            if os.path.isfile(destpath):
                 os.remove(destpath)
             if flag:
                 copyfile(lookedup, destpath)
                 ensure_writable(destpath)
             else:  # if not flag
                 if self.filesystem.shouldLink(src, lookedup) == CopyAction.Symlink:
-                    constants.link_relative(lookedup, destpath)
+                    link_relative(lookedup, destpath)
                 elif self.filesystem.shouldLink(src, lookedup) == CopyAction.Hardlink:
-                    constants.hardlink(lookedup, destpath)
+                    hardlink(lookedup, destpath)
                 else:
                     copyfile(lookedup, destpath)
                     ensure_writable(destpath)
@@ -376,7 +376,7 @@ def execute(self) -> None:
         # Create $sourcebase/Makefile.am.
         for_test = True
         directory = joinpath(self.testdir, sourcebase)
-        if not isdir(directory):
+        if not os.path.isdir(directory):
             os.mkdir(directory)
         destfile = joinpath(directory, 'Makefile.am')
         if single_configure:
@@ -390,14 +390,14 @@ def execute(self) -> None:
 
         # Create $m4base/Makefile.am.
         directory = joinpath(self.testdir, m4base)
-        if not isdir(directory):
+        if not os.path.isdir(directory):
             os.mkdir(directory)
         destfile = joinpath(directory, 'Makefile.am')
         emit = '## Process this file with automake to produce Makefile.in.\n\n'
         emit += 'EXTRA_DIST =\n'
         for file in filelist:
             if file.startswith('m4/'):
-                file = constants.substart('m4/', '', file)
+                file = substart('m4/', '', file)
                 emit += 'EXTRA_DIST += %s\n' % file
         with open(destfile, mode='w', newline='\n', encoding='utf-8') as file:
             file.write(emit)
@@ -408,7 +408,7 @@ def execute(self) -> None:
         inctests = self.config.checkInclTestCategory(TESTS['tests'])
         if inctests:
             directory = joinpath(self.testdir, testsbase)
-            if not isdir(directory):
+            if not os.path.isdir(directory):
                 os.mkdir(directory)
             if single_configure:
                 # Create $testsbase/Makefile.am.
@@ -664,77 +664,77 @@ def execute(self) -> None:
         # Create autogenerated files.
         # Do not use "${AUTORECONF} --force --install", because it may invoke
         # autopoint, which brings in older versions of some of our .m4 files.
-        constants.force_output()
+        force_output()
         os.chdir(self.testdir)
         # gettext
-        if isfile(joinpath(m4base, 'gettext.m4')):
+        if os.path.isfile(joinpath(m4base, 'gettext.m4')):
             args = [UTILS['autopoint'], '--force']
-            constants.execute(args, verbose)
+            execute(args, verbose)
             for src in os.listdir(m4base):
                 src = joinpath(m4base, src)
                 if src.endswith('.m4~'):
                     dest = src[:-1]
-                    if isfile(dest):
+                    if os.path.isfile(dest):
                         os.remove(dest)
                     movefile(src, dest)
         # libtoolize
         if libtool:
             args = [UTILS['libtoolize'], '--copy']
-            constants.execute(args, verbose)
+            execute(args, verbose)
         # aclocal
         args = [UTILS['aclocal'], '-I', m4base]
-        constants.execute(args, verbose)
-        if not isdir('build-aux'):
+        execute(args, verbose)
+        if not os.path.isdir('build-aux'):
             print('executing mkdir build-aux')
             os.mkdir('build-aux')
         # autoconf
         args = [UTILS['autoconf']]
-        constants.execute(args, verbose)
+        execute(args, verbose)
         # autoheader
         args = [UTILS['autoheader']]
-        constants.execute(args, verbose)
+        execute(args, verbose)
         # Explicit 'touch config.h.in': see <https://savannah.gnu.org/support/index.php?109406>.
         print('executing touch config.h.in')
         Path('config.h.in').touch()
         # automake
         args = [UTILS['automake'], '--add-missing', '--copy']
-        constants.execute(args, verbose)
-        constants.rmtree('autom4te.cache')
+        execute(args, verbose)
+        rmtree('autom4te.cache')
         os.chdir(DIRS['cwd'])
         if inctests and not single_configure:
             # Do not use "${AUTORECONF} --force --install", because it may invoke
             # autopoint, which brings in older versions of some of our .m4 files.
             os.chdir(joinpath(self.testdir, testsbase))
             # gettext
-            if isfile(joinpath(m4base, 'gettext.m4')):
+            if os.path.isfile(joinpath(m4base, 'gettext.m4')):
                 args = [UTILS['autopoint'], '--force']
-                constants.execute(args, verbose)
+                execute(args, verbose)
                 for src in os.listdir(m4base):
                     src = joinpath(m4base, src)
                     if src.endswith('.m4~'):
                         dest = src[:-1]
-                        if isfile(dest):
+                        if os.path.isfile(dest):
                             os.remove(dest)
                         movefile(src, dest)
             # aclocal
             args = [UTILS['aclocal'], '-I', joinpath('..', m4base)]
-            constants.execute(args, verbose)
-            if not isdir(joinpath('../build-aux')):
+            execute(args, verbose)
+            if not os.path.isdir(joinpath('../build-aux')):
                 print('executing mkdir ../build-aux')
                 os.mkdir('../build-aux')
             # autoconf
             args = [UTILS['autoconf']]
-            constants.execute(args, verbose)
+            execute(args, verbose)
             # autoheader
             args = [UTILS['autoheader']]
-            constants.execute(args, verbose)
+            execute(args, verbose)
             # Explicit 'touch config.h.in': see <https://savannah.gnu.org/support/index.php?109406>.
             print('executing touch config.h.in')
             Path('config.h.in').touch()
             # automake
             args = [UTILS['automake'], '--add-missing', '--copy']
-            constants.execute(args, verbose)
-            constants.rmtree('autom4te.cache')
+            execute(args, verbose)
+            rmtree('autom4te.cache')
             os.chdir(DIRS['cwd'])
 
         # Need to run configure and make once, to create built files that are to be
@@ -828,7 +828,7 @@ def execute(self) -> None:
 
         os.chdir(self.testdir)
         if distributed_built_sources or tests_distributed_built_sources:
-            constants.force_output()
+            force_output()
             sp.call('./configure')
             if distributed_built_sources:
                 os.chdir(sourcebase)
@@ -866,10 +866,10 @@ def execute(self) -> None:
                     'LIBTOOLIZE=%s' % UTILS['libtoolize'],
                     'distclean']
             sp.call(args)
-        if isfile(joinpath('build-aux', 'test-driver')):
+        if os.path.isfile(joinpath('build-aux', 'test-driver')):
             _patch_test_driver()
         os.chdir(DIRS['cwd'])
-        constants.rmtree(self.config['tempdir'])
+        rmtree(self.config['tempdir'])
 
 
 #===============================================================================
@@ -947,7 +947,7 @@ def execute(self) -> None:
         repdict['Nov'] = repdict['November'] = '11'
         repdict['Dec'] = repdict['December'] = '12'
         vc_witness = joinpath(DIRS['root'], '.git', 'refs', 'heads', 'master')
-        if not isfile(vc_witness):
+        if not os.path.isfile(vc_witness):
             vc_witness = joinpath(DIRS['root'], 'ChangeLog')
         mdate_sh = joinpath(DIRS['root'], 'build-aux', 'mdate-sh')
         args = ['sh', mdate_sh, vc_witness]
@@ -1009,22 +1009,22 @@ def execute(self) -> None:
             file.write(emit)
 
         # Create autogenerated files.
-        constants.force_output()
+        force_output()
         os.chdir(self.megatestdir)
         args = [UTILS['aclocal']]
-        constants.execute(args, verbose)
+        execute(args, verbose)
         try:  # Try to make a directory
-            if not isdir('build-aux'):
+            if not os.path.isdir('build-aux'):
                 print('executing mkdir build-aux')
                 os.mkdir('build-aux')
         except Exception:
             pass
         args = [UTILS['autoconf']]
-        constants.execute(args, verbose)
+        execute(args, verbose)
         args = [UTILS['automake'], '--add-missing', '--copy']
-        constants.execute(args, verbose)
-        constants.rmtree('autom4te.cache')
-        if isfile(joinpath('build-aux', 'test-driver')):
+        execute(args, verbose)
+        rmtree('autom4te.cache')
+        if os.path.isfile(joinpath('build-aux', 'test-driver')):
             _patch_test_driver()
         os.chdir(DIRS['cwd'])
-        constants.rmtree(self.config['tempdir'])
+        rmtree(self.config['tempdir'])
diff --git a/pygnulib/main.py b/pygnulib/main.py
index a333994525..ea781f5a97 100644
--- a/pygnulib/main.py
+++ b/pygnulib/main.py
@@ -85,7 +85,23 @@
 import subprocess as sp
 import shlex
 from tempfile import mktemp
-from pygnulib import constants
+from pygnulib.constants import (
+    APP,
+    DIRS,
+    TESTS,
+    UTILS,
+    MODES,
+    ENCS,
+    joinpath,
+    lines_to_multiline,
+    ensure_writable,
+    copyfile,
+    substart,
+    force_output,
+    init_DIRS,
+    rmtree,
+    DEFAULT_AUTOCONF_MINVERSION,
+)
 from pygnulib.enums import CopyAction
 from pygnulib.GLConfig import GLConfig
 from pygnulib.GLError import GLError
@@ -98,31 +114,13 @@
 from pygnulib.GLTestDir import GLMegaTestDir
 
 
-#===============================================================================
-# Define global constants
-#===============================================================================
-APP = constants.APP
-DIRS = constants.DIRS
-ENCS = constants.ENCS
-UTILS = constants.UTILS
-MODES = constants.MODES
-TESTS = constants.TESTS
-joinpath = constants.joinpath
-copyfile = constants.copyfile
-ensure_writable = constants.ensure_writable
-lines_to_multiline = constants.lines_to_multiline
-isabs = os.path.isabs
-isdir = os.path.isdir
-isfile = os.path.isfile
-
-
 #===============================================================================
 # Define main part
 #===============================================================================
 def main() -> None:
     info = GLInfo()
     parser = argparse.ArgumentParser(
-        prog=constants.APP['name'],
+        prog=APP['name'],
         usage='gnulib-tool.py --help',
         add_help=False)
 
@@ -510,7 +508,7 @@ def main() -> None:
         gnulib_dir = os.path.abspath(gnulib_dir[0])
     else:
         gnulib_dir = APP['root']
-    constants.init_DIRS(gnulib_dir)
+    init_DIRS(gnulib_dir)
 
     # Handle --help and --version, ignoring all other options.
     if cmdargs.help != None:
@@ -529,7 +527,7 @@ def main() -> None:
     # Report unhandled arguments.
     for arg in unhandled:
         if arg.startswith('-'):
-            message = '%s: Unrecognized option \'%s\'.\n' % (constants.APP['name'], arg)
+            message = '%s: Unrecognized option \'%s\'.\n' % (APP['name'], arg)
             message += 'Try \'gnulib-tool --help\' for more information.\n'
             sys.stderr.write(message)
             sys.exit(1)
@@ -568,7 +566,7 @@ def main() -> None:
                  for arg in args
                  if arg != None ]
     if len(overflow) > 1:
-        message = '%s: Unable to combine different modes of work.\n' % constants.APP['name']
+        message = '%s: Unable to combine different modes of work.\n' % APP['name']
         message += 'Try \'gnulib-tool --help\' for more information.\n'
         sys.stderr.write(message)
         sys.exit(1)
@@ -663,10 +661,10 @@ def main() -> None:
     if cmdargs.mode_copy_file != None:
         mode = 'copy-file'
         if len(cmdargs.non_option_arguments) < 1 or len(cmdargs.non_option_arguments) > 2:
-            message = '%s: *** ' % constants.APP['name']
+            message = '%s: *** ' % APP['name']
             message += 'invalid number of arguments for --%s\n' % mode
             message += 'Try \'gnulib-tool --help\' for more information.\n'
-            message += '%s: *** Stop.\n' % constants.APP['name']
+            message += '%s: *** Stop.\n' % APP['name']
             sys.stderr.write(message)
             sys.exit(1)
         files = list(cmdargs.non_option_arguments)
@@ -697,24 +695,24 @@ def main() -> None:
                  or cmdargs.automake_subdir_tests != None
                  or cmdargs.macro_prefix != None or cmdargs.podomain != None
                  or cmdargs.witness_c_macro != None or cmdargs.vc_files != None))):
-        message = '%s: *** ' % constants.APP['name']
+        message = '%s: *** ' % APP['name']
         message += 'invalid options for --%s mode\n' % mode
         message += 'Try \'gnulib-tool --help\' for more information.\n'
-        message += '%s: *** Stop.\n' % constants.APP['name']
+        message += '%s: *** Stop.\n' % APP['name']
         sys.stderr.write(message)
         sys.exit(1)
     if cmdargs.pobase != None and cmdargs.podomain == None:
-        message = '%s: *** ' % constants.APP['name']
+        message = '%s: *** ' % APP['name']
         message += 'together with --po-base, you need to specify --po-domain\n'
         message += 'Try \'gnulib-tool --help\' for more information.\n'
-        message += '%s: *** Stop.\n' % constants.APP['name']
+        message += '%s: *** Stop.\n' % APP['name']
         sys.stderr.write(message)
         sys.exit(1)
     if cmdargs.pobase == None and cmdargs.podomain != None:
         message = 'gnulib-tool: warning: --po-domain has no effect without a --po-base option\n'
         sys.stderr.write(message)
     if mode != None and 'test' in mode and cmdargs.gnu_make:
-        message = '%s: --gnu-make not supported when including tests\n' % constants.APP['name']
+        message = '%s: --gnu-make not supported when including tests\n' % APP['name']
         sys.stderr.write(message)
         sys.exit(1)
 
@@ -760,26 +758,26 @@ def main() -> None:
             inctests = True
     incl_test_categories = []
     if inctests:
-        incl_test_categories.append(constants.TESTS['tests'])
+        incl_test_categories.append(TESTS['tests'])
     if cmdargs.inc_cxx_tests:
-        incl_test_categories.append(constants.TESTS['cxx-tests'])
+        incl_test_categories.append(TESTS['cxx-tests'])
     if cmdargs.inc_longrunning_tests:
-        incl_test_categories.append(constants.TESTS['longrunning-tests'])
+        incl_test_categories.append(TESTS['longrunning-tests'])
     if cmdargs.inc_privileged_tests:
-        incl_test_categories.append(constants.TESTS['privileged-tests'])
+        incl_test_categories.append(TESTS['privileged-tests'])
     if cmdargs.inc_unportable_tests:
-        incl_test_categories.append(constants.TESTS['unportable-tests'])
+        incl_test_categories.append(TESTS['unportable-tests'])
     if cmdargs.alltests:
-        incl_test_categories.append(constants.TESTS['all-tests'])
+        incl_test_categories.append(TESTS['all-tests'])
     excl_test_categories = []
     if cmdargs.excl_cxx_tests:
-        excl_test_categories.append(constants.TESTS['cxx-tests'])
+        excl_test_categories.append(TESTS['cxx-tests'])
     if cmdargs.excl_longrunning_tests:
-        excl_test_categories.append(constants.TESTS['longrunning-tests'])
+        excl_test_categories.append(TESTS['longrunning-tests'])
     if cmdargs.excl_privileged_tests:
-        excl_test_categories.append(constants.TESTS['privileged-tests'])
+        excl_test_categories.append(TESTS['privileged-tests'])
     if cmdargs.excl_unportable_tests:
-        excl_test_categories.append(constants.TESTS['unportable-tests'])
+        excl_test_categories.append(TESTS['unportable-tests'])
     lgpl = cmdargs.lgpl
     if lgpl != None:
         lgpl = lgpl[-1]
@@ -861,9 +859,9 @@ def main() -> None:
     elif mode == 'find':
         modulesystem = GLModuleSystem(config)
         for filename in files:
-            if (isfile(joinpath(DIRS['root'], filename))
+            if (os.path.isfile(joinpath(DIRS['root'], filename))
                     or (localpath != None
-                        and any([ isfile(joinpath(localdir, filename))
+                        and any([ os.path.isfile(joinpath(localdir, filename))
                                   for localdir in localpath ]))):
                 # Convert the file name to a POSIX basic regex.
                 # Needs to handle . [ \ * ^ $.
@@ -872,7 +870,7 @@ def main() -> None:
                 filename_line_regex = '^' + filename_regex + '$'
                 # Read module candidates from gnulib root directory.
                 command = "find modules -type f -print | xargs -n 100 grep -l %s /dev/null | sed -e 's,^modules/,,'" % shlex.quote(filename_line_regex)
-                with sp.Popen(command, shell=True, cwd=constants.DIRS['root'], stdout=sp.PIPE) as proc:
+                with sp.Popen(command, shell=True, cwd=DIRS['root'], stdout=sp.PIPE) as proc:
                     result = proc.stdout.read().decode('UTF-8')
                 # Read module candidates from local directories.
                 if localpath != None and len(localpath) > 0:
@@ -910,9 +908,9 @@ def main() -> None:
         # Prefer configure.ac but also look for configure.in.
         # NOTE: Use os.path.join so the leading './' is not removed. This
         # is to make the gnulib-tool test suite happy.
-        if isfile(os.path.join(destdir, 'configure.ac')):
+        if os.path.isfile(os.path.join(destdir, 'configure.ac')):
             configure_ac = os.path.join(destdir, 'configure.ac')
-        elif isfile(os.path.join(destdir, 'configure.in')):
+        elif os.path.isfile(os.path.join(destdir, 'configure.in')):
             configure_ac = os.path.join(destdir, 'configure.in')
         else:
             raise GLError(3, os.path.join(destdir, 'configure.ac'))
@@ -958,7 +956,7 @@ def main() -> None:
             if m4base:
                 # Apply func_import to a particular gnulib directory.
                 # Any number of additional modules can be given.
-                if not isfile(joinpath(destdir, m4base, 'gnulib-cache.m4')):
+                if not os.path.isfile(joinpath(destdir, m4base, 'gnulib-cache.m4')):
                     # First use of gnulib in the given m4base.
                     if not sourcebase:
                         sourcebase = 'lib'
@@ -986,7 +984,7 @@ def main() -> None:
                 m4dirs = []
                 dirisnext = False
                 filepath = joinpath(destdir, 'Makefile.am')
-                if isfile(filepath):
+                if os.path.isfile(filepath):
                     with open(filepath, mode='r', newline='\n', encoding='utf-8') as file:
                         data = file.read()
                     data = data.split('ACLOCAL_AMFLAGS')[1]
@@ -995,8 +993,8 @@ def main() -> None:
                     for aclocal_amflag in aclocal_amflags:
                         if dirisnext:
                             # Ignore absolute directory pathnames, like /usr/local/share/aclocal.
-                            if not isabs(aclocal_amflag):
-                                if isfile(joinpath(destdir, aclocal_amflag, 'gnulib-cache.m4')):
+                            if not os.path.isabs(aclocal_amflag):
+                                if os.path.isfile(joinpath(destdir, aclocal_amflag, 'gnulib-cache.m4')):
                                     m4dirs.append(aclocal_amflag)
                             dirisnext = False
                         else:  # if not dirisnext
@@ -1006,13 +1004,13 @@ def main() -> None:
                                 dirisnext = False
                     for arg in guessed_m4dirs:
                         # Ignore absolute directory pathnames, like /usr/local/share/aclocal.
-                        if not isabs(arg):
-                            if isfile(joinpath(destdir, arg, 'gnulib-cache.m4')):
+                        if not os.path.isabs(arg):
+                            if os.path.isfile(joinpath(destdir, arg, 'gnulib-cache.m4')):
                                 m4dirs.append(arg)
-                else:  # if not isfile(filepath)
+                else:  # if not os.path.isfile(filepath)
                     # No Makefile.am! Oh well. Look at the last generated aclocal.m4.
                     filepath = joinpath(destdir, 'aclocal.m4')
-                    if isfile(filepath):
+                    if os.path.isfile(filepath):
                         pattern = re.compile(r'm4_include\(\[(.*?)]\)')
                         with open(filepath, mode='r', newline='\n', encoding='utf-8') as file:
                             m4dirs = pattern.findall(file.read())
@@ -1020,7 +1018,7 @@ def main() -> None:
                                    for m4dir in m4dirs ]
                         m4dirs = [ m4dir
                                    for m4dir in m4dirs
-                                   if isfile(joinpath(destdir, m4dir, 'gnulib-cache.m4')) ]
+                                   if os.path.isfile(joinpath(destdir, m4dir, 'gnulib-cache.m4')) ]
                         m4dirs = sorted(set(m4dirs))
                 if len(m4dirs) == 0:
                     # First use of gnulib in a package.
@@ -1063,9 +1061,9 @@ def main() -> None:
 
     elif mode == 'create-testdir':
         if not destdir:
-            message = '%s: *** ' % constants.APP['name']
+            message = '%s: *** ' % APP['name']
             message += 'please specify --dir option\n'
-            message += '%s: *** Stop.\n' % constants.APP['name']
+            message += '%s: *** Stop.\n' % APP['name']
             sys.stderr.write(message)
             sys.exit(1)
         if not auxdir:
@@ -1076,9 +1074,9 @@ def main() -> None:
 
     elif mode == 'create-megatestdir':
         if not destdir:
-            message = '%s: *** ' % constants.APP['name']
+            message = '%s: *** ' % APP['name']
             message += 'please specify --dir option\n'
-            message += '%s: *** Stop.\n' % constants.APP['name']
+            message += '%s: *** Stop.\n' % APP['name']
             sys.stderr.write(message)
             sys.exit(1)
         if not auxdir:
@@ -1095,7 +1093,7 @@ def main() -> None:
         config.setAuxDir(auxdir)
         testdir = GLTestDir(config, destdir)
         testdir.execute()
-        constants.force_output()
+        force_output()
         os.chdir(destdir)
         os.mkdir('build')
         os.chdir('build')
@@ -1118,7 +1116,7 @@ def main() -> None:
             sys.stderr.write(message)
             sys.exit(1)
         os.chdir('../..')
-        constants.rmtree(destdir)
+        rmtree(destdir)
 
     elif mode == 'megatest':
         if not destdir:
@@ -1128,7 +1126,7 @@ def main() -> None:
         config.setAuxDir(auxdir)
         testdir = GLMegaTestDir(config, destdir)
         testdir.execute()
-        constants.force_output()
+        force_output()
         os.chdir(destdir)
         os.mkdir('build')
         os.chdir('build')
@@ -1148,7 +1146,7 @@ def main() -> None:
             sys.stderr.write(message)
             sys.exit(1)
         os.chdir('../..')
-        constants.rmtree(destdir)
+        rmtree(destdir)
 
     elif mode == 'extract-description':
         modulesystem = GLModuleSystem(config)
@@ -1198,9 +1196,9 @@ def main() -> None:
 
     elif mode == 'extract-dependencies':
         if avoids:
-            message = '%s: *** ' % constants.APP['name']
+            message = '%s: *** ' % APP['name']
             message += 'cannot combine --avoid and --extract-dependencies\n'
-            message += '%s: *** Stop.\n' % constants.APP['name']
+            message += '%s: *** Stop.\n' % APP['name']
             sys.stderr.write(message)
             sys.exit(1)
         modulesystem = GLModuleSystem(config)
@@ -1211,9 +1209,9 @@ def main() -> None:
 
     elif mode == 'extract-recursive-dependencies':
         if avoids:
-            message = '%s: *** ' % constants.APP['name']
+            message = '%s: *** ' % APP['name']
             message += 'cannot combine --avoid and --extract-recursive-dependencies\n'
-            message += '%s: *** Stop.\n' % constants.APP['name']
+            message += '%s: *** Stop.\n' % APP['name']
             sys.stderr.write(message)
             sys.exit(1)
         modulesystem = GLModuleSystem(config)
@@ -1252,9 +1250,9 @@ def main() -> None:
 
     elif mode == 'extract-recursive-link-directive':
         if avoids:
-            message = '%s: *** ' % constants.APP['name']
+            message = '%s: *** ' % APP['name']
             message += 'cannot combine --avoid and --extract-recursive-link-directive\n'
-            message += '%s: *** Stop.\n' % constants.APP['name']
+            message += '%s: *** Stop.\n' % APP['name']
             sys.stderr.write(message)
             sys.exit(1)
         modulesystem = GLModuleSystem(config)
@@ -1309,29 +1307,29 @@ def main() -> None:
         config.setTestsBase(testsbase)
         filesystem = GLFileSystem(config)
         lookedup, flag = filesystem.lookup(srcpath)
-        if isdir(dest):
+        if os.path.isdir(dest):
             destdir = dest
             if srcpath.startswith('build-aux/'):
-                destpath = constants.substart('build-aux/', '%s/' % auxdir, srcpath)
+                destpath = substart('build-aux/', '%s/' % auxdir, srcpath)
             elif srcpath.startswith('doc/'):
-                destpath = constants.substart('doc/', '%s/' % docbase, srcpath)
+                destpath = substart('doc/', '%s/' % docbase, srcpath)
             elif srcpath.startswith('lib/'):
-                destpath = constants.substart('lib/', '%s/' % sourcebase, srcpath)
+                destpath = substart('lib/', '%s/' % sourcebase, srcpath)
             elif srcpath.startswith('m4/'):
-                destpath = constants.substart('m4/', '%s/' % m4base, srcpath)
+                destpath = substart('m4/', '%s/' % m4base, srcpath)
             elif srcpath.startswith('tests/'):
-                destpath = constants.substart('tests/', '%s/' % testsbase, srcpath)
+                destpath = substart('tests/', '%s/' % testsbase, srcpath)
             elif srcpath.startswith('top/'):
-                destpath = constants.substart('top/', '', srcpath)
+                destpath = substart('top/', '', srcpath)
             else:  # either case
                 destpath = srcpath
-        else:  # if not isdir(dest)
+        else:  # if not os.path.isdir(dest)
             destdir = os.path.dirname(dest)
             destpath = os.path.basename(dest)
         # Create the directory for destfile.
         dirname = os.path.dirname(joinpath(destdir, destpath))
         if not config['dryrun']:
-            if dirname and not isdir(dirname):
+            if dirname and not os.path.isdir(dirname):
                 try:  # Try to create directories
                     os.makedirs(dirname)
                 except FileExistsError:
@@ -1344,22 +1342,22 @@ def main() -> None:
         ensure_writable(tmpfile)
         assistant.setOriginal(srcpath)
         assistant.setRewritten(destpath)
-        if isfile(joinpath(destdir, destpath)):
+        if os.path.isfile(joinpath(destdir, destpath)):
             # The file already exists.
             assistant.update(lookedup, flag, tmpfile, True)
-        else:  # if not isfile(joinpath(destdir, destpath))
+        else:  # if not os.path.isfile(joinpath(destdir, destpath))
             # Install the file.
             # Don't protest if the file should be there but isn't: it happens
             # frequently that developers don't put autogenerated files under
             # version control.
             assistant.add(lookedup, flag, tmpfile)
-        if isfile(tmpfile):
+        if os.path.isfile(tmpfile):
             os.remove(tmpfile)
 
     else:
-        message = '%s: *** ' % constants.APP['name']
+        message = '%s: *** ' % APP['name']
         message += 'no mode specified\n'
-        message += '%s: *** Stop.\n' % constants.APP['name']
+        message += '%s: *** Stop.\n' % APP['name']
         sys.stderr.write(message)
         sys.exit(1)
 
@@ -1368,7 +1366,7 @@ def main() -> None:
         # This disturbs the result of the next "gitk" invocation.
         # Workaround: Let git scan the files. This can be done through
         # "git update-index --refresh" or "git status" or "git diff".
-        if isdir(joinpath(DIRS['root'], '.git')):
+        if os.path.isdir(joinpath(DIRS['root'], '.git')):
             try:
                 sp.run(['git', 'update-index', '--refresh'],
                        cwd=DIRS['root'], stdout=sp.DEVNULL)
@@ -1385,7 +1383,7 @@ def main_with_exception_handling() -> None:
         errno = error.errno
         errinfo = error.errinfo
         if errmode == 0:
-            message = '%s: *** ' % constants.APP['name']
+            message = '%s: *** ' % APP['name']
             if errinfo == None:
                 errinfo = ''
             if errno == 1:
@@ -1396,7 +1394,7 @@ def main_with_exception_handling() -> None:
                 message += 'cannot find %s - make sure you run gnulib-tool from within your package\'s directory' % errinfo
             elif errno == 4:
                 message += 'minimum supported autoconf version is 2.64. Try adding'
-                message += 'AC_PREREQ([%s])' % constants.DEFAULT_AUTOCONF_MINVERSION
+                message += 'AC_PREREQ([%s])' % DEFAULT_AUTOCONF_MINVERSION
                 message += ' to your configure.ac.'
             elif errno == 5:
                 message += '%s is expected to contain gl_M4_BASE([%s])' % (repr(os.path.join(errinfo, 'gnulib-comp.m4')), repr(errinfo))
@@ -1449,6 +1447,6 @@ def main_with_exception_handling() -> None:
                 message += ('Option --automake-subdir/--automake-subdir-tests are only '
                             'supported if the definition of AUTOMAKE_OPTIONS in '
                             'Makefile.am contains \'subdir-objects\'.')
-            message += '\n%s: *** Stop.\n' % constants.APP['name']
+            message += '\n%s: *** Stop.\n' % APP['name']
             sys.stderr.write(message)
             sys.exit(1)
-- 
2.44.0

Reply via email to