-
Notifications
You must be signed in to change notification settings - Fork 366
Make Value a drop-in replacement for flag.Value #436
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
base: master
Are you sure you want to change the base?
Conversation
| // Its value should be a constant string that identifies the type of | ||
| // the underlying flag value. | ||
| type TypedValue interface { | ||
| Value |
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.
This is a tricky one; this change removes the Type() string from the interface, which means that if someone used this interface for other code, and expect values to have a Type() function, they may now end up with a value that doesn't support it.
IIUC, the change is meant to make the Type() optional for functions in this repository, so that they can accept both stdlib Values and spf13/pflag values (which are "richer" as they provide the Type() method).
An alternative approach would be to;
- Add a new
StdValueinterface, which is the reduced interface - Keep the
Valueinterface untouched, but (optionally) alias it toTypedValue(mostly to be more expressive in its intent)
However, looking at stdlib; it looks like stdlib defines a flag.Value interface (which was already available in go1.12, so safe to use: https://pkg.go.dev/[email protected]#Value); perhaps it's better and more transparent to not define a local interface for that, but to embed the one from stdlib.
- Update all signatures that currently require a
spf13/pflag.Valueto useflag.Value(and be more permissive); at a quick glance, none of theFlagSetmethods are part of an interface, so possibly they can be made more permissive. Either that, or new methods to be added (but maybe that's not needed). - Add the new
TypedValueinterface, and make it embed the stdlibflag.Value - Deprecate the old
spf13/pflag.Valueinterface in favor ofTypedValueorflag.Value("depending on the use-case")
So something like;
// Value is the interface to the dynamic value stored in a flag as implemented.
//
// Deprecated: use [flag.Value] or [TypedValue], depending on your use-case.
type Value = TypedValue
// TypedValue wraps extends [flag.Value] with an additional Type() string, which
// can be used to special-case things like usage instructions, error
// messages, parsing, etc.
// Its value should be a constant string that identifies the type of
// the underlying flag value.
type TypedValue interface {
flag.Value
Type() string
}|
|
||
| line += usage | ||
| if !flag.defaultIsZeroValue() { | ||
| if flag.Value.Type() == "string" { |
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.
Hm... overlooked this part; this will be tricky, because we're removing the Type() from the Flag.Value - that will likely break people as they would now have to implement code similar to what's in the PR to assert that the flag Value implements the TypedValue;
Lines 192 to 196 in 1043857
| type Flag struct { | |
| Name string // name as it appears on command line | |
| Shorthand string // one-letter abbreviated flag | |
| Usage string // help message | |
| Value Value // value as set |
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.
Perhaps this requires a utility to convert/wrap as StdLib value to TypedValue (assign a type), but keeping this Field to implement Type() (TypedValue to be explicit).
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.
I guess the (philosophical) question is whether the breaking change is introducing this method on the Value type (thus breaking the promise of being a drop-in replacement for stdlib flag), or removing it. If one takes the former stance, then this is a bug fix; with the latter, it's a major version bump. (So after all the flak for 1.0.8, it turns out it's not even clear cut what a breaking change is. Who'da thunk? 😉)
My guess is that there are quite a few instances of people implementing Type because our interface requires it from them, but much fewer (if anyone) actually using the method for anything on their end.
Fixes #228.
This should allow users to provide their own types implementing
flag.Valuealso topflag, aspflag.Valueis now equivalent to the standard-library variant.The
Type()method is moved to a wrapper interfaceTypedValueand code relying on it must first test that the provided value implements this interface; this has been done in all code inpflagand tests are still passing, so I'm fairly confident that the changes are correct even if I haven't actually tried them out on a use case with a user-definedValueimplementation (withoutType()).