Another solution which doesn't rely on knowing the collection items' type beforehand.
Get the property special dictionary construct by accessing the holder's (bpy_struct.id_data) custom properties (barely documented bl_rna.properties
), and get the property by name using bpy_struct.path_from_id.
import bpy
from bpy.props import StringProperty, CollectionProperty
class MyCollectionProperty(bpy.types.PropertyGroup):
name = StringProperty(default="")
bpy.utils.register_class(MyCollectionProperty)
bpy.types.Scene.my_collection_prop = CollectionProperty(type=MyCollectionProperty)
def get_class(collection_prop: bpy.types.CollectionProperty) -> type:
prop = collection_prop.id_data.bl_rna.properties.get(collection_prop.path_from_id())
return type(prop.fixed_type) if prop is not None else None
assert MyCollectionProperty == get_class(bpy.data.scenes[0].my_collection_prop)
Note this will only work if the bpy.props.CollectionProperty
is a direct member of a bpy.types.ID
instance. In the case where a collection property is held in a property group you can use something like :
def get_class(collection_prop: bpy.types.CollectionProperty) -> type:
holder_path = ".".join(repr(collection_prop).split(".")[:-1]) # Get the path to the prop and remove the last element
holder = eval(holder_path)
prop_name = repr(collection_prop).split(".")[-1]
return type(holder.bl_rna.properties.get(prop_name).fixed_type)
It's a bit more hacky but more extendable.