From a61c828e7ac352231930f9fed6dd58c1b68a14c1 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Wed, 12 Jul 2023 08:14:01 +1200 Subject: [PATCH] fix: support requirements with options in `requirements.txt` (#196) --- pkg/lockfile/fixtures/pip/with-hash.txt | 2 + .../pip/with-per-requirement-options.txt | 12 ++++++ pkg/lockfile/parse-requirements-txt.go | 5 ++- pkg/lockfile/parse-requirements-txt_test.go | 37 +++++++++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 pkg/lockfile/fixtures/pip/with-hash.txt create mode 100644 pkg/lockfile/fixtures/pip/with-per-requirement-options.txt diff --git a/pkg/lockfile/fixtures/pip/with-hash.txt b/pkg/lockfile/fixtures/pip/with-hash.txt new file mode 100644 index 00000000..7954ecc8 --- /dev/null +++ b/pkg/lockfile/fixtures/pip/with-hash.txt @@ -0,0 +1,2 @@ +boto3==1.26.121 --hash=sha256:f87d694c351eba1dfd19b5bef5892a1047e7adb09c57c2c00049de209a8ab55d +foo == 1.0.0 diff --git a/pkg/lockfile/fixtures/pip/with-per-requirement-options.txt b/pkg/lockfile/fixtures/pip/with-per-requirement-options.txt new file mode 100644 index 00000000..cf672f4a --- /dev/null +++ b/pkg/lockfile/fixtures/pip/with-per-requirement-options.txt @@ -0,0 +1,12 @@ +boto3==1.26.121 --hash=sha256:f87d694c351eba1dfd19b5bef5892a1047e7adb09c57c2c00049de209a8ab55d +foo == 1.0.0 + +# from https://pip.pypa.io/en/stable/topics/secure-installs/#hash-checking-mode + +FooProject == 1.2 \ + --hash=sha256:2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 \ + --hash=sha256:486ea46224d1bb4fb680f34f7c9ad96a8f24ec88be73ea8e5a6c65260e9cb8a7 + +# from https://pip.pypa.io/en/stable/reference/requirements-file-format/#influencing-the-build-system + +BarProject >= 1.2 --global-option="--no-user-cfg" diff --git a/pkg/lockfile/parse-requirements-txt.go b/pkg/lockfile/parse-requirements-txt.go index 6c3cc01f..5db7cdeb 100644 --- a/pkg/lockfile/parse-requirements-txt.go +++ b/pkg/lockfile/parse-requirements-txt.go @@ -12,7 +12,8 @@ import ( const PipEcosystem Ecosystem = "PyPI" // todo: expand this to support more things, e.g. -// https://pip.pypa.io/en/stable/reference/requirements-file-format/#example +// +// https://pip.pypa.io/en/stable/reference/requirements-file-format/#example func parseLine(line string) PackageDetails { var constraint string name := line @@ -41,7 +42,7 @@ func parseLine(line string) PackageDetails { name = strings.TrimSpace(splitted[0]) if constraint != "!=" { - version = strings.TrimSpace(splitted[1]) + version = strings.Split(strings.TrimSpace(splitted[1]), " ")[0] } } diff --git a/pkg/lockfile/parse-requirements-txt_test.go b/pkg/lockfile/parse-requirements-txt_test.go index 0976ec6d..01e7fd1f 100644 --- a/pkg/lockfile/parse-requirements-txt_test.go +++ b/pkg/lockfile/parse-requirements-txt_test.go @@ -526,6 +526,43 @@ func TestParseRequirementsTxt_CyclicRComplex(t *testing.T) { }) } +func TestParseRequirementsTxt_WithPerRequirementOptions(t *testing.T) { + t.Parallel() + + packages, err := lockfile.ParseRequirementsTxt("fixtures/pip/with-per-requirement-options.txt") + + if err != nil { + t.Errorf("Got unexpected error: %v", err) + } + + expectPackages(t, packages, []lockfile.PackageDetails{ + { + Name: "boto3", + Version: "1.26.121", + Ecosystem: lockfile.PipEcosystem, + CompareAs: lockfile.PipEcosystem, + }, + { + Name: "foo", + Version: "1.0.0", + Ecosystem: lockfile.PipEcosystem, + CompareAs: lockfile.PipEcosystem, + }, + { + Name: "fooproject", + Version: "1.2", + Ecosystem: lockfile.PipEcosystem, + CompareAs: lockfile.PipEcosystem, + }, + { + Name: "barproject", + Version: "1.2", + Ecosystem: lockfile.PipEcosystem, + CompareAs: lockfile.PipEcosystem, + }, + }) +} + func TestParseRequirementsTxt_LineContinuation(t *testing.T) { t.Parallel()