Skip to content

Commit 4715a2d

Browse files
authored
feat: enable transitive extraction for Python requirements.txt (#1980)
This PR enables the transitive extractor for Python requirement files. Considering that there is only the native registry client for PyPI, we use that for requirements.txt transitive extractor.
1 parent cdd4c4f commit 4715a2d

9 files changed

Lines changed: 260 additions & 143 deletions

File tree

cmd/osv-scanner/scan/source/__snapshots__/command_test.snap

Lines changed: 225 additions & 128 deletions
Large diffs are not rendered by default.

cmd/osv-scanner/scan/source/command_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ func TestCommand_Licenses(t *testing.T) {
825825
}
826826
}
827827

828-
func TestCommand_MavenTransitive(t *testing.T) {
828+
func TestCommand_Transitive(t *testing.T) {
829829
t.Parallel()
830830

831831
tests := []testcmd.Case{
@@ -862,10 +862,25 @@ func TestCommand_MavenTransitive(t *testing.T) {
862862
Exit: 1,
863863
},
864864
{
865-
Name: "resolve transitive dependencies with native data source",
865+
Name: "resolves transitive dependencies with native data source",
866866
Args: []string{"", "source", "--config=./fixtures/osv-scanner-empty-config.toml", "--data-source=native", "-L", "pom.xml:./fixtures/maven-transitive/registry.xml"},
867867
Exit: 1,
868868
},
869+
{
870+
Name: "uses native data source for requirements.txt",
871+
Args: []string{"", "source", "--config=./fixtures/osv-scanner-empty-config.toml", "./fixtures/locks-requirements/requirements.txt"},
872+
Exit: 1,
873+
},
874+
{
875+
Name: "does not scan transitive dependencies for requirements.txt with no-resolve",
876+
Args: []string{"", "source", "--config=./fixtures/osv-scanner-empty-config.toml", "--no-resolve", "./fixtures/locks-requirements/requirements.txt"},
877+
Exit: 1,
878+
},
879+
{
880+
Name: "does not scan transitive dependencies for requirements.txt with offline mode",
881+
Args: []string{"", "source", "--config=./fixtures/osv-scanner-empty-config.toml", "--offline", "--download-offline-databases", "./fixtures/locks-requirements/requirements.txt"},
882+
Exit: 1,
883+
},
869884
}
870885

871886
for _, tt := range tests {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
black==1.0.0
1+
black==25.1.0
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
flask==1.0.0
2-
flask-cors==1.0.0
3-
pandas==0.23.4
2+
django==1.11.29
3+
requests==2.20.0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
pytest==1.0.0
1+
pytest==2.0.0

internal/builders/extractors.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ import (
2525
"github.com/google/osv-scalibr/extractor/filesystem/language/python/pdmlock"
2626
"github.com/google/osv-scalibr/extractor/filesystem/language/python/pipfilelock"
2727
"github.com/google/osv-scalibr/extractor/filesystem/language/python/poetrylock"
28-
"github.com/google/osv-scalibr/extractor/filesystem/language/python/requirements"
29-
"github.com/google/osv-scalibr/extractor/filesystem/language/python/requirementsnet"
3028
"github.com/google/osv-scalibr/extractor/filesystem/language/python/uvlock"
3129
"github.com/google/osv-scalibr/extractor/filesystem/language/python/wheelegg"
3230
"github.com/google/osv-scalibr/extractor/filesystem/language/r/renvlock"
@@ -119,10 +117,6 @@ func build(name string) filesystem.Extractor {
119117
return pdmlock.New()
120118
case poetrylock.Name:
121119
return poetrylock.New()
122-
case requirements.Name:
123-
return requirements.NewDefault()
124-
case requirementsnet.Name:
125-
return requirementsnet.NewDefault()
126120
case requirementsenhancable.Name:
127121
return requirementsenhancable.New()
128122
case uvlock.Name:

pkg/osvscanner/internal/scanners/lockfile.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"github.com/google/osv-scalibr/extractor/filesystem/language/python/pdmlock"
3030
"github.com/google/osv-scalibr/extractor/filesystem/language/python/pipfilelock"
3131
"github.com/google/osv-scalibr/extractor/filesystem/language/python/poetrylock"
32-
"github.com/google/osv-scalibr/extractor/filesystem/language/python/requirements"
3332
"github.com/google/osv-scalibr/extractor/filesystem/language/python/uvlock"
3433
"github.com/google/osv-scalibr/extractor/filesystem/language/r/renvlock"
3534
"github.com/google/osv-scalibr/extractor/filesystem/language/ruby/gemfilelock"
@@ -40,6 +39,7 @@ import (
4039
"github.com/google/osv-scanner/v2/internal/scalibrextract"
4140
"github.com/google/osv-scanner/v2/internal/scalibrextract/language/java/pomxmlenhanceable"
4241
"github.com/google/osv-scanner/v2/internal/scalibrextract/language/osv/osvscannerjson"
42+
"github.com/google/osv-scanner/v2/internal/scalibrextract/language/python/requirementsenhancable"
4343
)
4444

4545
var lockfileExtractorMapping = map[string][]string{
@@ -54,7 +54,7 @@ var lockfileExtractorMapping = map[string][]string{
5454
"poetry.lock": {poetrylock.Name},
5555
"Pipfile.lock": {pipfilelock.Name},
5656
"pdm.lock": {pdmlock.Name},
57-
"requirements.txt": {requirements.Name},
57+
"requirements.txt": {requirementsenhancable.Name},
5858
"uv.lock": {uvlock.Name},
5959
"Cargo.lock": {cargolock.Name},
6060
"composer.lock": {composerlock.Name},

pkg/osvscanner/osvscanner.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ func initializeExternalAccessors(actions ScannerActions) (ExternalAccessors, err
177177
externalAccessors.DependencyClients[osvschema.EcosystemMaven], err = resolution.NewMavenRegistryClient(actions.MavenRegistry, "")
178178
}
179179

180+
// We only support native registry client for PyPI.
181+
externalAccessors.DependencyClients[osvschema.EcosystemPyPI] = resolution.NewPyPIRegistryClient("")
182+
180183
if err != nil {
181184
return ExternalAccessors{}, err
182185
}

pkg/osvscanner/scan.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@ import (
1515
"github.com/google/osv-scalibr/extractor"
1616
"github.com/google/osv-scalibr/extractor/filesystem"
1717
"github.com/google/osv-scalibr/extractor/filesystem/language/java/pomxmlnet"
18+
"github.com/google/osv-scalibr/extractor/filesystem/language/python/requirements"
19+
"github.com/google/osv-scalibr/extractor/filesystem/language/python/requirementsnet"
1820
"github.com/google/osv-scalibr/fs"
1921
"github.com/google/osv-scalibr/plugin"
2022
"github.com/google/osv-scanner/v2/internal/builders"
2123
"github.com/google/osv-scanner/v2/internal/imodels"
2224
"github.com/google/osv-scanner/v2/internal/scalibrextract"
2325
"github.com/google/osv-scanner/v2/internal/scalibrextract/filesystem/vendored"
2426
"github.com/google/osv-scanner/v2/internal/scalibrextract/language/java/pomxmlenhanceable"
27+
"github.com/google/osv-scanner/v2/internal/scalibrextract/language/python/requirementsenhancable"
2528
"github.com/google/osv-scanner/v2/internal/scalibrextract/vcs/gitrepo"
2629
"github.com/google/osv-scanner/v2/internal/testlogger"
2730
"github.com/google/osv-scanner/v2/pkg/osvscanner/internal/scanners"
@@ -36,7 +39,12 @@ func configureExtractors(extractors []filesystem.Extractor, accessors ExternalAc
3639
MavenRegistryAPIClient: accessors.MavenRegistryAPIClient,
3740
})
3841
}
39-
// TODO: Enable requirementstxtnet extractor
42+
if accessors.DependencyClients[osvschema.EcosystemPyPI] != nil {
43+
requirementsenhancable.EnhanceIfPossible(tor, requirementsnet.Config{
44+
Extractor: &requirements.Extractor{},
45+
Client: accessors.DependencyClients[osvschema.EcosystemPyPI],
46+
})
47+
}
4048

4149
// todo: the "disabled" aspect should probably be worked into the extractor being present in the first place
4250
// since "IncludeRootGit" is always true

0 commit comments

Comments
 (0)