diff --git a/docs/wiki/oelint.var.suggestedvar.md b/docs/wiki/oelint.var.suggestedvar.md index fc0a577..2ab744a 100644 --- a/docs/wiki/oelint.var.suggestedvar.md +++ b/docs/wiki/oelint.var.suggestedvar.md @@ -33,3 +33,43 @@ SECTION = "graphics" BBCLASSEXTEND = "native" ``` + +### Fine tuning + +To fine tuned the behavior on the rule, you can apply the following [constants](https://github.com/priv-kweihmann/oelint-adv#adding-additional-constants) + +- `oelint-suggestedvar/pkggroup-excludes` to skip suggestedvar variables in a packagegroup +- `oelint-suggestedvar/image-excludes` to skip suggestedvar variables in images +- `oelint-suggestedvar/{varname}-exclude-classes` to skip `{varname}`, because of a class inherited that defines the variable already + +e.g. if your custom class ``foo.bbclass`` contains + +``` +BUGTRACKER = "https://my-homepage/issues" +CVE_PRODUCT ?= "my/product" +``` + +but resides in a different layer than the current, you can run the linter with + +```console +oelint-adv --constantmods=+.my-custom-src-uri-classes.json ... +``` + +with `.my-custom-src-uri-classes.json` being + +```json +{ + "oelint-suggestedvar": { + "BUGTRACKER-exclude-classes": [ + "foo" + ], + "CVE_PRODUCT-exclude-classes": [ + "foo" + ] + } +} +``` + +to let the linter know that this is fine in the given context. + +See also the [Configuration file](https://github.com/priv-kweihmann/oelint-adv#configuration-file) option to automatically apply that to the layer. diff --git a/oelint_adv/rule_base/rule_vars_suggested.py b/oelint_adv/rule_base/rule_vars_suggested.py index 598351d..23f95f9 100644 --- a/oelint_adv/rule_base/rule_vars_suggested.py +++ b/oelint_adv/rule_base/rule_vars_suggested.py @@ -1,6 +1,6 @@ from typing import List, Tuple -from oelint_parser.cls_item import Variable +from oelint_parser.cls_item import Inherit, Variable from oelint_parser.cls_stash import Stash from oelint_parser.constants import CONSTANTS @@ -14,19 +14,42 @@ def __init__(self) -> None: message='', onappend=False, appendix=CONSTANTS.VariablesSuggested) + # image-excludes + # pkggroup-excludes + # *-exclude-classes + CONSTANTS.AddConstants( + { + 'oelint-suggestedvar': + { + 'image-excludes': [], + 'pkggroup-excludes': ['LICENSE', 'CVE_PRODUCT'], + }, + }, + ) def check(self, _file: str, stash: Stash) -> List[Tuple[str, int, str]]: res = [] _is_pkg_group = stash.IsPackageGroup(_file) + _is_image = stash.IsImage(_file) all_items: List[Variable] = stash.GetItemsFor(filename=_file, classifier=Variable.CLASSIFIER, attribute=Variable.ATTR_VAR, attributeValue=CONSTANTS.VariablesSuggested) + inherits: List[Inherit] = stash.GetItemsFor(filename=_file, + classifier=Inherit.CLASSIFIER) + + def get_class_specific(varname: str, inherits: List[Inherit]) -> bool: + return any(True for x in inherits if any(y in x.get_items() + for y in (CONSTANTS.GetByPath(f'oelint-suggestedvar/{varname}-exclude-classes') or []))) for var_ in CONSTANTS.VariablesSuggested: if var_ == 'BBCLASSEXTEND': # this is better covered by oelint_adv/rule_base/rule_vars_bbclassextends.py continue - if _is_pkg_group and var_ in ['LICENSE', 'CVE_PRODUCT']: + if _is_pkg_group and var_ in CONSTANTS.GetByPath('oelint-suggestedvar/pkggroup-excludes'): + continue + if _is_image and var_ in CONSTANTS.GetByPath('oelint-suggestedvar/image-excludes'): + continue + if get_class_specific(var_, inherits): continue items = [x for x in all_items if x.VarName == var_] if not any(items): diff --git a/tests/test_class_oelint_var_suggested.py b/tests/test_class_oelint_var_suggested.py index ef973c6..f362014 100644 --- a/tests/test_class_oelint_var_suggested.py +++ b/tests/test_class_oelint_var_suggested.py @@ -62,3 +62,82 @@ def test_suppress(self, id_, occurrence, input_): ) def test_good(self, input_, id_, occurrence): self.check_for_id(self._create_args(input_), id_, occurrence) + + @pytest.mark.parametrize('id_', [ + 'oelint.var.suggestedvar.BUGTRACKER', + ]) + @pytest.mark.parametrize('occurrence', [0]) + @pytest.mark.parametrize('input_', + [ + { + 'oelint_adv_test.bb': + ''' + CVE_PRODUCT = "my/my" + SECTION = "foo" + inherit foo + ''', + }, + ], + ) + def test_good_custom_varname_class(self, input_, id_, occurrence): + __cnt = ''' + { + "oelint-suggestedvar": { + "BUGTRACKER-exclude-classes": [ + "foo" + ] + } + } + ''' + _extra_opts = [ + '--constantmod=+{mod}'.format(mod=self._create_tempfile('constmod', __cnt))] + self.check_for_id(self._create_args(input_, _extra_opts), id_, occurrence) + + @pytest.mark.parametrize('id_', [ + 'oelint.var.suggestedvar.BUGTRACKER', + ]) + @pytest.mark.parametrize('occurrence', [0]) + @pytest.mark.parametrize('input_', + [ + { + 'oelint_adv_test.bb': + ''' + CVE_PRODUCT = "my/my" + SECTION = "foo" + inherit image + ''', + }, + ], + ) + def test_good_custom_image(self, input_, id_, occurrence): + __cnt = ''' + { + "oelint-suggestedvar": { + "image-excludes": [ + "BUGTRACKER" + ] + } + } + ''' + _extra_opts = [ + '--constantmod=+{mod}'.format(mod=self._create_tempfile('constmod', __cnt))] + self.check_for_id(self._create_args(input_, _extra_opts), id_, occurrence) + + @pytest.mark.parametrize('id_', [ + 'oelint.var.suggestedvar.LICENSE', + ]) + @pytest.mark.parametrize('occurrence', [0]) + @pytest.mark.parametrize('input_', + [ + { + 'oelint_adv_test.bb': + ''' + CVE_PRODUCT = "my/my" + SECTION = "foo" + inherit packagegroup + ''', + }, + ], + ) + def test_good_custom_packagegroup(self, input_, id_, occurrence): + self.check_for_id(self._create_args(input_), id_, occurrence)