Skip to content

Commit

Permalink
Add poetry parser (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
masahiro331 authored and knqyf263 committed May 21, 2019
1 parent 0783088 commit 1ef8521
Show file tree
Hide file tree
Showing 6 changed files with 1,418 additions and 0 deletions.
39 changes: 39 additions & 0 deletions pkg/poetry/parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package poetry

import (
"io"

"github.com/BurntSushi/toml"
"github.com/knqyf263/go-dep-parser/pkg/types"
"golang.org/x/xerrors"
)

type Lockfile struct {
Packages []struct {
Category string `toml:"category"`
Description string `toml:"description"`
Marker string `toml:"marker,omitempty"`
Name string `toml:"name"`
Optional bool `toml:"optional"`
PythonVersions string `toml:"python-versions"`
Version string `toml:"version"`
Dependencies interface{}
Metadata interface{}
} `toml:"package"`
}

func Parse(r io.Reader) ([]types.Library, error) {
var lockfile Lockfile
if _, err := toml.DecodeReader(r, &lockfile); err != nil {
return nil, xerrors.Errorf("decode error: %w", err)
}

var libs []types.Library
for _, pkg := range lockfile.Packages {
libs = append(libs, types.Library{
Name: pkg.Name,
Version: pkg.Version,
})
}
return libs, nil
}
75 changes: 75 additions & 0 deletions pkg/poetry/parse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package poetry

import (
"os"
"path"
"sort"
"strings"
"testing"

"github.com/knqyf263/go-dep-parser/pkg/types"
"github.com/kylelemons/godebug/pretty"
)

func TestParse(t *testing.T) {
vectors := []struct {
file string // Test input file
libraries []types.Library
}{
{
file: "testdata/poetry_normal.lock",
libraries: PoetryNormal,
},
{
file: "testdata/poetry_many.lock",
libraries: PoetryMany,
},
{
file: "testdata/poetry_flask.lock",
libraries: PoetryFlask,
},
}

for _, v := range vectors {
t.Run(path.Base(v.file), func(t *testing.T) {
f, err := os.Open(v.file)
if err != nil {
t.Fatalf("Open() error: %v", err)
}
libList, err := Parse(f)
if err != nil {
t.Fatalf("Parse() error: %v", err)
}

sort.Slice(libList, func(i, j int) bool {
ret := strings.Compare(libList[i].Name, libList[j].Name)
if ret == 0 {
return libList[i].Version < libList[j].Version
}
return ret < 0
})

sort.Slice(v.libraries, func(i, j int) bool {
ret := strings.Compare(v.libraries[i].Name, v.libraries[j].Name)
if ret == 0 {
return v.libraries[i].Version < v.libraries[j].Version
}
return ret < 0
})

if len(libList) != len(v.libraries) {
t.Fatalf("lib length: %s", pretty.Compare(libList, v.libraries))
}

for i, got := range libList {
want := v.libraries[i]
if want.Name != got.Name {
t.Errorf("%d: Name: got %s, want %s", i, got.Name, want.Name)
}
if want.Version != got.Version {
t.Errorf("%d: Version: got %s, want %s", i, got.Version, want.Version)
}
}
})
}
}
126 changes: 126 additions & 0 deletions pkg/poetry/parse_testcase.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package poetry

import "github.com/knqyf263/go-dep-parser/pkg/types"

var (
// docker run --name poetry --rm -it jonatkinson/python-poetry:3.7
// poetry new normal
// poetry add pypi
// poetry show -a | awk '{gsub(/\(!\)/, ""); printf("{\""$1"\", \""$2"\"},\n") }'
PoetryNormal = []types.Library{
{"atomicwrites", "1.3.0"},
{"attrs", "19.1.0"},
{"colorama", "0.4.1"},
{"more-itertools", "7.0.0"},
{"pluggy", "0.11.0"},
{"py", "1.8.0"},
{"pypi", "2.1"},
{"pytest", "3.10.1"},
{"six", "1.12.0"},
}

// docker run --name poetry --rm -it jonatkinson/python-poetry:3.7
// Use https://github.com/sdispater/poetry/blob/master/poetry.lock
// poetry show -a | awk '{gsub(/\(!\)/, ""); printf("{\""$1"\", \""$2"\"},\n") }'
PoetryMany = []types.Library{
{"appdirs", "1.4.3"},
{"aspy.yaml", "1.2.0"},
{"atomicwrites", "1.3.0"},
{"attrs", "19.1.0"},
{"black", "19.3b0"},
{"cachecontrol", "0.12.5"},
{"cachy", "0.2.0"},
{"certifi", "2019.3.9"},
{"cfgv", "1.6.0"},
{"chardet", "3.0.4"},
{"cleo", "0.6.8"},
{"click", "7.0"},
{"colorama", "0.4.1"},
{"configparser", "3.7.4"},
{"contextlib2", "0.5.5"},
{"coverage", "4.5.3"},
{"enum34", "1.1.6"},
{"filelock", "3.0.10"},
{"funcsigs", "1.0.2"},
{"functools32", "3.2.3-2"},
{"futures", "3.2.0"},
{"glob2", "0.6"},
{"html5lib", "1.0.1"},
{"httpretty", "0.9.6"},
{"identify", "1.4.3"},
{"idna", "2.8"},
{"importlib-metadata", "0.12"},
{"importlib-resources", "1.0.2"},
{"jinja2", "2.10.1"},
{"jsonschema", "3.0.1"},
{"livereload", "2.6.1"},
{"lockfile", "0.12.2"},
{"markdown", "3.0.1"},
{"markdown", "3.1"},
{"markupsafe", "1.1.1"},
{"mkdocs", "1.0.4"},
{"mock", "3.0.5"},
{"more-itertools", "5.0.0"},
{"more-itertools", "7.0.0"},
{"msgpack", "0.6.1"},
{"nodeenv", "1.3.3"},
{"packaging", "19.0"},
{"pastel", "0.1.0"},
{"pathlib2", "2.3.3"},
{"pkginfo", "1.5.0.1"},
{"pluggy", "0.11.0"},
{"pre-commit", "1.16.1"},
{"py", "1.8.0"},
{"pygments", "2.3.1"},
{"pygments", "2.4.0"},
{"pygments-github-lexers", "0.0.5"},
{"pylev", "1.3.0"},
{"pymdown-extensions", "6.0"},
{"pyparsing", "2.4.0"},
{"pyrsistent", "0.14.11"},
{"pytest", "4.5.0"},
{"pytest-cov", "2.7.1"},
{"pytest-mock", "1.10.4"},
{"pytest-sugar", "0.9.2"},
{"pyyaml", "5.1"},
{"requests", "2.21.0"},
{"requests", "2.22.0"},
{"requests-toolbelt", "0.8.0"},
{"scandir", "1.10.0"},
{"shellingham", "1.3.1"},
{"six", "1.12.0"},
{"termcolor", "1.1.0"},
{"toml", "0.10.0"},
{"tomlkit", "0.5.3"},
{"tornado", "5.1.1"},
{"tox", "3.11.1"},
{"typing", "3.6.6"},
{"urllib3", "1.24.3"},
{"urllib3", "1.25.2"},
{"virtualenv", "16.6.0"},
{"wcwidth", "0.1.7"},
{"webencodings", "0.5.1"},
{"zipp", "0.5.1"},
}

// docker run --name poetry --rm -it jonatkinson/python-poetry:3.7
// poetry new flask
// poetry add flask
// poetry show -a | awk '{gsub(/\(!\)/, ""); printf("{\""$1"\", \""$2"\"},\n") }'
PoetryFlask = []types.Library{
{"atomicwrites", "1.3.0"},
{"attrs", "19.1.0"},
{"click", "7.0"},
{"colorama", "0.4.1"},
{"flask", "1.0.3"},
{"itsdangerous", "1.1.0"},
{"jinja2", "2.10.1"},
{"markupsafe", "1.1.1"},
{"more-itertools", "7.0.0"},
{"pluggy", "0.11.0"},
{"py", "1.8.0"},
{"pytest", "3.10.1"},
{"six", "1.12.0"},
{"werkzeug", "0.15.4"},
}
)
151 changes: 151 additions & 0 deletions pkg/poetry/testdata/poetry_flask.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
[[package]]
category = "dev"
description = "Atomic file writes."
name = "atomicwrites"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.3.0"

[[package]]
category = "dev"
description = "Classes Without Boilerplate"
name = "attrs"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "19.1.0"

[[package]]
category = "main"
description = "Composable command line interface toolkit"
name = "click"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "7.0"

[[package]]
category = "dev"
description = "Cross-platform colored terminal text."
marker = "sys_platform == \"win32\""
name = "colorama"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.4.1"

[[package]]
category = "main"
description = "A simple framework for building complex web applications."
name = "flask"
optional = false
python-versions = "*"
version = "1.0.3"

[package.dependencies]
Jinja2 = ">=2.10"
Werkzeug = ">=0.14"
click = ">=5.1"
itsdangerous = ">=0.24"

[[package]]
category = "main"
description = "Various helpers to pass data to untrusted environments and back."
name = "itsdangerous"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.1.0"

[[package]]
category = "main"
description = "A small but fast and easy to use stand-alone template engine written in pure python."
name = "jinja2"
optional = false
python-versions = "*"
version = "2.10.1"

[package.dependencies]
MarkupSafe = ">=0.23"

[[package]]
category = "main"
description = "Safely add untrusted strings to HTML/XML markup."
name = "markupsafe"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
version = "1.1.1"

[[package]]
category = "dev"
description = "More routines for operating on iterables, beyond itertools"
name = "more-itertools"
optional = false
python-versions = ">=3.4"
version = "7.0.0"

[[package]]
category = "dev"
description = "plugin and hook calling mechanisms for python"
name = "pluggy"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.11.0"

[[package]]
category = "dev"
description = "library with cross-python path, ini-parsing, io, code, log facilities"
name = "py"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.8.0"

[[package]]
category = "dev"
description = "pytest: simple powerful testing with Python"
name = "pytest"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "3.10.1"

[package.dependencies]
atomicwrites = ">=1.0"
attrs = ">=17.4.0"
colorama = "*"
more-itertools = ">=4.0.0"
pluggy = ">=0.7"
py = ">=1.5.0"
setuptools = "*"
six = ">=1.10.0"

[[package]]
category = "dev"
description = "Python 2 and 3 compatibility utilities"
name = "six"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*"
version = "1.12.0"

[[package]]
category = "main"
description = "The comprehensive WSGI web application library."
name = "werkzeug"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.15.4"

[metadata]
content-hash = "fee880497bb9c5efee7c034f3b559405104d3ef92f869a5f63d20606443597f8"
python-versions = "^3.6"

[metadata.hashes]
atomicwrites = ["03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", "75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"]
attrs = ["69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", "f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"]
click = ["2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"]
colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"]
flask = ["ad7c6d841e64296b962296c2c2dabc6543752985727af86a975072dea984b6f3", "e7d32475d1de5facaa55e3958bc4ec66d3762076b074296aa50ef8fdc5b9df61"]
itsdangerous = ["321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", "b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"]
jinja2 = ["065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", "14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"]
markupsafe = ["00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", "09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", "62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", "88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", "98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", "ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", "b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", "ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"]
more-itertools = ["2112d2ca570bb7c3e53ea1a35cd5df42bb0fd10c45f0fb97178679c3c03d64c7", "c3e4748ba1aad8dba30a4886b0b1a2004f9a863837b8654e7059eebf727afa5a"]
pluggy = ["25a1bc1d148c9a640211872b4ff859878d422bccb59c9965e04eed468a0aa180", "964cedd2b27c492fbf0b7f58b3284a09cf7f99b0f715941fb24a439b3af1bd1a"]
py = ["64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", "dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"]
pytest = ["3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec", "e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660"]
six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"]
werkzeug = ["865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c", "a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6"]
Loading

0 comments on commit 1ef8521

Please sign in to comment.