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

args_test refactorization after generalizing ValidArgs #841

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

umarcor
Copy link
Contributor

@umarcor umarcor commented Mar 18, 2019

Fix #838 and Fix #745.

5 of the commits in this PR are about refactoring args_test.go. The sixth one (feat: generalize ValidArgs; use it implicitly with any validator) moves the validation of ValidArgs from args.go to command.go. As a result:

  • Any validator can be used along with ValidArgs. ValidArgs is checked first, and then the defined validator.
  • OnlyValidArgs and ExactValidArgs are deprecated.

args_test.go is updated accordingly:

=== RUN   TestNoArgs
--- PASS: TestNoArgs (0.00s)
=== RUN   TestNoArgsWithArgs
--- PASS: TestNoArgsWithArgs (0.00s)
=== RUN   TestNoArgsWithArgsWithValid
--- PASS: TestNoArgsWithArgsWithValid (0.00s)
=== RUN   TestArbitraryArgs
--- PASS: TestArbitraryArgs (0.00s)
=== RUN   TestArbitraryArgsWithValid
--- PASS: TestArbitraryArgsWithValid (0.00s)
=== RUN   TestArbitraryArgsWithValidWithInvalidArgs
--- PASS: TestArbitraryArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestMinimumNArgs
--- PASS: TestMinimumNArgs (0.00s)
=== RUN   TestMinimumNArgsWithValid
--- PASS: TestMinimumNArgsWithValid (0.00s)
=== RUN   TestMinimumNArgsWithValidWithInvalidArgs
--- PASS: TestMinimumNArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestMinimumNArgsWithLessArgs
--- PASS: TestMinimumNArgsWithLessArgs (0.00s)
=== RUN   TestMinimumNArgsWithLessArgsWithValid
--- PASS: TestMinimumNArgsWithLessArgsWithValid (0.00s)
=== RUN   TestMinimumNArgsWithLessArgsWithValidWithInvalidArgs
--- PASS: TestMinimumNArgsWithLessArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestMaximumNArgs
--- PASS: TestMaximumNArgs (0.00s)
=== RUN   TestMaximumNArgsWithValid
--- PASS: TestMaximumNArgsWithValid (0.00s)
=== RUN   TestMaximumNArgsWithValidWithInvalidArgs
--- PASS: TestMaximumNArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestMaximumNArgsWithMoreArgs
--- PASS: TestMaximumNArgsWithMoreArgs (0.00s)
=== RUN   TestMaximumNArgsWithMoreArgsWithValid
--- PASS: TestMaximumNArgsWithMoreArgsWithValid (0.00s)
=== RUN   TestMaximumNArgsWithMoreArgsWithValidWithInvalidArgs
--- PASS: TestMaximumNArgsWithMoreArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestExactArgs
--- PASS: TestExactArgs (0.00s)
=== RUN   TestExactArgsWithValid
--- PASS: TestExactArgsWithValid (0.00s)
=== RUN   TestExactArgsWithValidWithInvalidArgs
--- PASS: TestExactArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestExactArgsWithInvalidCount
--- PASS: TestExactArgsWithInvalidCount (0.00s)
=== RUN   TestExactArgsWithInvalidCountWithValid
--- PASS: TestExactArgsWithInvalidCountWithValid (0.00s)
=== RUN   TestExactArgsWithInvalidCountWithValidWithInvalidArgs
--- PASS: TestExactArgsWithInvalidCountWithValidWithInvalidArgs (0.00s)
=== RUN   TestRangeArgs
--- PASS: TestRangeArgs (0.00s)
=== RUN   TestRangeArgsWithValid
--- PASS: TestRangeArgsWithValid (0.00s)
=== RUN   TestRangeArgsWithValidWithInvalidArgs
--- PASS: TestRangeArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestRangeArgsWithInvalidCount
--- PASS: TestRangeArgsWithInvalidCount (0.00s)
=== RUN   TestRangeArgsWithInvalidCountWithValid
--- PASS: TestRangeArgsWithInvalidCountWithValid (0.00s)
=== RUN   TestRangeArgsWithInvalidCountWithValidWithInvalidArgs
--- PASS: TestRangeArgsWithInvalidCountWithValidWithInvalidArgs (0.00s)
=== RUN   TestRootTakesNoArgs
--- PASS: TestRootTakesNoArgs (0.00s)
=== RUN   TestRootTakesArgs
--- PASS: TestRootTakesArgs (0.00s)
=== RUN   TestChildTakesNoArgs
--- PASS: TestChildTakesNoArgs (0.00s)
=== RUN   TestChildTakesArgs
--- PASS: TestChildTakesArgs (0.00s)

