{
  "@context": "https://spdx.org/rdf/3.0.1/spdx-context.jsonld",
  "@graph": [
    {
      "@id": "_:creationInfo_0",
      "type": "CreationInfo",
      "specVersion": "3.0.1",
      "createdBy": [
        "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd0"
      ],
      "createdUsing": [
        "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/additionalToolSPDXRef-gnrtd1"
      ],
      "created": "2026-07-04T04:28:12Z"
    },
    {
      "@id": "_:creationInfo_1",
      "type": "CreationInfo",
      "specVersion": "3.0.1",
      "createdBy": [
        "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd2"
      ],
      "createdUsing": [
        "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/additionalToolSPDXRef-gnrtd3"
      ],
      "created": "2026-07-04T04:28:12Z"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd758",
      "type": "Relationship",
      "relationshipType": "hasConcludedLicense",
      "to": [
        "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd759"
      ],
      "from": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd707",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd99470",
      "type": "Relationship",
      "relationshipType": "hasConcludedLicense",
      "to": [
        "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd53"
      ],
      "from": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd99468",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd761",
      "type": "Relationship",
      "relationshipType": "hasDeclaredLicense",
      "to": [
        "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd759"
      ],
      "from": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd707",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd99472",
      "type": "Relationship",
      "relationshipType": "hasDeclaredLicense",
      "to": [
        "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd53"
      ],
      "from": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd99468",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd99469",
      "type": "LifecycleScopedRelationship",
      "relationshipType": "dependsOn",
      "scope": "build",
      "completeness": "noAssertion",
      "to": [
        "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd707"
      ],
      "from": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd99468",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd759",
      "type": "simplelicensing_LicenseExpression",
      "simplelicensing_licenseExpression": "Python-2.0",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd53",
      "type": "simplelicensing_LicenseExpression",
      "simplelicensing_licenseExpression": "MIT",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd99471",
      "type": "Organization",
      "name": "http://openeuler.org",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd760",
      "type": "Organization",
      "name": "http://openeuler.org",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd99468",
      "type": "software_Package",
      "software_copyrightText": "",
      "suppliedBy": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd99471",
      "software_downloadLocation": "NOASSERTION",
      "summary": "Safely evaluate AST nodes without side effects",
      "software_packageVersion": "0:0.2.2-1.oe2403sp4",
      "software_homePage": "http://github.com/alexmojaki/pure_eval",
      "description": "\n\n[![Build Status](https://travis-ci.org/alexmojaki/pure_eval.svg?branch=master)](https://travis-ci.org/alexmojaki/pure_eval) [![Coverage Status](https://coveralls.io/repos/github/alexmojaki/pure_eval/badge.svg?branch=master)](https://coveralls.io/github/alexmojaki/pure_eval?branch=master) [![Supports Python versions 3.5+](https://img.shields.io/pypi/pyversions/pure_eval.svg)](https://pypi.python.org/pypi/pure_eval)\n\nThis is a Python package that lets you safely evaluate certain AST nodes without triggering arbitrary code that may have unwanted side effects.\n\nIt can be installed from PyPI:\n\n    pip install pure_eval\n\nTo demonstrate usage, suppose we have an object defined as follows:\n\n```python\nclass Rectangle:\n    def __init__(self, width, height):\n        self.width = width\n        self.height = height\n\n    @property\n    def area(self):\n        print(\"Calculating area...\")\n        return self.width * self.height\n\n\nrect = Rectangle(3, 5)\n```\n\nGiven the `rect` object, we want to evaluate whatever expressions we can in this source code:\n\n```python\nsource = \"(rect.width, rect.height, rect.area)\"\n```\n\nThis library works with the AST, so let's parse the source code and peek inside:\n\n```python\nimport ast\n\ntree = ast.parse(source)\nthe_tuple = tree.body[0].value\nfor node in the_tuple.elts:\n    print(ast.dump(node))\n```\n\nOutput:\n\n```python\nAttribute(value=Name(id='rect', ctx=Load()), attr='width', ctx=Load())\nAttribute(value=Name(id='rect', ctx=Load()), attr='height', ctx=Load())\nAttribute(value=Name(id='rect', ctx=Load()), attr='area', ctx=Load())\n```\n\nNow to actually use the library. First construct an Evaluator:\n\n```python\nfrom pure_eval import Evaluator\n\nevaluator = Evaluator({\"rect\": rect})\n```\n\nThe argument to `Evaluator` should be a mapping from variable names to their values. Or if you have access to the stack frame where `rect` is defined, you can instead use:\n\n```python\nevaluator = Evaluator.from_frame(frame)\n```\n\nNow to evaluate some nodes, using `evaluator[node]`:\n\n```python\nprint(\"rect.width:\", evaluator[the_tuple.elts[0]])\nprint(\"rect:\", evaluator[the_tuple.elts[0].value])\n```\n\nOutput:\n\n```\nrect.width: 3\nrect: <__main__.Rectangle object at 0x105b0dd30>\n```\n\nOK, but you could have done the same thing with `eval`. The useful part is that it will refuse to evaluate the property `rect.area` because that would trigger unknown code. If we try, it'll raise a `CannotEval` exception.\n\n```python\nfrom pure_eval import CannotEval\n\ntry:\n    print(\"rect.area:\", evaluator[the_tuple.elts[2]])  # fails\nexcept CannotEval as e:\n    print(e)  # prints CannotEval\n```\n\nTo find all the expressions that can be evaluated in a tree:\n\n```python\nfor node, value in evaluator.find_expressions(tree):\n    print(ast.dump(node), value)\n```\n\nOutput:\n\n```python\nAttribute(value=Name(id='rect', ctx=Load()), attr='width', ctx=Load()) 3\nAttribute(value=Name(id='rect', ctx=Load()), attr='height', ctx=Load()) 5\nName(id='rect', ctx=Load()) <__main__.Rectangle object at 0x105568d30>\nName(id='rect', ctx=Load()) <__main__.Rectangle object at 0x105568d30>\nName(id='rect', ctx=Load()) <__main__.Rectangle object at 0x105568d30>\n```\n\nNote that this includes `rect` three times, once for each appearance in the source code. Since all these nodes are equivalent, we can group them together:\n\n```python\nfrom pure_eval import group_expressions\n\nfor nodes, values in group_expressions(evaluator.find_expressions(tree)):\n    print(len(nodes), \"nodes with value:\", values)\n```\n\nOutput:\n\n```\n1 nodes with value: 3\n1 nodes with value: 5\n3 nodes with value: <__main__.Rectangle object at 0x10d374d30>\n```\n\nIf we want to list all the expressions in a tree, we may want to filter out certain expressions whose values are obvious. For example, suppose we have a function `foo`:\n\n```python\ndef foo():\n    pass\n```\n\nIf we refer to `foo` by its name as usual, then that's not interesting:\n\n```python\nfrom pure_eval import is_expression_interesting\n\nnode = ast.parse('foo').body[0].value\nprint(ast.dump(node))\nprint(is_expression_interesting(node, foo))\n```\n\nOutput:\n\n```python\nName(id='foo', ctx=Load())\nFalse\n```\n\nBut if we refer to it by a different name, then it's interesting:\n\n```python\nnode = ast.parse('bar').body[0].value\nprint(ast.dump(node))\nprint(is_expression_interesting(node, foo))\n```\n\nOutput:\n\n```python\nName(id='bar', ctx=Load())\nTrue\n```\n\nIn general `is_expression_interesting` returns False for the following values:\n- Literals (e.g. `123`, `'abc'`, `[1, 2, 3]`, `{'a': (), 'b': ([1, 2], [3])}`)\n- Variables or attributes whose name is equal to the value's `__name__`, such as `foo` above or `self.foo` if it was a method.\n- Builtins (e.g. `len`) referred to by their usual name.\n\nTo make things easier, you can combine finding expressions, grouping them, and filtering out the obvious ones with:\n\n```python\nevaluator.interesting_expressions_grouped(root)\n```\n\nTo get the source code of an AST node, I recommend [asttokens](https://github.com/gristlabs/asttokens).\n\nHere's a complete example that brings it all together:\n\n```python\nfrom asttokens import ASTTokens\nfrom pure_eval import Evaluator\n\nsource = \"\"\"\nx = 1\nd = {x: 2}\ny = d[x]\n\"\"\"\n\nnames = {}\nexec(source, names)\natok = ASTTokens(source, parse=True)\nfor nodes, value in Evaluator(names).interesting_expressions_grouped(atok.tree):\n    print(atok.get_text(nodes[0]), \"=\", value)\n```\n\nOutput:\n\n```python\nx = 1\nd = {1: 2}\ny = 2\nd[x] = 2\n```",
      "name": "python3-pure-eval",
      "software_sourceInfo": "acquired package info from repodata DB: repodata/f1f85c23079e7764ad00378a9fc5d660b89a03657290e75426caf7be5b7da462-primary.sqlite.bz2",
      "software_packageUrl": "pkg:rpm/python3-pure-eval@0.2.2-1.oe2403sp4?arch=noarch&epoch=0&upstream=python-pure-eval-0.2.2-1.oe2403sp4.src.rpm",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd707",
      "type": "software_Package",
      "software_copyrightText": "",
      "suppliedBy": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/SPDXRef-gnrtd760",
      "software_downloadLocation": "NOASSERTION",
      "summary": "Interpreter of the Python3 programming language",
      "software_packageVersion": "0:3.11.6-32.oe2403sp4",
      "software_homePage": "https://www.python.org/",
      "description": "Python combines remarkable power with very clear syntax. It has modules,\nclasses, exceptions, very high level dynamic data types, and dynamic\ntyping. There are interfaces to many system calls and libraries, as well\nas to various windowing systems. New built-in modules are easily written\nin C or C++ (or other languages, depending on the chosen implementation).\nPython is also usable as an extension language for applications written\nin other languages that need easy-to-use scripting or automation interfaces.\n\nThis package Provides python version 3.",
      "name": "python3",
      "software_sourceInfo": "acquired package info from repodata DB: repodata/f1f85c23079e7764ad00378a9fc5d660b89a03657290e75426caf7be5b7da462-primary.sqlite.bz2",
      "software_packageUrl": "pkg:rpm/python3@3.11.6-32.oe2403sp4?arch=aarch64&epoch=0&upstream=python3-3.11.6-32.oe2403sp4.src.rpm",
      "creationInfo": "_:creationInfo_0"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/additionalToolSPDXRef-gnrtd3",
      "type": "Tool",
      "name": "syft-[not provided]",
      "creationInfo": "_:creationInfo_1"
    },
    {
      "spdxId": "https://anchore.com/syft/dir/repo/openeuler/openEuler-24.03-LTS-SP4/everything/aarch64-074b704b-0eaf-4bcb-89c3-8ea4fa68b0fd-specv3/additionalToolSPDXRef-gnrtd1",
      "type": "Tool",
      "name": "syft-[not provided]",
      "creationInfo": "_:creationInfo_0"
    }
  ]
}