Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multilevel subcommands support to CLI #334

Closed
rusmux opened this issue Jul 28, 2023 · 7 comments · Fixed by #346
Closed

Add multilevel subcommands support to CLI #334

rusmux opened this issue Jul 28, 2023 · 7 comments · Fixed by #346
Labels
enhancement New feature or request

Comments

@rusmux
Copy link

rusmux commented Jul 28, 2023

🚀 Feature request

Currently jsonargparse.CLI can handle only one level of subcommands through classes. For example:

from jsonargparse import CLI

class mycli:
    @staticmethod
    def subcommand1(): ...


if __name__ == "__main__":
    CLI(components=[mycli])

But there is no easy way to add more subcommands, since embedding a class in another one will cause an error.:

from jsonargparse import CLI

class mycli:
    @staticmethod
    def subcommand1(): ...

    class subcommand2:
        @staticmethod
        def subsubcommand1(): ...


if __name__ == "__main__":
    CLI(components=[mycli])
ValueError: Invalid or unsupported input: class=<class '__main__.mycli'>, method_or_property=subcommand2

To add more subcommands, you need to use jsonargparse.ArgumentParser and implement all the logic manually.

Motivation

It would be great to be able to create multilevel subcommands easily.

Pitch

Add multilevel subcommands support to jsonargparse.CLI.

Alternatives

@rusmux rusmux added the enhancement New feature or request label Jul 28, 2023
@mauvilsa
Copy link
Member

A clarification. Two levels of subcommands is currently possible by having multiple classes. For example:

from jsonargparse import CLI

class level1_cmd_a:
    @staticmethod
    def level2_cmd_x(): ...

class level1_cmd_b:
    @staticmethod
    def level2_cmd_y(): ...

if __name__ == "__main__":
    CLI(components=[level1_cmd_a, level1_cmd_b])

Though, easier ways to implement can be added. For example similar to fire.Fire(<dict>). Two levels of subcommands could be defined as:

{
    "level1_cmd_a": {
        "level2_cmd_x": func_x,
    },
    "level1_cmd_b": {
        "level2_cmd_y": func_y,
    }
}

@rusmux
Copy link
Author

rusmux commented Jul 28, 2023

Oh, yes, I missed it, thank you! But how to add more levels? The fire way of doing this seems nice.

@mauvilsa
Copy link
Member

More than two levels currently is only possible by manually creating the ArgumentParser.

@rusmux
Copy link
Author

rusmux commented Jul 31, 2023

Would it be possible to support fire-like dictionaries in the future?

@mauvilsa
Copy link
Member

mauvilsa commented Aug 1, 2023

Yes.

@rusmux
Copy link
Author

rusmux commented Aug 1, 2023

Thank you, will look forward to it!

@mauvilsa
Copy link
Member

mauvilsa commented Aug 9, 2023

@rusmux @Borda I created a pull request (#346) that implements CLI subcommands via a dict. Please try it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants