Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

--[BE] Fix issues with bindings exposed by pybind11-stubgen #2430

Merged
merged 16 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
386 changes: 221 additions & 165 deletions src/esp/bindings/AttributesBindings.cpp

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/esp/bindings/AttributesManagersBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "esp/metadata/attributes/AbstractObjectAttributes.h"
#include "esp/metadata/attributes/LightLayoutAttributes.h"
#include "esp/metadata/attributes/ObjectAttributes.h"
#include "esp/metadata/attributes/SemanticAttributes.h"
#include "esp/metadata/attributes/StageAttributes.h"

#include "esp/metadata/managers/AOAttributesManager.h"
Expand Down Expand Up @@ -416,8 +417,8 @@ void initAttributesManagersBindings(py::module& m) {

// ==== Light Layout Attributes Template manager ====
declareBaseAttributesManager<LightLayoutAttributes,
ManagedObjectAccess::Copy>(m, "LightLayout",
"BaseLightLayout");
ManagedObjectAccess::Copy>(
m, "LightLayoutAttributes", "BaseLightLayout");
// NOLINTNEXTLINE(bugprone-unused-raii)
py::class_<
LightLayoutAttributesManager,
Expand Down
174 changes: 98 additions & 76 deletions src/esp/bindings/ConfigBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,68 @@ py::object getObjectForConfigValue(const ConfigValue& value) {
return py::cast(nullptr);
}

template <class T>
void declareSetter(
pybind11::class_<esp::core::config::Configuration,
esp::core::config::Configuration::ptr>& pyAbsAttr,
const std::string& typeName) {
pyAbsAttr.def(
"set",
[](Configuration& self, const std::string& key, const T val) {
self.set(key, val);
},
("Set the value specified by given string key to be specified " +
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this actually works, as far as I remember the reason def() accepted a plain const char* was because it just referenced it without actually copying anywhere. So when retrieving documentation of those, you'll get a crash due to a dangling pointer.

I might be wrong, but I personally hope it's not doing a string copy for every docstring. That'd be nasty.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mosra The __init__.pyi has an appropriate doc string listed :

    @typing.overload
    def set(self, key: str, value: str) -> None:
        """
        Set the value specified by given string key to be specified string value
        """

Would the problem be somewhere else?

__init__.pyi also has duplicate entries for the const char* and const str& versions. I going to get rid of the const char* specializations.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, alright, then it works. I wasn't sure.

typeName + " value")
.c_str(),
"key"_a, "value"_a);
} // declareSetter

void declareSetter(
pybind11::class_<esp::core::config::Configuration,
esp::core::config::Configuration::ptr>& pyAbsAttr,
const std::string& typeName) {
pyAbsAttr.def(
"set",
[](Configuration& self, const std::string& key, const char* val) {
self.set(key, val);
},
("Set the value specified by given string key to be specified " +
typeName + " value")
.c_str(),
"key"_a, "value"_a);
} // declareSetter

template <class T>
void declareInitializer(
pybind11::class_<esp::core::config::Configuration,
esp::core::config::Configuration::ptr>& pyAbsAttr,
const std::string& typeName) {
pyAbsAttr.def(
"set",
[](Configuration& self, const std::string& key, const T val) {
self.init(key, val);
},
("Initialize the value specified by given string key to be specified " +
typeName + " value")
.c_str(),
"key"_a, "value"_a);
} // declareInitializer

void declareInitializer(
pybind11::class_<esp::core::config::Configuration,
esp::core::config::Configuration::ptr>& pyAbsAttr,
const std::string& typeName) {
pyAbsAttr.def(
"set",
[](Configuration& self, const std::string& key, const char* val) {
self.init(key, val);
},
("Initialize the value specified by given string key to be specified " +
typeName + " value")
.c_str(),
"key"_a, "value"_a);
} // declareInitializer

void initConfigBindings(py::module& m) {
py::enum_<ConfigValType>(m, "ConfigValType")
.value("Unknown", ConfigValType::Unknown)
Expand All @@ -57,8 +119,10 @@ void initConfigBindings(py::module& m) {
.value("MagnumQuat", ConfigValType::MagnumQuat)
.value("MagnumRad", ConfigValType::MagnumRad);

py::class_<Configuration, Configuration::ptr>(m, "Configuration")
.def(py::init(&Configuration::create<>))
auto pyConfiguration =
py::class_<Configuration, Configuration::ptr>(m, "Configuration");
pyConfiguration.def(py::init(&Configuration::create<>))
.def("__repr__", &Configuration::getAllValsAsString, "new_line"_a = "\n")
.def_property_readonly(
"top_level_num_entries", &Configuration::getNumEntries,
R"(Holds the total number of values and subconfigs this Configuration holds
Expand Down Expand Up @@ -89,77 +153,6 @@ void initConfigBindings(py::module& m) {
return getObjectForConfigValue(self.get(key));
},
R"(Retrieve the requested value referenced by key argument, if it exists)")

.def(
"set",
[](Configuration& self, const std::string& key,
const std::string& val) { self.set(key, val); },
R"(Set the value specified by given string key to be specified string value)",
"key"_a, "value"_a)
.def(
"set",
[](Configuration& self, const std::string& key, const char* val) {
self.set(key, val);
},
R"(Set the value specified by given string key to be specified string value)",
"key"_a, "value"_a)
.def(
"set",
[](Configuration& self, const std::string& key, const bool val) {
self.set(key, val);
},
R"(Set the value specified by given string key to be specified boolean value)",
"key"_a, "value"_a)
.def(
"set",
[](Configuration& self, const std::string& key, const int val) {
self.set(key, val);
},
R"(Set the value specified by given string key to be specified integer value)",
"key"_a, "value"_a)
.def(
"set",
[](Configuration& self, const std::string& key, const double val) {
self.set(key, val);
},
R"(Set the value specified by given string key to be specified double value)",
"key"_a, "value"_a)
.def(
"set",
[](Configuration& self, const std::string& key,
const Magnum::Quaternion& val) { self.set(key, val); },
R"(Set the value specified by given string key to be specified Magnum::Quaternion value)",
"key"_a, "value"_a)
.def(
"set",
[](Configuration& self, const std::string& key,
const Magnum::Vector2& val) { self.set(key, val); },
R"(Set the value specified by given string key to be specified Magnum::Vector2 value)",
"key"_a, "value"_a)
.def(
"set",
[](Configuration& self, const std::string& key,
const Magnum::Vector3& val) { self.set(key, val); },
R"(Set the value specified by given string key to be specified Magnum::Vector3 value)",
"key"_a, "value"_a)
.def(
"set",
[](Configuration& self, const std::string& key,
const Magnum::Vector4& val) { self.set(key, val); },
R"(Set the value specified by given string key to be specified Magnum::Vector4 value)",
"key"_a, "value"_a)
.def(
"set",
[](Configuration& self, const std::string& key,
const Magnum::Matrix3& val) { self.set(key, val); },
R"(Set the value specified by given string key to be specified Magnum::Matrix3 value)",
"key"_a, "value"_a)
.def(
"set",
[](Configuration& self, const std::string& key,
const Magnum::Matrix4& val) { self.set(key, val); },
R"(Set the value specified by given string key to be specified Magnum::Matrix4 value)",
"key"_a, "value"_a)
.def(
"get_type", &Configuration::getType,
R"(Retrieves the ConfigValType of the value referred to by the passed key.)")
Expand Down Expand Up @@ -222,9 +215,38 @@ void initConfigBindings(py::module& m) {
R"(Returns true if specified key references an existing subconfiguration within this configuration.)")
.def(
"remove_subconfig", &Configuration::removeSubconfig,
R"(Removes and returns subconfiguration corresponding to passed key, if found. Gives warning otherwise.)")
.def("__repr__", &Configuration::getAllValsAsString, "new_line"_a = "\n");

R"(Removes and returns subconfiguration corresponding to passed key, if found. Gives warning otherwise.)");
// Setter bindings
declareSetter(pyConfiguration, "string"); // char *
declareSetter<std::string&>(pyConfiguration, "string");
declareSetter<bool>(pyConfiguration, "boolean");
declareSetter<int>(pyConfiguration, "integer");
declareSetter<double>(pyConfiguration, "floating-point");
declareSetter<Magnum::Vector2&>(pyConfiguration, "Magnum::Vector2");
declareSetter<Magnum::Vector3&>(pyConfiguration, "Magnum::Vector3");
declareSetter<Magnum::Vector4&>(pyConfiguration, "Magnum::Vector4");
declareSetter<Magnum::Color4&>(pyConfiguration, "Magnum::Color4");
declareSetter<Magnum::Quaternion&>(pyConfiguration, "Magnum::Quaternion");
declareSetter<Magnum::Matrix3&>(pyConfiguration, "Magnum::Matrix3");
declareSetter<Magnum::Matrix4&>(pyConfiguration, "Magnum::Matrix4");
declareSetter<Magnum::Rad&>(pyConfiguration, "Magnum::Rad");
// Initializer bindings
// Initializers are like setters but the value specified will not be
// automatically saved to file unless it is changed.
declareInitializer(pyConfiguration, "string"); // char *
declareInitializer<std::string&>(pyConfiguration, "string");
declareInitializer<bool>(pyConfiguration, "boolean");
declareInitializer<int>(pyConfiguration, "integer");
declareInitializer<double>(pyConfiguration, "floating-point");
declareInitializer<Magnum::Vector2&>(pyConfiguration, "Magnum::Vector2");
declareInitializer<Magnum::Vector3&>(pyConfiguration, "Magnum::Vector3");
declareInitializer<Magnum::Vector4&>(pyConfiguration, "Magnum::Vector4");
declareInitializer<Magnum::Color4&>(pyConfiguration, "Magnum::Color4");
declareInitializer<Magnum::Quaternion&>(pyConfiguration,
"Magnum::Quaternion");
declareInitializer<Magnum::Matrix3&>(pyConfiguration, "Magnum::Matrix3");
declareInitializer<Magnum::Matrix4&>(pyConfiguration, "Magnum::Matrix4");
declareInitializer<Magnum::Rad&>(pyConfiguration, "Magnum::Rad");
} // initConfigBindings

} // namespace config
Expand Down
9 changes: 9 additions & 0 deletions src/esp/bindings/MetadataMediatorBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@
namespace py = pybind11;
using py::literals::operator""_a;

