-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Support validation of positional arguments #284
Conversation
} | ||
|
||
// NoArgs returns an error if any args are included | ||
func NoArgs(cmd *Command, args []string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can a noarg command have subcommands? This seems like the trigger I wanted in #285, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, subcommand lookup happens before this is called in Find
, so these arg handling functions only take care of non-subcommand args. I believe this NoArgs
option is what you want in #285.
There's a problem with this PR. Arg validation happens before the I think the order of these operations needs to be adjusted. |
Ok, that issue should be fixed. Now legacy arg validation happens at the same time (before any flags are parsed), but any new arg validation will happen after flag parsing, so that flags like I updated the tests to catch this case. |
cobra_test.go
Outdated
@@ -513,6 +523,11 @@ func TestSubCmdTakesArgs(t *testing.T) { | |||
func TestCmdOnlyValidArgs(t *testing.T) { | |||
result := noRRSetupTest("echo times one two five") | |||
|
|||
if result.Error == nil { | |||
t.Errorf("Expected an error") | |||
t.FailNow() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The testing
package provides:
t.Fatal("Expected an error")
as a convenience method for wrapping the two calls you're making here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I've made that change. It did seem strange that I had to call two functions, but somehow I missed this.
This PR is in use by https://github.com/docker/docker to validation positional args. By using a function instead of an enum for the |
Am I understanding correctly? In addition to the documented features, you can now validate arguments in a custom contrived example (imagine if instead of : func validColorArgs(cmd *cobra.Command, args []string) error {
if err := cli.RequiresMinArgs(1)(cmd, args); err != nil {
return err
}
if myapp.IsValidColor(args[0]) {
return nil
}
return fmt.Errorf("Invalid color specified: %s", args[0])
} |
@rileytg yup, that's correct. You can write custom validation functions for the positional args. |
what do you think about changing the language to express something along the lines of: (im thinking maybe keep it like urs and add a Positional and Custom ArgumentsValidation of positional arguments can be specified using the Args: func validColorArgs(cmd *cobra.Command, args []string) error {
if err := cli.RequiresMinArgs(1)(cmd, args); err != nil {
return err
}
if myapp.IsValidColor(args[0]) {
return nil
}
return fmt.Errorf("Invalid color specified: %s", args[0])
} The follow validators are built in:
|
That sounds good. I'll update the PR with that change |
What about the help message of such commands? It would be great to automatically generate |
I find the |
Rebased and updated the README text as suggested |
c76d2fa
to
631cea0
Compare
Still waiting for feedback from the project maintainers. This code is being used in I pulled the latest from |
@dnephin, i just pulled it down and it seems your master branch is missing the commits from this branch. Could you rebase this branch with master so i can just use this branch from your fork? Thanks! |
The master branch has these changes, it just doesn't have the same commits. I think they were rebased from a different branch, so the commit ids are different. |
@@ -109,6 +113,16 @@ var cmdRootSameName = &Command{ | |||
Long: "The root description for help", | |||
} | |||
|
|||
var cmdRootTakesArgs = &Command{ | |||
Use: "root-with-args [random args]", | |||
Short: "The root can run it's own function and takes args!", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/it's/its
@dnephin what is the status of the PRs now? |
Status hasn't changed. Waiting on someone to accept or reject, or provide more feedback about how to get it accepted. |
@dnephin what do you think of it:
|
85279b9
to
fb31500
Compare
I've made those changes to the README. I'm not really a fan of |
Please solve merge conflicts. |
@dnephin I solved the merge conflicts by myself. Please copy all code from my branch ( |
…ry arguments Check that arguments are in ValidArgs If a command defined cmd.ValidArgs check that the argument is actually in ValidArgs and fail if it is not.
Fix some typos in README and comments. Move arg validation to after flag validation so that the help flag is run first. Pass the same args to ValidateArgs as the Run methods receive. Update README. Signed-off-by: Daniel Nephin <[email protected]>
rebased |
I know that this is coming from left field a little, however, I'm very new to Go and I'm trying to port an internal application and am currently very stuck primarily because the documentation simply does not make sense with regard to custom argument validation. I've been through this entire issue and the README.md, which briefly mentions it, but gives NO context about where it should go, how it should properly be used, etc, and everything I try ends up being an error. Would someone for the love of all that is good PLEASE explain how to use For instance, the docs say we can use this example (and I'm only supposing this belongs in the func validColorArgs(cmd *cobra.Command, args []string) error {
if err := cli.RequiresMinArgs(1)(cmd, args); err != nil {
return err
}
if myapp.IsValidColor(args[0]) {
return nil
}
return fmt.Errorf("Invalid color specified: %s", args[0])
} So, I used that. I get an error. Tangentially, the documentation for this project tries to be good, but it is seriously lacking some important details methinks. It almost seems like nobody is keeping it updated or at the very least is keeping it updated only minimally. For instance, I thought someone hijacked the documentation when mentioning even the ability for custom arg validation because when I tried to use it, my IDE screamed that it wasn't even available in the struct. Turns out, after reading this issue and seeing the change was just merged a couple of days ago that the problem was simply an outdated library on my system. Kudos for adding something about it at all in the documentation, but the details about how to properly use it are completely wrong or just missing. How are developers supposed to rely on this library if we can't track the changes or use the library reliably? Sorry for the rant. It's almost 4 AM so...it's just that I've lost a lot of time trying to figure this out and it seems like I shouldn't have had to. |
@notjames Sorry for inconvenience and this feature is documented really bad. I will make a PR now to fix this issue and we can discuss it there. |
Positional argument validation was added to spf13/cobra in spf13/cobra#284, but our cli still relies on custom validation in each of the "run" functions. This validation is unstandardized and overly permissive in certain cases. This change fixes this by replacing our custom logic with validation expressed using Cobra's `PositionalArgs` validators. Release note: None
Positional argument validation was added to spf13/cobra in spf13/cobra#284, but our cli still relies on custom validation in each of the "run" functions. This validation is unstandardized and overly permissive in certain cases. This change fixes this by replacing our custom logic with validation expressed using Cobra's `PositionalArgs` validators. Release note: None
Fixes #42
Branched from #120
Adds a new field
Args
that allows a user to define the expected positional arguments that a command should receive. If a command doesn't receive the expected args it returns an error.By accepting a validation function users can create their own custom validation for positional args. This PR includes validators for the most common cases.