Hi Bruno,
On 4/17/24 11:02 AM, Bruno Haible wrote:
>> $ pylint *.py | grep W0201
>> GLError.py:119:12: W0201: Attribute 'message' defined outside __init__
>> (attribute-defined-outside-init)
>
> This warning is bogus. In a dynamic language like Python, it is
> perfectly fine to have a property used only by one method. Only if
> it is used by more than one method, would I find it suitable to
> declare/initialize it in the constructor.
I respectfully disagree about the warning message being bogus, but I
think I generally agree beyond that. Though, when I see an instance
variable used only in one function it makes me think that it should be
local to the function it is used in.
The reason I dislike defining instance variables outside of __init__
is that you can run into situations like this, which I find hard to
follow:
var = GLImport(...) # self.assistant does not exist.
var.assistant.do_something() # This is invalid.
var.execute(...) # self.assistant is now defined.
var.assistant.do_something() # Now this is valid.
I think it is best to avoid this, but there are probably situations
where it may be intentional/necessary.
> Your patch is not good, because it increases the code that is
> necessary to read, in order to understand the property: before,
> it was one method, now it would be the class.
>
> Maybe you can silence the warning by prepending a '_' to the
> property name? That would be acceptable.
The issue with the 'self.messages' in GLError is that it appears that
__repr__ expects 'self.messages' to be initialized to None in
__init__. I think the idea was to have it so that under
'if __name__ == "__main__"':
try:
main()
except GLError as exc:
sys.stderr.write(repr(exc))
instead of rewriting the messages there. I didn't write it though so maybe
I am misreading. :)
Let's leave that until I can properly fix that class.
>> GLImport.py:1043:8: W0201: Attribute 'assistant' defined outside __init__
>> (attribute-defined-outside-init)
>
> Similarly. In the current state, this property could be turned into a
> local variable. If you need this attribute in other methods (see the
> other thread), please find a good place to initialize it. But the
> proposed patch here is not good, as it initializes the same property
> twice, and who knows if both initializations are really equivalent?
Good point. I was under the impression that GLConfig does not get
modified after being passed from main(). Though I should check and
document it before making changes with that assumption.
Patch 0002 makes this GLFileAssistant local to GLImport.execute().
Since it is only used there I agree that it makes more sense.
>> We already unnecessarily create a
>> GLFileSystem that we don't need to [2] [3]. :)
>
> You're welcome to remove the unneeded property.
In patch 0001 attached.
Collin
From e1c70606ae64faee9ced3ebc4c46e9c86a689a58 Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Wed, 17 Apr 2024 11:34:07 -0700
Subject: [PATCH 1/2] gnulib-tool.py: Remove an unused instance attribute.
* pygnulib/GLImport.py (GLImport.__init__): Remove the unused
GLFileSystem object.
---
ChangeLog | 6 ++++++
pygnulib/GLImport.py | 1 -
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/ChangeLog b/ChangeLog
index adf89411d2..dbe6edd52d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2024-04-17 Collin Funk <collin.fu...@gmail.com>
+
+ gnulib-tool.py: Remove an unused instance attribute.
+ * pygnulib/GLImport.py (GLImport.__init__): Remove the unused
+ GLFileSystem object.
+
2024-04-17 Collin Funk <collin.fu...@gmail.com>
gnulib-tool.py: Fix a pylint 'attribute-defined-outside-init' warning.
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index c6a4693c90..0933943d4c 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -302,7 +302,6 @@ def __init__(self, config: GLConfig, mode: int) -> None:
# Define GLImport attributes.
self.emitter = GLEmiter(self.config)
- self.filesystem = GLFileSystem(self.config)
self.modulesystem = GLModuleSystem(self.config)
self.moduletable = GLModuleTable(self.config,
self.config.checkInclTestCategory(TESTS['all-tests']),
--
2.44.0
From d3306868fdd69724442c05b1b1526bc9c279bd65 Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Wed, 17 Apr 2024 11:47:16 -0700
Subject: [PATCH 2/2] gnulib-tool.py: Make an instance variable local to a
function.
* pygnulib/GLImport.py (GLImport.execute): Define the GLFileAssistant as
local to this function because it is unused elsewhere.
---
ChangeLog | 6 ++++++
pygnulib/GLImport.py | 48 ++++++++++++++++++++++----------------------
2 files changed, 30 insertions(+), 24 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index dbe6edd52d..348c887be0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2024-04-17 Collin Funk <collin.fu...@gmail.com>
+
+ gnulib-tool.py: Make an instance variable local to a function.
+ * pygnulib/GLImport.py (GLImport.execute): Define the GLFileAssistant as
+ local to this function because it is unused elsewhere.
+
2024-04-17 Collin Funk <collin.fu...@gmail.com>
gnulib-tool.py: Remove an unused instance attribute.
diff --git a/pygnulib/GLImport.py b/pygnulib/GLImport.py
index 0933943d4c..0a19d50e00 100644
--- a/pygnulib/GLImport.py
+++ b/pygnulib/GLImport.py
@@ -1039,7 +1039,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
print('Create directory %s' % directory)
# Create GLFileAssistant instance to process files.
- self.assistant = GLFileAssistant(self.config, transformers)
+ assistant = GLFileAssistant(self.config, transformers)
# Files which are in filetable['old'] and not in filetable['new'].
# They will be removed and added to filetable['removed'] list.
@@ -1074,9 +1074,9 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
for pair in pairs:
original = pair[1]
rewritten = pair[0]
- self.assistant.setOriginal(original)
- self.assistant.setRewritten(rewritten)
- self.assistant.add_or_update(already_present)
+ assistant.setOriginal(original)
+ assistant.setRewritten(rewritten)
+ assistant.add_or_update(already_present)
# Files which are in filetable['new'] and in filetable['old'].
# They will be added/updated and added to filetable['added'] list.
@@ -1088,12 +1088,12 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
for pair in pairs:
original = pair[1]
rewritten = pair[0]
- self.assistant.setOriginal(original)
- self.assistant.setRewritten(rewritten)
- self.assistant.add_or_update(already_present)
+ assistant.setOriginal(original)
+ assistant.setRewritten(rewritten)
+ assistant.add_or_update(already_present)
# Add files which were added to the list of filetable['added'].
- filetable['added'] += self.assistant.getFiles()
+ filetable['added'] += assistant.getFiles()
filetable['added'] = sorted(set(filetable['added']))
# Default the source makefile name to Makefile.am.
@@ -1134,12 +1134,12 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
if pobase:
# Create po makefile and auxiliary files.
for file in ['Makefile.in.in', 'remove-potcdate.sin']:
- tmpfile = self.assistant.tmpfilename(joinpath(pobase, file))
+ tmpfile = assistant.tmpfilename(joinpath(pobase, file))
path = joinpath('build-aux', 'po', file)
lookedup, flag = filesystem.lookup(path)
copyfile(lookedup, tmpfile)
basename = joinpath(pobase, file)
- filename, backup, flag = self.assistant.super_update(basename, tmpfile)
+ filename, backup, flag = assistant.super_update(basename, tmpfile)
if flag == 1:
if not self.config['dryrun']:
print('Updating %s (backup in %s)' % (filename, backup))
@@ -1156,11 +1156,11 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
# Create po makefile parameterization, part 1.
basename = joinpath(pobase, 'Makevars')
- tmpfile = self.assistant.tmpfilename(basename)
+ tmpfile = assistant.tmpfilename(basename)
emit = self.emitter.po_Makevars()
with open(tmpfile, mode='w', newline='\n', encoding='utf-8') as file:
file.write(emit)
- filename, backup, flag = self.assistant.super_update(basename, tmpfile)
+ filename, backup, flag = assistant.super_update(basename, tmpfile)
if flag == 1:
if not self.config['dryrun']:
print('Updating %s (backup in %s)' % (filename, backup))
@@ -1177,11 +1177,11 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
# Create po makefile parameterization, part 2.
basename = joinpath(pobase, 'POTFILES.in')
- tmpfile = self.assistant.tmpfilename(basename)
+ tmpfile = assistant.tmpfilename(basename)
with open(tmpfile, mode='w', newline='\n', encoding='utf-8') as file:
file.write(self.emitter.po_POTFILES_in(filetable['all']))
basename = joinpath(pobase, 'POTFILES.in')
- filename, backup, flag = self.assistant.super_update(basename, tmpfile)
+ filename, backup, flag = assistant.super_update(basename, tmpfile)
if flag == 1:
if not self.config['dryrun']:
print('Updating %s (backup in %s)' % (filename, backup))
@@ -1211,7 +1211,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
# Create po/LINGUAS.
basename = joinpath(pobase, 'LINGUAS')
if not self.config['dryrun']:
- tmpfile = self.assistant.tmpfilename(basename)
+ tmpfile = assistant.tmpfilename(basename)
data = '# Set of available languages.\n'
files = sorted([ constants.subend('.po', '', file)
for file in os.listdir(joinpath(destdir, pobase))
@@ -1219,7 +1219,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
data += lines_to_multiline(files)
with open(tmpfile, mode='w', newline='\n', encoding='utf-8') as file:
file.write(data)
- filename, backup, flag = self.assistant.super_update(basename, tmpfile)
+ filename, backup, flag = assistant.super_update(basename, tmpfile)
if flag == 1:
print('Updating %s (backup in %s)' % (filename, backup))
elif flag == 2:
@@ -1236,11 +1236,11 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
# Create m4/gnulib-cache.m4.
basename = joinpath(m4base, 'gnulib-cache.m4')
- tmpfile = self.assistant.tmpfilename(basename)
+ tmpfile = assistant.tmpfilename(basename)
emit = self.gnulib_cache()
with open(tmpfile, mode='w', newline='\n', encoding='utf-8') as file:
file.write(emit)
- filename, backup, flag = self.assistant.super_update(basename, tmpfile)
+ filename, backup, flag = assistant.super_update(basename, tmpfile)
if flag == 1:
if not self.config['dryrun']:
print('Updating %s (backup in %s)' % (filename, backup))
@@ -1261,11 +1261,11 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
# Create m4/gnulib-comp.m4.
basename = joinpath(m4base, 'gnulib-comp.m4')
- tmpfile = self.assistant.tmpfilename(basename)
+ tmpfile = assistant.tmpfilename(basename)
emit = self.gnulib_comp(filetable, gentests)
with open(tmpfile, mode='w', newline='\n', encoding='utf-8') as file:
file.write(emit)
- filename, backup, flag = self.assistant.super_update(basename, tmpfile)
+ filename, backup, flag = assistant.super_update(basename, tmpfile)
if flag == 1:
if not self.config['dryrun']:
print('Updating %s (backup in %s)' % (filename, backup))
@@ -1288,7 +1288,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
# Do this after creating gnulib-comp.m4, because func_emit_lib_Makefile_am
# can run 'autoconf -t', which reads gnulib-comp.m4.
basename = joinpath(sourcebase, source_makefile_am)
- tmpfile = self.assistant.tmpfilename(basename)
+ tmpfile = assistant.tmpfilename(basename)
emit = self.emitter.lib_Makefile_am(basename, self.moduletable.getMainModules(),
self.moduletable, self.makefiletable,
actioncmd, for_test)
@@ -1298,7 +1298,7 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
input=emit, text=True, capture_output=True).stdout
with open(tmpfile, mode='w', newline='\n', encoding='utf-8') as file:
file.write(emit)
- filename, backup, flag = self.assistant.super_update(basename, tmpfile)
+ filename, backup, flag = assistant.super_update(basename, tmpfile)
if flag == 1:
if not self.config['dryrun']:
print('Updating %s (backup in %s)' % (filename, backup))
@@ -1316,13 +1316,13 @@ def execute(self, filetable: dict[str, list[str]], transformers: dict[str, str])
# Create tests Makefile.
if gentests:
basename = joinpath(testsbase, tests_makefile_am)
- tmpfile = self.assistant.tmpfilename(basename)
+ tmpfile = assistant.tmpfilename(basename)
emit = self.emitter.tests_Makefile_am(basename, self.moduletable.getTestsModules(),
self.moduletable, self.makefiletable,
'%stests_WITNESS' % macro_prefix, for_test)
with open(tmpfile, mode='w', newline='\n', encoding='utf-8') as file:
file.write(emit)
- filename, backup, flag = self.assistant.super_update(basename, tmpfile)
+ filename, backup, flag = assistant.super_update(basename, tmpfile)
if flag == 1:
if not self.config['dryrun']:
print('Updating %s (backup in %s)' % (filename, backup))
--
2.44.0