cli
cli copied to clipboard
Expected `cli.Generic` but actual is `string`
my urfave/cli version is
v2
Checklist
- [x] Are you running the latest v2 release? The list of releases is here.
- [x] Did you check the manual for your release? The v2 manual is here
- [x] Did you perform a search about this problem? Here's the Github guide about searching.
Dependency Management
- Bazel
Describe the bug
Trying to specify a generic flag to load from yaml.
To reproduce
Create a generic flag and provide a string value in yaml.
Observed behavior
Expected 'cli.Generic' but actual is 'string'
Expected behavior
It works
Additional context
Add any other context about the problem here.
If the issue relates to a specific open source Github repo, please link that repo here.
If you can reproduce this issue with a public CI system, please link a failing build here.
Want to fix this yourself?
We'd love to have more contributors on this project! If the fix for this bug is easily explained and very small, free free to create a pull request for it.
Run go version
and paste its output here
go version go1.13.1 linux/amd64
Run go env
and paste its output here
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/preston/.cache/go-build"
GOENV="/home/preston/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/preston/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build299372313=/tmp/go-build -gno-record-gcc-switches"
@prestonvanloon I need to see some code in your reproduction, your description of the reproduction doesn't have enough detail for me to look into it effectively.
This issue or PR has been automatically marked as stale because it has not had recent activity. Please add a comment bumping this if you're still interested in it's resolution! Thanks for your help, please let us know if you need anything else.
Closing this as it has become stale.
I think I have a reprex 🤔
package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli/v2"
"github.com/urfave/cli/v2/altsrc"
)
type Pants struct {
v string
}
func (p *Pants) Set(value string) error {
p.v = value
return nil
}
func (p *Pants) String() string {
return p.v
}
func main() {
pantsPtr := &Pants{}
flags := []cli.Flag{
altsrc.NewGenericFlag(&cli.GenericFlag{Name: "pants", Value: pantsPtr}),
&cli.StringFlag{Name: "load"},
}
app := &cli.App{
Action: func(cCtx *cli.Context) error {
pants := cCtx.Generic("pants")
fmt.Printf("pants (%T): %+#v\n", pants, pants)
return nil
},
Before: altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load")),
Flags: flags,
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
pants: eleven
$ go run 1072.go --load 1072.yml
2022/05/05 21:52:38 Mismatched type for flag 'pants'. Expected 'cli.Generic' but actual is 'string'
exit status 1
@meatballhat This is actually expected behaviour. The normal yaml load can only load vanilla data types, int, float, string, intslice etc . For other complex types like Generic the default yaml loader doesnt know that it needs to deserialize, for example the pants: eleven to a &Pants{v:"eleven"}. It is the responsibility of the user to write a custom input source context(backed by map input source) which can handle the deserialization.
@dearchap I'm glad you know how this is supposed to work! :joy: :shrug: Is it obvious that I don't use altsrc?
Works as designed.
@meatballhat This is actually expected behaviour. The normal yaml load can only load vanilla data types, int, float, string, intslice etc . For other complex types like Generic the default yaml loader doesnt know that it needs to deserialize, for example the pants: eleven to a &Pants{v:"eleven"}. It is the responsibility of the user to write a custom input source context(backed by map input source) which can handle the deserialization.
@dearchap I'm running into a similar issue. Do you have an example on how to extend the yaml loader to support deserializing to custom types?
@richard-ramos You have to create a new yaml loader and pass in your custom struct here https://github.com/urfave/cli/blob/v2-maint/altsrc/yaml_file_loader.go#L25
That way the correct types are unmarshalled here
https://github.com/urfave/cli/blob/v2-maint/altsrc/yaml_file_loader.go#L49
Perhaps we could allow the user to pass in a custom unmarshal function. I have to think about it.