From 7611388f3112e24f7b3dd8a44da717cf31cc982b Mon Sep 17 00:00:00 2001 From: Konrad Weihmann Date: Wed, 23 Aug 2023 14:53:45 +0000 Subject: [PATCH] Check LICENSE containing valid SPDX like code Closes #426 Signed-off-by: Konrad Weihmann --- README.md | 4 +- oelint_adv/rule_base/rule_var_license_spdx.py | 19 ++++++++ tests/test_class_oelint_var_licensespdx.py | 47 +++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 oelint_adv/rule_base/rule_var_license_spdx.py create mode 100644 tests/test_class_oelint_var_licensespdx.py diff --git a/README.md b/README.md index 21ca8dc5..d16efb39 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,7 @@ Rules marked with **[S]** can have multiple sub-IDs * oelint.var.filesoverride - FILES:*(FILES_*) variables should not be overridden * oelint.var.improperinherit - Warn about improperly named inherits * oelint.var.licenseremotefile - License shall be a file in remote source not a local file +* oelint.var.licensesdpx - Check for correct SPDX syntax in licenses * oelint.var.mandatoryvar - Check for mandatory variables **[S]** * oelint.var.multiinclude - Warn on including the same file more than once * oelint.var.multiinherit - Warn on inherit the same file more than once @@ -189,8 +190,7 @@ Rules marked with **[S]** can have multiple sub-IDs * oelint.vars.pbpusage - \$\{BP\} should be used instead of \$\{P\} **[F]** * oelint.vars.pkgspecific - Variable is package-specific, but isn't set in that way **[S]** * oelint.vars.pnbpnusage - \$\{BPN\} should be used instead of \$\{PN\} **[F]** -* oelint.vars.pnusagediscouraged - Variable shouldn't contain \$\{PN\} or -* \$\{BPN\} +* oelint.vars.pnusagediscouraged - Variable shouldn't contain \$\{PN\} or \$\{BPN\} * oelint.vars.sectionlowercase - SECTION should be lowercase only **[F]** * oelint.vars.spacesassignment - ' = ' should be correct variable assignment * oelint.vars.specific - Variable is specific to an unknown identifier diff --git a/oelint_adv/rule_base/rule_var_license_spdx.py b/oelint_adv/rule_base/rule_var_license_spdx.py new file mode 100644 index 00000000..6f2b063b --- /dev/null +++ b/oelint_adv/rule_base/rule_var_license_spdx.py @@ -0,0 +1,19 @@ +from oelint_parser.cls_item import Variable +from oelint_adv.cls_rule import Rule + + +class LicenseSDPX(Rule): + def __init__(self): + super().__init__(id='oelint.vars.licensesdpx', + severity='warning', + message='LICENSE is not a valid OpenEmbedded SPDX expression') + + def check(self, _file, stash): + res = [] + items = stash.GetItemsFor(filename=_file, classifier=Variable.CLASSIFIER, + attribute=Variable.ATTR_VAR) + for i in [x for x in items if x.VarName == 'LICENSE']: + if (('|' in i.VarValueStripped and ' | ' not in i.VarValueStripped) or + ('&' in i.VarValueStripped and ' & ' not in i.VarValueStripped)): + res += self.finding(i.Origin, i.InFileLine) + return res diff --git a/tests/test_class_oelint_var_licensespdx.py b/tests/test_class_oelint_var_licensespdx.py new file mode 100644 index 00000000..b4038056 --- /dev/null +++ b/tests/test_class_oelint_var_licensespdx.py @@ -0,0 +1,47 @@ +import pytest # noqa: I900 + +from .base import TestBaseClass + + +class TestClassOelintVarLicenseSPDX(TestBaseClass): + + @pytest.mark.parametrize('id_', ['oelint.vars.licensesdpx']) + @pytest.mark.parametrize('occurrence', [1]) + @pytest.mark.parametrize('input_', + [ + { + 'oelint_adv_test.bb': + ''' + LICENSE:a = "ISC &MIT" + ''', + }, + { + 'oelint_adv_test.bb': + ''' + LICENSE:e = "(ISC|MIT) & Apache-2.0 & BSD-3-Clause" + ''', + }, + ], + ) + def test_bad(self, input_, id_, occurrence): + self.check_for_id(self._create_args(input_), id_, occurrence) + + @pytest.mark.parametrize('id_', ['oelint.var.licensesdpx']) + @pytest.mark.parametrize('occurrence', [0]) + @pytest.mark.parametrize('input_', + [ + { + 'oelint_adv_test.bb': + ''' + LICENSE:${PN} = "BSD-2-Clause" + LICENSE:b = "(ISC | MIT)" + LICENSE:c = "(BSD-2-Clause | MIT)" + LICENSE:d = "(BSD-2-Clause | MIT) & MIT" + LICENSE:f = "BSD-3-Clause" + LICENSE = "Unknown" + ''', + }, + ], + ) + def test_good(self, input_, id_, occurrence): + self.check_for_id(self._create_args(input_), id_, occurrence)