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
Nested option groups with constraints #22
Comments
You should read the docs before opening an issue. It's not nice to do otherwise. I'll answer you this time... Option groups are primarily a way to organize your options in multiple help sections, not a way to define constraints. The Option groups are intentionally not nestable since the resulting help text would be a mess. You can define constraints on subsets of option groups using the If you still want to describe the constraints defined on subsets of an option groups you can either do it "manually" passing the |
Constraints like |
That comment was only meant to convey I'm new to your package, not that I'm literally new to the docs at the moment I'm writing the issue. I've been reading your docs, along with https://github.com/click-contrib/click-option-group, for the past few hours, testing each package to see if I can get it working for what I need. Once it became clear that it wasn't clear from the docs, I filed the issue. Sorry about that, next time I'll wait even longer before asking for help. Thanks for the clarification on Option groups that they cannot be nested. Although if you can combine constraints through operators and work out the help message, couldn't you do the same with multiple Option groups that each have a constraint?
Yeah maybe I can get something working with
but that didn't quite seem to work. It might be nice to be able to assign labels to a constraint that you can reference in other constraints, e.g.
I image it should be possible to compile each constraint down into a series of Predicates combined with logical operators. I'll keep playing around with it to see if I can get something working. |
Option groups are not going to be nestable, ever.
I don't like it. Writing custom Python code is much better. I have something better in mind but it requires a complete redesign, I need to evaluate if it's doable and worth it. Keep in mind that you can always validate your arguments inside your function with simple Python code. I'm not talking about calling the constraints, I mean simple Python code. You can raise Anyway, you can obtain something decent with the following: @command(show_constraints=True)
@option_group(
'Option group',
option('-a', is_flag=True), # using flags for easier testing
option('-b', is_flag=True),
option('-c', is_flag=True),
option('-d', is_flag=True),
option('-e', is_flag=True),
)
@constraint(all_or_none, ['d', 'e'])
@constraint(mutually_exclusive, ['c', 'd'])
@constraint(RequireExactly(1), ['a', 'b'])
@constraint(If('b', RequireExactly(1)), ['c', 'd'])
def cmd(a, b, c, d, e):
pass This generates the following help section:
Error messages will probably be suboptimal but you can use |
Note that if you use a tuple option for D and E, you don't need the @option_group(
'Option group',
option('-a', is_flag=True),
option('-b', is_flag=True),
option('-c', is_flag=True),
option('-d', nargs=2),
)
@constraint(mutually_exclusive, ['c', 'd'])
@constraint(RequireExactly(1), ['a', 'b'])
@constraint(If('b', RequireExactly(1)), ['c', 'd']) |
Yeah I agree for complex items it's probably easier to do it in the code. I do that now actually in my old code. I'm switching my code over from Thanks for the example. This goes a long way and gives me a good start. I'll play around with things a bit more. Thanks for your help! I appreciate it! |
In Cloup v0.9.0, a limited form of nesting will be possible. Specifically, one can constrain one or multiple subgroups of an @option_group(
'Number options',
RequireAtLeast(1)(
option('--one'),
option('--two')
),
option('--three'),
) Intentionally, only one level of nesting is allowed. Again, for very complex items, one should use custom code. This change is part of a bigger feature (#8) which is about using constraints as decorators to avoid rewriting parameter names. EDIT: I had forgotten the title in |
This looks pretty promising and helps the readable of the relationship between options. I like it. So, e.g. does the equivalent of this code num_group = OptionGroup('Number Options', help='blah')
@num_group.option('--one')
@num_group.option('--two')
@num_group.option('--three')
@cloup.constraint(RequireAtLeast(1), ['one', 'two'])
def hello(one, two, three):
... turns into num_group = OptionGroup('Number Options', help='blah')
@num_group(RequireAtLeast(1)(option('--one'), option('--two')), option('--three'))
def hello(one, two, three):
... And in #8 you mention the incompatibility below Python 3.9. So for users of Python <3.8 they'll just need to pin cloup to <0.9? |
@havok2063 No, since num_group = OptionGroup('Number Options', help='blah')
@RequireAtLeast(1)(
num_group.option('--one'),
num_group.option('--two'),
)
@num_group.option('--three')
def hello(one, two, three):
... I prefer the
No, Cloup will still be compatible with Python >= 3.6. It's just that in Python < 3.9 you can't use parametric/compound/conditional constraints with require_any = RequireAtLeast(1)
@require_any( # no more double call on the right of @
option('--one'),
...
) or this: @constrained_params(
RequireAtLeast(1),
option('--one'),
...
) Notice that there's not such a problem if you nest a parametric constraint inside |
Ahh yeah that makes sense, and looks pretty readable to me. Oh yeah I didn't notice the group name in |
Description
I am trying to create a group of options with a seemingly complex, but perhaps not, constraint system. I basically have 5 parameters that I want to house in one group, that are a combination of required and mutually exclusive, and at least x. For example, options:
A, B, C, D, and E
.D
andE
are an "all_or_none" group.C
andD+E
are "mutually_exclusive" group, but at least one is required.B
is required with one of(C,D+E)
. And eitherA
or group(B + (C or D+E))
is required. Is this possible? It's not clear to me if nested option groups are possible, i.e. if I can create oneoption_group
with a constraint and apply a constraint on top of it as part of anotheroption_group
.I just discovered this code and am digging into the docs, so perhaps the answer is buried in there.
something like the following...
or would I do something like
The text was updated successfully, but these errors were encountered: