diff --git a/extractor/filesystem/language/python/internal/pypipurl/pythonpurl.go b/extractor/filesystem/language/python/internal/pypipurl/pythonpurl.go new file mode 100644 index 00000000..9bcf69a2 --- /dev/null +++ b/extractor/filesystem/language/python/internal/pypipurl/pythonpurl.go @@ -0,0 +1,22 @@ +// Package pypipurl converts an inventory to a PyPI type PackageURL. +package pypipurl + +import ( + "strings" + + "github.com/google/osv-scalibr/extractor" + "github.com/google/osv-scalibr/purl" +) + +// MakePackageURL returns a package URL following the purl PyPI spec: +// - Name is lowercased +// - Replaces _ with - +// +// See: https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#pypi +func MakePackageURL(i *extractor.Inventory) *purl.PackageURL { + return &purl.PackageURL{ + Type: purl.TypePyPi, + Name: strings.ReplaceAll(strings.ToLower(i.Name), "_", "-"), + Version: i.Version, + } +} diff --git a/extractor/filesystem/language/python/pdmlock/extractor.go b/extractor/filesystem/language/python/pdmlock/extractor.go index e843f986..93946461 100644 --- a/extractor/filesystem/language/python/pdmlock/extractor.go +++ b/extractor/filesystem/language/python/pdmlock/extractor.go @@ -10,6 +10,7 @@ import ( "github.com/BurntSushi/toml" "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem" + "github.com/google/osv-scalibr/extractor/filesystem/language/python/internal/pypipurl" "github.com/google/osv-scalibr/extractor/filesystem/osv" "github.com/google/osv-scalibr/plugin" "github.com/google/osv-scalibr/purl" @@ -98,11 +99,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] // ToPURL converts an inventory created by this extractor into a PURL. func (e Extractor) ToPURL(i *extractor.Inventory) (*purl.PackageURL, error) { - return &purl.PackageURL{ - Type: purl.TypePyPi, - Name: i.Name, - Version: i.Version, - }, nil + return pypipurl.MakePackageURL(i), nil } // ToCPEs is not applicable as this extractor does not infer CPEs from the Inventory. diff --git a/extractor/filesystem/language/python/pipfilelock/extractor.go b/extractor/filesystem/language/python/pipfilelock/extractor.go index 5934fc53..5a674aa0 100644 --- a/extractor/filesystem/language/python/pipfilelock/extractor.go +++ b/extractor/filesystem/language/python/pipfilelock/extractor.go @@ -10,6 +10,7 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem" + "github.com/google/osv-scalibr/extractor/filesystem/language/python/internal/pypipurl" "github.com/google/osv-scalibr/extractor/filesystem/osv" "github.com/google/osv-scalibr/plugin" "github.com/google/osv-scalibr/purl" @@ -100,11 +101,7 @@ func addPkgDetails(details map[string]*extractor.Inventory, packages map[string] // ToPURL converts an inventory created by this extractor into a PURL. func (e Extractor) ToPURL(i *extractor.Inventory) (*purl.PackageURL, error) { - return &purl.PackageURL{ - Type: purl.TypePyPi, - Name: i.Name, - Version: i.Version, - }, nil + return pypipurl.MakePackageURL(i), nil } // ToCPEs is not applicable as this extractor does not infer CPEs from the Inventory. diff --git a/extractor/filesystem/language/python/poetrylock/extractor.go b/extractor/filesystem/language/python/poetrylock/extractor.go index 989d7a58..7321452b 100644 --- a/extractor/filesystem/language/python/poetrylock/extractor.go +++ b/extractor/filesystem/language/python/poetrylock/extractor.go @@ -10,6 +10,7 @@ import ( "github.com/BurntSushi/toml" "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem" + "github.com/google/osv-scalibr/extractor/filesystem/language/python/internal/pypipurl" "github.com/google/osv-scalibr/extractor/filesystem/osv" "github.com/google/osv-scalibr/plugin" "github.com/google/osv-scalibr/purl" @@ -91,11 +92,7 @@ func (e Extractor) Extract(ctx context.Context, input *filesystem.ScanInput) ([] // ToPURL converts an inventory created by this extractor into a PURL. func (e Extractor) ToPURL(i *extractor.Inventory) (*purl.PackageURL, error) { - return &purl.PackageURL{ - Type: purl.TypePyPi, - Name: i.Name, - Version: i.Version, - }, nil + return pypipurl.MakePackageURL(i), nil } // ToCPEs is not applicable as this extractor does not infer CPEs from the Inventory. diff --git a/extractor/filesystem/language/python/requirements/extractor.go b/extractor/filesystem/language/python/requirements/extractor.go index 5e1a77a4..81a6d954 100644 --- a/extractor/filesystem/language/python/requirements/extractor.go +++ b/extractor/filesystem/language/python/requirements/extractor.go @@ -28,6 +28,7 @@ import ( "github.com/google/osv-scalibr/extractor/filesystem" scalibrfs "github.com/google/osv-scalibr/fs" "github.com/google/osv-scalibr/log" + "github.com/google/osv-scalibr/extractor/filesystem/language/python/internal/pypipurl" "github.com/google/osv-scalibr/plugin" "github.com/google/osv-scalibr/purl" "github.com/google/osv-scalibr/stats" @@ -288,11 +289,7 @@ func splitPerRequirementOptions(s string) (string, []string) { // ToPURL converts an inventory created by this extractor into a PURL. func (e Extractor) ToPURL(i *extractor.Inventory) (*purl.PackageURL, error) { - return &purl.PackageURL{ - Type: purl.TypePyPi, - Name: strings.ToLower(i.Name), - Version: i.Version, - }, nil + return pypipurl.MakePackageURL(i), nil } // ToCPEs is not applicable as this extractor does not infer CPEs from the Inventory. diff --git a/extractor/filesystem/language/python/wheelegg/extractor.go b/extractor/filesystem/language/python/wheelegg/extractor.go index 9ba8284c..f34c2709 100644 --- a/extractor/filesystem/language/python/wheelegg/extractor.go +++ b/extractor/filesystem/language/python/wheelegg/extractor.go @@ -31,6 +31,7 @@ import ( "github.com/google/osv-scalibr/extractor" "github.com/google/osv-scalibr/extractor/filesystem" "github.com/google/osv-scalibr/extractor/filesystem/internal/units" + "github.com/google/osv-scalibr/extractor/filesystem/language/python/internal/pypipurl" "github.com/google/osv-scalibr/plugin" "github.com/google/osv-scalibr/purl" "github.com/google/osv-scalibr/stats" @@ -265,11 +266,7 @@ func parse(r io.Reader) (*extractor.Inventory, error) { // ToPURL converts an inventory created by this extractor into a PURL. func (e Extractor) ToPURL(i *extractor.Inventory) (*purl.PackageURL, error) { - return &purl.PackageURL{ - Type: purl.TypePyPi, - Name: strings.ToLower(i.Name), - Version: i.Version, - }, nil + return pypipurl.MakePackageURL(i), nil } // ToCPEs is not applicable as this extractor does not infer CPEs from the Inventory.