[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63.
|
From: |
Bruno Haible |
|
Subject: |
Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63. |
|
Date: |
Mon, 18 Mar 2024 00:49:53 +0100 |
Collin Funk wrote:
> > FWIW '\n'.join([]) is '', so perhaps it isn't necessary to check
> > len(cleansed).
>
> Oops, you are correct. Thanks, that should make the code look nicer. I
> think I originally had '\n'.join(cleansed) + '\n', where the goal was
> to remove the + '\n' but I removed it. Good catch.
This is the second time we have to deal with this unlucky '\n'.join(...)
idiom.
It is not good if, each time we deal with a list of lines, we have to give
extra thought to the case of 0 lines. This is only a recipe for inconsistencies.
Instead, I'm applying this patch, eliminating all uses of this unlucky
idiom.
2024-03-17 Bruno Haible <bruno@clisp.org>
gnulib-tool.py: Handle empty lists of lines consistently.
* pygnulib/constants.py (lines_to_multiline): New function.
(nlremove): Remove unused function.
* pygnulib/GLEmiter.py (_eliminate_NMD): Use lines_to_multiline instead
of the '\n'.join idiom.
(GLEmiter.autoconfSnippet, GLEmiter.autoconfSnippets,
GLEmiter.lib_Makefile_am): Likewise.
* pygnulib/GLImport.py (GLImport._update_ignorelist_, GLImport.execute):
Likewise.
* pygnulib/GLModuleSystem.py (GLModule.getDependenciesRecursively,
GLModule.getLinkDirectiveRecursively, GLModuleTable.remove_if_blocks):
Likewise.
* pygnulib/GLTestDir.py (GLTestDir.execute): Likewise.
* pygnulib/main.py (main): Likewise.
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index a988f9f51f..97a5b5f62e 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -49,6 +49,7 @@ UTILS = constants.UTILS
TESTS = constants.TESTS
joinpath = constants.joinpath
relinverse = constants.relinverse
+lines_to_multiline = constants.lines_to_multiline
isfile = os.path.isfile
normpath = os.path.normpath
@@ -104,10 +105,7 @@ def _eliminate_NMD(snippet: str, automake_subdir: bool) ->
str:
line = _eliminate_NMD_from_line(line, automake_subdir)
if line != None:
result.append(line)
- if len(result) > 0:
- return '\n'.join(result) + '\n'
- else:
- return ''
+ return lines_to_multiline(result)
#===============================================================================
@@ -230,7 +228,7 @@ class GLEmiter(object):
lines = [ line
for line in snippet.split('\n')
if line.strip() ]
- snippet = '%s\n' % '\n'.join(lines)
+ snippet = lines_to_multiline(lines)
pattern = re.compile('^(.*)$', re.M)
snippet = pattern.sub('%s\\1' % indentation, snippet)
if disable_libtool:
@@ -258,7 +256,7 @@ class GLEmiter(object):
lines = [ line
for line in emit.split('\n')
if line.strip() ]
- emit = '%s\n' % '\n'.join(lines)
+ emit = lines_to_multiline(lines)
return emit
def autoconfSnippets(self, modules, referenceable_modules, moduletable,
@@ -441,7 +439,7 @@ class GLEmiter(object):
lines = [ line
for line in emit.split('\n')
if line.strip() ]
- emit = '%s\n' % '\n'.join(lines)
+ emit = lines_to_multiline(lines)
return emit
def preEarlyMacros(self, require, indentation, modules):
@@ -908,9 +906,8 @@ AC_DEFUN([%V1%_LIBSOURCES], [
capture_output=True)
if result.returncode == 0:
# sort -u
- emit += '\n'.join(sorted(list(set(x.strip() for x in
-
result.stdout.decode(encoding='utf-8').splitlines()))))
- emit += '\n'
+ emit += lines_to_multiline(sorted(list(set(x.strip()
+ for x in
result.stdout.decode(encoding='utf-8').splitlines()))))
else:
emit += '== gnulib-tool GNU Make output failed as follows ==\n'
emit += ['# stderr: ' + x + '\n' for x in
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index c06f0f9f6b..5ab314af36 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -51,6 +51,7 @@ cleaner = constants.cleaner
copyfile = constants.copyfile
copyfile2 = constants.copyfile2
movefile = constants.movefile
+lines_to_multiline = constants.lines_to_multiline
isabs = os.path.isabs
isdir = os.path.isdir
isfile = os.path.isfile
@@ -803,7 +804,7 @@ AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix
dirs_ignore = [ line
for line in dirs_ignore
if line.strip() ]
- srcdata = '\n'.join(sorted(set(dirs_ignore))).strip()
+ srcdata = lines_to_multiline(sorted(set(dirs_ignore)))
dirs_ignore += [ d
for d in dirs_added
if d not in dirs_ignore ]
@@ -813,7 +814,7 @@ AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix
dirs_ignore = [ '%s%s' % (anchor, d)
for d in dirs_ignore ]
dirs_ignore = sorted(set(dirs_ignore))
- destdata = '\n'.join(sorted(set(dirs_ignore))).strip()
+ destdata = lines_to_multiline(sorted(set(dirs_ignore)))
if srcdata != destdata:
if not self.config['dryrun']:
print('Updating %s (backup in %s)' % (srcpath,
backupname))
@@ -833,8 +834,7 @@ AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix
if ignore == '.cvsignore':
dirs_added = ['.deps', '.dirstamp'] + dirs_added
with codecs.open(joinpath(destdir, srcpath), 'wb',
'UTF-8') as file:
- file.write('\n'.join(dirs_added))
- file.write('\n')
+ file.write(lines_to_multiline(dirs_added))
else: # if self.config['dryrun']
print('Create %s' % srcpath)
@@ -1297,7 +1297,7 @@ AC_DEFUN([%s_FILE_LIST], [\n''' % macro_prefix
data = '# Set of available languages.\n'
files = [ constants.subend('.po', '', file)
for file in os.listdir(joinpath(destdir, pobase)) ]
- data += '\n'.join(files)
+ data += lines_to_multiline(files)
with codecs.open(tmpfile, 'wb', 'UTF-8') as file:
file.write(data)
filename, backup, flag = self.assistant.super_update(basename,
tmpfile)
diff --git a/pygnulib/GLModuleSystem.py b/pygnulib/GLModuleSystem.py
index 55b479e096..13d03d3af8 100644
--- a/pygnulib/GLModuleSystem.py
+++ b/pygnulib/GLModuleSystem.py
@@ -44,6 +44,7 @@ ENCS = constants.ENCS
TESTS = constants.TESTS
joinpath = constants.joinpath
subend = constants.subend
+lines_to_multiline = constants.lines_to_multiline
isdir = os.path.isdir
isfile = os.path.isfile
filter_filelist = constants.filter_filelist
@@ -352,12 +353,9 @@ class GLModule(object):
# Remove handledmodules from inmodules.
inmodules = inmodules.difference(handledmodules)
- if len(outmodules) > 0:
- module_names = sorted([ str(module)
- for module in outmodules ])
- return '\n'.join(module_names) + '\n'
- else:
- return ''
+ module_names = sorted([ str(module)
+ for module in outmodules ])
+ return lines_to_multiline(module_names)
def getLinkDirectiveRecursively(self) -> str:
'''Return a list of the link directives of this module separated
@@ -386,17 +384,14 @@ class GLModule(object):
# Remove handledmodules from inmodules.
inmodules = inmodules.difference(handledmodules)
- if len(outmodules) > 0:
- # Remove whitespace from sections.
- link_sections = [ module.getLink().strip()
- for module in outmodules ]
- # Sort the link directives.
- directives = sorted([ line
- for section in link_sections
- for line in section.splitlines() ])
- return '\n'.join(directives) + '\n'
- else:
- return ''
+ # Remove whitespace from sections.
+ link_sections = [ module.getLink().strip()
+ for module in outmodules ]
+ # Sort the link directives.
+ directives = sorted([ line
+ for section in link_sections
+ for line in section.splitlines() ])
+ return lines_to_multiline(directives)
def getShellFunc(self):
'''GLModule.getShellFunc() -> str
@@ -1064,10 +1059,7 @@ class GLModuleTable(object):
cleansed.append(line[5:])
elif depth == 0:
cleansed.append(line)
- if len(cleansed) > 0:
- return '\n'.join(cleansed)
- else:
- return ''
+ return lines_to_multiline(cleansed)
def add_dummy(self, modules):
'''GLModuleTable.add_dummy(modules) -> list
diff --git a/pygnulib/GLTestDir.py b/pygnulib/GLTestDir.py
index 156af057b5..e33319b575 100644
--- a/pygnulib/GLTestDir.py
+++ b/pygnulib/GLTestDir.py
@@ -54,6 +54,7 @@ relinverse = constants.relinverse
copyfile = constants.copyfile
ensure_writable = constants.ensure_writable
movefile = constants.movefile
+lines_to_multiline = constants.lines_to_multiline
isdir = os.path.isdir
isfile = os.path.isfile
normpath = os.path.normpath
@@ -461,7 +462,7 @@ class GLTestDir(object):
lines = [ line
for line in snippet.split('\n')
if line.strip() ]
- snippet = '\n'.join(lines)
+ snippet = lines_to_multiline(lines)
pattern = re.compile('AC_REQUIRE\\(\\[([^()]*)\\]\\)',
re.M)
snippet = pattern.sub('\\1', snippet)
snippet = snippet.strip()
@@ -469,7 +470,7 @@ class GLTestDir(object):
snippets = [ snippet
for snippet in snippets
if snippet.strip()]
- emit += '%s\n' % '\n'.join(snippets)
+ emit += lines_to_multiline(snippets)
if libtool:
emit += 'LT_INIT([win32-dll])\n'
emit += 'LT_LANG([C++])\n'
@@ -578,7 +579,7 @@ class GLTestDir(object):
lines = [ line
for line in snippet.split('\n')
if line.strip() ]
- snippet = '\n'.join(lines)
+ snippet = lines_to_multiline(lines)
pattern = re.compile('AC_REQUIRE\\(\\[([^()]*)\\]\\)', re.M)
snippet = pattern.sub('\\1', snippet)
snippet = snippet.strip()
@@ -586,7 +587,7 @@ class GLTestDir(object):
snippets = [ snippet
for snippet in snippets
if snippet.strip() ]
- emit += '%s\n' % '\n'.join(snippets)
+ emit += lines_to_multiline(snippets)
if libtool:
emit += 'LT_INIT([win32-dll])\n'
emit += 'LT_LANG([C++])\n'
diff --git a/pygnulib/constants.py b/pygnulib/constants.py
index 047ecf6e6f..b7434155d8 100644
--- a/pygnulib/constants.py
+++ b/pygnulib/constants.py
@@ -465,6 +465,17 @@ def filter_filelist(separator, filelist,
return result
+def lines_to_multiline(lines):
+ '''lines_to_multiline(List[str]) -> str
+
+ Combine the lines to a single string, terminating each line with a newline
+ character.'''
+ if len(lines) > 0:
+ return '\n'.join(lines) + '\n'
+ else:
+ return ''
+
+
def substart(orig, repl, data):
'''Replaces the start portion of a string.
@@ -496,18 +507,6 @@ def nlconvert(text):
return text
-def nlremove(text):
- '''Remove empty lines from the source text.'''
- text = nlconvert(text)
- text = text.replace('\r\n', '\n')
- lines = [ line
- for line in text.split('\n')
- if line != '' ]
- text = '\n'.join(lines)
- text = nlconvert(text)
- return text
-
-
def remove_trailing_slashes(text):
'''Remove trailing slashes from a file name, except when the file name
consists only of slashes.'''
diff --git a/pygnulib/main.py b/pygnulib/main.py
index cf137ab616..e4499400c6 100644
--- a/pygnulib/main.py
+++ b/pygnulib/main.py
@@ -81,6 +81,7 @@ TESTS = constants.TESTS
joinpath = constants.joinpath
copyfile = constants.copyfile
ensure_writable = constants.ensure_writable
+lines_to_multiline = constants.lines_to_multiline
isabs = os.path.isabs
isdir = os.path.isdir
isfile = os.path.isfile
@@ -814,9 +815,9 @@ def main():
if mode == 'list':
modulesystem = classes.GLModuleSystem(config)
listing = modulesystem.list()
- result = '\n'.join(listing)
+ result = lines_to_multiline(listing)
os.rmdir(config['tempdir'])
- print(result)
+ print(result, end='')
elif mode == 'find':
modulesystem = classes.GLModuleSystem(config)
@@ -1124,7 +1125,7 @@ def main():
module = modulesystem.find(name)
if module:
files = module.getFiles()
- print('\n'.join(files))
+ print(lines_to_multiline(files), end='')
elif mode == 'extract-dependencies':
if avoids:
- [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63., Collin Funk, 2024/03/17
- Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63., Bruno Haible, 2024/03/17
- Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63., Basil L. Contovounesios, 2024/03/17
- Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63., Collin Funk, 2024/03/17
- Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63.,
Bruno Haible <=
- Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63., Collin Funk, 2024/03/17
- Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63., Bruno Haible, 2024/03/17
- Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63., Collin Funk, 2024/03/17
- Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63., Bruno Haible, 2024/03/17
- Re: [PATCH] gnulib-tool.py: Follow gnulib-tool changes, part 63., Collin Funk, 2024/03/17