On Thu, Nov 13, 2025 at 11:42 AM Stefano Tondo via
lists.openembedded.org <[email protected]>
wrote:
>
> From: Stefano Tondo <[email protected]>
>
> Fix incorrect function call when processing SPDX_CUSTOM_ANNOTATION_VARS.
> The code was calling new_annotation() as a standalone function, but it
> should be called as a method on the build_objset object.
>
> Error:
>     new_annotation(d, build_objset, build, ...)
>
> Corrected to:
>     build_objset.new_annotation(d, build_objset, build, ...)
>
> This bug would cause a NameError at runtime if SPDX_CUSTOM_ANNOTATION_VARS
> was set to a non-empty value, preventing SPDX document generation.
>
> The fix aligns with how new_annotation() is called elsewhere in the
> codebase and matches the SBOMObjset class method signature.

LGTM, thanks

Reviewed-by: Joshua Watt <[email protected]>

>
> Signed-off-by: Stefano Tondo <[email protected]>
> ---
>  meta/lib/oe/spdx30_tasks.py          |  4 +-
>  meta/lib/oeqa/selftest/cases/spdx.py | 74 ++++++++++++++++++++++++++++
>  2 files changed, 75 insertions(+), 3 deletions(-)
>
> diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py
> index f2f133005d..4d11b3c289 100644
> --- a/meta/lib/oe/spdx30_tasks.py
> +++ b/meta/lib/oe/spdx30_tasks.py
> @@ -498,9 +498,7 @@ def create_spdx(d):
>      build_objset.set_is_native(is_native)
>
>      for var in (d.getVar("SPDX_CUSTOM_ANNOTATION_VARS") or "").split():
> -        new_annotation(
> -            d,
> -            build_objset,
> +        build_objset.new_annotation(
>              build,
>              "%s=%s" % (var, d.getVar(var)),
>              oe.spdx30.AnnotationType.other,
> diff --git a/meta/lib/oeqa/selftest/cases/spdx.py 
> b/meta/lib/oeqa/selftest/cases/spdx.py
> index 8cd4e83ca2..eda41cf952 100644
> --- a/meta/lib/oeqa/selftest/cases/spdx.py
> +++ b/meta/lib/oeqa/selftest/cases/spdx.py
> @@ -286,3 +286,77 @@ class SPDX30Check(SPDX3CheckBase, OESelftestTestCase):
>                  break
>          else:
>              self.assertTrue(False, "Unable to find imported Host SpdxID")
> +
> +    def test_custom_annotation_vars(self):
> +        """
> +        Test that SPDX_CUSTOM_ANNOTATION_VARS properly creates annotations
> +        without runtime errors. This is a regression test for the bug where
> +        new_annotation() was called as a standalone function instead of as
> +        a method on build_objset, causing a NameError.
> +
> +        The test verifies:
> +        1. The build completes successfully (no NameError)
> +        2. Each configured annotation variable appears exactly once
> +        3. The annotation values match the configured variables
> +
> +        We check for exact equality (not >=) to prevent regressions where
> +        one annotation might appear multiple times while another is missing.
> +        """
> +        ANNOTATION_VAR1 = "TestAnnotation1"
> +        ANNOTATION_VAR2 = "TestAnnotation2"
> +
> +        # This will fail with NameError if new_annotation() is called 
> incorrectly
> +        objset = self.check_recipe_spdx(
> +            "base-files",
> +            
> "{DEPLOY_DIR_SPDX}/{MACHINE_ARCH}/packages/package-base-files.spdx.json",
> +            extraconf=textwrap.dedent(
> +                f"""\
> +                ANNOTATION1 = "{ANNOTATION_VAR1}"
> +                ANNOTATION2 = "{ANNOTATION_VAR2}"
> +                SPDX_CUSTOM_ANNOTATION_VARS = "ANNOTATION1 ANNOTATION2"
> +                """
> +            ),
> +        )
> +
> +        # If we got here, the build succeeded (no NameError)
> +        # Now verify the annotations were actually created
> +
> +        # Find the build element
> +        build = None
> +        for o in objset.foreach_type(oe.spdx30.build_Build):
> +            build = o
> +            break
> +
> +        self.assertIsNotNone(build, "Unable to find Build element")
> +
> +        # Find annotation objects that reference our build
> +        found_annotations = []
> +        for obj in objset.objects():
> +            if isinstance(obj, oe.spdx30.Annotation):
> +                if hasattr(obj, "subject") and build._id == obj.subject._id:
> +                    found_annotations.append(obj)
> +
> +        # Check each annotation separately to ensure exactly one occurrence 
> of each
> +        annotation1_count = 0
> +        annotation2_count = 0
> +
> +        for annotation in found_annotations:
> +            if hasattr(annotation, "statement"):
> +                if f"ANNOTATION1={ANNOTATION_VAR1}" in annotation.statement:
> +                    annotation1_count += 1
> +                    self.logger.info(f"Found ANNOTATION1: 
> {annotation.statement}")
> +                if f"ANNOTATION2={ANNOTATION_VAR2}" in annotation.statement:
> +                    annotation2_count += 1
> +                    self.logger.info(f"Found ANNOTATION2: 
> {annotation.statement}")
> +
> +        # Each annotation should appear exactly once
> +        self.assertEqual(
> +            annotation1_count,
> +            1,
> +            f"Expected exactly 1 occurrence of ANNOTATION1, found 
> {annotation1_count}",
> +        )
> +        self.assertEqual(
> +            annotation2_count,
> +            1,
> +            f"Expected exactly 1 occurrence of ANNOTATION2, found 
> {annotation2_count}",
> +        )
> --
> 2.51.1
>
>
> 
>
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#226263): 
https://lists.openembedded.org/g/openembedded-core/message/226263
Mute This Topic: https://lists.openembedded.org/mt/116279440/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to