Skip to content

Commit 2a2b77a

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents aae8e19 + d661846 commit 2a2b77a

File tree

4 files changed

+314
-28
lines changed

4 files changed

+314
-28
lines changed

errors.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package pflag
2+
3+
import "fmt"
4+
5+
// notExistErrorMessageType specifies which flavor of "flag does not exist"
6+
// is printed by NotExistError. This allows the related errors to be grouped
7+
// under a single NotExistError struct without making a breaking change to
8+
// the error message text.
9+
type notExistErrorMessageType int
10+
11+
const (
12+
flagNotExistMessage notExistErrorMessageType = iota
13+
flagNotDefinedMessage
14+
flagNoSuchFlagMessage
15+
flagUnknownFlagMessage
16+
flagUnknownShorthandFlagMessage
17+
)
18+
19+
// NotExistError is the error returned when trying to access a flag that
20+
// does not exist in the FlagSet.
21+
type NotExistError struct {
22+
name string
23+
specifiedShorthands string
24+
messageType notExistErrorMessageType
25+
}
26+
27+
// Error implements error.
28+
func (e *NotExistError) Error() string {
29+
switch e.messageType {
30+
case flagNotExistMessage:
31+
return fmt.Sprintf("flag %q does not exist", e.name)
32+
33+
case flagNotDefinedMessage:
34+
return fmt.Sprintf("flag accessed but not defined: %s", e.name)
35+
36+
case flagNoSuchFlagMessage:
37+
return fmt.Sprintf("no such flag -%v", e.name)
38+
39+
case flagUnknownFlagMessage:
40+
return fmt.Sprintf("unknown flag: --%s", e.name)
41+
42+
case flagUnknownShorthandFlagMessage:
43+
c := rune(e.name[0])
44+
return fmt.Sprintf("unknown shorthand flag: %q in -%s", c, e.specifiedShorthands)
45+
}
46+
47+
panic(fmt.Errorf("unknown flagNotExistErrorMessageType: %v", e.messageType))
48+
}
49+
50+
// GetSpecifiedName returns the name of the flag (without dashes) as it
51+
// appeared in the parsed arguments.
52+
func (e *NotExistError) GetSpecifiedName() string {
53+
return e.name
54+
}
55+
56+
// GetSpecifiedShortnames returns the group of shorthand arguments
57+
// (without dashes) that the flag appeared within. If the flag was not in a
58+
// shorthand group, this will return an empty string.
59+
func (e *NotExistError) GetSpecifiedShortnames() string {
60+
return e.specifiedShorthands
61+
}
62+
63+
// ValueRequiredError is the error returned when a flag needs an argument but
64+
// no argument was provided.
65+
type ValueRequiredError struct {
66+
flag *Flag
67+
specifiedName string
68+
specifiedShorthands string
69+
}
70+
71+
// Error implements error.
72+
func (e *ValueRequiredError) Error() string {
73+
if len(e.specifiedShorthands) > 0 {
74+
c := rune(e.specifiedName[0])
75+
return fmt.Sprintf("flag needs an argument: %q in -%s", c, e.specifiedShorthands)
76+
}
77+
78+
return fmt.Sprintf("flag needs an argument: --%s", e.specifiedName)
79+
}
80+
81+
// GetFlag returns the flag for which the error occurred.
82+
func (e *ValueRequiredError) GetFlag() *Flag {
83+
return e.flag
84+
}
85+
86+
// GetSpecifiedName returns the name of the flag (without dashes) as it
87+
// appeared in the parsed arguments.
88+
func (e *ValueRequiredError) GetSpecifiedName() string {
89+
return e.specifiedName
90+
}
91+
92+
// GetSpecifiedShortnames returns the group of shorthand arguments
93+
// (without dashes) that the flag appeared within. If the flag was not in a
94+
// shorthand group, this will return an empty string.
95+
func (e *ValueRequiredError) GetSpecifiedShortnames() string {
96+
return e.specifiedShorthands
97+
}
98+
99+
// InvalidValueError is the error returned when an invalid value is used
100+
// for a flag.
101+
type InvalidValueError struct {
102+
flag *Flag
103+
value string
104+
cause error
105+
}
106+
107+
// Error implements error.
108+
func (e *InvalidValueError) Error() string {
109+
flag := e.flag
110+
var flagName string
111+
if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
112+
flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
113+
} else {
114+
flagName = fmt.Sprintf("--%s", flag.Name)
115+
}
116+
return fmt.Sprintf("invalid argument %q for %q flag: %v", e.value, flagName, e.cause)
117+
}
118+
119+
// Unwrap implements errors.Unwrap.
120+
func (e *InvalidValueError) Unwrap() error {
121+
return e.cause
122+
}
123+
124+
// GetFlag returns the flag for which the error occurred.
125+
func (e *InvalidValueError) GetFlag() *Flag {
126+
return e.flag
127+
}
128+
129+
// GetValue returns the invalid value that was provided.
130+
func (e *InvalidValueError) GetValue() string {
131+
return e.value
132+
}
133+
134+
// InvalidSyntaxError is the error returned when a bad flag name is passed on
135+
// the command line.
136+
type InvalidSyntaxError struct {
137+
specifiedFlag string
138+
}
139+
140+
// Error implements error.
141+
func (e *InvalidSyntaxError) Error() string {
142+
return fmt.Sprintf("bad flag syntax: %s", e.specifiedFlag)
143+
}
144+
145+
// GetSpecifiedName returns the exact flag (with dashes) as it
146+
// appeared in the parsed arguments.
147+
func (e *InvalidSyntaxError) GetSpecifiedFlag() string {
148+
return e.specifiedFlag
149+
}

