github.com/lineaje-labs/syft@v0.98.1-0.20231227153149-9e393f60ff1b/syft/pkg/cataloger/python/parse_setup.go (about) 1 package python 2 3 import ( 4 "bufio" 5 "regexp" 6 "strings" 7 8 "github.com/anchore/syft/syft/artifact" 9 "github.com/anchore/syft/syft/file" 10 "github.com/anchore/syft/syft/pkg" 11 "github.com/anchore/syft/syft/pkg/cataloger/generic" 12 "github.com/lineaje-labs/syft/internal/log" 13 ) 14 15 // integrity check 16 var _ generic.Parser = parseSetup 17 18 // match examples: 19 // 20 // 'pathlib3==2.2.0;python_version<"3.6"' --> match(name=pathlib3 version=2.2.0) 21 // "mypy==v0.770", --> match(name=mypy version=v0.770) 22 // " mypy2 == v0.770", ' mypy3== v0.770', --> match(name=mypy2 version=v0.770), match(name=mypy3, version=v0.770) 23 var pinnedDependency = regexp.MustCompile(`['"]\W?(\w+\W?==\W?[\w.]*)`) 24 25 func parseSetup( 26 _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser, 27 ) ([]pkg.Package, []artifact.Relationship, error) { 28 var packages []pkg.Package 29 30 scanner := bufio.NewScanner(reader) 31 32 for scanner.Scan() { 33 line := scanner.Text() 34 line = strings.TrimRight(line, "\n") 35 36 for _, match := range pinnedDependency.FindAllString(line, -1) { 37 parts := strings.Split(match, "==") 38 if len(parts) != 2 { 39 continue 40 } 41 name := strings.Trim(parts[0], "'\"") 42 name = strings.TrimSpace(name) 43 name = strings.Trim(name, "'\"") 44 45 version := strings.TrimSpace(parts[len(parts)-1]) 46 version = strings.Trim(version, "'\"") 47 48 if hasTemplateDirective(name) || hasTemplateDirective(version) { 49 // this can happen in more dynamic setup.py where there is templating 50 continue 51 } 52 53 if name == "" || version == "" { 54 log.WithFields("path", reader.RealPath).Debugf("unable to parse package in setup.py line: %q", line) 55 continue 56 } 57 58 packages = append( 59 packages, 60 newPackageForIndex( 61 name, 62 version, 63 reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), 64 ), 65 ) 66 } 67 } 68 69 return packages, nil, nil 70 } 71 72 func hasTemplateDirective(s string) bool { 73 return strings.Contains(s, `%s`) || strings.Contains(s, `{`) || strings.Contains(s, `}`) 74 }