@CLAassistant
Copy link

CLAassistant commented Mar 18, 2019

CLA assistant check
All committers have signed the CLA.

@umarcor umarcor force-pushed the feat-matchvalid branch 2 times, most recently from f872d88 to 3a72951 Compare March 19, 2019 20:30
@jharshman
Copy link
Collaborator

IMO this PR overreaches a little over what was originally intended. Changing to Go modules is great but not required for this feature.

I think there is a case for improvement here but perhaps it can be approached differently. Issue #838 mentions that there is not currently a method of combining these validation functions. A fix for this could to introduce a method of chaining them.

@umarcor
Copy link
Contributor Author

umarcor commented Mar 19, 2019

IMO this PR overreaches a little over what was originally intended. Changing to Go modules is great but not required for this feature.

This PR was based on #840 because I expected that branch to be merged before this, so it could be fast-forwarded. #840 provides some interesting features, such as fixing CI, which would help evaluate this PR.

Anyway, I have now made this PR independent from #840.

I think there is a case for improvement here but perhaps it can be approached differently. Issue #838 mentions that there is not currently a method of combining these validation functions. A fix for this could to introduce a method of chaining them.

I think that it does not make sense to combine any of NoArgs, ArbitraryArgs, MinimumNArgs, MaximumNArgs, ExactArgs, RangeArgs, because all of them are mutually exclusive. Instead, my proposal is to apply ValidArgs (when defined) to the selected validator. That's why OnlyValidArgs and ExactValidArgs are deprecated.

Moreover, if a user wants to combine any of the provided validators and extend it with custom logic, an example can be added.

@jharshman
Copy link
Collaborator

Thanks for making this independent of #840 .

Maybe some clarification on the goal here was needed because it seems to have strayed away from the original issue you referenced. That issue proposed the addition of validation functions which were combinations of what is currently available. Hence why I suggested adding a method to allow the chaining of validation functions.

However, I think I see where you're coming from. You want to remove OnlyValidArgs and ExactValidArgs and instead have a check within the validation function to decide whether or not the argument slice matched some provided valid arguments.

However, this check inside the validation function contains the same logic as OnlyValidArgs. You could perhaps keep OnlyValidArgs and therefore only have to depreciate one function instead of two.

@umarcor
Copy link
Contributor Author

umarcor commented Mar 19, 2019

@jharshman, I had the same point of view as you when I started to implement this. As I went forward and I saw the codebase, I concluded that the proposed solution is the best. Some hints to better understand the changes:

Maybe some clarification on the goal here was needed because it seems to have strayed away from the original issue you referenced. That issue proposed the addition of validation functions which were combinations of what is currently available. Hence why I suggested adding a method to allow the chaining of validation functions.

The issue requested some method to combine e.g. MinimumNArgs(1) with OnlyValidArgs. That's possible with the current proposal:

Args: cobra.MinimumNArgs(1),
ValidArgs: []string{"one", "two", "three"},

compared to the prototype suggested in #838:

Args: cobra.MatchValid(cobra.MinimumNArgs(1)),
ValidArgs: []string{"one", "two", "three"},

Moreover, in #838 it was suggested that it would be better not to require the user to type MatchValid:

Certainly, MatchValid can be used implicitly when ValidArgs is defined, so the user is not required to type it. Therefore, OnlyValidArgs and ExactValidArgs can be deprecated from the public API.


However, I think I see where you're coming from. You want to remove OnlyValidArgs and ExactValidArgs and instead have a check within the validation function to decide whether or not the argument slice matched some provided valid arguments.

All of the original validators care about the number of arguments that a command accepts: NoArgs, ArbitraryArgs, MinimumNArgs(int), MaximumNArgs(int), ExactArgs(int), RangeArgs(min, max). We can consider it an enumeration of 6 items.

When ValidArgs was introduced, up to 6 additional validators might have been added, in order to provide functions covering the full combination matrix. Certainly, ValidArgs is a boolean condition which is orthogonal to Args, because it is focused on the content of the args, not the number of them. Therefore, the full matrix covers 6 x 2 = 12 combinations. However, NoArgs + ValidArgs == NoArgs + !ValidArgs, so 11.

Nonetheless, the implementation was partial and a single one was introduced. Later, a second one was added. Still, there are 3 combinations missing, which is what was pointed out in #838 at first.

Hence, the design decission is to provide one explicit validator for each combination of the multiple criterias to filter the arguments (original approach), or to enforce the orthogonality in the code (proposed approach).

