Skip to content

Commit

Permalink
fix after review
Browse files Browse the repository at this point in the history
Signed-off-by: nikpivkin <nikita.pivkin@smartforce.io>
  • Loading branch information
nikpivkin committed Dec 16, 2024
1 parent 8ee3c36 commit e67015d
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 61 deletions.
30 changes: 12 additions & 18 deletions pkg/dependency/parser/python/uv/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,18 @@ func (l Lock) packages() map[string]Package {
})
}

func (l Lock) directDeps() map[string]struct{} {
func (l Lock) directDeps(root Package) map[string]struct{} {
deps := make(map[string]struct{})
root := l.root()
for _, dep := range root.Dependencies {
deps[dep.Name] = struct{}{}
}
return deps
}

func (l Lock) prodDeps() map[string]struct{} {
func (l Lock) prodDeps(root Package) map[string]struct{} {
packages := l.packages()
visited := make(map[string]struct{})
walkPackageDeps(l.root(), packages, visited)
walkPackageDeps(root, packages, visited)
return visited
}

Expand Down Expand Up @@ -96,18 +95,19 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc
}

rootPackage := lock.root()
// lock file must include root package
// cf. https://github.com/astral-sh/uv/blob/f80ddf10b63c3e7b421ca4658e63f97db1e0378c/crates/uv/src/commands/project/lock.rs#L933-L936
if rootPackage.Name == "" {
return nil, nil, xerrors.New("uv lockfile does not contain a root package. " +
"See https://github.com/astral-sh/uv/blob/f80ddf10b63c3e7b421ca4658e63f97db1e0378c/crates/uv/src/commands/project/lock.rs#L933-L936")
return nil, nil, xerrors.New("uv lockfile does not contain a root package.")
}

packages := lock.packages()
directDeps := lock.directDeps()
prodDeps := lock.prodDeps()
directDeps := lock.directDeps(rootPackage)
prodDeps := lock.prodDeps(rootPackage)

var (
pkgs []ftypes.Package
deps []ftypes.Dependency
pkgs ftypes.Packages
deps ftypes.Dependencies
)

for _, pkg := range lock.Packages {
Expand Down Expand Up @@ -150,14 +150,8 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc
}
}

sort.Slice(pkgs, func(i, j int) bool {
return pkgs[i].ID < pkgs[j].ID
})

sort.Slice(deps, func(i, j int) bool {
return deps[i].ID < deps[j].ID
})

sort.Sort(pkgs)
sort.Sort(deps)
return pkgs, deps, nil
}

