Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 26 additions & 11 deletions cyclonedx/factory/license.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,51 +21,66 @@

if TYPE_CHECKING: # pragma: no cover
from ..model import AttachedText, XsUri
from ..model.license import License
from ..model.license import License, LicenseAcknowledgement


class LicenseFactory:
"""Factory for :class:`cyclonedx.model.license.License`."""

def make_from_string(self, value: str, *,
license_text: Optional['AttachedText'] = None,
license_url: Optional['XsUri'] = None) -> 'License':
license_url: Optional['XsUri'] = None,
license_acknowledgement: Optional['LicenseAcknowledgement'] = None
) -> 'License':
"""Make a :class:`cyclonedx.model.license.License` from a string."""
try:
return self.make_with_id(value, text=license_text, url=license_url)
return self.make_with_id(value,
text=license_text,
url=license_url,
acknowledgement=license_acknowledgement)
except InvalidSpdxLicenseException:
pass
try:
return self.make_with_expression(value)
return self.make_with_expression(value,
acknowledgement=license_acknowledgement)
except InvalidLicenseExpressionException:
pass
return self.make_with_name(value, text=license_text, url=license_url)
return self.make_with_name(value,
text=license_text,
url=license_url,
acknowledgement=license_acknowledgement)

def make_with_expression(self, expression: str) -> LicenseExpression:
def make_with_expression(self, expression: str, *,
acknowledgement: Optional['LicenseAcknowledgement'] = None
) -> LicenseExpression:
"""Make a :class:`cyclonedx.model.license.LicenseExpression` with a compound expression.

Utilizes :func:`cyclonedx.spdx.is_compound_expression`.

:raises InvalidLicenseExpressionException: if param `value` is not known/supported license expression
"""
if is_spdx_compound_expression(expression):
return LicenseExpression(expression)
return LicenseExpression(expression, acknowledgement=acknowledgement)
raise InvalidLicenseExpressionException(expression)

def make_with_id(self, spdx_id: str, *,
text: Optional['AttachedText'] = None,
url: Optional['XsUri'] = None) -> DisjunctiveLicense:
url: Optional['XsUri'] = None,
acknowledgement: Optional['LicenseAcknowledgement'] = None
) -> DisjunctiveLicense:
"""Make a :class:`cyclonedx.model.license.DisjunctiveLicense` from an SPDX-ID.

:raises InvalidSpdxLicenseException: if param `spdx_id` was not known/supported SPDX-ID
"""
spdx_license_id = spdx_fixup(spdx_id)
if spdx_license_id is None:
raise InvalidSpdxLicenseException(spdx_id)
return DisjunctiveLicense(id=spdx_license_id, text=text, url=url)
return DisjunctiveLicense(id=spdx_license_id, text=text, url=url, acknowledgement=acknowledgement)

def make_with_name(self, name: str, *,
text: Optional['AttachedText'] = None,
url: Optional['XsUri'] = None) -> DisjunctiveLicense:
url: Optional['XsUri'] = None,
acknowledgement: Optional['LicenseAcknowledgement'] = None
) -> DisjunctiveLicense:
"""Make a :class:`cyclonedx.model.license.DisjunctiveLicense` with a name."""
return DisjunctiveLicense(name=name, text=text, url=url)
return DisjunctiveLicense(name=name, text=text, url=url, acknowledgement=acknowledgement)
1 change: 1 addition & 0 deletions cyclonedx/model/license.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ class LicenseExpression:

def __init__(
self, value: str,
# *, # all optional args are intended to be keyword-args
acknowledgement: Optional[LicenseAcknowledgement] = None
) -> None:
self._value = value
Expand Down
39 changes: 26 additions & 13 deletions tests/test_factory_license.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,49 +21,60 @@
from cyclonedx.exception.factory import InvalidLicenseExpressionException, InvalidSpdxLicenseException
from cyclonedx.factory.license import LicenseFactory
from cyclonedx.model import AttachedText, XsUri
from cyclonedx.model.license import DisjunctiveLicense, LicenseExpression
from cyclonedx.model.license import DisjunctiveLicense, LicenseAcknowledgement, LicenseExpression


class TestFactoryLicense(unittest.TestCase):

def test_make_from_string_with_id(self) -> None:
text = unittest.mock.NonCallableMock(spec=AttachedText)
url = unittest.mock.NonCallableMock(spec=XsUri)
expected = DisjunctiveLicense(id='bar', text=text, url=url)
acknowledgement = unittest.mock.NonCallableMock(spec=LicenseAcknowledgement)
expected = DisjunctiveLicense(id='bar', text=text, url=url, acknowledgement=acknowledgement)