However, this check inside the validation function contains the same logic as OnlyValidArgs. You could perhaps keep OnlyValidArgs and therefore only have to depreciate one function instead of two.

It is possible to make I now made OnlyValidArgs an alias of ArbitraryArgs and ExactArgs an alias of ExactValidArgs, so that backward compatibility is retained. I don't think it makes sense to deprecate only one of them (see comment above).

command.go Outdated Show resolved Hide resolved
@jharshman
Copy link
Collaborator

@umarcor thanks for taking the time to detail your approach and solution. Looks like one of the tests doesn't like the go tool vet command.

+vet: invoking "go tool vet" directly is unsupported; use "go vet"

@umarcor
Copy link
Contributor Author

umarcor commented Mar 20, 2019

@umarcor thanks for taking the time to detail your approach and solution. Looks like one of the tests doesn't like the go tool vet command.

+vet: invoking "go tool vet" directly is unsupported; use "go vet"

This is why I originally based this PR on top of #840. Those CI issues are fixed there, as commented above. The commit that fixes it is precisely: bbec970. Nonetheless, I think that it would be better to use golangci-lint. That's what I'm doing in my fork (umarcor@3b60284), while I wait for maintainers to respond.

@umarcor umarcor force-pushed the feat-matchvalid branch 2 times, most recently from cf18056 to 178cb83 Compare March 20, 2019 21:55
@umarcor
Copy link
Contributor Author

umarcor commented Mar 20, 2019

#840 is merged now, so I rebased this on top of master. Since all the tests are passing, I believe it is ready for review, @eparis.

Copy link
Collaborator

@jharshman jharshman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@umarcor umarcor force-pushed the feat-matchvalid branch 2 times, most recently from d2d4015 to 2e3862d Compare March 21, 2019 00:05
args.go Outdated Show resolved Hide resolved
@umarcor umarcor force-pushed the feat-matchvalid branch 2 times, most recently from 3149d7c to 9f4a04e Compare March 21, 2019 14:30
command.go Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
args.go Outdated Show resolved Hide resolved
args.go Outdated Show resolved Hide resolved
args_test.go Outdated Show resolved Hide resolved
args_test.go Outdated Show resolved Hide resolved
args_test.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@jharshman jharshman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine to me. @eparis

@umarcor
Copy link
Contributor Author

umarcor commented Mar 26, 2019

ping

@spf13 spf13 requested a review from eparis June 7, 2019 14:50
@umarcor
Copy link
Contributor Author

umarcor commented Mar 10, 2022

Can we change the milestone of this PR to 1.5.0?

@umarcor umarcor force-pushed the feat-matchvalid branch 3 times, most recently from 7f742d0 to a34ecc9 Compare March 22, 2022 18:39
@umarcor umarcor changed the title Generalize ValidArgs: use it implicitly with any validator args_test refactorization after generalizing ValidArgs Mar 22, 2022
@johnSchnake johnSchnake added lifecycle/active Actively being worked on by a community member or maintainer. Corresponds to someone being assigned and removed kind/stale labels Mar 23, 2022
@johnSchnake
Copy link
Collaborator

This has an approval and green tests; is it waiting for anything else? I know this PR is connected to a lot of issues and if everyones happy I'm just curious what the hold is right now? [FWIW I haven't reviewed this, just cleaning up the backlog and kept finding links to this PR]

@umarcor
Copy link
Contributor Author

umarcor commented Mar 23, 2022

@johnSchnake this is only waiting for some maintainer to decide merging it. It was approved by a maintainer several years ago, and then reviewed by a user who is a maintainer now. It was not merged since then because none of the currently active maintainers had time to sit down, read it, and understand what's it about. That's why I split #1426 in november, and I now split #1643. Please, review #1643, since that's the commit that modifies the functionality. This PR is now just style/refactorization based on #1643.

BTW, you might want to merge #1612, which is a low-hanging fruit after #1547 was merged last week.

@github-actions
Copy link

This PR exceeds the recommended size of 200 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size.

@github-actions github-actions bot added the size/XL Denotes a PR that exceeds 200 lines. Caution! label Aug 21, 2022
umarcor added a commit to umarcor/cobra that referenced this pull request Aug 21, 2022
umarcor added a commit to umarcor/cobra that referenced this pull request Aug 21, 2022
@umarcor umarcor mentioned this pull request Nov 1, 2022
hoshsadiq pushed a commit to zulucmd/zulu that referenced this pull request Dec 31, 2022
5 of the commits in this PR are about refactoring args_test.go.
The sixth one (feat: generalize ValidArgs; use it implicitly with
any validator) moves the validation of ValidArgs from args.go to
command.go. As a result:

