diff --git a/src/pyhpp/pinocchio/device.cc b/src/pyhpp/pinocchio/device.cc index f0689a8..1a68797 100644 --- a/src/pyhpp/pinocchio/device.cc +++ b/src/pyhpp/pinocchio/device.cc @@ -224,19 +224,71 @@ static JointIndex getParentJointId(const GripperPtr_t& gripper) { return model.frames[model.getFrameId(gripper->name())].parentJoint; } +// Class NameResult and NameDescriptor are temporary work-around to tranform +// getter "name" in class Gripper into a property and to warn users when they +// call the deprecated name method. +class NameResult { + public: + explicit NameResult(const std::string& name) : name_(name) {} + + std::string str() const { return name_; } + std::string call() const { + std::cerr + << "Calling pyhpp.pinocchio.Gripper.name() as a method is deprecated. " + "Use the 'name' property instead." + << std::endl; + return name_; + } + + private: + std::string name_; +}; + +// --- 2. Descriptor to handle both attribute access and calls --- +class NameDescriptor { + public: + explicit NameDescriptor(std::string (*getter)(const GripperPtr_t&)) + : getter_(getter) {} + + // Python descriptor protocol: __get__(self, instance, owner) + bp::object get(const bp::object& instance, + const bp::object& /*owner*/) const { + if (instance.is_none()) { + // Accessed via class (e.g., Gripper.name), not an instance + return bp::object(); + } + GripperPtr_t g = bp::extract(instance); + return bp::object(NameResult(getter_(g))); + } + + private: + std::string (*getter_)(const GripperPtr_t&); +}; + void exposeGripper() { + // Expose NameResult (callable + string-like) + bp::class_("NameResult", bp::no_init) + .def("__str__", &NameResult::str) + .def("__repr__", &NameResult::str) + .def("__call__", &NameResult::call); + + // Expose NameDescriptor + bp::class_("NameDescriptor", bp::no_init) + .def("__get__", &NameDescriptor::get); // DocClass(Gripper) - class_("Gripper", DocClassDoc(), no_init) - .add_property("localPosition", &getObjectPositionInJoint) + class_ gripper_class("Gripper", DocClassDoc(), + no_init); + gripper_class.add_property("localPosition", &getObjectPositionInJoint) .add_property( "clearance", static_cast(&Gripper::clearance), static_cast( &Gripper::clearance)) - .def("name", &getGripperName) .def("getParentJointId", &getParentJointId, "Get index of the joint the handle is attached to" " in pinocchio Model"); + // Add the 'name' descriptor + gripper_class.attr("name") = NameDescriptor(&getGripperName); class_ >("GripperMap") .def( boost::python::map_indexing_suite,