github m3trik/pythontk v0.18.2
pythontk v0.18.2

2 hours ago
  • 2026-10-27 -- Moved names survive from package import Name; record hooks re-read on a new path; fingerprints pin a record's fields (core_utils/module_resolver.py, core_utils/engines/scene_export/scene_records.py, file_utils/mesh_convert/export_fingerprint.py). CPython turns an AttributeError under from package import Name into a bare "cannot import name", so that statement now gets MovedImportError (an ImportError) with the same message, while a plain read keeps MovedNameError and hasattr stays safe. SceneRecords.registered_hooks reads its metadata again when sys.path changes, warns when two distributions name one entry (the first on the path wins), and stager_rows skips a slot naming no method, with a warning. ExportFingerprint keeps a record's fields, list lengths and numbers (a JSON user property read as its shape), so a record written with the right key but a wrong value is a difference; its text reads as "text". These add 78 source lines (line_budget 659,503 -> 659,581).
    • Test(s): test_module_resolver.py +1, test_scene_records.py +3, test_export_verify.py +1; test/surface_snapshot.json gains ExportFingerprint.
  • 2026-10-27 -- SceneRecords.hook_row: a library's single call into tool code, registrable (core_utils/engines/scene_export/scene_records.py). A seam such as the take stash or the offset fold is one (module, class, method) row: the library's own while the tool lives there, else the one an installed package registers for the host and role, so the call survives the tool's move without importing upward. Several registered: the first by key is used and the rest warned about. With the two hosts' FbxUtils.HOOKS this adds 74 source lines (line_budget 659,429 -> 659,503).
    • Test(s): test_scene_records.py +1.
  • 2026-10-27 -- Record hooks register through an entry-point group (core_utils/engines/scene_export/scene_records.py, scene_store.py, core_utils/package_manager.py). A tool outside a library registers its record producer, stager or owner as an entry point in group SceneRecords.HOOK_GROUP (m3trik.scene_records), named <host>.<role>.<key> and pointing at module:Class.method (module:Class for an owner). SceneRecords.registered_hooks(host, role) reads them from metadata alone, once a session (forget_registered_hooks reads again), so nothing is imported and a batch export that imports one library still writes an installed tool's record. SceneRecords.producer_rows / stager_rows merge them under a host's own tables, and SceneStoreBase.HOST + owner_rows() do the same for record owners; a key both name keeps the library's row. PackageManager.entry_points(group) is the one reader across importlib versions (uitk's external-app handler now uses it). Nothing registers yet, so no export changes. The hooks add 149 source lines across the four libraries (line_budget 659,280 -> 659,429).
    • Test(s): test_scene_records.py +5 (TestRegisteredHooks), test_package_manager.py +2 (EntryPointsTests).
  • 2026-10-27 -- A name that left a package answers with its new home (core_utils/module_resolver.py, __init__.py). bootstrap_package(..., moved=MOVED_NAMES) takes the package's moved-names table, {name: (new home, version)}, and a read of a listed name raises the new MovedNameError, an AttributeError naming where the name went and from which release, so hasattr and getattr(..., default) behave as for any missing name. A move to tentacle gets no alias (no library imports it), and one table per library replaces an alias per name. pythontk declares its table, empty for now. With the four libraries' tables this adds 48 source lines (line_budget 659,232 -> 659,280).
    • Test(s): test_module_resolver.py +2 (MovedNamesTests).
  • 2026-10-27 -- ExportFingerprint pins what an export wrote, and FbxFile.object_name is public (file_utils/mesh_convert/export_fingerprint.py, new; fbx_file.py). ExportFingerprint.of(path) reads a GLB or FBX into plain JSON-able data: a GLB's node tree by name path with its transforms, meshes with their attribute and index counts, materials, skins and each clip's channels and span; an FBX's object census, each model's type and local transform, geometry sizes (read without inflating an array), materials with their texture slots, each take's curves with their key spans, and user-property names. What legitimately differs run over run (generator strings, buffer packing, the paths and dates inside records) stays out. diff(baseline, current, tolerance) names each change by path, and against(path, baseline, update=False) compares an export with a saved fingerprint, so a code move that must change no output can prove it. FbxFile._object_name becomes object_name, the display name of a record iter_objects yields. The module adds 367 source lines (line_budget 658,865 -> 659,232).
    • Test(s): test_export_verify.py +7 (TestExportFingerprint).

Don't miss a new pythontk release

NewReleases is sending notifications on new releases.