- Any validator can be used along with ValidArgs. ValidArgs is
  checked first, and then the defined validator.
- OnlyValidArgs and ExactValidArgs are deprecated.

args_test.go is updated accordingly:

```
=== RUN   TestNoArgs
--- PASS: TestNoArgs (0.00s)
=== RUN   TestNoArgsWithArgs
--- PASS: TestNoArgsWithArgs (0.00s)
=== RUN   TestNoArgsWithArgsWithValid
--- PASS: TestNoArgsWithArgsWithValid (0.00s)
=== RUN   TestArbitraryArgs
--- PASS: TestArbitraryArgs (0.00s)
=== RUN   TestArbitraryArgsWithValid
--- PASS: TestArbitraryArgsWithValid (0.00s)
=== RUN   TestArbitraryArgsWithValidWithInvalidArgs
--- PASS: TestArbitraryArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestMinimumNArgs
--- PASS: TestMinimumNArgs (0.00s)
=== RUN   TestMinimumNArgsWithValid
--- PASS: TestMinimumNArgsWithValid (0.00s)
=== RUN   TestMinimumNArgsWithValidWithInvalidArgs
--- PASS: TestMinimumNArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestMinimumNArgsWithLessArgs
--- PASS: TestMinimumNArgsWithLessArgs (0.00s)
=== RUN   TestMinimumNArgsWithLessArgsWithValid
--- PASS: TestMinimumNArgsWithLessArgsWithValid (0.00s)
=== RUN   TestMinimumNArgsWithLessArgsWithValidWithInvalidArgs
--- PASS: TestMinimumNArgsWithLessArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestMaximumNArgs
--- PASS: TestMaximumNArgs (0.00s)
=== RUN   TestMaximumNArgsWithValid
--- PASS: TestMaximumNArgsWithValid (0.00s)
=== RUN   TestMaximumNArgsWithValidWithInvalidArgs
--- PASS: TestMaximumNArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestMaximumNArgsWithMoreArgs
--- PASS: TestMaximumNArgsWithMoreArgs (0.00s)
=== RUN   TestMaximumNArgsWithMoreArgsWithValid
--- PASS: TestMaximumNArgsWithMoreArgsWithValid (0.00s)
=== RUN   TestMaximumNArgsWithMoreArgsWithValidWithInvalidArgs
--- PASS: TestMaximumNArgsWithMoreArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestExactArgs
--- PASS: TestExactArgs (0.00s)
=== RUN   TestExactArgsWithValid
--- PASS: TestExactArgsWithValid (0.00s)
=== RUN   TestExactArgsWithValidWithInvalidArgs
--- PASS: TestExactArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestExactArgsWithInvalidCount
--- PASS: TestExactArgsWithInvalidCount (0.00s)
=== RUN   TestExactArgsWithInvalidCountWithValid
--- PASS: TestExactArgsWithInvalidCountWithValid (0.00s)
=== RUN   TestExactArgsWithInvalidCountWithValidWithInvalidArgs
--- PASS: TestExactArgsWithInvalidCountWithValidWithInvalidArgs (0.00s)
=== RUN   TestRangeArgs
--- PASS: TestRangeArgs (0.00s)
=== RUN   TestRangeArgsWithValid
--- PASS: TestRangeArgsWithValid (0.00s)
=== RUN   TestRangeArgsWithValidWithInvalidArgs
--- PASS: TestRangeArgsWithValidWithInvalidArgs (0.00s)
=== RUN   TestRangeArgsWithInvalidCount
--- PASS: TestRangeArgsWithInvalidCount (0.00s)
=== RUN   TestRangeArgsWithInvalidCountWithValid
--- PASS: TestRangeArgsWithInvalidCountWithValid (0.00s)
=== RUN   TestRangeArgsWithInvalidCountWithValidWithInvalidArgs
--- PASS: TestRangeArgsWithInvalidCountWithValidWithInvalidArgs (0.00s)
=== RUN   TestRootTakesNoArgs
--- PASS: TestRootTakesNoArgs (0.00s)
=== RUN   TestRootTakesArgs
--- PASS: TestRootTakesArgs (0.00s)
=== RUN   TestChildTakesNoArgs
--- PASS: TestChildTakesNoArgs (0.00s)
=== RUN   TestChildTakesArgs
--- PASS: TestChildTakesArgs (0.00s)
```

Merge spf13/cobra#841

Fix #838 and Fix #745
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lifecycle/active Actively being worked on by a community member or maintainer. Corresponds to someone being assigned size/XL Denotes a PR that exceeds 200 lines. Caution!
Projects
None yet