errors_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package pflag
2+
3+
import (
4+
"errors"
5+
"testing"
6+
)
7+
8+
func TestNotExistError(t *testing.T) {
9+
err := &NotExistError{
10+
name: "foo",
11+
specifiedShorthands: "bar",
12+
}
13+
14+
if err.GetSpecifiedName() != "foo" {
15+
t.Errorf("Expected GetSpecifiedName to return %q, got %q", "foo", err.GetSpecifiedName())
16+
}
17+
if err.GetSpecifiedShortnames() != "bar" {
18+
t.Errorf("Expected GetSpecifiedShortnames to return %q, got %q", "bar", err.GetSpecifiedShortnames())
19+
}
20+
}
21+
22+
func TestValueRequiredError(t *testing.T) {
23+
err := &ValueRequiredError{
24+
flag: &Flag{},
25+
specifiedName: "foo",
26+
specifiedShorthands: "bar",
27+
}
28+
29+
if err.GetFlag() == nil {
30+
t.Error("Expected GetSpecifiedName to return its flag field, but got nil")
31+
}
32+
if err.GetSpecifiedName() != "foo" {
33+
t.Errorf("Expected GetSpecifiedName to return %q, got %q", "foo", err.GetSpecifiedName())
34+
}
35+
if err.GetSpecifiedShortnames() != "bar" {
36+
t.Errorf("Expected GetSpecifiedShortnames to return %q, got %q", "bar", err.GetSpecifiedShortnames())
37+
}
38+
}
39+
40+
func TestInvalidValueError(t *testing.T) {
41+
expectedCause := errors.New("error")
42+
err := &InvalidValueError{
43+
flag: &Flag{},
44+
value: "foo",
45+
cause: expectedCause,
46+
}
47+
48+
if err.GetFlag() == nil {
49+
t.Error("Expected GetSpecifiedName to return its flag field, but got nil")
50+
}
51+
if err.GetValue() != "foo" {
52+
t.Errorf("Expected GetValue to return %q, got %q", "foo", err.GetValue())
53+
}
54+
if err.Unwrap() != expectedCause {
55+
t.Errorf("Expected Unwrwap to return %q, got %q", expectedCause, err.Unwrap())
56+
}
57+
}
58+
59+
func TestInvalidSyntaxError(t *testing.T) {
60+
err := &InvalidSyntaxError{
61+
specifiedFlag: "--=",
62+
}
63+
64+
if err.GetSpecifiedFlag() != "--=" {
65+
t.Errorf("Expected GetSpecifiedFlag to return %q, got %q", "--=", err.GetSpecifiedFlag())
66+
}
67+
}