Expand Down
24 changes: 12 additions & 12 deletions pkg/dependency/parser/python/uv/parse_testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ var (
// add a root project
// fill in the relationships between the packages
uvNormal = []ftypes.Package{
{ID: "normal@0.1.0", Name: "normal", Version: "0.1.0", Relationship: ftypes.RelationshipRoot},
{ID: "requests@2.32.0", Name: "requests", Version: "2.32.0", Relationship: ftypes.RelationshipDirect},
{ID: "certifi@2024.8.30", Name: "certifi", Version: "2024.8.30", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "charset-normalizer@3.4.0", Name: "charset-normalizer", Version: "3.4.0", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "idna@3.10", Name: "idna", Version: "3.10", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "normal@0.1.0", Name: "normal", Version: "0.1.0", Relationship: ftypes.RelationshipRoot},
{ID: "requests@2.32.0", Name: "requests", Version: "2.32.0", Relationship: ftypes.RelationshipDirect},
{ID: "urllib3@2.2.3", Name: "urllib3", Version: "2.2.3", Relationship: ftypes.RelationshipIndirect, Indirect: true},
}

Expand All @@ -41,45 +41,45 @@ var (
// add a root project
// fill in the relationships between the packages
uvLarge = []ftypes.Package{
{ID: "aiohappyeyeballs@2.4.4", Name: "aiohappyeyeballs", Version: "2.4.4", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "large@0.1.0", Name: "large", Version: "0.1.0", Relationship: ftypes.RelationshipRoot},
{ID: "aiohttp@3.11.10", Name: "aiohttp", Version: "3.11.10", Relationship: ftypes.RelationshipDirect},
{ID: "asyncio@3.4.3", Name: "asyncio", Version: "3.4.3", Relationship: ftypes.RelationshipDirect},
{ID: "boto3@1.35.79", Name: "boto3", Version: "1.35.79", Relationship: ftypes.RelationshipDirect},
{ID: "fastapi@0.115.6", Name: "fastapi", Version: "0.115.6", Relationship: ftypes.RelationshipDirect},
{ID: "pydantic@2.10.3", Name: "pydantic", Version: "2.10.3", Relationship: ftypes.RelationshipDirect},
{ID: "simplejson@3.19.3", Name: "simplejson", Version: "3.19.3", Relationship: ftypes.RelationshipDirect},
{ID: "sqlalchemy@2.0.36", Name: "sqlalchemy", Version: "2.0.36", Relationship: ftypes.RelationshipDirect},
{ID: "uvicorn@0.32.1", Name: "uvicorn", Version: "0.32.1", Relationship: ftypes.RelationshipDirect},
{ID: "aiohappyeyeballs@2.4.4", Name: "aiohappyeyeballs", Version: "2.4.4", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "aiosignal@1.3.1", Name: "aiosignal", Version: "1.3.1", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "annotated-types@0.7.0", Name: "annotated-types", Version: "0.7.0", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "anyio@4.7.0", Name: "anyio", Version: "4.7.0", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "async-timeout@5.0.1", Name: "async-timeout", Version: "5.0.1", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "asyncio@3.4.3", Name: "asyncio", Version: "3.4.3", Relationship: ftypes.RelationshipDirect},
{ID: "attrs@24.2.0", Name: "attrs", Version: "24.2.0", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "boto3@1.35.79", Name: "boto3", Version: "1.35.79", Relationship: ftypes.RelationshipDirect},
{ID: "botocore@1.35.79", Name: "botocore", Version: "1.35.79", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "click@8.1.7", Name: "click", Version: "8.1.7", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "colorama@0.4.6", Name: "colorama", Version: "0.4.6", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "exceptiongroup@1.2.2", Name: "exceptiongroup", Version: "1.2.2", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "fastapi@0.115.6", Name: "fastapi", Version: "0.115.6", Relationship: ftypes.RelationshipDirect},
{ID: "frozenlist@1.5.0", Name: "frozenlist", Version: "1.5.0", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "greenlet@3.1.1", Name: "greenlet", Version: "3.1.1", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "h11@0.14.0", Name: "h11", Version: "0.14.0", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "idna@3.10", Name: "idna", Version: "3.10", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "jmespath@1.0.1", Name: "jmespath", Version: "1.0.1", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "large@0.1.0", Name: "large", Version: "0.1.0", Relationship: ftypes.RelationshipRoot},
{ID: "multidict@6.1.0", Name: "multidict", Version: "6.1.0", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "propcache@0.2.1", Name: "propcache", Version: "0.2.1", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "pydantic-core@2.27.1", Name: "pydantic-core", Version: "2.27.1", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "pydantic@2.10.3", Name: "pydantic", Version: "2.10.3", Relationship: ftypes.RelationshipDirect},
{ID: "python-dateutil@2.9.0.post0", Name: "python-dateutil", Version: "2.9.0.post0", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "s3transfer@0.10.4", Name: "s3transfer", Version: "0.10.4", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "simplejson@3.19.3", Name: "simplejson", Version: "3.19.3", Relationship: ftypes.RelationshipDirect},
{ID: "six@1.17.0", Name: "six", Version: "1.17.0", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "sniffio@1.3.1", Name: "sniffio", Version: "1.3.1", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "sqlalchemy@2.0.36", Name: "sqlalchemy", Version: "2.0.36", Relationship: ftypes.RelationshipDirect},
{ID: "starlette@0.41.3", Name: "starlette", Version: "0.41.3", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "typing-extensions@4.12.2", Name: "typing-extensions", Version: "4.12.2", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "urllib3@1.26.20", Name: "urllib3", Version: "1.26.20", Relationship: ftypes.RelationshipIndirect, Indirect: true},
{ID: "uvicorn@0.32.1", Name: "uvicorn", Version: "0.32.1", Relationship: ftypes.RelationshipDirect},
{ID: "yarl@1.18.3", Name: "yarl", Version: "1.18.3", Relationship: ftypes.RelationshipIndirect, Indirect: true},
}

/*
uv pip list --format json | jq -r '.[] | .name' | xargs uv pip show | awk -F ': ' '
uv pip list --format json | jq -r '.[] | .name' | xargs uv pip show | awk -F ': ' '
/^Name/ {name=$2}
/^Version/ {version=$2}
/^Requires/ {requires=$2}
Expand Down
5 changes: 2 additions & 3 deletions pkg/fanal/analyzer/language/python/uv/uv.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (a *uvAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysisI
// Parse uv.lock
app, err := language.Parse(types.Uv, path, r, a.lockParser)
if err != nil {
a.logger.Debug("Failed to parse uv lockfile", log.Err(err))
a.logger.Warn("Failed to parse uv lockfile", log.Err(err))
return nil
} else if app == nil {
return nil
Expand All @@ -65,8 +65,7 @@ func (a *uvAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysisI
}

func (a *uvAnalyzer) Required(filePath string, _ os.FileInfo) bool {
fileName := filepath.Base(filePath)
return fileName == types.UvLock
return filepath.Base(filePath) == types.UvLock
}

func (a *uvAnalyzer) Type() analyzer.Type {
Expand Down
56 changes: 28 additions & 28 deletions pkg/fanal/analyzer/language/python/uv/uv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,34 @@ func Test_uvAnalyzer_PostAnalyze(t *testing.T) {
Type: types.Uv,
FilePath: "uv.lock",
Packages: types.Packages{
{
ID: "uv-test@0.1.0",
Name: "uv-test",
Version: "0.1.0",
Relationship: types.RelationshipRoot,
DependsOn: []string{
"pluggy@1.5.0",
"requests@2.32.3",
},
},
{
ID: "pluggy@1.5.0",
Name: "pluggy",
Version: "1.5.0",
Relationship: types.RelationshipDirect,
},
{
ID: "requests@2.32.3",
Name: "requests",
Version: "2.32.3",
Relationship: types.RelationshipDirect,
DependsOn: []string{
"certifi@2024.8.30",
"charset-normalizer@3.4.0",
"idna@3.10",
"urllib3@2.2.3",
},
},
{
ID: "certifi@2024.8.30",
Name: "certifi",
Expand All @@ -47,41 +75,13 @@ func Test_uvAnalyzer_PostAnalyze(t *testing.T) {
Indirect: true,
Relationship: types.RelationshipIndirect,
},
{
ID: "pluggy@1.5.0",
Name: "pluggy",
Version: "1.5.0",
Relationship: types.RelationshipDirect,
},
{
ID: "requests@2.32.3",
Name: "requests",
Version: "2.32.3",
Relationship: types.RelationshipDirect,
DependsOn: []string{
"certifi@2024.8.30",
"charset-normalizer@3.4.0",
"idna@3.10",
"urllib3@2.2.3",
},
},
{
ID: "urllib3@2.2.3",
Name: "urllib3",
Version: "2.2.3",
Indirect: true,
Relationship: types.RelationshipIndirect,
},
{
ID: "uv-test@0.1.0",
Name: "uv-test",
Version: "0.1.0",
Relationship: types.RelationshipRoot,
DependsOn: []string{
"pluggy@1.5.0",
"requests@2.32.3",
},
},
},
},
},
Expand Down

0 comments on commit e67015d

Please sign in to comment.