Closed t-reents closed 3 months ago
Thanks for the analysis @t-reents . Coincidentally, I had just responded to @edan-bainglass comment on the related PR. I will copy the comment here:
It is in fact related to this PR. The PR fixed a bug where the conditional would always raise an
AttributeError
for non-process plugins and so would always skip and simply print that no description was available. After this fix, the code now actually goes to the else-clause and callsplugin.get_description
, but this is also a bug that simply was always hidden by the first bug. Theget_description
method is an instance method and theplugin
is a class, so that call fails. There is noget_description
classmethod though that provides a description of the plugin. The best we can do I think is to simply display the docstring of the plugin
As to your suggestion:
Without thinking too much about it, one possible fix would be to create an object, i.e. calling plugin().get_description() (this would work for methods and class methods).
This would be vulnerable still, because it requires constructing the class and that might require arguments. An example would be a Parser
plugin which raises if you construct it without arguments.
What we really need to have is something that would work for all "plugins". And plugins here really can be any class, or even function really. So I think our best bet would be to use the docstring. It is guaranteed to exist and at worst returns None
when not defined. We can check for this case and just print the default message that no help is available.
Ah, I missed that Edan has already commented, I thought he stopped after our discussion :D sorry for the kind of duplicated issue
True, the Parser
is one of the examples that I was assuming without having a specific example, thanks for the clarification.
The doc-string approach makes sense!
Thanks @t-reents and @edan-bainglass for finding this issue.
For some reason, I always assumed get_description()
was defined as a class method across the interface.
Now, by doing a simple search, just realized that's not always the case.
So for backward compatibility, I would keep the if.. else
clause, and in case get_description()
exists and is not a classmethod, handle the TypeError
, and as @sphuber suggests print the docstring.
@edan-bainglass encountered the following issue and I've quickly investigated it.
Running e.g.
verdi plugin list aiida.data core.array
causes an exception:This error was introduced in #6411. In previous versions, e.g.
aiida-core 2.5
, the command would simply print the error:Error: No description available for core.array
Due to the changes in the aforementioned PR #6411, the
try except
is not triggered. As noAttributeError
is raised anymore after adding thehasattr(plugin, 'is_process_function')
: https://github.com/aiidateam/aiida-core/blob/fb3686271fcdeb5506838a5a3069955546b05460/src/aiida/cmdline/commands/cmd_plugin.py#L50-L58Since the
hasattr
simply returnsFalse
in case of theArrayData
, theelse
statement is executed. Here, the error shown above is raised, asplugin.get_description()
tries to callget_description
on the class and not on an object. However,get_description
is not a class method inorm.Node
, leading to the exception.Without thinking too much about it, one possible fix would be to create an object, i.e. calling
plugin().get_description()
(this would work for methods and class methods). However, I'm not sure if this will cause additional problems. Furthermore, one could catch theTypeError
in theexcept
statement as well. Again, these were just some ideas that came to my mind. There might be more things to consider that could lead to different solutions.Pinging @sphuber and @khsrali who have worked on the previous PR.