namespace AttrMgrs = esp::metadata::managers;

using AttrMgrs::AOAttributesManager;
using AttrMgrs::AssetAttributesManager;
using AttrMgrs::LightLayoutAttributesManager;
using AttrMgrs::ObjectAttributesManager;
using AttrMgrs::PhysicsAttributesManager;
using AttrMgrs::StageAttributesManager;

namespace esp {
namespace metadata {

Expand Down
24 changes: 12 additions & 12 deletions src/esp/bindings/SensorBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,18 @@ void initSensorBindings(py::module& m) {
.def("delete_sensor", &SensorFactory::deleteSensor)
.def("delete_subtree_sensor", &SensorFactory::deleteSubtreeSensor);

// ==== Sensor ====
py::class_<Sensor, Magnum::SceneGraph::PyFeature<Sensor>,
Magnum::SceneGraph::AbstractFeature3D,
Magnum::SceneGraph::PyFeatureHolder<Sensor>>(m, "Sensor")
.def("specification", &Sensor::specification)
.def("set_transformation_from_spec", &Sensor::setTransformationFromSpec)
.def("is_visual_sensor", &Sensor::isVisualSensor)
.def("get_observation", &Sensor::getObservation)
.def_property_readonly("node", nodeGetter<Sensor>,
"Node this object is attached to")
.def_property_readonly("object", nodeGetter<Sensor>, "Alias to node");

// ==== SensorSuite ====
py::class_<SensorSuite, Magnum::SceneGraph::PyFeature<SensorSuite>,
Magnum::SceneGraph::AbstractFeature3D,
Expand All @@ -185,18 +197,6 @@ void initSensorBindings(py::module& m) {
"Node this object is attached to")
.def_property_readonly("object", nodeGetter<Sensor>, "Alias to node");

// ==== Sensor ====
py::class_<Sensor, Magnum::SceneGraph::PyFeature<Sensor>,
Magnum::SceneGraph::AbstractFeature3D,
Magnum::SceneGraph::PyFeatureHolder<Sensor>>(m, "Sensor")
.def("specification", &Sensor::specification)
.def("set_transformation_from_spec", &Sensor::setTransformationFromSpec)
.def("is_visual_sensor", &Sensor::isVisualSensor)
.def("get_observation", &Sensor::getObservation)
.def_property_readonly("node", nodeGetter<Sensor>,
"Node this object is attached to")
.def_property_readonly("object", nodeGetter<Sensor>, "Alias to node");

// ==== VisualSensor ====
py::class_<VisualSensor, Magnum::SceneGraph::PyFeature<VisualSensor>, Sensor,
Magnum::SceneGraph::PyFeatureHolder<VisualSensor>>(m,
Expand Down
19 changes: 11 additions & 8 deletions src/esp/metadata/attributes/LightLayoutAttributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,15 @@ class LightInstanceAttributes : public AbstractAttributes {

/**
* @brief Gets a smart pointer reference to a copy of the spotlight
* configuration data for this light instance.
* configuration data for this @ref LightInstanceAttributes.
*/
std::shared_ptr<Configuration> getSpotlightConfiguration() const {
return getSubconfigCopy<Configuration>("spot");
}

/**
* @brief Gets a smart pointer reference to the actual spotlight
* configuration data for this light instance.
* configuration data for this @ref LightInstanceAttributes.
*/
std::shared_ptr<Configuration> editSpotlightConfiguration() {
return editSubconfig<Configuration>("spot");
Expand Down Expand Up @@ -248,28 +248,31 @@ class LightLayoutAttributes : public AbstractAttributes {
}

/**
* @brief Add a light instance to this lighting layout
* @brief Add a @ref LightInstanceAttributes to this lighting layout
*/
void addLightInstance(LightInstanceAttributes::ptr _lightInstance) {
this->setSubAttributesInternal<LightInstanceAttributes>(
_lightInstance, availableLightIDs_, lightInstConfig_, "");
}

/**
* @brief Remove a light from this lighting layout
* @brief Remove a named @ref LightInstanceAttributes from this lighting layout
*/
LightInstanceAttributes::ptr removeLightInstance(const std::string& handle) {
return this->removeNamedSubAttributesInternal<LightInstanceAttributes>(
handle, availableLightIDs_, lightInstConfig_);
}

/**
* @brief Retrieve a reference to the named @ref LightInstanceAttributes
*/
LightInstanceAttributes::cptr getLightInstance(const std::string& handle) {
return getNamedSubAttributesInternal<LightInstanceAttributes>(
handle, lightInstConfig_);
}

/**
* @brief Get the lighting instances for this layout
* @brief Get all the @ref LightInstanceAttributes for this layout
*/
std::vector<LightInstanceAttributes::cptr> getLightInstances() const {
return this->getSubAttributesListInternal<LightInstanceAttributes>(
Expand All @@ -278,7 +281,7 @@ class LightLayoutAttributes : public AbstractAttributes {

/**
* @brief Return how many lights are in this light layout - number of
* subconfigs in @ref lightInstConfig_ subconfig.
* @ref LightInstanceAttributes in @ref lightInstConfig_ subconfig.
*/
int getNumLightInstances() const {
return this->getNumSubAttributesInternal("", lightInstConfig_);
Expand Down Expand Up @@ -307,13 +310,13 @@ class LightLayoutAttributes : public AbstractAttributes {
std::string getObjectInfoInternal() const override;

/**
* @brief Smartpointer to created light instance configuration. The
* @brief Smartpointer to created @ref LightInstanceAttributes configuration. The
* configuration is created on LightLayoutAttributes construction.
*/
std::shared_ptr<Configuration> lightInstConfig_{};

/**
* @brief Deque holding all released IDs to consume for light instances when
* @brief Deque holding all released IDs to consume for @ref LightInstanceAttributess when
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: LightInstanceAttributess

* one is deleted, before using size of lightInstances_ container.
*/
std::deque<int> availableLightIDs_;
Expand Down
10 changes: 5 additions & 5 deletions src/esp/metadata/attributes/SemanticAttributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class SemanticVolumeAttributes : public AbstractAttributes {
*/
class SemanticAttributes : public AbstractAttributes {
public:
explicit SemanticAttributes(const std::string& handle);
explicit SemanticAttributes(const std::string& handle = "");

SemanticAttributes(const SemanticAttributes& otr);
SemanticAttributes(SemanticAttributes&& otr) noexcept;
Expand Down Expand Up @@ -356,16 +356,16 @@ class SemanticAttributes : public AbstractAttributes {
}

/**
* @brief Set whether or not the semantic asset for this stage supports
* texture semantics.
* @brief Set whether or not the semantic asset described by this attributes
* supports texture semantics.
*/
void setHasSemanticTextures(bool hasSemanticTextures) {
set("has_semantic_textures", hasSemanticTextures);
}

/**
* @brief Get whether or not the semantic asset for this stage supports
* texture semantics.
* @brief Get whether or not the semantic asset described by this attributes
* supports texture semantics.
*/
bool getHasSemanticTextures() const {
return get<bool>("has_semantic_textures");
Expand Down
Loading