flag.go

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ func (f *FlagSet) lookup(name NormalizedName) *Flag {
381381
func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {
382382
flag := f.Lookup(name)
383383
if flag == nil {
384-
err := fmt.Errorf("flag accessed but not defined: %s", name)
384+
err := &NotExistError{name: name, messageType: flagNotDefinedMessage}
385385
return nil, err
386386
}
387387

@@ -411,7 +411,7 @@ func (f *FlagSet) ArgsLenAtDash() int {
411411
func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
412412
flag := f.Lookup(name)
413413
if flag == nil {
414-
return fmt.Errorf("flag %q does not exist", name)
414+
return &NotExistError{name: name, messageType: flagNotExistMessage}
415415
}
416416
if usageMessage == "" {
417417
return fmt.Errorf("deprecated message for flag %q must be set", name)
@@ -427,7 +427,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
427427
func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error {
428428
flag := f.Lookup(name)
429429
if flag == nil {
430-
return fmt.Errorf("flag %q does not exist", name)
430+
return &NotExistError{name: name, messageType: flagNotExistMessage}
431431
}
432432
if usageMessage == "" {
433433
return fmt.Errorf("deprecated message for flag %q must be set", name)
@@ -441,7 +441,7 @@ func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) erro
441441
func (f *FlagSet) MarkHidden(name string) error {
442442
flag := f.Lookup(name)
443443
if flag == nil {
444-
return fmt.Errorf("flag %q does not exist", name)
444+
return &NotExistError{name: name, messageType: flagNotExistMessage}
445445
}
446446
flag.Hidden = true
447447
return nil
@@ -464,18 +464,16 @@ func (f *FlagSet) Set(name, value string) error {
464464
normalName := f.normalizeFlagName(name)
465465
flag, ok := f.formal[normalName]
466466
if !ok {
467-
return fmt.Errorf("no such flag -%v", name)
467+
return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
468468
}
469469

470470
err := flag.Value.Set(value)
471471
if err != nil {
472-
var flagName string
473-
if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
474-
flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)
475-
} else {
476-
flagName = fmt.Sprintf("--%s", flag.Name)
472+
return &InvalidValueError{
473+
flag: flag,
474+
value: value,
475+
cause: err,
477476
}
478-
return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
479477
}
480478

481479
if !flag.Changed {
@@ -501,7 +499,7 @@ func (f *FlagSet) SetAnnotation(name, key string, values []string) error {
501499
normalName := f.normalizeFlagName(name)
502500
flag, ok := f.formal[normalName]
503501
if !ok {
504-
return fmt.Errorf("no such flag -%v", name)
502+
return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
505503
}
506504
if flag.Annotations == nil {
507505
flag.Annotations = map[string][]string{}
@@ -551,7 +549,7 @@ func (f *Flag) defaultIsZeroValue() bool {
551549
case *intSliceValue, *stringSliceValue, *stringArrayValue:
552550
return f.DefValue == "[]"
553551
default:
554-
switch f.Value.String() {
552+
switch f.DefValue {
555553
case "false":
556554
return true
557555
case "<nil>":
@@ -911,10 +909,9 @@ func VarP(value Value, name, shorthand, usage string) {
911909
CommandLine.VarP(value, name, shorthand, usage)
912910
}
913911

914-
// failf prints to standard error a formatted error and usage message and
912+
// fail prints an error message and usage message to standard error and
915913
// returns the error.
916-
func (f *FlagSet) failf(format string, a ...interface{}) error {
917-
err := fmt.Errorf(format, a...)
914+
func (f *FlagSet) fail(err error) error {
918915
if f.errorHandling != ContinueOnError {
919916
fmt.Fprintln(f.Output(), err)
920917
f.usage()
@@ -960,7 +957,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
960957
a = args
961958
name := s[2:]
962959
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
963-
err = f.failf("bad flag syntax: %s", s)
960+
err = f.fail(&InvalidSyntaxError{specifiedFlag: s})
964961
return
965962
}
966963

@@ -982,7 +979,7 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
982979

983980
return stripUnknownFlagValue(a), nil
984981
default:
985-
err = f.failf("unknown flag: --%s", name)
982+
err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage})
986983
return
987984
}
988985
}
@@ -1000,13 +997,16 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
1000997
a = a[1:]
1001998
} else {
1002999
// '--flag' (arg was required)
1003-
err = f.failf("flag needs an argument: %s", s)
1000+
err = f.fail(&ValueRequiredError{
1001+
flag: flag,
1002+
specifiedName: name,
1003+
})
10041004
return
10051005
}
10061006

10071007
err = fn(flag, value)
10081008
if err != nil {
1009-
f.failf(err.Error())
1009+
f.fail(err)
10101010
}
10111011
return
10121012
}
@@ -1039,7 +1039,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
10391039
outArgs = stripUnknownFlagValue(outArgs)
10401040
return
10411041
default:
1042-
err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
1042+
err = f.fail(&NotExistError{
1043+
name: string(c),
1044+
specifiedShorthands: shorthands,
1045+
messageType: flagUnknownShorthandFlagMessage,
1046+
})
10431047
return
10441048
}
10451049
}
@@ -1062,7 +1066,11 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
10621066
outArgs = args[1:]
10631067
} else {
10641068
// '-f' (arg was required)
1065-
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
1069+
err = f.fail(&ValueRequiredError{
1070+
flag: flag,
1071+
specifiedName: string(c),
1072+
specifiedShorthands: shorthands,
1073+
})
10661074
return
10671075
}
10681076

@@ -1072,7 +1080,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
10721080

10731081
err = fn(flag, value)
10741082
if err != nil {
1075-
f.failf(err.Error())
1083+
f.fail(err)
10761084
}
10771085
return
10781086
}

0 commit comments

Comments
 (0)