Medical Imaging Interaction Toolkit  2026.06.00
Medical Imaging Interaction Toolkit
PropertyOwnerBindings.h
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #ifndef PropertyOwnerBindings_h
14 #define PropertyOwnerBindings_h
15 
16 #include "PropertyAutoWrap.h"
18 #include "PropertyNotOwnedError.h"
19 #include <mitkIPropertyOwner.h>
20 #include <pybind11/pybind11.h>
21 
22 namespace py = pybind11;
23 
35 template <typename PyClass>
36 void bind_property_owner(PyClass &cls)
37 {
38  using CppClass = typename PyClass::type;
39 
40  cls.def(
41  "get_property",
42  [](const CppClass &obj, const std::string &key, bool raw) -> py::object
43  {
44  auto prop = obj.GetConstProperty(key);
45  if (!prop)
46  return py::none();
47  if (raw)
48  return py::cast(prop, py::return_value_policy::reference);
50  },
51  py::arg("key"),
52  py::arg("raw") = false,
53  R"(Return the property value for *key*, or ``None`` if not set.
54 
55 By default returns a coerced Python-native value: ``bool``, ``int``,
56 ``float``, ``str``, or an ``(r, g, b)`` tuple for ``ColorProperty``. For
57 types without a known Python equivalent the raw ``mitk.BaseProperty``
58 object is returned.
59 
60 Args:
61  key: Property name.
62  raw: If True, always return the underlying ``mitk.BaseProperty`` object
63  (useful to access metadata or to pass to a C++ function that
64  expects one). Defaults to False.
65 
66 Returns:
67  The property value, or ``None`` if the property is not set.
68 )");
69 
70  cls.def(
71  "property_is_owned",
72  [](const CppClass &obj, const std::string &key) -> bool { return obj.PropertyIsOwned(key); },
73  py::arg("key"),
74  R"(Return True if the property *key* is owned (writable) by this object.
75 
76 Returns False if the property does not exist or is provided read-only
77 (for example, routed from an internal component like a Label inside a
78 MultiLabelSegmentation).
79 
80 Args:
81  key: Property name.
82 )");
83 
84  cls.def(
85  "set_property",
86  [](CppClass &obj, const std::string &key, py::object value)
87  {
88  auto existing = obj.GetConstProperty(key);
89  if (existing && !obj.PropertyIsOwned(key))
90  {
91  throw PropertyNotOwnedError("Property '" + key +
92  "' is provided read-only by this object "
93  "and cannot be changed via set_property(). "
94  "It may be owned by an internal component "
95  "(e.g., a Label in a MultiLabelSegmentation).");
96  }
97  obj.SetProperty(key, resolvePropertyValue(obj, key, value));
98  },
99  py::arg("key"),
100  py::arg("value"),
101  R"(Set the property *key* to *value*.
102 
103 The value is auto-wrapped into the appropriate ``BaseProperty`` subtype
104 based on its Python type: ``bool`` -> ``BoolProperty``, ``int`` ->
105 ``IntProperty``, ``float`` -> ``DoubleProperty``, ``str`` ->
106 ``StringProperty``, 3-tuple -> ``ColorProperty``, or an existing
107 ``mitk.BaseProperty`` instance is used as-is.
108 
109 Args:
110  key: Property name.
111  value: Property value (auto-wrapped to a ``BaseProperty`` subtype).
112 
113 Raises:
114  PropertyNotOwnedError: If the property is provided read-only (not
115  owned) by this object.
116 )");
117 
118  cls.def(
119  "remove_property",
120  [](CppClass &obj, const std::string &key)
121  {
122  auto existing = obj.GetConstProperty(key);
123  if (existing && !obj.PropertyIsOwned(key))
124  {
125  throw PropertyNotOwnedError("Property '" + key +
126  "' is provided read-only by this object "
127  "and cannot be removed via remove_property().");
128  }
129  obj.RemoveProperty(key);
130  },
131  py::arg("key"),
132  R"(Remove the property *key* if it exists.
133 
134 Args:
135  key: Property name.
136 
137 Raises:
138  PropertyNotOwnedError: If the property is provided read-only and
139  cannot be removed.
140 )");
141 
142  cls.def_property_readonly("property_keys",
143  [](const CppClass &obj)
144  {
145  auto keys = obj.GetPropertyKeys();
146  return std::vector<std::string>(keys.begin(), keys.end());
147  },
148  "List of all property keys currently set on this object.");
149 }
150 
151 #endif
mitk::BaseProperty::Pointer resolvePropertyValue(mitk::IPropertyOwner &owner, const std::string &key, py::object value)
Resolves a Python value to a BaseProperty, respecting any existing property's type.
Centralized property conversion utilities for Python bindings.
void bind_property_owner(PyClass &cls)
Binds IPropertyOwner methods to a Python class.
Thrown when a write operation targets a property that is provided read-only (not owned) by the surrou...
py::object propertyToPythonValue(const mitk::BaseProperty &prop)
Converts a BaseProperty to its Python native value.