diff --git a/cyclonedx_py/_internal/utils/pep621.py b/cyclonedx_py/_internal/utils/pep621.py index cfb3ac97..16138e6a 100644 --- a/cyclonedx_py/_internal/utils/pep621.py +++ b/cyclonedx_py/_internal/utils/pep621.py @@ -26,6 +26,7 @@ from collections.abc import Generator, Iterable, Iterator from itertools import chain from os.path import dirname, join +from pathlib import PurePosixPath from typing import TYPE_CHECKING, Any from cyclonedx.exception.model import InvalidUriException @@ -72,7 +73,7 @@ def project2licenses(project: dict[str, Any], lfac: 'LicenseFactory', *, # per spec: # > [...] a string value that is a relative file path [...]. # > Tools MUST assume the file’s encoding is UTF-8. - with open(join(dirname(fpath), plicense['file']), 'rb') as plicense_fileh: + with open(join(dirname(fpath), *PurePosixPath(plicense['file']).parts), 'rb') as plicense_fileh: yield DisjunctiveLicense(name=f"declared license of '{project['name']}'", acknowledgement=lack, text=AttachedText(encoding=Encoding.BASE_64, diff --git a/tests/integration/test_utils_pep621.py b/tests/integration/test_utils_pep621.py index 463cddd4..b0cebba3 100644 --- a/tests/integration/test_utils_pep621.py +++ b/tests/integration/test_utils_pep621.py @@ -15,6 +15,7 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) OWASP Foundation. All Rights Reserved. +from os import mkdir from os.path import join from tempfile import TemporaryDirectory from unittest import TestCase @@ -53,7 +54,25 @@ def test_project2licenses_license_dict_file(self) -> None: } lfac = LicenseFactory() with TemporaryDirectory() as tmpdir: - with open(join(tmpdir, project['license']['file']), 'w') as tf: + with open(join(tmpdir, 'license.txt'), 'w') as tf: + tf.write('File license text') + licenses = list(project2licenses(project, lfac, fpath=join(tmpdir, 'pyproject.toml'))) + self.assertEqual(len(licenses), 1) + lic = licenses[0] + self.assertIsInstance(lic, DisjunctiveLicense) + self.assertIs(lic.text.encoding, Encoding.BASE_64) + self.assertEqual(lic.text.content, 'RmlsZSBsaWNlbnNlIHRleHQ=') + self.assertEqual(lic.acknowledgement, LicenseAcknowledgement.DECLARED) + + def test_project2licenses_license_dict_file_in_subfolder(self) -> None: + project = { + 'name': 'testpkg', + 'license': {'file': 'foo/license.txt'}, + } + lfac = LicenseFactory() + with TemporaryDirectory() as tmpdir: + mkdir(join(tmpdir, 'foo')) + with open(join(tmpdir, 'foo', 'license.txt'), 'w') as tf: tf.write('File license text') licenses = list(project2licenses(project, lfac, fpath=join(tmpdir, 'pyproject.toml'))) self.assertEqual(len(licenses), 1)