with unittest.mock.patch('cyclonedx.factory.license.spdx_fixup', return_value='bar'), \
unittest.mock.patch('cyclonedx.factory.license.is_spdx_compound_expression', return_value=True):
actual = LicenseFactory().make_from_string('foo', license_text=text, license_url=url)
actual = LicenseFactory().make_from_string('foo',
license_text=text,
license_url=url,
license_acknowledgement=acknowledgement)

self.assertEqual(expected, actual)

def test_make_from_string_with_name(self) -> None:
text = unittest.mock.NonCallableMock(spec=AttachedText)
url = unittest.mock.NonCallableMock(spec=XsUri)
expected = DisjunctiveLicense(name='foo', text=text, url=url)
acknowledgement = unittest.mock.NonCallableMock(spec=LicenseAcknowledgement)
expected = DisjunctiveLicense(name='foo', text=text, url=url, acknowledgement=acknowledgement)

with unittest.mock.patch('cyclonedx.factory.license.spdx_fixup', return_value=None), \
unittest.mock.patch('cyclonedx.factory.license.is_spdx_compound_expression', return_value=False):
actual = LicenseFactory().make_from_string('foo', license_text=text, license_url=url)
actual = LicenseFactory().make_from_string('foo',
license_text=text,
license_url=url,
license_acknowledgement=acknowledgement)

self.assertEqual(expected, actual)

def test_make_from_string_with_expression(self) -> None:
expected = LicenseExpression('foo')
acknowledgement = unittest.mock.NonCallableMock(spec=LicenseAcknowledgement)
expected = LicenseExpression('foo', acknowledgement=acknowledgement)

with unittest.mock.patch('cyclonedx.factory.license.spdx_fixup', return_value=None), \
unittest.mock.patch('cyclonedx.factory.license.is_spdx_compound_expression', return_value=True):
actual = LicenseFactory().make_from_string('foo')
actual = LicenseFactory().make_from_string('foo',
license_acknowledgement=acknowledgement)

self.assertEqual(expected, actual)

def test_make_with_id(self) -> None:
text = unittest.mock.NonCallableMock(spec=AttachedText)
url = unittest.mock.NonCallableMock(spec=XsUri)
expected = DisjunctiveLicense(id='bar', text=text, url=url)
acknowledgement = unittest.mock.NonCallableMock(spec=LicenseAcknowledgement)
expected = DisjunctiveLicense(id='bar', text=text, url=url, acknowledgement=acknowledgement)

with unittest.mock.patch('cyclonedx.factory.license.spdx_fixup', return_value='bar'):
actual = LicenseFactory().make_with_id(spdx_id='foo', text=text, url=url)
actual = LicenseFactory().make_with_id(spdx_id='foo', text=text, url=url, acknowledgement=acknowledgement)

self.assertEqual(expected, actual)

Expand All @@ -75,14 +86,16 @@ def test_make_with_id_raises(self) -> None:
def test_make_with_name(self) -> None:
text = unittest.mock.NonCallableMock(spec=AttachedText)
url = unittest.mock.NonCallableMock(spec=XsUri)
expected = DisjunctiveLicense(name='foo', text=text, url=url)
actual = LicenseFactory().make_with_name(name='foo', text=text, url=url)
acknowledgement = unittest.mock.NonCallableMock(spec=LicenseAcknowledgement)
expected = DisjunctiveLicense(name='foo', text=text, url=url, acknowledgement=acknowledgement)
actual = LicenseFactory().make_with_name(name='foo', text=text, url=url, acknowledgement=acknowledgement)
self.assertEqual(expected, actual)

def test_make_with_expression(self) -> None:
expected = LicenseExpression('foo')
acknowledgement = unittest.mock.NonCallableMock(spec=LicenseAcknowledgement)
expected = LicenseExpression('foo', acknowledgement=acknowledgement)
with unittest.mock.patch('cyclonedx.factory.license.is_spdx_compound_expression', return_value=True):
actual = LicenseFactory().make_with_expression(expression='foo')
actual = LicenseFactory().make_with_expression(expression='foo', acknowledgement=acknowledgement)
self.assertEqual(expected, actual)

def test_make_with_expression_raises(self) -> None:
Expand Down