github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/python/package.go (about)

     1  package python
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"regexp"
     7  	"strings"
     8  
     9  	"github.com/anchore/packageurl-go"
    10  	"github.com/anchore/syft/syft/file"
    11  	"github.com/anchore/syft/syft/pkg"
    12  )
    13  
    14  func normalize(name string) string {
    15  	// https://packaging.python.org/en/latest/specifications/name-normalization/
    16  	re := regexp.MustCompile(`[-_.]+`)
    17  	normalized := re.ReplaceAllString(name, "-")
    18  	return strings.ToLower(normalized)
    19  }
    20  
    21  func newPackageForIndex(ctx context.Context, lr pythonLicenseResolver, name, version string, locations ...file.Location) pkg.Package {
    22  	name = normalize(name)
    23  	licenseSet := lr.getLicenses(ctx, name, version)
    24  
    25  	p := pkg.Package{
    26  		Name:      name,
    27  		Version:   version,
    28  		Licenses:  licenseSet,
    29  		Locations: file.NewLocationSet(locations...),
    30  		PURL:      packageURL(name, version, nil),
    31  		Language:  pkg.Python,
    32  		Type:      pkg.PythonPkg,
    33  	}
    34  
    35  	p.SetID()
    36  
    37  	return p
    38  }
    39  
    40  func newPackageForIndexWithMetadata(ctx context.Context, lr pythonLicenseResolver, name, version string, metadata interface{}, locations ...file.Location) pkg.Package {
    41  	name = normalize(name)
    42  	licenseSet := lr.getLicenses(ctx, name, version)
    43  
    44  	p := pkg.Package{
    45  		Name:      name,
    46  		Version:   version,
    47  		Licenses:  licenseSet,
    48  		Locations: file.NewLocationSet(locations...),
    49  		PURL:      packageURL(name, version, nil),
    50  		Language:  pkg.Python,
    51  		Type:      pkg.PythonPkg,
    52  		Metadata:  metadata,
    53  	}
    54  
    55  	p.SetID()
    56  
    57  	return p
    58  }
    59  
    60  func newPackageForRequirementsWithMetadata(ctx context.Context, lr pythonLicenseResolver, name, version string, metadata pkg.PythonRequirementsEntry, locations ...file.Location) pkg.Package {
    61  	name = normalize(name)
    62  	licenseSet := lr.getLicenses(ctx, name, version)
    63  
    64  	p := pkg.Package{
    65  		Name:      name,
    66  		Version:   version,
    67  		Licenses:  licenseSet,
    68  		Locations: file.NewLocationSet(locations...),
    69  		PURL:      packageURL(name, version, nil),
    70  		Language:  pkg.Python,
    71  		Type:      pkg.PythonPkg,
    72  		Metadata:  metadata,
    73  	}
    74  
    75  	p.SetID()
    76  
    77  	return p
    78  }
    79  
    80  func newPackageForPackage(m parsedData, licenses pkg.LicenseSet, sources ...file.Location) pkg.Package {
    81  	name := normalize(m.Name)
    82  
    83  	p := pkg.Package{
    84  		Name:      name,
    85  		Version:   m.Version,
    86  		PURL:      packageURL(name, m.Version, &m.PythonPackage),
    87  		Locations: file.NewLocationSet(sources...),
    88  		Licenses:  licenses,
    89  		Language:  pkg.Python,
    90  		Type:      pkg.PythonPkg,
    91  		Metadata:  m.PythonPackage,
    92  	}
    93  
    94  	p.SetID()
    95  
    96  	return p
    97  }
    98  
    99  func packageURL(name, version string, m *pkg.PythonPackage) string {
   100  	// generate a purl from the package data
   101  	pURL := packageurl.NewPackageURL(
   102  		packageurl.TypePyPi,
   103  		"",
   104  		name,
   105  		version,
   106  		purlQualifiersForPackage(m),
   107  		"")
   108  
   109  	return pURL.ToString()
   110  }
   111  
   112  func purlQualifiersForPackage(m *pkg.PythonPackage) packageurl.Qualifiers {
   113  	q := packageurl.Qualifiers{}
   114  	if m == nil {
   115  		return q
   116  	}
   117  	if m.DirectURLOrigin != nil {
   118  		q = append(q, vcsURLQualifierForPackage(m.DirectURLOrigin)...)
   119  	}
   120  	return q
   121  }
   122  
   123  func vcsURLQualifierForPackage(p *pkg.PythonDirectURLOriginInfo) packageurl.Qualifiers {
   124  	if p == nil || p.VCS == "" {
   125  		return nil
   126  	}
   127  	// Taken from https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst#known-qualifiers-keyvalue-pairs
   128  	// packageurl-go still doesn't support all qualifier names
   129  	return packageurl.Qualifiers{
   130  		{Key: pkg.PURLQualifierVCSURL, Value: fmt.Sprintf("%s+%s@%s", p.VCS, p.URL, p.CommitID)},
   131  	}
   132  }