mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-23 07:29:00 -08:00
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Co-authored-by: Nikita Pivkin <nikita.pivkin@smartforce.io>
95 lines
2.4 KiB
Go
95 lines
2.4 KiB
Go
package pyproject
|
|
|
|
import (
|
|
"io"
|
|
"strings"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
"github.com/samber/lo"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/aquasecurity/trivy/pkg/dependency/parser/python"
|
|
"github.com/aquasecurity/trivy/pkg/set"
|
|
)
|
|
|
|
type PyProject struct {
|
|
Tool Tool `toml:"tool"`
|
|
Project Project `toml:"project"`
|
|
}
|
|
|
|
type Project struct {
|
|
Dependencies Dependencies `toml:"dependencies"`
|
|
}
|
|
|
|
type Tool struct {
|
|
Poetry Poetry `toml:"poetry"`
|
|
}
|
|
|
|
type Poetry struct {
|
|
Dependencies Dependencies `toml:"dependencies"`
|
|
Groups map[string]Group `toml:"group"`
|
|
}
|
|
|
|
type Group struct {
|
|
Dependencies Dependencies `toml:"dependencies"`
|
|
}
|
|
|
|
type Dependencies struct {
|
|
set.Set[string]
|
|
}
|
|
|
|
// MainDeps returns set of main deps
|
|
// `poetry` only uses 1 list of main dependencies
|
|
// `project.dependencies` (first priority) or `tool.poetry.dependencies` (if `project.dependencies` is missing)
|
|
func (p PyProject) MainDeps() set.Set[string] {
|
|
deps := set.New[string]()
|
|
if p.Project.Dependencies.Set != nil {
|
|
deps.Append(p.Project.Dependencies.Items()...)
|
|
} else if p.Tool.Poetry.Dependencies.Set != nil {
|
|
deps.Append(p.Tool.Poetry.Dependencies.Items()...)
|
|
}
|
|
return deps
|
|
}
|
|
|
|
func (d *Dependencies) UnmarshalTOML(data any) error {
|
|
switch deps := data.(type) {
|
|
case map[string]any: // For Poetry v1
|
|
d.Set = set.New[string](lo.MapToSlice(deps, func(pkgName string, _ any) string {
|
|
return python.NormalizePkgName(pkgName)
|
|
})...)
|
|
case []any: // For Poetry v2
|
|
d.Set = set.New[string]()
|
|
for i := range deps {
|
|
dep, ok := deps[i].(string)
|
|
if !ok {
|
|
return xerrors.Errorf("dependencies must be string, but got: %T", deps[i])
|
|
}
|
|
// There are some formats:
|
|
// e.g. `Flask == 1.1.4`, `Flask==1.1.4`, `Flask(>= 1.0.0)`, `pluggy[pre-commit,tox] (==0.13.1)`, etc.
|
|
dep = strings.NewReplacer(">", " ", "<", " ", "=", " ", "(", " ", "[", " ").Replace(dep)
|
|
d.Set.Append(strings.Fields(dep)[0]) // Save only name
|
|
}
|
|
default:
|
|
return xerrors.Errorf("dependencies must be map, but got: %T", data)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Parser parses pyproject.toml defined in PEP518.
|
|
// https://peps.python.org/pep-0518/
|
|
type Parser struct {
|
|
}
|
|
|
|
func NewParser() *Parser {
|
|
return &Parser{}
|
|
}
|
|
|
|
func (p *Parser) Parse(r io.Reader) (PyProject, error) {
|
|
var conf PyProject
|
|
if _, err := toml.NewDecoder(r).Decode(&conf); err != nil {
|
|
return PyProject{}, xerrors.Errorf("toml decode error: %w", err)
|
|
}
|
|
return conf, nil
|
|
}
|