Skip to content

Commit 37ba7c6

Browse files
authored
Merge pull request #3 from CycloneDX/feat/poetry-lock-support
FEATURE: Adde poetry.lock parser support
2 parents 1c0aa71 + 15bc553 commit 37ba7c6

File tree

9 files changed

+110
-2
lines changed

9 files changed

+110
-2
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ You can use one of the parsers to obtain information about your project or envir
5050
| Parser | Class / Import | Description |
5151
| ------- | ------ | ------ |
5252
| Environment | `from cyclonedx.parser.environment import EnvironmentParser` | Looks at the packaged installed in your current Python environment. |
53+
| PoetryParser | `from cyclonedx.parser.poetry import PoetryParser` | Parses `poetry.lock` content passed in as a string. |
54+
| PoetryFileParser | `from cyclonedx.parser.poetry import PoetryFileParser` | Parses the `poetry.lock` file at the supplied path. |
5355
| RequirementsParser | `from cyclonedx.parser.requirements import RequirementsParser` | Parses a multiline string that you provide that conforms to the `requirements.txt` [PEP-508](https://www.python.org/dev/peps/pep-0508/) standard. |
5456
| RequirementsFileParser | `from cyclonedx.parser.requirements import RequirementsFileParser` | Parses a file that you provide the path to that conforms to the `requirements.txt` [PEP-508](https://www.python.org/dev/peps/pep-0508/) standard. |
5557

cyclonedx/parser/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
class BaseParser(ABC):
2424
_components: List[Component] = []
2525

26+
def __init__(self):
27+
self._components.clear()
28+
2629
def component_count(self) -> int:
2730
return len(self._components)
2831

cyclonedx/parser/environment.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class EnvironmentParser(BaseParser):
3737
"""
3838

3939
def __init__(self):
40+
super().__init__()
41+
4042
import pkg_resources
4143

4244
i: pkg_resources.DistInfoDistribution

cyclonedx/parser/poetry.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# encoding: utf-8
2+
3+
# This file is part of CycloneDX Python Lib
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
# SPDX-License-Identifier: Apache-2.0
18+
# Copyright (c) OWASP Foundation. All Rights Reserved.
19+
20+
import toml
21+
22+
from . import BaseParser
23+
from ..model.component import Component
24+
25+
26+
class PoetryParser(BaseParser):
27+
28+
def __init__(self, poetry_lock_contents: str):
29+
super().__init__()
30+
print("Starting Poetry Parser {}".format(len(self.get_components())))
31+
poetry_lock = toml.loads(poetry_lock_contents)
32+
33+
for package in poetry_lock['package']:
34+
self._components.append(Component(
35+
name=package['name'], version=package['version'],
36+
))
37+
38+
39+
class PoetryFileParser(PoetryParser):
40+
41+
def __init__(self, poetry_lock_filename: str):
42+
with open(poetry_lock_filename) as r:
43+
super(PoetryFileParser, self).__init__(poetry_lock_contents=r.read())
44+
r.close()

cyclonedx/parser/requirements.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
class RequirementsParser(BaseParser):
2727

2828
def __init__(self, requirements_content: str):
29+
super().__init__()
30+
2931
requirements = pkg_resources.parse_requirements(requirements_content)
3032
for requirement in requirements:
3133
"""

poetry.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ packageurl-python = "^0.9.4"
4242
requirements_parser = "^0.2.0"
4343
setuptools = "^50.3.2"
4444
importlib-metadata = "^4.8.1"
45+
toml = "^0.10.2"
4546

4647
[tool.poetry.dev-dependencies]
4748
tox = "^3.24.3"

tests/fixtures/poetry-lock-simple.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[[package]]
2+
name = "toml"
3+
version = "0.10.2"
4+
description = "Python Library for Tom's Obvious, Minimal Language"
5+
category = "main"
6+
optional = false
7+
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
8+
9+
[metadata]
10+
lock-version = "1.1"
11+
python-versions = "^3.9"
12+
content-hash = "3dc7af43729f7ff1e7cf84103a3e2c1945f233884eaa149c7e8d92cccb593984"
13+
14+
[metadata.files]
15+
toml = [
16+
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
17+
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
18+
]

tests/test_parser_poetry.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# encoding: utf-8
2+
3+
# This file is part of CycloneDX Python Lib
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
# SPDX-License-Identifier: Apache-2.0
18+
# Copyright (c) OWASP Foundation. All Rights Reserved.
19+
20+
import os
21+
from unittest import TestCase
22+
23+
from cyclonedx.parser.poetry import PoetryFileParser
24+
25+
26+
class TestPoetryParser(TestCase):
27+
28+
def test_simple(self):
29+
tests_poetry_lock_file = os.path.join(os.path.dirname(__file__), 'fixtures/poetry-lock-simple.txt')
30+
31+
parser = PoetryFileParser(poetry_lock_filename=tests_poetry_lock_file)
32+
self.assertEqual(1, parser.component_count())
33+
components = parser.get_components()
34+
print(components)
35+
self.assertEqual('toml', components[0].get_name())
36+
self.assertEqual('0.10.2', components[0].get_version())

0 commit comments

Comments
 (0)