Today's changes:
2022-08-07 Bruno Haible <[email protected]>
gnulib-tool.py: Finish implementing option --extract-test-module.
* gnulib-tool.py (main): Accept option --extract-tests-module.
gnulib-tool.py: Fix handling of nonexistent module names in --extract-*.
* gnulib-tool.py (main): To test whether a module exists, just call
GLModuleSystem.find and test its return value.
gnulib-tool.py: Fix --extract-dependencies result.
* pygnulib/GLModuleSystem.py (GLModule.getDependencies): Return a
snippet, not a list. Implement dependency of ${module}-tests on
${module}.
(GLModule.getDependenciesWithoutConditions,
GLModule.getDependenciesWithConditions): New methods.
(GLModuleTable.transitive_closure): Call getDependenciesWithConditions.
* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippets): Call
getDependenciesWithoutConditions.
* gnulib-tool.py (main) [--extract-dependencies]: Update.
gnulib-tool.py: Rename a method.
* pygnulib/GLModuleSystem.py (GLModule.getAutoconfEarlySnippet): Renamed
from GLModule.getAutoconfSnippet_Early.
* pygnulib/GLImport.py: Update.
* pygnulib/GLTestDir.py: Likewise.
gnulib-tool.py: Fix section extraction from module descriptions.
The code with self.content.split(section)[-1]
was broken because it recognizes an indented section label.
Similar code with ('\n' + self.content).split('\n' + section)[-1]
would still be broken because it recognizes an indented section label
in the first line of the file.
The code with section_label_regex
was broken because sometimes it returns the second-to-last section with
the given label, not the last one.
Also, whitespace after the colon was not ignored.
* pygnulib/GLModuleSystem.py (GLModule.__init__): Dissect the module
description's contents immediately, once only, in a reliable way.
(GLModule.getDescription, GLModule.getComment): Simplify.
(GLModule.getStatus): Simplify. Return a string.
(GLModule.getStatuses): New function. Return a list.
(GLModule.getNotice, GLModule.getApplicability, GLModule.getFiles,
GLModule.getDependencies, GLModules.getAutoconfSnippet_Early,
GLModules.getAutoconfSnippet, GLModule.getAutomakeSnippet_Conditional,
GLModule.getInclude, GLModule.getLink, GLModule.getLicense_Raw):
Simplify.
(GLModule.getLicense): Remove whitespace after calling getLicense_Raw.
(GLModule.getMaintainer): Simplify.
(GLModuleTable.transitive_closure): Call getStatuses() instead of
getStatus().
* pygnulib/GLEmiter.py: Likewise.
* gnulib-tool.py (main): For --extract-description, --extract-comment,
--extract-status, --extract-notice, --extract-autoconf-snippet,
--extract-automake-snippet, --extract-include-directive,
--extract-link-directive, --extract-maintainer, don't add an extra
newline after the snippet.
gnulib-tool.py: Improve field naming.
* pygnulib/GLModuleSystem.py (GLModule): Rename field 'module' to
'path'. Fix a typo in a TypeError message.
gnulib-tool.py: Simplify.
* pygnulib/GLModuleSystem.py (GLModule): Convert Windows newlines right
after reading the module description, not in every accessor.
gnulib-tool.py: Reduce code duplication.
* pygnulib/GLModuleSystem.py (GLModule): Declare two regexes are class
variables.
gnulib-tool.py: Implement option --find.
* pygnulib/GLModuleSystem.py (GLModuleSystem.file_is_module): New
method.
(GLModuleSystem.list): Filter the listing in memory; don't use a 'sed'
subprocess.
* gnulib-tool.py (main): Handle mode 'find'.
gnulib-tool.py: Fix some regexes.
* pygnulib/GLEmiter.py (GLEmiter.lib_Makefile_am): Use an equivalent
regex as gnulib-tool.
* pygnulib/GLTestDir.py (GLTestDir.execute): Likewise.
gnulib-tool.py: Fix some regex uses.
* pygnulib/GLModuleSystem.py (GLModuleTable.transitive_closure): Match
the regex against all lines of the snippet, not only the first line.
* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippet): Likewise.
gnulib-tool.py: Make regex uses more straightforward.
* pygnulib/constants.py: Don't use the "minimal matching" *? construct
when it makes no difference (because we're matching a single line only
and flag re.M is not specified).
* pygnulib/GLModuleSystem.py: Likewise.
gnulib-tool.py: Make regex uses more straightforward.
* pygnulib/GLModuleSystem.py: Don't use flag re.S on regular expressions
that are meant to match a single line only, and remove the use of the
"minimal matching" *? construct whose only purpose was to neutralize the
re.S flag.
* pygnulib/GLEmiter.py: Likewise.
* pygnulib/GLImport.py: Likewise.
* pygnulib/GLTestDir.py: Likewise.
gnulib-tool.py: Make regex uses more straightforward.
* pygnulib/GLEmiter.py: Don't use flag re.S on regular expressions on
regular expressions with no '.'.
* pygnulib/GLImport.py: Likewise.
2022-08-06 Bruno Haible <[email protected]>
gnulib-tool.py: Fix output in --dry-run mode.
* pygnulib/GLImport.py (GLImport._update_ignorelist_): In dry-run mode,
say "Update", not "Updating".
gnulib-tool.py: Finish implementing options --vc-files, --no-vc-files.
* gnulib-tool.py (main): Accept options --vc-files, --no-vc-files.
* pygnulib/GLImport.py (GLImport.__init__): Correct parsing of
gl_VC_FILES directive.
(GLImport.gnulib_cache): Don't treat the value False like None.
(GLImport.execute): Skip the .gitignore file manipulations if vc_files
is False.
gnulib-tool.py: Finish implementing option --witness-c-macro.
* gnulib-tool.py (main): Accept option --witness-c-macro.
* pygnulib/GLConfig.py (GLConfig.__init__): Remove wrong type check of
witness_c_macro argument.
>From 860df12df83dd27ae2b83e0ed6b485c4ffbb640e Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 6 Aug 2022 21:54:04 +0200
Subject: [PATCH 01/19] gnulib-tool.py: Finish implementing option
--witness-c-macro.
* gnulib-tool.py (main): Accept option --witness-c-macro.
* pygnulib/GLConfig.py (GLConfig.__init__): Remove wrong type check of
witness_c_macro argument.
---
ChangeLog | 7 +++++++
gnulib-tool.py | 12 ++++++++++--
gnulib-tool.py.TODO | 1 -
pygnulib/GLConfig.py | 9 +--------
4 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index dc968b8982..0043103914 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2022-08-06 Bruno Haible <[email protected]>
+
+ gnulib-tool.py: Finish implementing option --witness-c-macro.
+ * gnulib-tool.py (main): Accept option --witness-c-macro.
+ * pygnulib/GLConfig.py (GLConfig.__init__): Remove wrong type check of
+ witness_c_macro argument.
+
2022-08-05 Bruno Haible <[email protected]>
gnulib-tool.py: Don't initialize local variables too early.
diff --git a/gnulib-tool.py b/gnulib-tool.py
index 78bb326a69..0bf72bf3a0 100755
--- a/gnulib-tool.py
+++ b/gnulib-tool.py
@@ -358,6 +358,11 @@ def main():
dest='podomain',
default=None,
nargs=1)
+ # witness-c-macro
+ parser.add_argument('--witness-c-macro',
+ dest='witness_c_macro',
+ default=None,
+ nargs=1)
# single-configure
parser.add_argument('--single-configure',
dest='single_configure',
@@ -547,7 +552,8 @@ def main():
or cmdargs.excl_unportable_tests != None
or cmdargs.avoids != None or cmdargs.lgpl != None
or cmdargs.makefile_name != None
- or cmdargs.macro_prefix != None or cmdargs.podomain != None))):
+ or cmdargs.macro_prefix != None or cmdargs.podomain != None
+ or cmdargs.witness_c_macro != None))):
message = '%s: *** ' % constants.APP['name']
message += 'invalid options for --%s mode\n' % mode
message += 'Try \'gnulib-tool --help\' for more information.\n'
@@ -640,6 +646,9 @@ def main():
podomain = cmdargs.podomain
if podomain != None:
podomain = podomain[0]
+ witness_c_macro = cmdargs.witness_c_macro
+ if witness_c_macro != None:
+ witness_c_macro = witness_c_macro[0]
avoids = cmdargs.avoids
if avoids != None:
avoids = [ module
@@ -650,7 +659,6 @@ def main():
single_configure = cmdargs.single_configure
docbase = None
conddeps = None
- witness_c_macro = None
vc_files = None
# Create pygnulib configuration.
diff --git a/gnulib-tool.py.TODO b/gnulib-tool.py.TODO
index b59e89cc59..c37fcbeebf 100644
--- a/gnulib-tool.py.TODO
+++ b/gnulib-tool.py.TODO
@@ -29,7 +29,6 @@ Implement the options:
--gnu-make
--tests-makefile-name
--automake-subdir
- --witness-c-macro
--vc-files
--no-vc-files
-h | --hardlink
diff --git a/pygnulib/GLConfig.py b/pygnulib/GLConfig.py
index e571dff2b3..5f30a80797 100644
--- a/pygnulib/GLConfig.py
+++ b/pygnulib/GLConfig.py
@@ -153,14 +153,7 @@ class GLConfig(object):
# witness_c_macro
self.resetWitnessCMacro()
if witness_c_macro != None:
- if type(witness_c_macro) is bool:
- if not witness_c_macro:
- self.setWitnessCMacro()
- else: # if witness_c_macro
- self.resetWitnessCMacro()
- else: # if type(witness_c_macro) is not bool
- raise TypeError('witness_c_macro must be a bool, not %s'
- % type(witness_c_macro).__name__)
+ self.setWitnessCMacro(witness_c_macro)
# vc_files
self.resetVCFiles()
if vc_files != None:
--
2.34.1
>From 9812027a9afa87b12eb3b7e3c28600e6eff7ca98 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 6 Aug 2022 23:01:36 +0200
Subject: [PATCH 02/19] gnulib-tool.py: Finish implementing options --vc-files,
--no-vc-files.
* gnulib-tool.py (main): Accept options --vc-files, --no-vc-files.
* pygnulib/GLImport.py (GLImport.__init__): Correct parsing of
gl_VC_FILES directive.
(GLImport.gnulib_cache): Don't treat the value False like None.
(GLImport.execute): Skip the .gitignore file manipulations if vc_files
is False.
---
ChangeLog | 8 ++++++
gnulib-tool.py | 13 ++++++++--
gnulib-tool.py.TODO | 4 +--
pygnulib/GLConfig.py | 2 +-
pygnulib/GLImport.py | 62 ++++++++++++++++++++++----------------------
5 files changed, 53 insertions(+), 36 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 0043103914..29da7a3a6e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2022-08-06 Bruno Haible <[email protected]>
+ gnulib-tool.py: Finish implementing options --vc-files, --no-vc-files.
+ * gnulib-tool.py (main): Accept options --vc-files, --no-vc-files.
+ * pygnulib/GLImport.py (GLImport.__init__): Correct parsing of
+ gl_VC_FILES directive.
+ (GLImport.gnulib_cache): Don't treat the value False like None.
+ (GLImport.execute): Skip the .gitignore file manipulations if vc_files
+ is False.
+
gnulib-tool.py: Finish implementing option --witness-c-macro.
* gnulib-tool.py (main): Accept option --witness-c-macro.
* pygnulib/GLConfig.py (GLConfig.__init__): Remove wrong type check of
diff --git a/gnulib-tool.py b/gnulib-tool.py
index 0bf72bf3a0..bb763a2245 100755
--- a/gnulib-tool.py
+++ b/gnulib-tool.py
@@ -363,6 +363,15 @@ def main():
dest='witness_c_macro',
default=None,
nargs=1)
+ # vc-files
+ parser.add_argument('--vc-files',
+ dest='vc_files',
+ default=None,
+ action='store_true')
+ parser.add_argument('--no-vc-files',
+ dest='vc_files',
+ default=None,
+ action='store_false')
# single-configure
parser.add_argument('--single-configure',
dest='single_configure',
@@ -553,7 +562,7 @@ def main():
or cmdargs.avoids != None or cmdargs.lgpl != None
or cmdargs.makefile_name != None
or cmdargs.macro_prefix != None or cmdargs.podomain != None
- or cmdargs.witness_c_macro != None))):
+ or cmdargs.witness_c_macro != None or cmdargs.vc_files != None))):
message = '%s: *** ' % constants.APP['name']
message += 'invalid options for --%s mode\n' % mode
message += 'Try \'gnulib-tool --help\' for more information.\n'
@@ -649,6 +658,7 @@ def main():
witness_c_macro = cmdargs.witness_c_macro
if witness_c_macro != None:
witness_c_macro = witness_c_macro[0]
+ vc_files = cmdargs.vc_files
avoids = cmdargs.avoids
if avoids != None:
avoids = [ module
@@ -659,7 +669,6 @@ def main():
single_configure = cmdargs.single_configure
docbase = None
conddeps = None
- vc_files = None
# Create pygnulib configuration.
config = classes.GLConfig(
diff --git a/gnulib-tool.py.TODO b/gnulib-tool.py.TODO
index c37fcbeebf..53915662b8 100644
--- a/gnulib-tool.py.TODO
+++ b/gnulib-tool.py.TODO
@@ -29,14 +29,14 @@ Implement the options:
--gnu-make
--tests-makefile-name
--automake-subdir
- --vc-files
- --no-vc-files
-h | --hardlink
--local-hardlink
-S | --more-symlinks
-H | --more-hardlinks
--help (same output)
+Remove exit() in GLImport.py.
+
--------------------------------------------------------------------------------
commit 76c7703cb2e9e0e803d1296618d8ab9e86e13d6c
diff --git a/pygnulib/GLConfig.py b/pygnulib/GLConfig.py
index 5f30a80797..216f2e05fa 100644
--- a/pygnulib/GLConfig.py
+++ b/pygnulib/GLConfig.py
@@ -276,7 +276,7 @@ class GLConfig(object):
elif key in ['libtool', 'lgpl', 'conddeps', 'symbolic', 'lsymbolic',
'libtests', 'dryrun']:
return False
- if key == 'vc_files':
+ elif key == 'vc_files':
return None
elif key == 'errors':
return True
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index 9de4b3b93c..b06fc5b603 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -141,9 +141,6 @@ class GLImport(object):
if 'gl_CONDITIONAL_DEPENDENCIES' in data:
self.cache.setCondDeps(True)
data = data.replace('gl_CONDITIONAL_DEPENDENCIES', '')
- if 'gl_VC_FILES' in data:
- self.cache.setVCFiles(True)
- data = data.replace('gl_VC_FILES', '')
if 'gl_WITH_TESTS' in data:
self.cache.enableInclTestCategory(TESTS['tests'])
data = data.replace('gl_WITH_TESTS', '')
@@ -202,6 +199,8 @@ class GLImport(object):
self.cache.setPoDomain(cleaner(tempdict['gl_PO_DOMAIN']))
if tempdict['gl_WITNESS_C_MACRO']:
self.cache.setWitnessCMacro(cleaner(tempdict['gl_WITNESS_C_MACRO']))
+ if tempdict['gl_VC_FILES']:
+ self.cache.setVCFiles(cleaner(tempdict['gl_VC_FILES']))
# Get cached filelist from gnulib-comp.m4.
destdir, m4base = self.config.getDestDir(), self.config.getM4Base()
@@ -542,7 +541,7 @@ class GLImport(object):
emit += 'gl_MACRO_PREFIX([%s])\n' % macro_prefix
emit += 'gl_PO_DOMAIN([%s])\n' % podomain
emit += 'gl_WITNESS_C_MACRO([%s])\n' % witness_c_macro
- if vc_files:
+ if vc_files != None:
emit += 'gl_VC_FILES([%s])\n' % vc_files
return constants.nlconvert(emit)
@@ -1334,33 +1333,34 @@ AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix
if isfile(tmpfile):
os.remove(tmpfile)
- # Update the .cvsignore and .gitignore files.
- ignorelist = list()
- filetable['added'] = sorted(set(filetable['added']))
- filetable['removed'] = sorted(set(filetable['added']))
- for file in filetable['added']:
- directory, basename = os.path.split(file)
- ignorelist += [tuple([directory, '|A|', basename])]
- for file in filetable['removed']:
- directory, basename = os.path.split(file)
- ignorelist += [tuple([directory, '|R|', basename])]
- last_dir = ''
- last_dirs_added = list()
- last_dirs_removed = list()
- for row in ignorelist:
- next_dir = row[0]
- operand = row[1]
- filename = row[2]
- if next_dir != last_dir:
- self._done_dir_(last_dir, last_dirs_added, last_dirs_removed)
- last_dir = next_dir
- last_dirs_added = list()
- last_dirs_removed = list()
- if operand == '|A|':
- last_dirs_added += [filename]
- elif operand == '|R|':
- last_dirs_removed += [filename]
- self._done_dir_(last_dir, last_dirs_added, last_dirs_removed)
+ if vc_files != False:
+ # Update the .cvsignore and .gitignore files.
+ ignorelist = list()
+ filetable['added'] = sorted(set(filetable['added']))
+ filetable['removed'] = sorted(set(filetable['added']))
+ for file in filetable['added']:
+ directory, basename = os.path.split(file)
+ ignorelist += [tuple([directory, '|A|', basename])]
+ for file in filetable['removed']:
+ directory, basename = os.path.split(file)
+ ignorelist += [tuple([directory, '|R|', basename])]
+ last_dir = ''
+ last_dirs_added = list()
+ last_dirs_removed = list()
+ for row in ignorelist:
+ next_dir = row[0]
+ operand = row[1]
+ filename = row[2]
+ if next_dir != last_dir:
+ self._done_dir_(last_dir, last_dirs_added, last_dirs_removed)
+ last_dir = next_dir
+ last_dirs_added = list()
+ last_dirs_removed = list()
+ if operand == '|A|':
+ last_dirs_added += [filename]
+ elif operand == '|R|':
+ last_dirs_removed += [filename]
+ self._done_dir_(last_dir, last_dirs_added, last_dirs_removed)
exit()
# Finish the work.
--
2.34.1
>From 07d41642fbad4a36a7ece9ee33db6a4d641cb585 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 6 Aug 2022 23:10:14 +0200
Subject: [PATCH 03/19] gnulib-tool.py: Fix output in --dry-run mode.
* pygnulib/GLImport.py (GLImport._update_ignorelist_): In dry-run mode,
say "Update", not "Updating".
---
ChangeLog | 4 ++++
pygnulib/GLImport.py | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/ChangeLog b/ChangeLog
index 29da7a3a6e..e5af4e34c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2022-08-06 Bruno Haible <[email protected]>
+ gnulib-tool.py: Fix output in --dry-run mode.
+ * pygnulib/GLImport.py (GLImport._update_ignorelist_): In dry-run mode,
+ say "Update", not "Updating".
+
gnulib-tool.py: Finish implementing options --vc-files, --no-vc-files.
* gnulib-tool.py (main): Accept options --vc-files, --no-vc-files.
* pygnulib/GLImport.py (GLImport.__init__): Correct parsing of
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index b06fc5b603..13418400af 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -739,7 +739,7 @@ AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix
with codecs.open(srcpath, 'ab', 'UTF-8') as file:
file.write(destdata)
else: # if self.config['dryrun']
- print('Updating %s (backup in %s)' % (srcpath, backupname))
+ print('Update %s (backup in %s)' % (srcpath, backupname))
else: # if not isfile(srcpath)
if dirs_added:
if not self.config['dryrun']:
--
2.34.1
>From a68f103cc3863310e1c1b4dd9e05b7924381d9a1 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 13:11:07 +0200
Subject: [PATCH 05/19] gnulib-tool.py: Make regex uses more straightforward.
* pygnulib/GLEmiter.py: Don't use flag re.S on regular expressions on
regular expressions with no '.'.
* pygnulib/GLImport.py: Likewise.
---
ChangeLog | 7 +++++++
pygnulib/GLEmiter.py | 4 ++--
pygnulib/GLImport.py | 6 +++---
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 5396f935a3..bcaedf98e4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2022-08-07 Bruno Haible <[email protected]>
+
+ gnulib-tool.py: Make regex uses more straightforward.
+ * pygnulib/GLEmiter.py: Don't use flag re.S on regular expressions on
+ regular expressions with no '.'.
+ * pygnulib/GLImport.py: Likewise.
+
2022-08-06 Bruno Haible <[email protected]>
gnulib-tool: In the VC files messages, omit the destination directory.
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index b6c31fa603..f85ef30d52 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -750,7 +750,7 @@ AC_DEFUN([%V1%_LIBSOURCES], [
# * https://debbugs.gnu.org/10997
# * https://debbugs.gnu.org/11030
# So we need this workaround.
- pattern = re.compile('^pkgdata_DATA *\\+=', re.S | re.M)
+ pattern = re.compile('^pkgdata_DATA *\\+=', re.M)
if pattern.findall(allsnippets):
emit += 'pkgdata_DATA =\n'
emit += 'EXTRA_DIST =\n'
@@ -1032,7 +1032,7 @@ AC_DEFUN([%V1%_LIBSOURCES], [
# * https://debbugs.gnu.org/10997
# * https://debbugs.gnu.org/11030
# So we need this workaround.
- pattern = re.compile('^pkgdata_DATA *\\+=', re.S | re.M)
+ pattern = re.compile('^pkgdata_DATA *\\+=', re.M)
if bool(pattern.findall(main_snippets)) or bool(pattern.findall(longrun_snippets)):
emit += 'pkgdata_DATA =\n'
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index 935a662593..7a6312ec39 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -100,7 +100,7 @@ class GLImport(object):
if match:
result = cleaner(match)[0]
self.cache.setAuxDir(joinpath(self.config['destdir'], result))
- pattern = re.compile(r'A[CM]_PROG_LIBTOOL', re.S | re.M)
+ pattern = re.compile(r'A[CM]_PROG_LIBTOOL', re.M)
guessed_libtool = bool(pattern.findall(data))
if self.config['auxdir'] == None:
self.config.setAuxDir(self.cache['auxdir'])
@@ -1439,9 +1439,9 @@ in <library>_a_LDFLAGS or <library>_la_LDFLAGS when linking a library.''')
with codecs.open(configure_ac, 'rb', 'UTF-8') as file:
data = file.read()
match_result1 = \
- bool(re.compile('^ *AC_PROG_CC_STDC', re.S | re.M).findall(data))
+ bool(re.compile('^ *AC_PROG_CC_STDC', re.M).findall(data))
match_result2 = \
- bool(re.compile('^ *AC_PROG_CC_C99', re.S | re.M).findall(data))
+ bool(re.compile('^ *AC_PROG_CC_C99', re.M).findall(data))
if match_result1:
position_early_after = 'AC_PROG_CC_STDC'
elif match_result2:
--
2.34.1
>From 54bf87fe01941049356177a1902bdf1a3eb49f7f Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 13:29:59 +0200
Subject: [PATCH 06/19] gnulib-tool.py: Make regex uses more straightforward.
* pygnulib/GLModuleSystem.py: Don't use flag re.S on regular expressions
that are meant to match a single line only, and remove the use of the
"minimal matching" *? construct whose only purpose was to neutralize the
re.S flag.
* pygnulib/GLEmiter.py: Likewise.
* pygnulib/GLImport.py: Likewise.
* pygnulib/GLTestDir.py: Likewise.
---
ChangeLog | 9 +++++++++
pygnulib/GLEmiter.py | 18 +++++++++---------
pygnulib/GLImport.py | 4 ++--
pygnulib/GLModuleSystem.py | 6 +++---
pygnulib/GLTestDir.py | 20 ++++++++++----------
5 files changed, 33 insertions(+), 24 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index bcaedf98e4..0e162e8d0a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Make regex uses more straightforward.
+ * pygnulib/GLModuleSystem.py: Don't use flag re.S on regular expressions
+ that are meant to match a single line only, and remove the use of the
+ "minimal matching" *? construct whose only purpose was to neutralize the
+ re.S flag.
+ * pygnulib/GLEmiter.py: Likewise.
+ * pygnulib/GLImport.py: Likewise.
+ * pygnulib/GLTestDir.py: Likewise.
+
gnulib-tool.py: Make regex uses more straightforward.
* pygnulib/GLEmiter.py: Don't use flag re.S on regular expressions on
regular expressions with no '.'.
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index f85ef30d52..02fa6654e7 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -153,7 +153,7 @@ class GLEmiter(object):
if line.strip() ]
snippet = '%s\n' % '\n'.join(lines)
transformer = fileassistant.transformers.get('aux', '')
- pattern = re.compile('(^.*?$)', re.S | re.M)
+ pattern = re.compile('^(.*)$', re.M)
snippet = pattern.sub('%s\\1' % indentation, snippet)
if transformer:
args = ['sed', '-e', transformer]
@@ -182,9 +182,9 @@ class GLEmiter(object):
emit += 'changequote([, ])dnl\n'
emit += 'AC_SUBST([LTALLOCA])'
if replace_auxdir:
- regex = 'AC_CONFIG_FILES\\(\\[(.*?)\\:build-aux/(.*?)\\]\\)'
+ regex = 'AC_CONFIG_FILES\\(\\[(.*)\\:build-aux/(.*)\\]\\)'
repl = 'AC_CONFIG_FILES([\\1:%s/\\2])' % auxdir
- pattern = re.compile(regex, re.S | re.M)
+ pattern = re.compile(regex, re.M)
emit = pattern.sub(repl, emit)
lines = [ line
for line in emit.split('\n')
@@ -688,9 +688,9 @@ AC_DEFUN([%V1%_LIBSOURCES], [
amsnippet1 = amsnippet1.replace('lib_LIBRARIES', 'lib%_LIBRARIES')
amsnippet1 = amsnippet1.replace('lib_LTLIBRARIES', 'lib%_LTLIBRARIES')
if LD_flags:
- pattern = re.compile('lib_LDFLAGS[\t ]*\\+=(.*?)$', re.S | re.M)
+ pattern = re.compile('lib_LDFLAGS[\t ]*\\+=(.*)$', re.M)
amsnippet1 = pattern.sub('', amsnippet1)
- pattern = re.compile('lib_([A-Z][A-Z](?:.*?))', re.S | re.M)
+ pattern = re.compile('lib_([A-Z][A-Z](?:.*))', re.M)
amsnippet1 = pattern.sub('%s_%s_\\1' % (libname, libext),
amsnippet1)
amsnippet1 = amsnippet1.replace('$(GNULIB_', '$(' + module_indicator_prefix + '_GNULIB_')
@@ -708,7 +708,7 @@ AC_DEFUN([%V1%_LIBSOURCES], [
# Get unconditional snippet, edit it and save to amsnippet2.
amsnippet2 = module.getAutomakeSnippet_Unconditional()
- pattern = re.compile('lib_([A-Z][A-Z](?:.*?))', re.S | re.M)
+ pattern = re.compile('lib_([A-Z][A-Z](?:.*))', re.M)
amsnippet2 = pattern.sub('%s_%s_\\1' % (libname, libext),
amsnippet2)
amsnippet2 = amsnippet2.replace('$(GNULIB_',
@@ -802,7 +802,7 @@ AC_DEFUN([%V1%_LIBSOURCES], [
insnippets = False
inmakefile = False
regex = '^[a-zA-Z0-9_]*_%sLIBRARIES *\\+{0,1}= *%s.%s' % (perhapsLT, libname, libext)
- pattern = re.compile(regex, re.S | re.M)
+ pattern = re.compile(regex, re.M)
insnippets = bool(pattern.findall(allsnippets))
# Then test if $sourcebase/Makefile.am (if it exists) specifies it.
path = joinpath(sourcebase, 'Makefile.am')
@@ -955,9 +955,9 @@ AC_DEFUN([%V1%_LIBSOURCES], [
snippet = snippet.replace('lib_LIBRARIES', 'lib%_LIBRARIES')
snippet = snippet.replace('lib_LTLIBRARIES', 'lib%_LTLIBRARIES')
if LD_flags:
- pattern = re.compile('lib_LDFLAGS[\t ]*\\+=(.*?)$', re.S | re.M)
+ pattern = re.compile('lib_LDFLAGS[\t ]*\\+=(.*)$', re.M)
snippet = pattern.sub('', snippet)
- pattern = re.compile('lib_([A-Z][A-Z](?:.*?))', re.S | re.M)
+ pattern = re.compile('lib_([A-Z][A-Z](?:.*))', re.M)
snippet = pattern.sub('libtests_a_\\1', snippet)
snippet = snippet.replace('$(GNULIB_', '$(' + module_indicator_prefix + '_GNULIB_')
snippet = snippet.replace('lib%_LIBRARIES', 'lib_LIBRARIES')
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index 7a6312ec39..818f3d57c0 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -95,7 +95,7 @@ class GLImport(object):
self.config.setAutoconfFile(path)
with codecs.open(path, 'rb', 'UTF-8') as file:
data = file.read()
- pattern = re.compile(r'^AC_CONFIG_AUX_DIR\((.*?)\)$', re.S | re.M)
+ pattern = re.compile(r'^AC_CONFIG_AUX_DIR\((.*)\)$', re.M)
match = pattern.findall(data)
if match:
result = cleaner(match)[0]
@@ -106,7 +106,7 @@ class GLImport(object):
self.config.setAuxDir(self.cache['auxdir'])
# Guess autoconf version.
- pattern = re.compile(r'.*AC_PREREQ\((.*?)\)', re.S | re.M)
+ pattern = re.compile(r'.*AC_PREREQ\((.*)\)', re.M)
versions = cleaner(pattern.findall(data))
if versions:
version = sorted(set([ float(version)
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index 6b8f20e54f..afc7a472cf 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -705,7 +705,7 @@ Include:|Link:|License:|Maintainer:)'
# TODO: unconditional automake snippet for nontests modules
snippet = self.getAutomakeSnippet_Conditional()
snippet = constants.combine_lines(snippet)
- pattern = re.compile('^lib_SOURCES[\t ]*\\+=[\t ]*(.*?)$', re.S | re.M)
+ pattern = re.compile('^lib_SOURCES[\t ]*\\+=[\t ]*(.*)$', re.M)
mentioned_files = pattern.findall(snippet)
if mentioned_files != list():
mentioned_files = mentioned_files[-1].split(' ')
@@ -780,7 +780,7 @@ Include:|Link:|License:|Maintainer:)'
parts += [line]
result = ''.join(parts)
result = result.strip()
- pattern = re.compile('^(["<].*?[>"])', re.S | re.M)
+ pattern = re.compile('^(["<].*[>"])', re.M)
result = pattern.sub('#include \\1', result)
self.cache['include'] = result
return self.cache['include']
@@ -1164,7 +1164,7 @@ class GLModuleTable(object):
raise TypeError('each module must be a GLModule instance')
snippet = module.getAutomakeSnippet()
snippet = constants.remove_backslash_newline(snippet)
- pattern = re.compile('^lib_SOURCES[\t ]*\\+=[\t ]*(.*?)$', re.S | re.M)
+ pattern = re.compile('^lib_SOURCES[\t ]*\\+=[\t ]*(.*)$', re.M)
files = pattern.findall(snippet)
if files: # if source files were found
files = files[-1].split(' ')
diff --git a/pygnulib/GLTestDir.py b/pygnulib/GLTestDir.py
index 757c494011..f8d9910ab7 100644
--- a/pygnulib/GLTestDir.py
+++ b/pygnulib/GLTestDir.py
@@ -299,7 +299,7 @@ class GLTestDir(object):
notice = module.getNotice()
if notice:
print('Notice from module %s:' % str(module))
- pattern = re.compile('^(.*?)$', re.S | re.M)
+ pattern = re.compile('^(.*)$', re.M)
notice = pattern.sub(' \\1', notice)
print(notice)
else: # if not single_configure
@@ -307,7 +307,7 @@ class GLTestDir(object):
notice = module.getNotice()
if notice:
print('Notice from module %s:' % str(module))
- pattern = re.compile('^(.*?)$', re.S | re.M)
+ pattern = re.compile('^(.*)$', re.M)
notice = pattern.sub(' \\1', notice)
print(notice)
@@ -461,7 +461,7 @@ class GLTestDir(object):
for line in snippet.split('\n')
if line.strip() ]
snippet = '\n'.join(lines)
- pattern = re.compile('AC_REQUIRE\\(\\[([^()].*?)\\]\\)', re.S | re.M)
+ pattern = re.compile('AC_REQUIRE\\(\\[([^()].*)\\]\\)', re.M)
snippet = pattern.sub('\\1', snippet)
snippet = snippet.strip()
snippets += [snippet]
@@ -578,7 +578,7 @@ class GLTestDir(object):
for line in snippet.split('\n')
if line.strip() ]
snippet = '\n'.join(lines)
- pattern = re.compile('AC_REQUIRE\\(\\[([^()].*?)\\]\\)', re.S | re.M)
+ pattern = re.compile('AC_REQUIRE\\(\\[([^()].*)\\]\\)', re.M)
snippet = pattern.sub('\\1', snippet)
snippet = snippet.strip()
snippets += [snippet]
@@ -749,9 +749,9 @@ class GLTestDir(object):
# Extract the value of "CLEANFILES += ..." and "MOSTLYCLEANFILES += ...".
regex_find = list()
- pattern = re.compile('^CLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M)
+ pattern = re.compile('^CLEANFILES[\t ]*\\+=(.*)$', re.M)
regex_find += pattern.findall(snippet)
- pattern = re.compile('^MOSTLYCLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M)
+ pattern = re.compile('^MOSTLYCLEANFILES[\t ]*\\+=(.*)$', re.M)
regex_find += pattern.findall(snippet)
regex_find = [ line.strip()
for line in regex_find
@@ -765,7 +765,7 @@ class GLTestDir(object):
# Extract the value of "BUILT_SOURCES += ...". Remove variable references
# such $(FOO_H) because they don't refer to distributed files.
regex_find = list()
- pattern = re.compile('^BUILT_SOURCES[\t ]*\\+=(.*?)$', re.S | re.M)
+ pattern = re.compile('^BUILT_SOURCES[\t ]*\\+=(.*)$', re.M)
regex_find += pattern.findall(snippet)
regex_find = [ line.strip()
for line in regex_find
@@ -791,9 +791,9 @@ class GLTestDir(object):
# Extract the value of "CLEANFILES += ..." and "MOSTLYCLEANFILES += ...".
regex_find = list()
- pattern = re.compile('^CLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M)
+ pattern = re.compile('^CLEANFILES[\t ]*\\+=(.*)$', re.M)
regex_find += pattern.findall(snippet)
- pattern = re.compile('^MOSTLYCLEANFILES[\t ]*\\+=(.*?)$', re.S | re.M)
+ pattern = re.compile('^MOSTLYCLEANFILES[\t ]*\\+=(.*)$', re.M)
regex_find += pattern.findall(snippet)
regex_find = [ line.strip()
for line in regex_find
@@ -808,7 +808,7 @@ class GLTestDir(object):
# such $(FOO_H) because they don't refer to distributed files.
regex_find = list()
tests_built_sources = list()
- pattern = re.compile('^BUILT_SOURCES[\t ]*\\+=(.*?)$', re.S | re.M)
+ pattern = re.compile('^BUILT_SOURCES[\t ]*\\+=(.*)$', re.M)
regex_find += pattern.findall(snippet)
regex_find = [ line.strip()
for line in regex_find
--
2.34.1
>From 9d722ddced2e46a06255be8eb24a54015f611af7 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 13:40:07 +0200
Subject: [PATCH 07/19] gnulib-tool.py: Make regex uses more straightforward.
* pygnulib/constants.py: Don't use the "minimal matching" *? construct
when it makes no difference (because we're matching a single line only
and flag re.M is not specified).
* pygnulib/GLModuleSystem.py: Likewise.
---
ChangeLog | 6 ++++++
pygnulib/GLModuleSystem.py | 2 +-
pygnulib/constants.py | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 0e162e8d0a..f50e756d60 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Make regex uses more straightforward.
+ * pygnulib/constants.py: Don't use the "minimal matching" *? construct
+ when it makes no difference (because we're matching a single line only
+ and flag re.M is not specified).
+ * pygnulib/GLModuleSystem.py: Likewise.
+
gnulib-tool.py: Make regex uses more straightforward.
* pygnulib/GLModuleSystem.py: Don't use flag re.S on regular expressions
that are meant to match a single line only, and remove the use of the
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index afc7a472cf..e1b62ec56c 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -280,7 +280,7 @@ Include:|Link:|License:|Maintainer:)'
'''GLModule.getName() -> str
Return the name of the module.'''
- pattern = re.compile(joinpath('modules', '(.*?)$'))
+ pattern = re.compile(joinpath('modules', '(.*)$'))
result = pattern.findall(self.module)[0]
return result
diff --git a/pygnulib/constants.py b/pygnulib/constants.py
index 46c0cbc152..ba0ebc9942 100644
--- a/pygnulib/constants.py
+++ b/pygnulib/constants.py
@@ -412,7 +412,7 @@ def filter_filelist(separator, filelist,
listing = list()
for filename in filelist:
if filename.startswith(prefix) and filename.endswith(suffix):
- pattern = re.compile('^%s(.*?)%s$'
+ pattern = re.compile('^%s(.*)%s$'
% (removed_prefix, removed_suffix))
result = pattern.sub('%s\\1%s'
% (added_prefix, added_suffix), filename)
--
2.34.1
>From 5c087011efa2817a7e857f69a1cdd22c21a5053d Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 13:46:15 +0200
Subject: [PATCH 08/19] gnulib-tool.py: Fix some regex uses.
* pygnulib/GLModuleSystem.py (GLModuleTable.transitive_closure): Match
the regex against all lines of the snippet, not only the first line.
* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippet): Likewise.
---
ChangeLog | 5 +++++
pygnulib/GLEmiter.py | 2 +-
pygnulib/GLModuleSystem.py | 2 +-
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index f50e756d60..a44504ae20 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Fix some regex uses.
+ * pygnulib/GLModuleSystem.py (GLModuleTable.transitive_closure): Match
+ the regex against all lines of the snippet, not only the first line.
+ * pygnulib/GLEmiter.py (GLEmiter.autoconfSnippet): Likewise.
+
gnulib-tool.py: Make regex uses more straightforward.
* pygnulib/constants.py: Don't use the "minimal matching" *? construct
when it makes no difference (because we're matching a single line only
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index 02fa6654e7..9aa638d693 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -174,7 +174,7 @@ class GLEmiter(object):
else:
# Don't indent AM_GNU_GETTEXT_VERSION line, as that confuses
# autopoint through at least GNU gettext version 0.18.2.
- snippet = re.compile('^ *AM_GNU_GETTEXT_VERSION').sub('AM_GNU_GETTEXT_VERSION', snippet)
+ snippet = re.compile('^ *AM_GNU_GETTEXT_VERSION', re.M).sub('AM_GNU_GETTEXT_VERSION', snippet)
emit += snippet
if str(module) == 'alloca' and libtool and not disable_libtool:
emit += 'changequote(,)dnl\n'
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index e1b62ec56c..75316515b8 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -1041,7 +1041,7 @@ class GLModuleTable(object):
if self.config['conddeps']:
automake_snippet = \
module.getAutomakeSnippet_Conditional()
- pattern = re.compile('^if')
+ pattern = re.compile('^if', re.M)
if not pattern.findall(automake_snippet):
self.addUnconditional(module)
conditional = self.isConditional(module)
--
2.34.1
>From 6a795cb6b5c9f2b42058f444c61291f751c356e2 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 13:49:49 +0200
Subject: [PATCH 09/19] gnulib-tool.py: Fix some regexes.
* pygnulib/GLEmiter.py (GLEmiter.lib_Makefile_am): Use an equivalent
regex as gnulib-tool.
* pygnulib/GLTestDir.py (GLTestDir.execute): Likewise.
---
ChangeLog | 5 +++++
pygnulib/GLEmiter.py | 2 +-
pygnulib/GLTestDir.py | 4 ++--
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index a44504ae20..b052583c01 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Fix some regexes.
+ * pygnulib/GLEmiter.py (GLEmiter.lib_Makefile_am): Use an equivalent
+ regex as gnulib-tool.
+ * pygnulib/GLTestDir.py (GLTestDir.execute): Likewise.
+
gnulib-tool.py: Fix some regex uses.
* pygnulib/GLModuleSystem.py (GLModuleTable.transitive_closure): Match
the regex against all lines of the snippet, not only the first line.
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index 9aa638d693..e0164ed7cc 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -801,7 +801,7 @@ AC_DEFUN([%V1%_LIBSOURCES], [
# First test if allsnippets already specify an installation location.
insnippets = False
inmakefile = False
- regex = '^[a-zA-Z0-9_]*_%sLIBRARIES *\\+{0,1}= *%s.%s' % (perhapsLT, libname, libext)
+ regex = '^[a-zA-Z0-9_]*_%sLIBRARIES *\\+{0,1}= *%s\\.%s' % (perhapsLT, libname, libext)
pattern = re.compile(regex, re.M)
insnippets = bool(pattern.findall(allsnippets))
# Then test if $sourcebase/Makefile.am (if it exists) specifies it.
diff --git a/pygnulib/GLTestDir.py b/pygnulib/GLTestDir.py
index f8d9910ab7..9a3fde66ea 100644
--- a/pygnulib/GLTestDir.py
+++ b/pygnulib/GLTestDir.py
@@ -461,7 +461,7 @@ class GLTestDir(object):
for line in snippet.split('\n')
if line.strip() ]
snippet = '\n'.join(lines)
- pattern = re.compile('AC_REQUIRE\\(\\[([^()].*)\\]\\)', re.M)
+ pattern = re.compile('AC_REQUIRE\\(\\[([^()]*)\\]\\)', re.M)
snippet = pattern.sub('\\1', snippet)
snippet = snippet.strip()
snippets += [snippet]
@@ -578,7 +578,7 @@ class GLTestDir(object):
for line in snippet.split('\n')
if line.strip() ]
snippet = '\n'.join(lines)
- pattern = re.compile('AC_REQUIRE\\(\\[([^()].*)\\]\\)', re.M)
+ pattern = re.compile('AC_REQUIRE\\(\\[([^()]*)\\]\\)', re.M)
snippet = pattern.sub('\\1', snippet)
snippet = snippet.strip()
snippets += [snippet]
--
2.34.1
>From 72ac023526e84e7847cc67788be9afca2f3204fb Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 17:02:21 +0200
Subject: [PATCH 11/19] gnulib-tool.py: Implement option --find.
* pygnulib/GLModuleSystem.py (GLModuleSystem.file_is_module): New
method.
(GLModuleSystem.list): Filter the listing in memory; don't use a 'sed'
subprocess.
* gnulib-tool.py (main): Handle mode 'find'.
---
ChangeLog | 7 +++++
gnulib-tool.py | 60 +++++++++++++++++++++++++++++++++++++-
gnulib-tool.py.TODO | 5 +++-
pygnulib/GLModuleSystem.py | 59 +++++++++++++++++--------------------
4 files changed, 97 insertions(+), 34 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index e259a09333..acb82e903c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Implement option --find.
+ * pygnulib/GLModuleSystem.py (GLModuleSystem.file_is_module): New
+ method.
+ (GLModuleSystem.list): Filter the listing in memory; don't use a 'sed'
+ subprocess.
+ * gnulib-tool.py (main): Handle mode 'find'.
+
gnulib-tool: Fix option --find in combination with option --local-dir.
* gnulib-tool (func_prefixed_modules_in_dir): New function.
(find): Use it, and filter the directory names away after the 'grep'
diff --git a/gnulib-tool.py b/gnulib-tool.py
index bb763a2245..032deee6e0 100755
--- a/gnulib-tool.py
+++ b/gnulib-tool.py
@@ -43,15 +43,18 @@ import codecs
import random
import argparse
import subprocess as sp
+import shlex
from tempfile import mktemp
from pygnulib import constants
from pygnulib import classes
+from pygnulib import GLError
#===============================================================================
# Define global constants
#===============================================================================
APP = constants.APP
+DIRS = constants.DIRS
ENCS = constants.ENCS
UTILS = constants.UTILS
MODES = constants.MODES
@@ -422,6 +425,7 @@ def main():
# Determine when user tries to combine modes.
args = [
cmdargs.mode_list,
+ cmdargs.mode_find,
cmdargs.mode_import,
cmdargs.mode_add_import,
cmdargs.mode_remove_import,
@@ -460,6 +464,9 @@ def main():
files = None
if cmdargs.mode_list != None:
mode = 'list'
+ if cmdargs.mode_find != None:
+ mode = 'find'
+ files = list(cmdargs.non_option_arguments)
if cmdargs.mode_import != None:
mode = 'import'
modules = list(cmdargs.non_option_arguments)
@@ -701,13 +708,64 @@ def main():
)
# Work in the given mode.
- if mode in ['list']:
+ if mode == 'list':
modulesystem = classes.GLModuleSystem(config)
listing = modulesystem.list()
result = '\n'.join(listing)
os.rmdir(config['tempdir'])
print(result)
+ elif mode == 'find':
+ # Prepare GLModuleSystem.find to throw an exception.
+ config.setErrors(True)
+ modulesystem = classes.GLModuleSystem(config)
+ for filename in files:
+ if (isfile(joinpath(DIRS['root'], filename))
+ or (localpath != None
+ and any([ isfile(joinpath(localdir, filename))
+ for localdir in localpath ]))):
+ # Convert the file name to a POSIX basic regex.
+ # Needs to handle . [ \ * ^ $.
+ filename_regex = filename.replace('\\', '\\\\').replace('[', '\\[').replace('^', '\\^')
+ filename_regex = re.compile('([.*$])').sub('[\\1]', filename_regex)
+ 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)
+ os.chdir(constants.DIRS['root'])
+ with sp.Popen(command, shell=True, stdout=sp.PIPE) as proc:
+ result = proc.stdout.read().decode("UTF-8")
+ os.chdir(DIRS['cwd'])
+ # Read module candidates from local directories.
+ if localpath != None and len(localpath) > 0:
+ command = "find modules -type f -print | xargs -n 100 grep -l %s /dev/null | sed -e 's,^modules/,,' -e 's,\\.diff$,,'" % shlex.quote(filename_line_regex)
+ for localdir in localpath:
+ os.chdir(localdir)
+ with sp.Popen(command, shell=True, stdout=sp.PIPE) as proc:
+ result += proc.stdout.read().decode("UTF-8")
+ os.chdir(DIRS['cwd'])
+ listing = [ line
+ for line in result.split('\n')
+ if line.strip() ]
+ # Remove modules/ prefix from each file name.
+ pattern = re.compile('^modules/')
+ listing = [ pattern.sub('', line)
+ for line in listing ]
+ # Filter out undesired file names.
+ listing = [ line
+ for line in listing
+ if modulesystem.file_is_module(line) ]
+ module_candidates = sorted(set(listing))
+ for module in module_candidates:
+ try:
+ if filename in modulesystem.find(module).getFiles():
+ print(module)
+ except GLError:
+ # Ignore module candidates that don't actually exist.
+ pass
+ else:
+ message = '%s: warning: file %s does not exist\n' % (constants.APP['name'], filename)
+ sys.stderr.write(message)
+
elif mode in ['import', 'add-import', 'remove-import', 'update']:
mode = MODES[mode]
if not destdir:
diff --git a/gnulib-tool.py.TODO b/gnulib-tool.py.TODO
index 53915662b8..a46da5e2ad 100644
--- a/gnulib-tool.py.TODO
+++ b/gnulib-tool.py.TODO
@@ -20,7 +20,6 @@ Inline all 'sed' invocations.
--------------------------------------------------------------------------------
Implement the options:
- --find
--extract-recursive-dependencies
--extract-recursive-link-directive
--extract-tests-module
@@ -37,6 +36,10 @@ Implement the options:
Remove exit() in GLImport.py.
+Optimize:
+ - GLModuleSystem: Parse each module description only once.
+ - os.chdir around subprocess creation -> cwd=... argument instead.
+
--------------------------------------------------------------------------------
commit 76c7703cb2e9e0e803d1296618d8ab9e86e13d6c
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index 75316515b8..3383b22b28 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -43,6 +43,7 @@ DIRS = constants.DIRS
ENCS = constants.ENCS
TESTS = constants.TESTS
joinpath = constants.joinpath
+subend = constants.subend
isdir = os.path.isdir
isfile = os.path.isfile
filter_filelist = constants.filter_filelist
@@ -113,6 +114,18 @@ class GLModuleSystem(object):
sys.stderr.write('gnulib-tool: warning: ')
sys.stderr.write('file %s does not exist\n' % str(module))
+ def file_is_module(self, filename):
+ '''Given the name of a file in the modules/ directory, return true
+ if should be viewed as a module description file.'''
+ return not (filename == 'ChangeLog' or filename.endswith('/ChangeLog')
+ or filename == 'COPYING' or filename.endswith('/COPYING')
+ or filename == 'README' or filename.endswith('/README')
+ or filename == 'TEMPLATE'
+ or filename == 'TEMPLATE-EXTENDED'
+ or filename == 'TEMPLATE-TESTS'
+ or filename.startswith('.')
+ or filename.endswith('~'))
+
def list(self):
'''GLModuleSystem.list() -> list
@@ -123,23 +136,6 @@ class GLModuleSystem(object):
listing = list()
localpath = self.config['localpath']
find_args = ['find', 'modules', '-type', 'f', '-print']
- sed_args = \
- [
- 'sed',
- '-e', r's,^modules/,,',
- '-e', r'/^ChangeLog$/d',
- '-e', r'/\/ChangeLog$/d',
- '-e', r'/^COPYING$/d',
- '-e', r'/\/COPYING$/d',
- '-e', r'/^README$/d',
- '-e', r'/\/README$/d',
- '-e', r'/^TEMPLATE$/d',
- '-e', r'/^TEMPLATE-EXTENDED$/d',
- '-e', r'/^TEMPLATE-TESTS$/d',
- '-e', r'/^\..*/d',
- '-e', r'/~$/d',
- '-e', r'/-tests$/d',
- ]
# Read modules from gnulib root directory.
os.chdir(constants.DIRS['root'])
@@ -154,24 +150,23 @@ class GLModuleSystem(object):
find = sp.Popen(find_args, stdout=sp.PIPE)
result += find.stdout.read().decode("UTF-8")
os.chdir(DIRS['cwd'])
- sed_args += ['-e', r's,\.diff$,,']
-
- # Save the list of the modules to file.
- path = joinpath(self.config['tempdir'], 'list')
- with codecs.open(path, 'wb', 'UTF-8') as file:
- file.write(result)
-
- # Filter the list of the modules.
- stdin = codecs.open(path, 'rb', 'UTF-8')
- sed = sp.Popen(sed_args, stdin=stdin, stdout=sp.PIPE)
- result = sed.stdout.read().decode("UTF-8")
- stdin.close()
- os.remove(path)
+
listing = [ line
for line in result.split('\n')
if line.strip() ]
- listing = sorted(set(listing))
- return listing
+ if len(localpath) > 0:
+ listing = [ subend('.diff', '', line)
+ for line in listing ]
+ # Remove modules/ prefix from each file name.
+ pattern = re.compile('^modules/')
+ listing = [ pattern.sub('', line)
+ for line in listing ]
+ # Filter out undesired file names.
+ listing = [ line
+ for line in listing
+ if self.file_is_module(line) and not line.endswith('-tests') ]
+ modules = sorted(set(listing))
+ return modules
#===============================================================================
--
2.34.1
>From 8341b4a206b8f1f6ec14966292afb5134de2a4c2 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 17:29:16 +0200
Subject: [PATCH 12/19] gnulib-tool.py: Reduce code duplication.
* pygnulib/GLModuleSystem.py (GLModule): Declare two regexes are class
variables.
---
ChangeLog | 4 ++
pygnulib/GLModuleSystem.py | 84 +++++++++++---------------------------
2 files changed, 27 insertions(+), 61 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index acb82e903c..a8d020edab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Reduce code duplication.
+ * pygnulib/GLModuleSystem.py (GLModule): Declare two regexes are class
+ variables.
+
gnulib-tool.py: Implement option --find.
* pygnulib/GLModuleSystem.py (GLModuleSystem.file_is_module): New
method.
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index 3383b22b28..33495f9c07 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -177,6 +177,15 @@ class GLModule(object):
path. GLModule can get all information about module, get its dependencies,
files, etc.'''
+ section_label_regex = '(?:Description:|Comment:|Status:|Notice:|Applicability:|\
+Files:|Depends-on:|configure\\.ac-early:|configure\\.ac:|Makefile\\.am:|\
+Include:|Link:|License:|Maintainer:)'
+
+ section_label_pattern = \
+ re.compile('^(Description|Comment|Status|Notice|Applicability|'
+ + 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
+ + 'Makefile\\.am|Include|Link|License|Maintainer):$')
+
def __init__(self, config, module, patched=False):
'''GLModule.__init__(config, module[, patched]) -> GLModule
@@ -202,9 +211,6 @@ class GLModule(object):
self.modulesystem = GLModuleSystem(self.config)
with codecs.open(module, 'rb', 'UTF-8') as file:
self.content = file.read()
- self.regex = '(?:Description:|Comment:|Status:|Notice:|Applicability:|\
-Files:|Depends-on:|configure\\.ac-early:|configure\\.ac:|Makefile\\.am:|\
-Include:|Link:|License:|Maintainer:)'
def __eq__(self, module):
'''x.__eq__(y) <==> x==y'''
@@ -379,7 +385,7 @@ Include:|Link:|License:|Maintainer:)'
if section not in self.content:
result = ''
else: # if section in self.content
- pattern = '^%s[\t ]*(.*?)%s' % (section, self.regex)
+ pattern = '^%s[\t ]*(.*?)%s' % (section, GLModule.section_label_regex)
pattern = re.compile(pattern, re.S | re.M)
result = pattern.findall(self.content)
if type(result) is list:
@@ -400,7 +406,7 @@ Include:|Link:|License:|Maintainer:)'
if section not in self.content:
result = ''
else: # if section in self.content
- pattern = '^%s[\t ]*(.*?)%s' % (section, self.regex)
+ pattern = '^%s[\t ]*(.*?)%s' % (section, GLModule.section_label_regex)
pattern = re.compile(pattern, re.S | re.M)
result = pattern.findall(self.content)
if type(result) is list:
@@ -427,11 +433,7 @@ Include:|Link:|License:|Maintainer:)'
for line in snippet.split('\n') ]
parts = list()
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
@@ -456,11 +458,7 @@ Include:|Link:|License:|Maintainer:)'
for line in snippet.split('\n') ]
parts = list()
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
@@ -483,11 +481,7 @@ Include:|Link:|License:|Maintainer:)'
for line in snippet.split('\n') ]
parts = list()
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
@@ -521,11 +515,7 @@ Include:|Link:|License:|Maintainer:)'
for line in snippet.split('\n') ]
parts = list()
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
@@ -555,11 +545,7 @@ Include:|Link:|License:|Maintainer:)'
for line in snippet.split('\n') ]
parts = list()
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
@@ -599,11 +585,7 @@ Include:|Link:|License:|Maintainer:)'
for line in snippet.split('\n') ]
parts = list()
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
@@ -626,11 +608,7 @@ Include:|Link:|License:|Maintainer:)'
for line in snippet.split('\n') ]
parts = list()
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
@@ -667,11 +645,7 @@ Include:|Link:|License:|Maintainer:)'
for line in snippet.split('\n') ]
parts = list()
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
@@ -765,11 +739,7 @@ Include:|Link:|License:|Maintainer:)'
for line in snippet.split('\n') ]
parts = list()
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
@@ -793,11 +763,7 @@ Include:|Link:|License:|Maintainer:)'
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
@@ -838,7 +804,7 @@ Include:|Link:|License:|Maintainer:)'
if section not in self.content:
result = ''
else: # if section in self.content
- pattern = '^%s[\t ]*(.*?)%s' % (section, self.regex)
+ pattern = '^%s[\t ]*(.*?)%s' % (section, GLModule.section_label_regex)
pattern = re.compile(pattern, re.S | re.M)
result = pattern.findall(self.content)
if type(result) is list:
@@ -865,11 +831,7 @@ Include:|Link:|License:|Maintainer:)'
for line in snippet.split('\n') ]
parts = list()
for line in lines:
- regex = '^(Description|Comment|Status|Notice|Applicability|'
- regex += 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- regex += 'Makefile\\.am|Include|Link|License|Maintainer):$'
- pattern = re.compile(regex)
- findflag = pattern.findall(line)
+ findflag = GLModule.section_label_pattern.findall(line)
if findflag:
break
parts += [line]
--
2.34.1
>From 9b2a7c800a82de247a92d43c10cc926fdcc11031 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 19:26:51 +0200
Subject: [PATCH 13/19] gnulib-tool.py: Simplify.
* pygnulib/GLModuleSystem.py (GLModule): Convert Windows newlines right
after reading the module description, not in every accessor.
---
ChangeLog | 4 ++++
pygnulib/GLModuleSystem.py | 13 +------------
2 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index a8d020edab..fceb1538a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Simplify.
+ * pygnulib/GLModuleSystem.py (GLModule): Convert Windows newlines right
+ after reading the module description, not in every accessor.
+
gnulib-tool.py: Reduce code duplication.
* pygnulib/GLModuleSystem.py (GLModule): Declare two regexes are class
variables.
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index 33495f9c07..b736bf2ed1 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -210,7 +210,7 @@ Include:|Link:|License:|Maintainer:)'
self.filesystem = GLFileSystem(self.config)
self.modulesystem = GLModuleSystem(self.config)
with codecs.open(module, 'rb', 'UTF-8') as file:
- self.content = file.read()
+ self.content = file.read().replace('\r\n', '\n')
def __eq__(self, module):
'''x.__eq__(y) <==> x==y'''
@@ -428,7 +428,6 @@ Include:|Link:|License:|Maintainer:)'
result = ''
else: # if section in self.content
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
parts = list()
@@ -453,7 +452,6 @@ Include:|Link:|License:|Maintainer:)'
result = ''
else: # if section in self.content
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
parts = list()
@@ -476,7 +474,6 @@ Include:|Link:|License:|Maintainer:)'
result = ''
else: # if section in self.content
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
parts = list()
@@ -510,7 +507,6 @@ Include:|Link:|License:|Maintainer:)'
result = list()
else: # if section in self.content
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
parts = list()
@@ -540,7 +536,6 @@ Include:|Link:|License:|Maintainer:)'
depmodules = list()
else: # if section in self.content
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
parts = list()
@@ -580,7 +575,6 @@ Include:|Link:|License:|Maintainer:)'
result = ''
else: # if section in self.content
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
parts = list()
@@ -603,7 +597,6 @@ Include:|Link:|License:|Maintainer:)'
result = ''
else: # if section in self.content
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
parts = list()
@@ -640,7 +633,6 @@ Include:|Link:|License:|Maintainer:)'
result = ''
else: # if section in self.content
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
parts = list()
@@ -734,7 +726,6 @@ Include:|Link:|License:|Maintainer:)'
result = ''
else: # if section in self.content
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
parts = list()
@@ -759,7 +750,6 @@ Include:|Link:|License:|Maintainer:)'
parts = list()
if section in self.content:
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
for line in lines:
@@ -826,7 +816,6 @@ Include:|Link:|License:|Maintainer:)'
result = ''
else: # if section in self.content
snippet = self.content.split(section)[-1]
- snippet = snippet.replace('\r\n', '\n')
lines = [ '%s\n' % line
for line in snippet.split('\n') ]
parts = list()
--
2.34.1
>From 586000e597d4ef7cba8de869a15ad5c922a2010c Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 20:04:56 +0200
Subject: [PATCH 14/19] gnulib-tool.py: Improve field naming.
* pygnulib/GLModuleSystem.py (GLModule): Rename field 'module' to
'path'. Fix a typo in a TypeError message.
---
ChangeLog | 4 ++++
pygnulib/GLModuleSystem.py | 38 ++++++++++++++++++--------------------
2 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index fceb1538a8..36962c2dd2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Improve field naming.
+ * pygnulib/GLModuleSystem.py (GLModule): Rename field 'module' to
+ 'path'. Fix a typo in a TypeError message.
+
gnulib-tool.py: Simplify.
* pygnulib/GLModuleSystem.py (GLModule): Convert Windows newlines right
after reading the module description, not in every accessor.
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index b736bf2ed1..ec2ff0c35c 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -186,11 +186,11 @@ Include:|Link:|License:|Maintainer:)'
+ 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
+ 'Makefile\\.am|Include|Link|License|Maintainer):$')
- def __init__(self, config, module, patched=False):
- '''GLModule.__init__(config, module[, patched]) -> GLModule
+ def __init__(self, config, path, patched=False):
+ '''GLModule.__init__(config, path[, patched]) -> GLModule
- Create new GLModule instance. Arguments are module and patched, where
- module is a string representing the path to the module and patched is a
+ Create new GLModule instance. Arguments are path and patched, where
+ path is a string representing the path to the module and patched is a
bool indicating that module was created after applying patch.'''
self.args = dict()
self.cache = dict()
@@ -198,25 +198,25 @@ Include:|Link:|License:|Maintainer:)'
if type(config) is not GLConfig:
raise TypeError('config must be a GLConfig, not %s'
% type(config).__name__)
- if type(module) is not str:
- raise TypeError('module must be a string, not %s'
- % type(module).__name__)
+ if type(path) is not str:
+ raise TypeError('path must be a string, not %s'
+ % type(path).__name__)
if type(patched) is not bool:
raise TypeError('patched must be a bool, not %s'
- % type(module).__name__)
- self.module = module
+ % type(patched).__name__)
+ self.path = path
self.patched = patched
self.config = config
self.filesystem = GLFileSystem(self.config)
self.modulesystem = GLModuleSystem(self.config)
- with codecs.open(module, 'rb', 'UTF-8') as file:
+ with codecs.open(path, 'rb', 'UTF-8') as file:
self.content = file.read().replace('\r\n', '\n')
def __eq__(self, module):
'''x.__eq__(y) <==> x==y'''
result = bool()
if type(module) is GLModule:
- if self.module == module.module:
+ if self.path == module.path:
result = True
return result
@@ -224,7 +224,7 @@ Include:|Link:|License:|Maintainer:)'
'''x.__ne__(y) <==> x!=y'''
result = bool()
if type(module) is GLModule:
- if self.module != module.module:
+ if self.path != module.path:
result = True
return result
@@ -232,7 +232,7 @@ Include:|Link:|License:|Maintainer:)'
'''x.__ge__(y) <==> x>=y'''
result = bool()
if type(module) is GLModule:
- if self.module >= module.module:
+ if self.path >= module.path:
result = True
return result
@@ -240,22 +240,20 @@ Include:|Link:|License:|Maintainer:)'
'''x.__gt__(y) <==> x>y'''
result = bool()
if type(module) is GLModule:
- if self.module > module.module:
+ if self.path > module.path:
result = True
return result
def __hash__(self):
'''x.__hash__() <==> hash(x)'''
- module = hash(self.module)
- patched = hash(self.patched)
- result = module ^ patched
+ result = hash(self.path) ^ hash(self.patched)
return result
def __le__(self, module):
'''x.__le__(y) <==> x<=y'''
result = bool()
if type(module) is GLModule:
- if self.module <= module.module:
+ if self.path <= module.path:
result = True
return result
@@ -263,7 +261,7 @@ Include:|Link:|License:|Maintainer:)'
'''x.__lt__(y) <==> x<y'''
result = bool()
if type(module) is GLModule:
- if self.module < module.module:
+ if self.path < module.path:
result = True
return result
@@ -282,7 +280,7 @@ Include:|Link:|License:|Maintainer:)'
Return the name of the module.'''
pattern = re.compile(joinpath('modules', '(.*)$'))
- result = pattern.findall(self.module)[0]
+ result = pattern.findall(self.path)[0]
return result
def isPatched(self):
--
2.34.1
>From 81b8c4d5565dbbea10eb3561063d2e8da52148d7 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 22:53:32 +0200
Subject: [PATCH 15/19] gnulib-tool.py: Fix section extraction from module
descriptions.
The code with self.content.split(section)[-1]
was broken because it recognizes an indented section label.
Similar code with ('\n' + self.content).split('\n' + section)[-1]
would still be broken because it recognizes an indented section label
in the first line of the file.
The code with section_label_regex
was broken because sometimes it returns the second-to-last section with
the given label, not the last one.
Also, whitespace after the colon was not ignored.
* pygnulib/GLModuleSystem.py (GLModule.__init__): Dissect the module
description's contents immediately, once only, in a reliable way.
(GLModule.getDescription, GLModule.getComment): Simplify.
(GLModule.getStatus): Simplify. Return a string.
(GLModule.getStatuses): New function. Return a list.
(GLModule.getNotice, GLModule.getApplicability, GLModule.getFiles,
GLModule.getDependencies, GLModules.getAutoconfSnippet_Early,
GLModules.getAutoconfSnippet, GLModule.getAutomakeSnippet_Conditional,
GLModule.getInclude, GLModule.getLink, GLModule.getLicense_Raw):
Simplify.
(GLModule.getLicense): Remove whitespace after calling getLicense_Raw.
(GLModule.getMaintainer): Simplify.
(GLModuleTable.transitive_closure): Call getStatuses() instead of
getStatus().
* pygnulib/GLEmiter.py: Likewise.
* gnulib-tool.py (main): For --extract-description, --extract-comment,
--extract-status, --extract-notice, --extract-autoconf-snippet,
--extract-automake-snippet, --extract-include-directive,
--extract-link-directive, --extract-maintainer, don't add an extra
newline after the snippet.
---
ChangeLog | 31 +++
gnulib-tool.py | 19 +-
gnulib-tool.py.TODO | 1 -
pygnulib/GLEmiter.py | 4 +-
pygnulib/GLModuleSystem.py | 387 ++++++++++---------------------------
5 files changed, 140 insertions(+), 302 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 36962c2dd2..305d02be51 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,36 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Fix section extraction from module descriptions.
+ The code with self.content.split(section)[-1]
+ was broken because it recognizes an indented section label.
+ Similar code with ('\n' + self.content).split('\n' + section)[-1]
+ would still be broken because it recognizes an indented section label
+ in the first line of the file.
+ The code with section_label_regex
+ was broken because sometimes it returns the second-to-last section with
+ the given label, not the last one.
+ Also, whitespace after the colon was not ignored.
+ * pygnulib/GLModuleSystem.py (GLModule.__init__): Dissect the module
+ description's contents immediately, once only, in a reliable way.
+ (GLModule.getDescription, GLModule.getComment): Simplify.
+ (GLModule.getStatus): Simplify. Return a string.
+ (GLModule.getStatuses): New function. Return a list.
+ (GLModule.getNotice, GLModule.getApplicability, GLModule.getFiles,
+ GLModule.getDependencies, GLModules.getAutoconfSnippet_Early,
+ GLModules.getAutoconfSnippet, GLModule.getAutomakeSnippet_Conditional,
+ GLModule.getInclude, GLModule.getLink, GLModule.getLicense_Raw):
+ Simplify.
+ (GLModule.getLicense): Remove whitespace after calling getLicense_Raw.
+ (GLModule.getMaintainer): Simplify.
+ (GLModuleTable.transitive_closure): Call getStatuses() instead of
+ getStatus().
+ * pygnulib/GLEmiter.py: Likewise.
+ * gnulib-tool.py (main): For --extract-description, --extract-comment,
+ --extract-status, --extract-notice, --extract-autoconf-snippet,
+ --extract-automake-snippet, --extract-include-directive,
+ --extract-link-directive, --extract-maintainer, don't add an extra
+ newline after the snippet.
+
gnulib-tool.py: Improve field naming.
* pygnulib/GLModuleSystem.py (GLModule): Rename field 'module' to
'path'. Fix a typo in a TypeError message.
diff --git a/gnulib-tool.py b/gnulib-tool.py
index 032deee6e0..0e888e6fd8 100755
--- a/gnulib-tool.py
+++ b/gnulib-tool.py
@@ -974,29 +974,28 @@ def main():
modules = [ modulesystem.find(module)
for module in modules ]
for module in modules:
- print(module.getDescription())
+ sys.stdout.write(module.getDescription())
elif mode == 'extract-comment':
modulesystem = classes.GLModuleSystem(config)
modules = [ modulesystem.find(module)
for module in modules ]
for module in modules:
- print(module.getComment())
+ sys.stdout.write(module.getComment())
elif mode == 'extract-status':
modulesystem = classes.GLModuleSystem(config)
modules = [ modulesystem.find(module)
for module in modules ]
for module in modules:
- status = module.getStatus()
- print('\n'.join(status))
+ sys.stdout.write(module.getStatus())
elif mode == 'extract-notice':
modulesystem = classes.GLModuleSystem(config)
modules = [ modulesystem.find(module)
for module in modules ]
for module in modules:
- print(module.getNotice())
+ sys.stdout.write(module.getNotice())
elif mode == 'extract-applicability':
modulesystem = classes.GLModuleSystem(config)
@@ -1039,28 +1038,28 @@ def main():
modules = [ modulesystem.find(module)
for module in modules ]
for module in modules:
- print(module.getAutoconfSnippet())
+ sys.stdout.write(module.getAutoconfSnippet())
elif mode == 'extract-automake-snippet':
modulesystem = classes.GLModuleSystem(config)
modules = [ modulesystem.find(module)
for module in modules ]
for module in modules:
- print(module.getAutomakeSnippet())
+ sys.stdout.write(module.getAutomakeSnippet())
elif mode == 'extract-include-directive':
modulesystem = classes.GLModuleSystem(config)
modules = [ modulesystem.find(module)
for module in modules ]
for module in modules:
- print(module.getInclude())
+ sys.stdout.write(module.getInclude())
elif mode == 'extract-link-directive':
modulesystem = classes.GLModuleSystem(config)
modules = [ modulesystem.find(module)
for module in modules ]
for module in modules:
- print(module.getLink())
+ sys.stdout.write(module.getLink())
elif mode == 'extract-license':
modulesystem = classes.GLModuleSystem(config)
@@ -1074,7 +1073,7 @@ def main():
modules = [ modulesystem.find(module)
for module in modules ]
for module in modules:
- print(module.getMaintainer())
+ sys.stdout.write(module.getMaintainer())
elif mode == 'extract-tests-module':
modulesystem = classes.GLModuleSystem(config)
diff --git a/gnulib-tool.py.TODO b/gnulib-tool.py.TODO
index a46da5e2ad..9efcda510d 100644
--- a/gnulib-tool.py.TODO
+++ b/gnulib-tool.py.TODO
@@ -37,7 +37,6 @@ Implement the options:
Remove exit() in GLImport.py.
Optimize:
- - GLModuleSystem: Parse each module description only once.
- os.chdir around subprocess creation -> cwd=... argument instead.
--------------------------------------------------------------------------------
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index e0164ed7cc..61cabc92fa 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -974,9 +974,9 @@ AC_DEFUN([%V1%_LIBSOURCES], [
# Skip the contents if it's entirely empty.
if snippet.strip():
# Check status of the module.
- status = module.getStatus()
+ statuses = module.getStatuses()
islongrun = False
- for word in status:
+ for word in statuses:
if word == 'longrunning-test':
islongrun = True
break
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index ec2ff0c35c..32a133009a 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -177,14 +177,11 @@ class GLModule(object):
path. GLModule can get all information about module, get its dependencies,
files, etc.'''
- section_label_regex = '(?:Description:|Comment:|Status:|Notice:|Applicability:|\
-Files:|Depends-on:|configure\\.ac-early:|configure\\.ac:|Makefile\\.am:|\
-Include:|Link:|License:|Maintainer:)'
-
section_label_pattern = \
re.compile('^(Description|Comment|Status|Notice|Applicability|'
+ 'Files|Depends-on|configure\\.ac-early|configure\\.ac|'
- + 'Makefile\\.am|Include|Link|License|Maintainer):$')
+ + 'Makefile\\.am|Include|Link|License|Maintainer):$',
+ re.M)
def __init__(self, config, path, patched=False):
'''GLModule.__init__(config, path[, patched]) -> GLModule
@@ -209,8 +206,20 @@ Include:|Link:|License:|Maintainer:)'
self.config = config
self.filesystem = GLFileSystem(self.config)
self.modulesystem = GLModuleSystem(self.config)
+ # Read the module description file into memory.
with codecs.open(path, 'rb', 'UTF-8') as file:
self.content = file.read().replace('\r\n', '\n')
+ # Dissect it into sections.
+ self.sections = dict()
+ last_section_label = None
+ last_section_start = 0
+ for match in GLModule.section_label_pattern.finditer(self.content):
+ if last_section_label != None:
+ self.sections[last_section_label] = self.content[last_section_start : match.start()]
+ last_section_label = match.group(1)
+ last_section_start = match.end() + 1
+ if last_section_label != None:
+ self.sections[last_section_label] = self.content[last_section_start:]
def __eq__(self, module):
'''x.__eq__(y) <==> x==y'''
@@ -378,117 +387,51 @@ Include:|Link:|License:|Maintainer:)'
'''GLModule.getDescription() -> str
Return description of the module.'''
- section = 'Description:'
- if 'description' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- pattern = '^%s[\t ]*(.*?)%s' % (section, GLModule.section_label_regex)
- pattern = re.compile(pattern, re.S | re.M)
- result = pattern.findall(self.content)
- if type(result) is list:
- if not result:
- result = ''
- else: # if result
- result = result[-1]
- result = result.strip()
- self.cache['description'] = result
- return self.cache['description']
+ return self.sections.get('Description', '')
def getComment(self):
'''GLModule.getComment() -> str
Return comment to module.'''
- section = 'Comment:'
- if 'comment' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- pattern = '^%s[\t ]*(.*?)%s' % (section, GLModule.section_label_regex)
- pattern = re.compile(pattern, re.S | re.M)
- result = pattern.findall(self.content)
- if type(result) is list:
- if not result:
- result = ''
- else: # if result
- result = result[-1]
- result = result.strip()
- self.cache['comment'] = result
- return self.cache['comment']
+ return self.sections.get('Comment', '')
def getStatus(self):
'''GLModule.getStatus() -> str
Return module status.'''
- section = 'Status:'
- if 'status' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- parts = list()
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- result = [ part.strip()
- for part in parts
- if part.strip() ]
- self.cache['status'] = list(result)
- return list(self.cache['status'])
+ return self.sections.get('Status', '')
+
+ def getStatuses(self):
+ '''GLModule.getStatuses() -> list
+
+ Return module status.'''
+ if 'statuses' not in self.cache:
+ snippet = self.getStatus()
+ result = [ line.strip()
+ for line in snippet.split('\n')
+ if line.strip() ]
+ self.cache['statuses'] = result
+ return self.cache['statuses']
def getNotice(self):
'''GLModule.getNotice() -> str
Return notice to module.'''
- section = 'Notice:'
- if 'notice' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- parts = list()
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- result = ''.join(parts)
- self.cache['notice'] = result
- return self.cache['notice']
+ return self.sections.get('Notice', '')
def getApplicability(self):
'''GLModule.getApplicability() -> str
Return applicability of module.'''
- section = 'Applicability:'
if 'applicability' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- parts = list()
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- parts = [ part.strip()
- for part in parts ]
- result = ''.join(parts)
- if not result.strip():
- if self.getName().endswith('-tests'):
+ result = self.sections.get('Applicability', '')
+ result = result.strip()
+ if not result:
+ # The default is 'main' or 'tests', depending on the module's name.
+ if self.isTests():
result = 'tests'
- else: # if not self.getName().endswith('-tests')
+ else:
result = 'main'
- result = result.strip()
self.cache['applicability'] = result
return self.cache['applicability']
@@ -497,115 +440,56 @@ Include:|Link:|License:|Maintainer:)'
Return list of files.
GLConfig: ac_version.'''
- ac_version = self.config['ac_version']
- section = 'Files:'
- result = list()
if 'files' not in self.cache:
- if section not in self.content:
- result = list()
- else: # if section in self.content
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- parts = list()
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- result = [ part.strip()
- for part in parts
- if part.strip() ]
- result += [joinpath('m4', '00gnulib.m4')]
- result += [joinpath('m4', 'zzgnulib.m4')]
- result += [joinpath('m4', 'gnulib-common.m4')]
- self.cache['files'] = list(result)
- return list(self.cache['files'])
+ snippet = self.sections.get('Files', '')
+ result = [ line.strip()
+ for line in snippet.split('\n')
+ if line.strip() ]
+ result.append(joinpath('m4', '00gnulib.m4'))
+ result.append(joinpath('m4', 'zzgnulib.m4'))
+ result.append(joinpath('m4', 'gnulib-common.m4'))
+ self.cache['files'] = result
+ return self.cache['files']
def getDependencies(self):
'''GLModule.getDependencies() -> list
Return list of dependencies.
GLConfig: localpath.'''
- result = list()
- section = 'Depends-on:'
if 'dependencies' not in self.cache:
- if section not in self.content:
- depmodules = list()
- else: # if section in self.content
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- parts = list()
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- modules = ''.join(parts)
- modules = [ line
- for line in modules.split('\n')
- if line.strip() ]
- modules = [ module
- for module in modules
- if not module.startswith('#') ]
- for line in modules:
- split = [ part
- for part in line.split(' ')
- if part.strip() ]
- if len(split) == 1:
- module = line.strip()
- condition = None
- else: # if len(split) != 1
- module = split[0]
- condition = split[1]
- result += [tuple([self.modulesystem.find(module), condition])]
+ snippet = self.sections.get('Depends-on', '')
+ modules = [ line.strip()
+ for line in snippet.split('\n')
+ if line.strip() ]
+ modules = [ module
+ for module in modules
+ if not module.startswith('#') ]
+ result = list()
+ for line in modules:
+ split = [ part
+ for part in line.split(' ')
+ if part.strip() ]
+ if len(split) == 1:
+ module = line.strip()
+ condition = None
+ else: # if len(split) != 1
+ module = split[0]
+ condition = split[1]
+ result += [tuple([self.modulesystem.find(module), condition])]
self.cache['dependencies'] = result
- return list(self.cache['dependencies'])
+ return self.cache['dependencies']
def getAutoconfSnippet_Early(self):
'''GLModule.getAutoconfSnippet_Early() -> str
Return autoconf-early snippet.'''
- section = 'configure.ac-early:'
- if 'autoconf-early' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- parts = list()
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- result = ''.join(parts)
- self.cache['autoconf-early'] = result
- return self.cache['autoconf-early']
+ return self.sections.get('configure.ac-early', '')
def getAutoconfSnippet(self):
'''GLModule.getAutoconfSnippet() -> str
Return autoconf snippet.'''
- section = 'configure.ac:'
- if 'autoconf' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- parts = list()
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- result = ''.join(parts)
- self.cache['autoconf'] = result
- return self.cache['autoconf']
+ return self.sections.get('configure.ac', '')
def getAutomakeSnippet(self):
'''getAutomakeSnippet() -> str
@@ -625,23 +509,7 @@ Include:|Link:|License:|Maintainer:)'
'''GLModule.getAutomakeSnippet_Conditional() -> str
Return conditional automake snippet.'''
- section = 'Makefile.am:'
- if 'makefile-conditional' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- parts = list()
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- result = ''.join(parts)
- self.cache['makefile-conditional'] = result
- return self.cache['makefile-conditional']
+ return self.sections.get('Makefile.am', '')
def getAutomakeSnippet_Unconditional(self):
'''GLModule.getAutomakeSnippet_Unconditional() -> str
@@ -718,24 +586,10 @@ Include:|Link:|License:|Maintainer:)'
'''GLModule.getInclude() -> str
Return include directive.'''
- section = 'Include:'
if 'include' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- parts = list()
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- result = ''.join(parts)
- result = result.strip()
- pattern = re.compile('^(["<].*[>"])', re.M)
- result = pattern.sub('#include \\1', result)
+ snippet = self.sections.get('Include', '')
+ pattern = re.compile('^(["<])', re.M)
+ result = pattern.sub('#include \\1', snippet)
self.cache['include'] = result
return self.cache['include']
@@ -743,64 +597,36 @@ Include:|Link:|License:|Maintainer:)'
'''GLModule.getLink() -> str
Return link directive.'''
- section = 'Link:'
- if 'link' not in self.cache:
- parts = list()
- if section in self.content:
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- parts = [ part.strip()
- for part in parts
- if part.strip() ]
- # result = ' '.join(parts)
- self.cache['link'] = parts
- return self.cache['link']
-
- def getLicense(self):
- '''GLModule.getLicense(self) -> str
-
- Get license and warn user if module lacks a license.'''
- if str(self) == 'parse-datetime':
- # This module is under a weaker license only for the purpose of some
- # users who hand-edit it and don't use gnulib-tool. For the regular
- # gnulib users they are under a stricter license.
- return 'GPL'
- else:
- license = self.getLicense_Raw()
- if not self.isTests():
- if not license:
- if self.config['errors']:
- raise GLError(18, str(self))
- else: # if not self.config['errors']
- sys.stderr.write('gnulib-tool: warning: module %s lacks a license\n' % str(self))
- if not license:
- license = 'GPL'
- return license
+ return self.sections.get('Link', '')
def getLicense_Raw(self):
'''GLModule.getLicense_Raw() -> str
Return module license.'''
- section = 'License:'
+ return self.sections.get('License', '')
+
+ def getLicense(self):
+ '''GLModule.getLicense(self) -> str
+
+ Get license and warn user if module lacks a license.'''
if 'license' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- pattern = '^%s[\t ]*(.*?)%s' % (section, GLModule.section_label_regex)
- pattern = re.compile(pattern, re.S | re.M)
- result = pattern.findall(self.content)
- if type(result) is list:
- if not result:
- result = ''
- else: # if result
- result = result[-1]
- result = result.strip()
+ result = None
+ if str(self) == 'parse-datetime':
+ # This module is under a weaker license only for the purpose of some
+ # users who hand-edit it and don't use gnulib-tool. For the regular
+ # gnulib users they are under a stricter license.
+ result = 'GPL'
+ else:
+ license = self.getLicense_Raw().strip()
+ if not self.isTests():
+ if not license:
+ if self.config['errors']:
+ raise GLError(18, str(self))
+ else: # if not self.config['errors']
+ sys.stderr.write('gnulib-tool: warning: module %s lacks a license\n' % str(self))
+ if not license:
+ license = 'GPL'
+ result = license
self.cache['license'] = result
return self.cache['license']
@@ -808,24 +634,7 @@ Include:|Link:|License:|Maintainer:)'
'''GLModule.getMaintainer() -> str
Return maintainer directive.'''
- section = 'Maintainer:'
- if 'maintainer' not in self.cache:
- if section not in self.content:
- result = ''
- else: # if section in self.content
- snippet = self.content.split(section)[-1]
- lines = [ '%s\n' % line
- for line in snippet.split('\n') ]
- parts = list()
- for line in lines:
- findflag = GLModule.section_label_pattern.findall(line)
- if findflag:
- break
- parts += [line]
- result = ''.join(parts)
- result = result.strip()
- self.cache['maintainer'] = result
- return self.cache['maintainer']
+ return self.sections.get('Maintainer', '')
#===============================================================================
@@ -1002,8 +811,8 @@ class GLModuleTable(object):
conditions += [None]
for depmodule in depmodules:
include = True
- status = depmodule.getStatus()
- for word in status:
+ statuses = depmodule.getStatuses()
+ for word in statuses:
if word == 'obsolete':
if not self.config.checkInclTestCategory(TESTS['obsolete']):
include = False
--
2.34.1
>From d528738ac3449ce1c4897882e6032eb3a3e929e2 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sun, 7 Aug 2022 22:59:08 +0200
Subject: [PATCH 16/19] gnulib-tool.py: Rename a method.
* pygnulib/GLModuleSystem.py (GLModule.getAutoconfEarlySnippet): Renamed
from GLModule.getAutoconfSnippet_Early.
* pygnulib/GLImport.py: Update.
* pygnulib/GLTestDir.py: Likewise.
---
ChangeLog | 6 ++++++
pygnulib/GLImport.py | 2 +-
pygnulib/GLModuleSystem.py | 4 ++--
pygnulib/GLTestDir.py | 4 ++--
4 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 305d02be51..1278d8e4d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Rename a method.
+ * pygnulib/GLModuleSystem.py (GLModule.getAutoconfEarlySnippet): Renamed
+ from GLModule.getAutoconfSnippet_Early.
+ * pygnulib/GLImport.py: Update.
+ * pygnulib/GLTestDir.py: Likewise.
+
gnulib-tool.py: Fix section extraction from module descriptions.
The code with self.content.split(section)[-1]
was broken because it recognizes an indented section label.
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index 818f3d57c0..87d85c5181 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -606,7 +606,7 @@ AC_DEFUN([%s_EARLY],
emit += ' AC_REQUIRE([AM_PROG_CC_C_O])\n'
for module in moduletable['final']:
emit += ' # Code from module %s:\n' % str(module)
- snippet = module.getAutoconfSnippet_Early()
+ snippet = module.getAutoconfEarlySnippet()
lines = [ line
for line in snippet.split(constants.NL)
if line != '' ]
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index 32a133009a..14bc089b27 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -479,8 +479,8 @@ class GLModule(object):
self.cache['dependencies'] = result
return self.cache['dependencies']
- def getAutoconfSnippet_Early(self):
- '''GLModule.getAutoconfSnippet_Early() -> str
+ def getAutoconfEarlySnippet(self):
+ '''GLModule.getAutoconfEarlySnippet() -> str
Return autoconf-early snippet.'''
return self.sections.get('configure.ac-early', '')
diff --git a/pygnulib/GLTestDir.py b/pygnulib/GLTestDir.py
index 9a3fde66ea..746b815b49 100644
--- a/pygnulib/GLTestDir.py
+++ b/pygnulib/GLTestDir.py
@@ -456,7 +456,7 @@ class GLTestDir(object):
pass
# if str(module) not in ['gnumakefile', 'maintainer-makefile']
else:
- snippet = module.getAutoconfSnippet_Early()
+ snippet = module.getAutoconfEarlySnippet()
lines = [ line
for line in snippet.split('\n')
if line.strip() ]
@@ -573,7 +573,7 @@ class GLTestDir(object):
else: # if not single_configure
solution = module.isNonTests()
if solution:
- snippet = module.getAutoconfSnippet_Early()
+ snippet = module.getAutoconfEarlySnippet()
lines = [ line
for line in snippet.split('\n')
if line.strip() ]
--
2.34.1
>From 276c20ee288873b519be96ffe9b3a98bfe3bb8f1 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Mon, 8 Aug 2022 00:02:59 +0200
Subject: [PATCH 17/19] gnulib-tool.py: Fix --extract-dependencies result.
* pygnulib/GLModuleSystem.py (GLModule.getDependencies): Return a
snippet, not a list. Implement dependency of ${module}-tests on
${module}.
(GLModule.getDependenciesWithoutConditions,
GLModule.getDependenciesWithConditions): New methods.
(GLModuleTable.transitive_closure): Call getDependenciesWithConditions.
* pygnulib/GLEmiter.py (GLEmiter.autoconfSnippets): Call
getDependenciesWithoutConditions.
* gnulib-tool.py (main) [--extract-dependencies]: Update.
---
ChangeLog | 11 +++++
gnulib-tool.py | 10 +----
pygnulib/GLEmiter.py | 4 +-
pygnulib/GLModuleSystem.py | 83 ++++++++++++++++++++++++++++----------
4 files changed, 75 insertions(+), 33 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 1278d8e4d9..beb60578d0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Fix --extract-dependencies result.
+ * pygnulib/GLModuleSystem.py (GLModule.getDependencies): Return a
+ snippet, not a list. Implement dependency of ${module}-tests on
+ ${module}.
+ (GLModule.getDependenciesWithoutConditions,
+ GLModule.getDependenciesWithConditions): New methods.
+ (GLModuleTable.transitive_closure): Call getDependenciesWithConditions.
+ * pygnulib/GLEmiter.py (GLEmiter.autoconfSnippets): Call
+ getDependenciesWithoutConditions.
+ * gnulib-tool.py (main) [--extract-dependencies]: Update.
+
gnulib-tool.py: Rename a method.
* pygnulib/GLModuleSystem.py (GLModule.getAutoconfEarlySnippet): Renamed
from GLModule.getAutoconfSnippet_Early.
diff --git a/gnulib-tool.py b/gnulib-tool.py
index 0e888e6fd8..0cd5accd21 100755
--- a/gnulib-tool.py
+++ b/gnulib-tool.py
@@ -1013,7 +1013,6 @@ def main():
print('\n'.join(files))
elif mode == 'extract-dependencies':
- result = ''
if avoids:
message = '%s: *** ' % constants.APP['name']
message += 'cannot combine --avoid and --extract-dependencies\n'
@@ -1024,14 +1023,7 @@ def main():
modules = [ modulesystem.find(module)
for module in modules ]
for module in modules:
- dependencies = module.getDependencies()
- if dependencies:
- for depmodule, condition in dependencies:
- if condition == None:
- result += '%s\n' % str(depmodule)
- else: # if condition != None
- result += '%s\t%s' % (str(depmodule), condition)
- print(result)
+ sys.stdout.write(module.getDependencies())
elif mode == 'extract-autoconf-snippet':
modulesystem = classes.GLModuleSystem(config)
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index 61cabc92fa..a02b44bdd5 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -309,9 +309,7 @@ class GLEmiter(object):
emit += self.autoconfSnippet(module, fileassistant, toplevel,
disable_libtool, disable_gettext, replace_auxdir, ' ')
emit += ' %s=true\n' % shellvar
- dependencies = module.getDependencies()
- depmodules = [ pair[0]
- for pair in dependencies ]
+ depmodules = module.getDependenciesWithoutConditions()
# Intersect dependencies with the modules list.
depmodules = [ dep
for dep in depmodules
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index 14bc089b27..19d13d213b 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -452,33 +452,74 @@ class GLModule(object):
return self.cache['files']
def getDependencies(self):
- '''GLModule.getDependencies() -> list
+ '''GLModule.getDependencies() -> str
- Return list of dependencies.
+ Return list of dependencies, as a snippet.
GLConfig: localpath.'''
if 'dependencies' not in self.cache:
+ result = ''
+ # ${module}-tests implicitly depends on ${module}, if that module exists.
+ if self.isTests():
+ main_module = subend('-tests', '', self.getName())
+ if self.modulesystem.exists(main_module):
+ result += '%s\n' % main_module
+ # Then the explicit dependencies listed in the module description.
snippet = self.sections.get('Depends-on', '')
- modules = [ line.strip()
- for line in snippet.split('\n')
- if line.strip() ]
- modules = [ module
- for module in modules
- if not module.startswith('#') ]
- result = list()
- for line in modules:
- split = [ part
- for part in line.split(' ')
- if part.strip() ]
- if len(split) == 1:
- module = line.strip()
- condition = None
- else: # if len(split) != 1
- module = split[0]
- condition = split[1]
- result += [tuple([self.modulesystem.find(module), condition])]
+ # Remove comment lines.
+ snippet = re.compile('^#.*$[\n]', re.M).sub('', snippet)
+ result += snippet
self.cache['dependencies'] = result
return self.cache['dependencies']
+ def getDependenciesWithoutConditions(self):
+ '''GLModule.getDependenciesWithoutConditions() -> list
+
+ Return list of dependencies, as a list of GLModule objects.
+ GLConfig: localpath.'''
+ if 'dependenciesWithoutCond' not in self.cache:
+ snippet = self.getDependencies()
+ lines = [ line.strip()
+ for line in snippet.split('\n')
+ if line.strip() ]
+ pattern = re.compile(' *\\[.*$')
+ lines = [ pattern.sub('', line)
+ for line in lines ]
+ result = [ self.modulesystem.find(module)
+ for module in lines
+ if module != '' ]
+ self.cache['dependenciesWithoutCond'] = result
+ return self.cache['dependenciesWithoutCond']
+
+ def getDependenciesWithConditions(self):
+ '''GLModule.getDependenciesWithConditions() -> list
+
+ Return list of dependencies, as a list of pairs (GLModule object, condition).
+ The "true" condition is denoted by None.
+ GLConfig: localpath.'''
+
+ if 'dependenciesWithCond' not in self.cache:
+ snippet = self.getDependencies()
+ lines = [ line.strip()
+ for line in snippet.split('\n')
+ if line.strip() ]
+ pattern = re.compile(' *\\[')
+ result = []
+ for line in lines:
+ match = pattern.search(line)
+ if match:
+ module = line[0 : match.start()]
+ condition = line[match.end() :]
+ condition = subend(']', '', condition)
+ else:
+ module = line
+ condition = None
+ if module != '':
+ if condition == 'true':
+ condition = None
+ result.append(tuple([self.modulesystem.find(module), condition]))
+ self.cache['dependenciesWithCond'] = result
+ return self.cache['dependenciesWithCond']
+
def getAutoconfEarlySnippet(self):
'''GLModule.getAutoconfEarlySnippet() -> str
@@ -798,7 +839,7 @@ class GLModuleTable(object):
if not pattern.findall(automake_snippet):
self.addUnconditional(module)
conditional = self.isConditional(module)
- dependencies = module.getDependencies()
+ dependencies = module.getDependenciesWithConditions()
depmodules = [ pair[0]
for pair in dependencies ]
conditions = [ pair[1]
--
2.34.1
>From 6d29a15180d7ba0360d8fb56793a0766926b0dee Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Mon, 8 Aug 2022 00:43:25 +0200
Subject: [PATCH 18/19] gnulib-tool.py: Fix handling of nonexistent module
names in --extract-*.
* gnulib-tool.py (main): To test whether a module exists, just call
GLModuleSystem.find and test its return value.
---
ChangeLog | 4 ++
gnulib-tool.py | 133 ++++++++++++++++++++++++-------------------------
2 files changed, 68 insertions(+), 69 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index beb60578d0..f3a37cea1c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Fix handling of nonexistent module names in --extract-*.
+ * gnulib-tool.py (main): To test whether a module exists, just call
+ GLModuleSystem.find and test its return value.
+
gnulib-tool.py: Fix --extract-dependencies result.
* pygnulib/GLModuleSystem.py (GLModule.getDependencies): Return a
snippet, not a list. Implement dependency of ${module}-tests on
diff --git a/gnulib-tool.py b/gnulib-tool.py
index 0cd5accd21..0abe8c5ca7 100755
--- a/gnulib-tool.py
+++ b/gnulib-tool.py
@@ -47,7 +47,6 @@ import shlex
from tempfile import mktemp
from pygnulib import constants
from pygnulib import classes
-from pygnulib import GLError
#===============================================================================
@@ -716,8 +715,6 @@ def main():
print(result)
elif mode == 'find':
- # Prepare GLModuleSystem.find to throw an exception.
- config.setErrors(True)
modulesystem = classes.GLModuleSystem(config)
for filename in files:
if (isfile(joinpath(DIRS['root'], filename))
@@ -754,14 +751,12 @@ def main():
listing = [ line
for line in listing
if modulesystem.file_is_module(line) ]
- module_candidates = sorted(set(listing))
- for module in module_candidates:
- try:
- if filename in modulesystem.find(module).getFiles():
- print(module)
- except GLError:
- # Ignore module candidates that don't actually exist.
- pass
+ candidates = sorted(set(listing))
+ for name in candidates:
+ module = modulesystem.find(name)
+ if module: # Ignore module candidates that don't actually exist.
+ if module.getFiles():
+ print(name)
else:
message = '%s: warning: file %s does not exist\n' % (constants.APP['name'], filename)
sys.stderr.write(message)
@@ -971,46 +966,46 @@ def main():
elif mode == 'extract-description':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- sys.stdout.write(module.getDescription())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ sys.stdout.write(module.getDescription())
elif mode == 'extract-comment':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- sys.stdout.write(module.getComment())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ sys.stdout.write(module.getComment())
elif mode == 'extract-status':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- sys.stdout.write(module.getStatus())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ sys.stdout.write(module.getStatus())
elif mode == 'extract-notice':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- sys.stdout.write(module.getNotice())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ sys.stdout.write(module.getNotice())
elif mode == 'extract-applicability':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- print(module.getApplicability())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ print(module.getApplicability())
elif mode == 'extract-filelist':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- files = module.getFiles()
- print('\n'.join(files))
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ files = module.getFiles()
+ print('\n'.join(files))
elif mode == 'extract-dependencies':
if avoids:
@@ -1020,60 +1015,60 @@ def main():
sys.stderr.write(message)
sys.exit(1)
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- sys.stdout.write(module.getDependencies())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ sys.stdout.write(module.getDependencies())
elif mode == 'extract-autoconf-snippet':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- sys.stdout.write(module.getAutoconfSnippet())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ sys.stdout.write(module.getAutoconfSnippet())
elif mode == 'extract-automake-snippet':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- sys.stdout.write(module.getAutomakeSnippet())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ sys.stdout.write(module.getAutomakeSnippet())
elif mode == 'extract-include-directive':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- sys.stdout.write(module.getInclude())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ sys.stdout.write(module.getInclude())
elif mode == 'extract-link-directive':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- sys.stdout.write(module.getLink())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ sys.stdout.write(module.getLink())
elif mode == 'extract-license':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- print(module.getLicense())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ print(module.getLicense())
elif mode == 'extract-maintainer':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- sys.stdout.write(module.getMaintainer())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ sys.stdout.write(module.getMaintainer())
elif mode == 'extract-tests-module':
modulesystem = classes.GLModuleSystem(config)
- modules = [ modulesystem.find(module)
- for module in modules ]
- for module in modules:
- if module.getTestsModule():
- print(module.getTestsName())
+ for name in modules:
+ module = modulesystem.find(name)
+ if module:
+ if module.getTestsModule():
+ print(module.getTestsName())
elif mode == 'copy-file':
srcpath = files[0]
--
2.34.1
>From a7bcb91088e7fa6a533528aec076fc536789b96f Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Mon, 8 Aug 2022 00:46:13 +0200
Subject: [PATCH 19/19] gnulib-tool.py: Finish implementing option
--extract-test-module.
* gnulib-tool.py (main): Accept option --extract-tests-module.
---
ChangeLog | 3 +++
gnulib-tool.py | 8 ++++++++
gnulib-tool.py.TODO | 1 -
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/ChangeLog b/ChangeLog
index f3a37cea1c..63691ebfb6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2022-08-07 Bruno Haible <[email protected]>
+ gnulib-tool.py: Finish implementing option --extract-test-module.
+ * gnulib-tool.py (main): Accept option --extract-tests-module.
+
gnulib-tool.py: Fix handling of nonexistent module names in --extract-*.
* gnulib-tool.py (main): To test whether a module exists, just call
GLModuleSystem.find and test its return value.
diff --git a/gnulib-tool.py b/gnulib-tool.py
index 0abe8c5ca7..9988c84de9 100755
--- a/gnulib-tool.py
+++ b/gnulib-tool.py
@@ -180,6 +180,10 @@ def main():
dest='mode_xmaintainer',
default=None,
action='store_true')
+ parser.add_argument('--extract-tests-module',
+ dest='mode_xtests',
+ default=None,
+ action='store_true')
# copy-file
parser.add_argument('--copy-file',
dest='mode_copy_file',
@@ -446,6 +450,7 @@ def main():
cmdargs.mode_xlink,
cmdargs.mode_xlicense,
cmdargs.mode_xmaintainer,
+ cmdargs.mode_xtests,
cmdargs.mode_copy_file,
]
overflow = [ arg
@@ -535,6 +540,9 @@ def main():
if cmdargs.mode_xmaintainer != None:
mode = 'extract-maintainer'
modules = list(cmdargs.non_option_arguments)
+ if cmdargs.mode_xtests != None:
+ mode = 'extract-tests-module'
+ modules = list(cmdargs.non_option_arguments)
if cmdargs.mode_copy_file != None:
mode = 'copy-file'
if len(cmdargs.non_option_arguments) < 1 or len(cmdargs.non_option_arguments) > 2:
diff --git a/gnulib-tool.py.TODO b/gnulib-tool.py.TODO
index 9efcda510d..be6a2e2b10 100644
--- a/gnulib-tool.py.TODO
+++ b/gnulib-tool.py.TODO
@@ -22,7 +22,6 @@ Inline all 'sed' invocations.
Implement the options:
--extract-recursive-dependencies
--extract-recursive-link-directive
- --extract-tests-module
--conditional-dependencies
--no-conditional-dependencies
--gnu-make
--
2.34.1