-
-
Notifications
You must be signed in to change notification settings - Fork 4
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
Group Support #39
Comments
Oh wow, this looks like it's gonna be great 😃 |
This feature has now been implemented in the Docs are available at: https://cyclopts.readthedocs.io/en/develop-v2/groups.html I will leave this issue open until v2 is released to further discuss this feature. |
from pathlib import Path
from typing import Annotated
from cyclopts import App, Group, Parameter, validators
app = App(
name="myapp",
help="my cli app",
default_parameter=Parameter(negative=(), show_default=False)
)
exclusive = Group(
name="Flags",
validator=validators.LimitedChoice(), # Mutually Exclusive Options
)
# fairly minor issue (maybe not even an issue) but mypy type checker doesn't like this
# Incompatible types in assignment (expression has type "Group", variable has type "tuple[Group | str, ...]")
app["--help"].group = exclusive # type: ignore
app["--version"].group = "Flags" # type: ignore
# app["--help"].group = (exclusive,) # happy mypy
@app.default # type: ignore
def cli(
path: Annotated[
Path,
Parameter(
help="File or directory.",
show_default=True,
validator=validators.Path(exists=True),
group="Input"
)
] = Path.cwd(),
/,
*,
no_resume: Annotated[
bool,
Parameter(
help="Ignore existing resume data.",
group=exclusive
)
] = False,
clear_resume: Annotated[
bool,
Parameter(
help="Delete existing resume data.",
group=exclusive
),
] = False,
) -> None:
print(path)
print(no_resume)
print(clear_resume)
if __name__ == "__main__":
app() help: python .\test.py --help
Usage: myapp COMMAND [ARGS] [OPTIONS]
my cli app
╭─ Input ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ PATH File or directory. [default: C:\Users\raven\Documents\GitHub\juicenet-cli] │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Flags ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --no-resume Ignore existing resume data. │
│ --clear-resume Delete existing resume data. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Flags ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --help,-h Display this message and exit. │
│ --version Display application version. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ This ends up with two |
I'll see what I can do about this; i've been type checking with pyright, but I'll give mypy a go as well. It seems like the attrs converter typing isn't being interpreted correctly. As for your 2 groups, this is kind of expected. Basically, even though the groups have a unified interface, they're still separated between "commands" and "arguments/parameters." In this example, I understand this is probably not 100% desireable, but I have an idea on how I could fix this (if we deem this worth fixing), let me play with it a bit. |
the mypy issue basically comes down to this: I think I can ruin the type internally a bit (e.g. say that it can be a |
Panels with the same name across groups/parameters are now combined now that #61 has been merged into Panels are now displayed in alphabetical order, which is better in someways and worse in some ways than previously. It's better that there's a logical order. It's worse that originally meta-app panels were at the top. We can revisit this if we desire in the future. There is some undocumented ambiguous merging logic when it happens (particularly for group descriptions) for display elements. But this situation is so rare (and obvious what happens) that I think it's not really an issue (until someone says it is 😄 ). |
This has been mitigated a little bit by #62. Thanks for the feedback so far! Please keep them coming! |
Both #61 and #62 work wonderfully
Perhaps allow the user to define hierarchy? Otherwise maybe first sort by Positional and then keyword and then sort by alphabetical within each? |
also another question, can i have groups that apply their affect but are not seperated in help? |
Thoughts:
If you create a group with an empty name, or with
|
I'm going to think through |
Here's an API that could work: New field to
When performing the help-page panel sort, we can make the data structure look something like this:
where this can be sorted by the first element of the tuple. Proposed logic:
Ad Hoc Example:
Centralized example (would have same response):
This brings up a separate, but related topic. Maybe I should add a
and then if you want "in order added" functionality:
Thoughts are a bit scattered here, but what do you think? |
The I'm still on the fence about adding/implementing the above mentioned |
I've updated #64 to also include a convenience I'm pretty happy with #64 now and will probably merge it to I have decided against adding |
I think I'm pretty happy that you didn't go with |
Played with it a bit, found no issues. Although I was wondering, what would be the easiest way to sort the default groups (args, params, commands)? |
Thanks for giving it a try! I'm gonna tweak a few minor things (I think there might be some edge-cases).
You can explicitly set the
Currently, these values don't propagate as far as you might expect. For example, it won't propagate to commands/subcommands. I'll try and improve this in another PR. Expanding on above, whenever you do |
perfect!
That does sound like something an end user would expect |
closing with the release of v2. We can reopen this issue, or open a new one, should the need arise. |
Design document for adding "groups" to Cyclopts v2.
Motivation
Groups are to achieve 2 purposes:
mutually_exclusive
parameters.The implementation goals of this implementation are to:
App
,@app.command
,Group
, andParameter
.Group Class (new)
There will be a new public class,
Group
, which can be used withParameter
and@app.command
.Only advanced Cyclopts users will need to know/use this class.
Implicitly created groups are scoped to the command.
Externally created groups should be scope to the command (i.e. don't use the same
Group
object for multiple commands).Built-in Validators
A new
LimitedChoice
validator that can be used with groups.LimitedChoice
is a superset of mutually-exclusive functionality.To make a mutually exclusive group:
Parameter Class (changes)
The
Parameter
class will take a new optional argument,group
.The allowing of a string identifier to implicitly/lazily create/reference a group cuts down on the API verbosity.
App Class (changes)
The
App
class will be gaining agroup
andgroups
attribute.There will also be a
get_group
helper method.The will also be a new
validator
field, which is similar toGroup.validator
, but applies to the entiredefault_command
.It will be losing
help_title_commands
andhelp_title_parameters
because that functionality is nowencompassed by groups.
Example Usage
Examples on how to use the new features.
Explicit Group Creation
Explicitly creating a Group for maximum control:
The lookup-by-name only works because a previous Parameter (left-to-right) used (registered) the group with name
"Environment"
.Implicit Group Creation
This example shows implicit creation of a group purely for help-organtization purposes.
Command groups
This examples shows organizing commands into groups.
Other Thoughts
Group.default
, not by name,their help-page panel title can be changed without impacting functionality.
Group.default
options have their first letter capitalized to be consistentwith how typical group naming.
POSITIONAL_ONLY
arguments._children
) will not be displayed on the help-page.--help
) must become proper commands instead of specially handled.Related Work
argparse
uses groups for the help-page and mutual exclusion.--help
similar to argparse and typer #30 - Seperate positional only and keyword only arguments in --help similar to argparse and typerThe text was updated successfully, but these errors were encountered: