github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/pkg/cataloger/python/parse_poetry_lock.go (about) 1 package python 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/pelletier/go-toml" 8 9 "github.com/anchore/syft/syft/artifact" 10 "github.com/anchore/syft/syft/file" 11 "github.com/anchore/syft/syft/pkg" 12 "github.com/anchore/syft/syft/pkg/cataloger/generic" 13 ) 14 15 // integrity check 16 var _ generic.Parser = parsePoetryLock 17 18 type poetryPackageSource struct { 19 URL string `toml:"url"` 20 } 21 22 type poetryPackages struct { 23 Packages []struct { 24 Name string `toml:"name"` 25 Version string `toml:"version"` 26 Category string `toml:"category"` 27 Description string `toml:"description"` 28 Optional bool `toml:"optional"` 29 Source poetryPackageSource `toml:"source"` 30 } `toml:"package"` 31 } 32 33 // parsePoetryLock is a parser function for poetry.lock contents, returning all python packages discovered. 34 func parsePoetryLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { 35 tree, err := toml.LoadReader(reader) 36 if err != nil { 37 return nil, nil, fmt.Errorf("unable to load poetry.lock for parsing: %w", err) 38 } 39 40 metadata := poetryPackages{} 41 err = tree.Unmarshal(&metadata) 42 if err != nil { 43 return nil, nil, fmt.Errorf("unable to parse poetry.lock: %w", err) 44 } 45 46 var pkgs []pkg.Package 47 for _, p := range metadata.Packages { 48 var index string 49 if p.Source.URL != "" { 50 index = p.Source.URL 51 } else { 52 // https://python-poetry.org/docs/repositories/ 53 index = "https://pypi.org/simple" 54 } 55 pkgs = append( 56 pkgs, 57 newPackageForIndexWithMetadata( 58 p.Name, 59 p.Version, 60 pkg.PythonPoetryLockEntry{Index: index}, 61 reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), 62 ), 63 ) 64 } 65 66 return pkgs, nil, nil 67 }