Changelog
0.11.0 (2026-10-20)
Support for Blender 5.1 alongside 5.2, with the tests run against each supported version, and much faster small writes through AttributeArray.
Changed
AttributeArraywrites only the values that changed, directly into the attribute’s memory, rather than writing the entire attribute withforeach_set.bob.position[:10, 2] = 10on 1M points is ~6x faster, and a single-row write to a held array is ~25x faster. Values changed in Blender since the array was read are no longer overwritten by writes elsewhere in the array. STRING attributes and attributes that can’t be written directly still write the entire array.Reading an
AttributeArrayis up to ~6x faster for large attributes, as arrays are freed as soon as they are unused instead of waiting for the garbage collector.Requires
bpy >= 5.1(previously>= 5.2). Features that need a newer Blender are only used when available, whichdatabpy.attribute.HAS_FLOAT4reports for theFLOAT4attribute type.Before Blender 5.2,
guess_atype_from_array()maps(n, 4)float arrays toFLOAT_COLOR, as there is no genericFLOAT4type. Storing an attribute withatype="FLOAT4"raisesValueErrorbefore Blender 5.2.The tests run against Blender 5.1, 5.2 5.3, and the 5.4 daily builds in separate workflows, each with a status badge in the README.
Deprecated
Node groups and appending from .blend files are handled by nodebpy, so databpy no longer ships them. Everything deprecated is removed in databpy 0.13.0, a release later than the 0.12.0 announced previously, so the new deprecations have the same window.
import databpyno longer importsdatabpy.nodes. It is imported when first used, and importing it warns with aFutureWarning.databpy.material.append_from_blend()is deprecated.BlenderObject.vertices,BlenderObject.edgesandAttribute.n_valueswarn with aFutureWarninginstead of aDeprecationWarning, which Python hides by default, and are removed in 0.13.0 (previously 1.0.0, or unspecified forn_values).databpy.register(),databpy.unregister()and theAttributeErrorbase ofNamedAttributeErrorare removed in 0.13.0 (previously 0.12.0).
Fixed
- The tests for the daily builds of bpy ran against the locked release instead, as
uv runreinstalled it.
0.10.1 (2026-10-08)
Faster mesh construction and attribute access, with benchmarks tracked by CodSpeed.
Changed
create_mesh_object(),create_object(),create_bob()andBlenderObject.new_from_pydata()write vertices, edges and faces directly to the mesh’s attributes instead of usingMesh.from_pydata(). Creating a mesh is ~500x faster for vertices, ~250x for edges and ~17x for faces given as an array. The resulting meshes are unchanged.- Breaking:
create_mesh_object()andBlenderObject.new_from_pydata()raiseValueErrorfor vertices that aren’t shaped(n, 3)(previously Blender’sRuntimeError, leaving an orphan mesh) or edges without exactly two indices, andTypeErrorfor non-integer indices, before any mesh is created. - Reading and writing attributes has about half the overhead per call, which matters most for small geometry.
AttributeTypes.BYTE_COLORreads and writes through Blender’scolor_srgbproperty, so itsvalue_nameis"color_srgb".
Fixed
- Reading or writing
BYTE_COLORattributes truncated every value to 0 or 1. Values from 0 to 255 now round-trip, and reading and writing is 4-7x faster. GeometrySet.instancesand readingpositionfrom theINSTANCEScomponent returned uninitialised values, as Blender doesn’t set the positions of the instances point cloud. They are now filled frominstance_transform.
0.10.0 (2026-09-27)
A robustness release, in preparation for wider use of databpy across projects. Node related functionality is deprecated in favour of nodebpy, objects are tracked in a way that survives renames, reallocation and other add-ons, and attribute data is validated instead of being silently corrupted.
databpy follows semantic versioning. Deprecated functionality raises a FutureWarning and is kept for at least two minor releases before removal. Everything deprecated in this release is removed in 0.12.0.
Deprecated
databpy.nodes:new_tree,swap_tree,custom_string_iswitch,append_from_blend,DuplicatePrevention,cleanup_duplicates,deduplicate_node_trees,get_input,get_output,MaintainConnections,tree_interface,new_socket,input_socket,output_socket,socket_valueandset_socket_value. Node functionality is moving to nodebpy.register()is no longer required.unregister()is now a no-op: it previously removedObject.uuid, which broke every other add-on using databpy.- The registered
Object.uuidproperty. The uuid is now stored as the custom propertyobj["_databpy_uuid"], which needs no registration.Object.uuidis kept in sync and values from existing .blend files are migrated automatically. NamedAttributeErrorsubclassingAttributeError, ashasattr()andgetattr()silently swallow it. CatchNamedAttributeErrororDatabpyErrorinstead.
Added
DatabpyError, the base class for all databpy errors.AttributeNotFoundError, raised for missing attributes. It is both aNamedAttributeErrorand aKeyError, and its message lists the available attributes.get_from_uuid(name_hint=...), to choose between duplicated objects that share a uuid.py.typed, so type checkers use databpy’s type hints.
Changed
BlenderObjecttracks its object bysession_uidwithin a session, surviving renames and memory reallocation, and by its persistent uuid after a file is loaded. As before, a wrapper stops resolving its object once another wrapper stores a different uuid on it.- Breaking: accessing a
BlenderObjectwhose object was removed raisesLinkedObjectError, instead of resolving to a duplicate that shares its uuid. databpy.object.get_uuid()/set_uuid()read and write the new custom property, falling back to and keeping in sync the registeredObject.uuidproperty.AttributeArraytracks its object bysession_uidinstead of holding a direct reference. Syncing raisesLinkedObjectErrorif the object was removed or a file was loaded, instead of warning or writing to stale data.AttributeArraysyncs every in-place modification: all in-place operators,out=,ufunc.at,fill,sort,put,partition,np.copyto,np.place,np.putmaskandnp.fill_diagonal. Augmented assignment on a view (pos[:, 2] += 1) writes to Blender once instead of twice.- Breaking: the
domainargument ofstore_named_attribute()defaults toNone, using the domain of an existing attribute, otherwisePOINT. Adomainthat doesn’t match an existing attribute raisesNamedAttributeErrorinstead of being ignored. - Writing to an existing attribute without
atypeuses the attribute’s type, instead of raising if the guessed type differed. - Breaking: 1D unsigned integer arrays are stored as
INT(uint8was stored asINT8, wrapping values above 127) and(n, 2)unsigned arrays asINT32_2D. - Breaking: attribute type guessing raises
ValueErrorwhen no type matches (0-d,(n, 5),(n, 2)bool, complex or non-numeric multi-column arrays), instead of falling back toFLOAT. - Breaking: values that can’t be represented by an integer attribute (overflow, NaN or inf) and complex data raise
AttributeMismatchError, instead of being silently wrapped or truncated. - Breaking: removing a required attribute such as
positionraisesNamedAttributeErrorinstead of Blender’sRuntimeError. bob["name"],named_attribute(),remove_named_attribute(),AttributeArray()andGeometrySet.named_attribute()raiseAttributeNotFoundErrorfor missing attributes.bob["name"]previously raised a bareKeyError, which it remains a subclass of.store_named_attribute()andAttribute.from_array()accept any array-like data.create_pointcloud_object()creates the point cloud directly instead of converting a mesh with an operator, so it no longer depends on the context. The.selectionattribute added by the conversion is no longer present.create_curves_object()raisesValueErrorif only one ofpositionsandcurve_sizesis given, instead of creating an empty object.create_mesh_object()andBlenderObject.new_from_pydata()raiseValueErrorfor out of range edge or face indices, instead of creating an invalid mesh.ObjectTrackeridentifies new objects bysession_uid.new_objects()is ordered from oldest to newest andlatest()returns the most recently created object.- Object data is refreshed with
update_tag()after writing attributes, replacing the workaround of reassigning a vertex position. - The string attribute warning points at the calling code, so it is shown once per call site.
AttributeArrayno longer has the private_attributeand_attr_nameattributes._blender_objectis kept as a read-only lookup.
Fixed
- In-place operations other than
+=,-=,*=and/=modified anAttributeArraywithout syncing to Blender. - Writing attributes to empty geometry raised
IndexErrororKeyError. create_pointcloud_object()returned a mesh when given a collection not linked to the scene, and left an orphan mesh behind.create_mesh_object()raised for faces with different numbers of vertices.BlenderObject.centroid()ignored boolean masks and unsigned index arrays, returning the unweighted centroid. Unsupported dtypes now raiseTypeError.ObjectTrackerreported renamed objects as new.- After a uuid mismatch, every access of
BlenderObject.objectsearched all objects.
0.9.0 (2026-09-14)
A full static-typing pass over the package and test suite. The code base now passes ty with zero errors and zero suppression comments (every # type: ignore has been removed), and ty runs in CI alongside ruff. Blender API values that are typed as Something | None or as wide data-block unions are now handled through small helpers that check at runtime and narrow the type, instead of being ignored.
Added
- Typed narrowing helpers, exported from the top-level
databpynamespace:require()— return a value, raisingValueErrorif it isNonerequire_data(),mesh_data(),curves_data(),pointcloud_data(),volume_data()— returnObject.datachecked to be the expected data-block type, raisingTypeErrorotherwiseactive_scene()andactive_object()— non-optional accessors forbpy.context.scene/bpy.context.active_object
- Node helpers in
databpy.nodesfor the optional-heavy node APIs:tree_interface(),new_socket(),input_socket(),output_socket(),socket_value()andset_socket_value(). databpy.object.get_uuid()/set_uuid()for the dynamically registereduuidproperty onbpy.types.Object.- Type checking with ty in CI (new
typecheckjob in the lint workflow), withtyandruffadded as locked dev dependencies. - API documentation sections for the new utility and node helpers.
Changed
- Breaking: invalid-type errors now consistently raise
TypeError(some previously raisedValueErrororAttributeError):utils.path_resolve(),attribute.guess_atype_from_array(),BlenderObject.__getitem__()with a non-string key, assigning a non-ObjecttoBlenderObjectBase.object, and the deprecatedvertices/edgesproperties on non-mesh objects. - Object creation functions (
create_object(),create_mesh_object(),create_curves_object(),create_pointcloud_object(),create_bob()and theBlenderObject.from_*()classmethods) are now typed to accept any array-like (lists and tuples always worked at runtime). utils.lerp()accepts scalars and array-likes, converting to numpy arrays internally (the documented list example now actually works).Attribute()accepts anybpy.types.Attributeand validates it against the supported concrete attribute types, raisingNamedAttributeErrorfor unsupported ones.nodes.new_tree()is typed as returning aGeometryNodeTreeand raisesNodeGroupCreationErrorif an existing node group with the requested name is not a geometry node tree.nodes.MaintainConnectionsandnodes.swap_tree()raiseTypeErrorwhen given a node that is not aGeometryNodeGroup.custom_string_iswitch()catches specific exception types during node group creation (rather than a blindexcept Exception) and chains the original error onto the raisedNodeGroupCreationError.
Fixed
from databpy import utilswas shadowed bydatabpy.nodes.utilsin the package namespace, so static analysis (and potentially import order) resolveddatabpy.utilsto the wrong module.- Docs builds failed with the latest griffe (quartodoc 0.11.1 is incompatible with griffe 2.x); griffe is now pinned to
<2in the dev dependencies.
0.8.0 (2026-07-21)
Support for the new attribute types introduced in Blender 5.2, alongside a cleanup of the attribute typing system. Requires bpy >= 5.2.
Added
- Support for the new Blender 5.2 attribute types:
FLOAT4— 4D float vectors (Float4Attribute)INT16_2D— 2D 16-bit signed integer vectors (Short2Attribute)STRING— text strings (StringAttribute). String support is experimental and raises a warning when used: string attributes are accessible through the Python API but are not yet properly supported within Geometry Nodes. Values are read and written per-element (as unicode numpy arrays) since Blender’sforeach_get/foreach_setdo not support string properties.
GeometrySet, for accessing all components of an object’s evaluated geometry — including multi-component Geometry Nodes outputs (mesh, point cloud, curves and instances) that a normally evaluated object doesn’t expose. Providesnamed_attribute()/list_attributes()across components and an informativerepr()suited to snapshot testing.Attribute.storage_type, exposing Blender 5.2’s new attribute storage types ("ARRAY"or"SINGLE").SINGLE-storage attributes (produced by Geometry Nodes for constant values) read transparently as full arrays.named_attribute(evaluate=True)andevaluate_object()now work for Curves and PointCloud objects, not just meshes.BlenderObject.store_named_attribute()now returns the created or modified attribute (previously returnedNone).
Changed
- Results of
AttributeArrayoperations (e.g.pos + 1, comparisons) are now plainnumpy.ndarrays, and copies (pos.copy(), boolean-mask indexing) are detached from Blender — neither syncs back on modification. True views (slices, column access) remain connected and continue to auto-sync. - Data is cast to the attribute’s storage dtype before writing, letting Blender’s
foreach_setuse its fast buffer path instead of per-element iteration (a significant speedup for the common case of passing float64 arrays). - Breaking: attribute type guessing for
(n, 4)float arrays now maps to the genericFLOAT4type instead ofFLOAT_COLOR. To store colors or quaternions, explicitly request them with e.g.store_named_attribute(..., atype="FLOAT_COLOR").(n, 4)uint8arrays still map toBYTE_COLOR. - Attribute type guessing for
(n, 2)int16/uint16arrays now maps toINT16_2D(other integer widths still map toINT32_2D), and string arrays map toSTRING. - Requires
bpy >= 5.2(previously>= 5.1). - Improved type hints throughout the attribute module: precise
Literaltypes for attribute type and domain names,tuple[int, ...]shapes, and an immutableAttributeTypedataclass.
Fixed
- Setting an existing attribute with dictionary syntax (
bob["color"] = data) no longer performs a second, redundant write with a re-guessed attribute type, which could raise a type mismatch error for color and quaternion attributes. Attribute.from_array()now triggers the same object-data refresh workaround asstore_named_attribute(), so writes through the low-level interface update reliably in the viewport.repr()of anAttributeArraythat has lost its attribute reference no longer raises an error.
Removed
- Breaking: removed the unused legacy
AttributeTypeInfoandAttributeDomainclasses from the public API. Use theAttributeTypesandAttributeDomainsenums instead.
0.7.0 (2026-03-05)
- Updated dependencies for Blender 5.1 (#69).
0.6.2 (2026-03-05)
- Improved typing for the attribute module (#67).
- Added
move_to_collection()for moving objects from one collection into another (#62, thanks @kolibril13).
0.6.0 (2025-11-25)
0.5.1 (2025-11-06)
0.5.0 (2025-10-25)
- Better point cloud and curves support (#57).
- Requires Blender >= 4.5 for compatibility with point cloud support.
0.4.2 (2025-10-24)
- Internal improvements and cleanup (#56).
- Deprecated
Attribute.n_valuesin favor ofAttribute.size.
0.4.1 (2025-10-21)
- Fixed
AttributeArray.__str__(#55).
0.4.0 (2025-10-21)
- Fixed integer attribute returns to be
int32(#54).
For older releases, see the GitHub releases page.