Skip to content

Accessor: not exported from top-level namespace, Paint.id not exposed, accessor_generate_id() crashes #2

@ElliotGarbus

Description

@ElliotGarbus

Overview

While building a Kivy SVG widget that uses thorvg-python to rasterize and manipulate SVG elements at runtime, I found three related issues with the Accessor API. They are reported together because they all affect the same workflow: traversing a loaded Picture to identify which paint nodes carry SVG id attributes. See: thorvg/thorvg#4217 for background.

Issue 1 — Accessor is not exported from the top-level namespace

Accessor lives in thorvg_python.accessor but is not re-exported in __init__.py. It does not appear in dir(tvg) and cannot be imported as tvg.Accessor.

All other major classes (Picture, Scene, Shape, Engine, etc.) are available directly from import thorvg_python as tvg. It would seen natural that Accessor should follow the same convention.

Issue 2 — accessor_generate_id() crashes with AttributeError

Calling Accessor.accessor_generate_id() raises: AttributeError: 'int' object has no attribute 'value'
The method calls .value on the return of tvg_accessor_generate_id, but the ctypes restype is set to ctypes.c_uint32 which on some platforms returns a plain Python int rather than a ctypes instance. Removing the .value call, or switching the restype to ctypes.c_uint32 and reading it correctly, would fix this.

Minimal Reproducer:

from thorvg_python.accessor import Accessor
import thorvg_python as tvg
engine = tvg.Engine(threads=0)
acc = Accessor(engine, None)
acc.accessor_generate_id('my-element')  # raises AttributeError

Issue 3 — Paint.id (the uint32_t SVG element hash) is not exposed

The ThorVG C++ Paint struct carries a uint32_t id field that, since PR thorvg/thorvg#2827 (merged Oct 2024), is populated with a hash of the SVG id attribute when an SVG is loaded. This field is not exposed by thorvg_python's Paint class.

Without it, calling Accessor.set() to traverse the paint tree is of limited use: the callback visits every node but there is no way to determine which nodes carry an SVG id and what their hash value is. This makes it impossible to enumerate named elements from Python, even though the data is present in ThorVG's internal representation.

Environment

thorvg-python version: latest from PyPI
Python: 3.13 (32-bit, Windows)
ThorVG upstream: latest main

Test case:

from thorvg_python.accessor import Accessor
import thorvg_python as tvg

SVG = (
    b'<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">'
    b'<circle id="ring" r="40" cx="50" cy="50" fill="red"/>'
    b'<rect id="box" x="10" y="10" width="30" height="30" fill="blue"/>'
    b'<circle r="20" cx="50" cy="50" fill="green"/>'
    b'</svg>'
)

engine = tvg.Engine(threads=0)
acc = Accessor(engine, None)
pic = tvg.Picture(engine)
pic.load_data(SVG, 'svg', None, False)

found = []

def visitor(paint_ptr, data_ptr):
    p = tvg.Paint(engine, paint_ptr)
    attrs = [x for x in dir(p) if 'id' in x.lower() or 'name' in x.lower()]
    print(f'  Paint attrs with id/name: {attrs}')
    found.append(paint_ptr)
    return True

print('Traversing with Accessor.set()...')
result = acc.set(pic, visitor, b'x')
print(f'Result: {result}')
print(f'Nodes visited: {len(found)}')

print()
print('Can we get the uint32 id from a Paint via get_paint(hash)?')
hash_ring = acc.accessor_generate_id('ring')
hash_box = acc.accessor_generate_id('box')
print(f'  hash("ring") = {hash_ring}')
print(f'  hash("box")  = {hash_box}')
node = pic.get_paint(hash_ring)
print(f'  pic.get_paint(hash_ring) = {node}')

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions