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  }