mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
python-cataloger: normalize package names (#3069)
Signed-off-by: mikcl <mikesmikes400@gmail.com>
This commit is contained in:
parent
68b96ae444
commit
36f95d6828
@ -35,7 +35,7 @@ var imageOnlyTestCases = []testCase{
|
|||||||
pkgType: pkg.PythonPkg,
|
pkgType: pkg.PythonPkg,
|
||||||
pkgLanguage: pkg.Python,
|
pkgLanguage: pkg.Python,
|
||||||
pkgInfo: map[string]string{
|
pkgInfo: map[string]string{
|
||||||
"Pygments": "2.6.1",
|
"pygments": "2.6.1",
|
||||||
"requests": "2.22.0",
|
"requests": "2.22.0",
|
||||||
"somerequests": "3.22.0",
|
"somerequests": "3.22.0",
|
||||||
"someotherpkg": "3.19.0",
|
"someotherpkg": "3.19.0",
|
||||||
@ -172,7 +172,7 @@ var dirOnlyTestCases = []testCase{
|
|||||||
"passlib": "1.7.2",
|
"passlib": "1.7.2",
|
||||||
"mypy": "v0.770",
|
"mypy": "v0.770",
|
||||||
// common to image and directory
|
// common to image and directory
|
||||||
"Pygments": "2.6.1",
|
"pygments": "2.6.1",
|
||||||
"requests": "2.22.0",
|
"requests": "2.22.0",
|
||||||
"somerequests": "3.22.0",
|
"somerequests": "3.22.0",
|
||||||
"someotherpkg": "3.19.0",
|
"someotherpkg": "3.19.0",
|
||||||
|
|||||||
@ -119,9 +119,9 @@ func Test_PackageCataloger(t *testing.T) {
|
|||||||
"test-fixtures/dist-info/direct_url.json",
|
"test-fixtures/dist-info/direct_url.json",
|
||||||
},
|
},
|
||||||
expectedPackage: pkg.Package{
|
expectedPackage: pkg.Package{
|
||||||
Name: "Pygments",
|
Name: "pygments",
|
||||||
Version: "2.6.1",
|
Version: "2.6.1",
|
||||||
PURL: "pkg:pypi/Pygments@2.6.1?vcs_url=git%2Bhttps://github.com/python-test/test.git%40aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
PURL: "pkg:pypi/pygments@2.6.1?vcs_url=git%2Bhttps://github.com/python-test/test.git%40aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
Type: pkg.PythonPkg,
|
Type: pkg.PythonPkg,
|
||||||
Language: pkg.Python,
|
Language: pkg.Python,
|
||||||
Licenses: pkg.NewLicenseSet(
|
Licenses: pkg.NewLicenseSet(
|
||||||
@ -161,9 +161,9 @@ func Test_PackageCataloger(t *testing.T) {
|
|||||||
"test-fixtures/casesensitive/DIST-INFO/direct_url.json",
|
"test-fixtures/casesensitive/DIST-INFO/direct_url.json",
|
||||||
},
|
},
|
||||||
expectedPackage: pkg.Package{
|
expectedPackage: pkg.Package{
|
||||||
Name: "Pygments",
|
Name: "pygments",
|
||||||
Version: "2.6.1",
|
Version: "2.6.1",
|
||||||
PURL: "pkg:pypi/Pygments@2.6.1?vcs_url=git%2Bhttps://github.com/python-test/test.git%40aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
PURL: "pkg:pypi/pygments@2.6.1?vcs_url=git%2Bhttps://github.com/python-test/test.git%40aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
Type: pkg.PythonPkg,
|
Type: pkg.PythonPkg,
|
||||||
Language: pkg.Python,
|
Language: pkg.Python,
|
||||||
Licenses: pkg.NewLicenseSet(
|
Licenses: pkg.NewLicenseSet(
|
||||||
@ -199,9 +199,9 @@ func Test_PackageCataloger(t *testing.T) {
|
|||||||
"test-fixtures/malformed-record/dist-info/RECORD",
|
"test-fixtures/malformed-record/dist-info/RECORD",
|
||||||
},
|
},
|
||||||
expectedPackage: pkg.Package{
|
expectedPackage: pkg.Package{
|
||||||
Name: "Pygments",
|
Name: "pygments",
|
||||||
Version: "2.6.1",
|
Version: "2.6.1",
|
||||||
PURL: "pkg:pypi/Pygments@2.6.1",
|
PURL: "pkg:pypi/pygments@2.6.1",
|
||||||
Type: pkg.PythonPkg,
|
Type: pkg.PythonPkg,
|
||||||
Language: pkg.Python,
|
Language: pkg.Python,
|
||||||
Licenses: pkg.NewLicenseSet(
|
Licenses: pkg.NewLicenseSet(
|
||||||
@ -231,9 +231,9 @@ func Test_PackageCataloger(t *testing.T) {
|
|||||||
name: "partial dist-info directory",
|
name: "partial dist-info directory",
|
||||||
fixtures: []string{"test-fixtures/partial.dist-info/METADATA"},
|
fixtures: []string{"test-fixtures/partial.dist-info/METADATA"},
|
||||||
expectedPackage: pkg.Package{
|
expectedPackage: pkg.Package{
|
||||||
Name: "Pygments",
|
Name: "pygments",
|
||||||
Version: "2.6.1",
|
Version: "2.6.1",
|
||||||
PURL: "pkg:pypi/Pygments@2.6.1",
|
PURL: "pkg:pypi/pygments@2.6.1",
|
||||||
Type: pkg.PythonPkg,
|
Type: pkg.PythonPkg,
|
||||||
Language: pkg.Python,
|
Language: pkg.Python,
|
||||||
Licenses: pkg.NewLicenseSet(
|
Licenses: pkg.NewLicenseSet(
|
||||||
|
|||||||
@ -2,6 +2,8 @@ package python
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/anchore/packageurl-go"
|
"github.com/anchore/packageurl-go"
|
||||||
"github.com/anchore/syft/internal/licenses"
|
"github.com/anchore/syft/internal/licenses"
|
||||||
@ -10,7 +12,16 @@ import (
|
|||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func normalize(name string) string {
|
||||||
|
// https://packaging.python.org/en/latest/specifications/name-normalization/
|
||||||
|
re := regexp.MustCompile(`[-_.]+`)
|
||||||
|
normalized := re.ReplaceAllString(name, "-")
|
||||||
|
return strings.ToLower(normalized)
|
||||||
|
}
|
||||||
|
|
||||||
func newPackageForIndex(name, version string, locations ...file.Location) pkg.Package {
|
func newPackageForIndex(name, version string, locations ...file.Location) pkg.Package {
|
||||||
|
name = normalize(name)
|
||||||
|
|
||||||
p := pkg.Package{
|
p := pkg.Package{
|
||||||
Name: name,
|
Name: name,
|
||||||
Version: version,
|
Version: version,
|
||||||
@ -26,6 +37,8 @@ func newPackageForIndex(name, version string, locations ...file.Location) pkg.Pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newPackageForIndexWithMetadata(name, version string, metadata interface{}, locations ...file.Location) pkg.Package {
|
func newPackageForIndexWithMetadata(name, version string, metadata interface{}, locations ...file.Location) pkg.Package {
|
||||||
|
name = normalize(name)
|
||||||
|
|
||||||
p := pkg.Package{
|
p := pkg.Package{
|
||||||
Name: name,
|
Name: name,
|
||||||
Version: version,
|
Version: version,
|
||||||
@ -42,6 +55,8 @@ func newPackageForIndexWithMetadata(name, version string, metadata interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.PythonRequirementsEntry, locations ...file.Location) pkg.Package {
|
func newPackageForRequirementsWithMetadata(name, version string, metadata pkg.PythonRequirementsEntry, locations ...file.Location) pkg.Package {
|
||||||
|
name = normalize(name)
|
||||||
|
|
||||||
p := pkg.Package{
|
p := pkg.Package{
|
||||||
Name: name,
|
Name: name,
|
||||||
Version: version,
|
Version: version,
|
||||||
@ -87,10 +102,12 @@ func newPackageForPackage(resolver file.Resolver, m parsedData, sources ...file.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := normalize(m.Name)
|
||||||
|
|
||||||
p := pkg.Package{
|
p := pkg.Package{
|
||||||
Name: m.Name,
|
Name: name,
|
||||||
Version: m.Version,
|
Version: m.Version,
|
||||||
PURL: packageURL(m.Name, m.Version, &m.PythonPackage),
|
PURL: packageURL(name, m.Version, &m.PythonPackage),
|
||||||
Locations: file.NewLocationSet(sources...),
|
Locations: file.NewLocationSet(sources...),
|
||||||
Licenses: licenseSet,
|
Licenses: licenseSet,
|
||||||
Language: pkg.Python,
|
Language: pkg.Python,
|
||||||
|
|||||||
@ -44,3 +44,21 @@ func Test_packageURL(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_normalization(t *testing.T) {
|
||||||
|
normalForm := "friendly-bard"
|
||||||
|
tests := []string{
|
||||||
|
normalForm,
|
||||||
|
"Friendly-Bard",
|
||||||
|
"FRIENDLY-BARD",
|
||||||
|
"friendly.bard",
|
||||||
|
"friendly_bard",
|
||||||
|
"friendly--bard",
|
||||||
|
"FrIeNdLy-._.-bArD",
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt, func(t *testing.T) {
|
||||||
|
assert.Equal(t, normalForm, normalize(tt))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -41,9 +41,9 @@ func TestParseRequirementsTxt(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "SomeProject",
|
Name: "someproject",
|
||||||
Version: "5.4",
|
Version: "5.4",
|
||||||
PURL: "pkg:pypi/SomeProject@5.4",
|
PURL: "pkg:pypi/someproject@5.4",
|
||||||
Locations: locations,
|
Locations: locations,
|
||||||
Language: pkg.Python,
|
Language: pkg.Python,
|
||||||
Type: pkg.PythonPkg,
|
Type: pkg.PythonPkg,
|
||||||
@ -91,9 +91,9 @@ func TestParseRequirementsTxt(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "GithubSampleProject",
|
Name: "githubsampleproject",
|
||||||
Version: "3.7.1",
|
Version: "3.7.1",
|
||||||
PURL: "pkg:pypi/GithubSampleProject@3.7.1",
|
PURL: "pkg:pypi/githubsampleproject@3.7.1",
|
||||||
Locations: locations,
|
Locations: locations,
|
||||||
Language: pkg.Python,
|
Language: pkg.Python,
|
||||||
Type: pkg.PythonPkg,
|
Type: pkg.PythonPkg,
|
||||||
@ -103,6 +103,18 @@ func TestParseRequirementsTxt(t *testing.T) {
|
|||||||
URL: "git+https://github.com/owner/repo@releases/tag/v3.7.1",
|
URL: "git+https://github.com/owner/repo@releases/tag/v3.7.1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "friendly-bard",
|
||||||
|
Version: "1.0.0",
|
||||||
|
PURL: "pkg:pypi/friendly-bard@1.0.0",
|
||||||
|
Locations: locations,
|
||||||
|
Language: pkg.Python,
|
||||||
|
Type: pkg.PythonPkg,
|
||||||
|
Metadata: pkg.PythonRequirementsEntry{
|
||||||
|
Name: "FrIeNdLy-_-bArD",
|
||||||
|
VersionConstraint: "== 1.0.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var testCases = []struct {
|
var testCases = []struct {
|
||||||
@ -128,9 +140,9 @@ func TestParseRequirementsTxt(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectedPkgs: append([]pkg.Package{
|
expectedPkgs: append([]pkg.Package{
|
||||||
{
|
{
|
||||||
Name: "Mopidy-Dirble",
|
Name: "mopidy-dirble",
|
||||||
Version: "1.1",
|
Version: "1.1",
|
||||||
PURL: "pkg:pypi/Mopidy-Dirble@1.1",
|
PURL: "pkg:pypi/mopidy-dirble@1.1",
|
||||||
Locations: locations,
|
Locations: locations,
|
||||||
Language: pkg.Python,
|
Language: pkg.Python,
|
||||||
Type: pkg.PythonPkg,
|
Type: pkg.PythonPkg,
|
||||||
|
|||||||
@ -22,3 +22,4 @@ argh==0.26.3 --hash=sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971
|
|||||||
celery[redis, pytest] == 4.4.7 # should remove [redis, pytest]
|
celery[redis, pytest] == 4.4.7 # should remove [redis, pytest]
|
||||||
requests[security] == 2.8.* ; python_version < "2.7" and sys_platform == "linux"
|
requests[security] == 2.8.* ; python_version < "2.7" and sys_platform == "linux"
|
||||||
GithubSampleProject == 3.7.1 @ git+https://github.com/owner/repo@releases/tag/v3.7.1
|
GithubSampleProject == 3.7.1 @ git+https://github.com/owner/repo@releases/tag/v3.7.1
|
||||||
|
FrIeNdLy-_-bArD == 1.0.0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user