You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Help text duplicated when using more than 1 CLI instance #1002
With this program, run alias -h. The subcommand help gets repeated.
SUBCOMMAND
create create or overwrite an alias
delete delete aliases
list delete aliases
create create or overwrite an alias
delete delete aliases
list delete aliases
Since the parsers (e.g. Cmd.alias_parser) are class objects, they get updated with each instantiation. This problem has existed since we added the argparse decorators, but it's being exercised a bit more since we added CommandSet and as_subcommand_to decorators. This specific issue of repeated text was introduced when cmd2.py started using the as_subcommand_to decorator.
For the 2.0 release, we need to find a way to make deep copies of the parsers and tie each copy to an instance. We won't have 1 parser attached to the functions anymore. Instead the decorators will need to retrieve the instance-specific parser.
I have a very vague recollection of researching how to make a deep copy of a parser and finding that it was possible in Python 3.7+ (or something similar) but not beforehand.
@anselor and I agree the 2.0 release does not have to wait for this fix. The risk of someone using two cmd2 objects and editing common parsers between them is pretty low.
Could this be avoided if the decorators accepted a argparser factory (a callable that returns an instance of argparser) so the instance is created when needed?
I tried this today to be sure but I was pretty sure this suggestion by itself wouldn't work because the decorator, just like the the ArgumentParser instances, only runs once during the class declaration.
I've been digging around the code a bit and I think may have a solution uses the factory suggestion while also maintaining backwards compatibility. I think what we need to do is, as a command is registered in the commandset (be it during construction or later) we need to at that point either clone the provided ArgumentParser or call the factory method and then store that in the Cmd or CommandSet instance. The innermost cmd_wrapper() method inside of with_argparser() would instead look up the ArgumentParser instance from the provider_self rather than the one passed in the decorator.
Activity
tleonhardt commentedon Sep 28, 2020
I have a very vague recollection of researching how to make a deep copy of a parser and finding that it was possible in Python 3.7+ (or something similar) but not beforehand.
tleonhardt commentedon Sep 28, 2020
Yeah, inability to deep-copy an
ArgumentParserwas fixed in Python 3.7. The context is in older issue #522tleonhardt commentedon Nov 11, 2020
@kmvanbrunt #1005 appears to have fixed this, at least temporarily. Are we awaiting a more permanent fix? Or should this issue be closed?
kmvanbrunt commentedon Nov 11, 2020
@tleonhardt The permanent fix needs to be in 2.0. We need a way to support instance-specific parsers and that will most likely be a breaking change.
kmvanbrunt commentedon Nov 20, 2020
@anselor Do you have any thoughts on this issue?
anselor commentedon Nov 20, 2020
I'm sure I do I've just been busy with other more immediate deadlines and haven't had time to come back to this and other cmd2 stuff.
kmvanbrunt commentedon Jan 21, 2021
@anselor and I agree the 2.0 release does not have to wait for this fix. The risk of someone using two cmd2 objects and editing common parsers between them is pretty low.
tleonhardt commentedon Jul 14, 2022
@kmvanbrunt Is this fixed now? Or are we waiting on some better fix?
federicoemartinez commentedon Jun 30, 2023
Could this be avoided if the decorators accepted a argparser factory (a callable that returns an instance of argparser) so the instance is created when needed?
anselor commentedon Sep 25, 2023
I tried this today to be sure but I was pretty sure this suggestion by itself wouldn't work because the decorator, just like the the ArgumentParser instances, only runs once during the class declaration.
I've been digging around the code a bit and I think may have a solution uses the factory suggestion while also maintaining backwards compatibility. I think what we need to do is, as a command is registered in the commandset (be it during construction or later) we need to at that point either clone the provided ArgumentParser or call the factory method and then store that in the Cmd or CommandSet instance. The innermost
cmd_wrapper()method inside ofwith_argparser()would instead look up the ArgumentParser instance from theprovider_selfrather than the one passed in the decorator.@federicoemartinez
Changed with_argparser() and as_subcommand_to() to accept either an A…
Changed with_argparser() and as_subcommand_to() to accept either an A…
Changed with_argparser() and as_subcommand_to() to accept either an A…
Changed with_argparser() and as_subcommand_to() to accept either an A…
Changed with_argparser() and as_subcommand_to() to accept either an A…
Changed with_argparser() and as_subcommand_to() to accept either an A…
Changed with_argparser() and as_subcommand_to() to accept either an A…
Changed with_argparser() and as_subcommand_to() to accept either an A…
Changed with_argparser() and as_subcommand_to() to accept either an A…
Changed with_argparser() and as_subcommand_to() to accept either an A…
Changed with_argparser() and as_subcommand_to() to accept either an A…
kmvanbrunt commentedon Sep 12, 2024
@anselor Can this issue be closed? It appears it was fixed in #1278.