Skip to content

Commit

Permalink
Added PYMATERIALX_DOCSTRING macro to erase the first newline character
Browse files Browse the repository at this point in the history
from docstrings.

This allows us to start docstrings on a new line, while keeping the help
text that `help()` in a `python` session provides clean.

Also added docstrings to a couple more functions.

Signed-off-by: Stefan Habel <19556655+StefanHabel@users.noreply.github.com>
  • Loading branch information
StefanHabel committed Oct 20, 2023
1 parent ab6860b commit 26a972f
Show file tree
Hide file tree
Showing 63 changed files with 527 additions and 382 deletions.
11 changes: 9 additions & 2 deletions source/PyMaterialX/PyMaterialX.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
#define MATERIALX_PYMATERIALX_H

//
// This header is used to include PyBind11 headers consistently across the
// This header is used to include pybind11 headers consistently across the
// translation units in the PyMaterialX library, and it should be the first
// include within any PyMaterialX source file.
//

// Set a flag to allow PyBind11 to provide more helpful error messages
// Set a flag to allow pybind11 to provide more helpful error messages
// (see `pybind11/detail/common.h`)
#define PYBIND11_DETAILED_ERROR_MESSAGES 1

#include <pybind11/functional.h>
Expand All @@ -30,4 +31,10 @@
pybind11::module::import(#MODULE_NAME); \
}

// Define a macro to process a block of docstring text
// (currently, we strip the first character from the given text, so that we can
// write the first line of the docstring on a new line, rather than on the same
// line that starts the docstring)
#define PYMATERIALX_DOCSTRING(TEXT) std::string(TEXT).erase(0, 1).c_str()

#endif
36 changes: 18 additions & 18 deletions source/PyMaterialX/PyMaterialXCore/PyDefinition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ void bindPyDefinition(py::module& mod)
.def_readonly_static("ADJUSTMENT_NODE_GROUP", &mx::NodeDef::ADJUSTMENT_NODE_GROUP)
.def_readonly_static("CONDITIONAL_NODE_GROUP", &mx::NodeDef::CONDITIONAL_NODE_GROUP)
.def_readonly_static("ORGANIZATION_NODE_GROUP", &mx::NodeDef::ORGANIZATION_NODE_GROUP)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing a node definition element within a `Document`.
A `NodeDef` provides the declaration of a node interface, which may then
be instantiated as a `Node`.
:see: https://materialx.org/docs/api/class_node_def.html
)docstring";
)docstring");

py::class_<mx::Implementation, mx::ImplementationPtr, mx::InterfaceElement>(mod, "Implementation")
.def("setFile", &mx::Implementation::setFile)
Expand All @@ -57,15 +57,15 @@ void bindPyDefinition(py::module& mod)
.def_readonly_static("CATEGORY", &mx::Implementation::CATEGORY)
.def_readonly_static("FILE_ATTRIBUTE", &mx::Implementation::FILE_ATTRIBUTE)
.def_readonly_static("FUNCTION_ATTRIBUTE", &mx::Implementation::FUNCTION_ATTRIBUTE)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing an implementation element within a `Document`.
An `Implementation` is used to associate external source code with a specific
`NodeDef`, providing a definition for the node that may either be universal or
restricted to a specific target.
:see: https://materialx.org/docs/api/class_implementation.html
)docstring";
)docstring");

py::class_<mx::TypeDef, mx::TypeDefPtr, mx::Element>(mod, "TypeDef")
.def("setSemantic", &mx::TypeDef::setSemantic)
Expand All @@ -82,27 +82,27 @@ void bindPyDefinition(py::module& mod)
.def_readonly_static("CATEGORY", &mx::TypeDef::CATEGORY)
.def_readonly_static("SEMANTIC_ATTRIBUTE", &mx::TypeDef::SEMANTIC_ATTRIBUTE)
.def_readonly_static("CONTEXT_ATTRIBUTE", &mx::TypeDef::CONTEXT_ATTRIBUTE)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing a type definition element within a `Document`.
:see: https://materialx.org/docs/api/class_type_def.html
)docstring";
)docstring");

py::class_<mx::Member, mx::MemberPtr, mx::TypedElement>(mod, "Member")
.def_readonly_static("CATEGORY", &mx::TypeDef::CATEGORY)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing a member element within a `TypeDef`.
:see: https://materialx.org/docs/api/class_member.html
)docstring";
)docstring");

py::class_<mx::Unit, mx::UnitPtr, mx::Element>(mod, "Unit")
.def_readonly_static("CATEGORY", &mx::Unit::CATEGORY)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing a unit declaration element within a `UnitDef`.
:see: https://materialx.org/docs/api/class_unit.html
)docstring";
)docstring");

py::class_<mx::UnitDef, mx::UnitDefPtr, mx::Element>(mod, "UnitDef")
.def("setUnitType", &mx::UnitDef::hasUnitType)
Expand All @@ -113,20 +113,20 @@ void bindPyDefinition(py::module& mod)
.def("getUnits", &mx::UnitDef::getUnits)
.def_readonly_static("CATEGORY", &mx::UnitDef::CATEGORY)
.def_readonly_static("UNITTYPE_ATTRIBUTE", &mx::UnitDef::UNITTYPE_ATTRIBUTE)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing a unit definition element within a `Document`.
:see: https://materialx.org/docs/api/class_unit_def.html
)docstring";
)docstring");

py::class_<mx::UnitTypeDef, mx::UnitTypeDefPtr, mx::Element>(mod, "UnitTypeDef")
.def("getUnitDefs", &mx::UnitTypeDef::getUnitDefs)
.def_readonly_static("CATEGORY", &mx::UnitTypeDef::CATEGORY)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing a unit type definition element within a `Document`.
:see: https://materialx.org/docs/api/class_unit_type_def.html
)docstring";
)docstring");

py::class_<mx::AttributeDef, mx::AttributeDefPtr, mx::TypedElement>(mod, "AttributeDef")
.def("setAttrName", &mx::AttributeDef::setAttrName)
Expand All @@ -138,18 +138,18 @@ void bindPyDefinition(py::module& mod)
.def("setExportable", &mx::AttributeDef::setExportable)
.def("getExportable", &mx::AttributeDef::getExportable)
.def_readonly_static("CATEGORY", &mx::AttributeDef::CATEGORY)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing an attribute definition element within a `Document`.
:see: https://materialx.org/docs/api/class_attribute_def.html
)docstring";
)docstring");

py::class_<mx::TargetDef, mx::TargetDefPtr, mx::TypedElement>(mod, "TargetDef")
.def("getMatchingTargets", &mx::TargetDef::getMatchingTargets)
.def_readonly_static("CATEGORY", &mx::TargetDef::CATEGORY)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing the definition of an implementation target as a `TypedElement`.
:see: https://materialx.org/docs/api/class_target_def.html
)docstring";
)docstring");
}
4 changes: 2 additions & 2 deletions source/PyMaterialX/PyMaterialXCore/PyDocument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ namespace mx = MaterialX;
void bindPyDocument(py::module& mod)
{
mod.def("createDocument", &mx::createDocument,
R"docstring(
PYMATERIALX_DOCSTRING(R"docstring(
Create a MaterialX `Document` instance, which represents the top-level
element in the MaterialX ownership hierarchy.
)docstring");
)docstring"));

py::class_<mx::Document, mx::DocumentPtr, mx::GraphElement>(mod, "Document")
.def("initialize", &mx::Document::initialize)
Expand Down
55 changes: 29 additions & 26 deletions source/PyMaterialX/PyMaterialXCore/PyElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,10 @@ void bindPyElement(py::module& mod)
.def("createStringResolver", &mx::Element::createStringResolver,
py::arg("geom") = mx::EMPTY_STRING)
.def("asString", &mx::Element::asString,
"Return a single-line description of this element, including its "
"category, name, and attributes.")
PYMATERIALX_DOCSTRING(R"docstring(
Return a single-line description of this element, including its category,
name, and attributes.
)docstring"))
.def("__str__", &mx::Element::asString)

BIND_ELEMENT_FUNC_INSTANCE(Collection)
Expand All @@ -123,14 +125,14 @@ void bindPyElement(py::module& mod)
BIND_ELEMENT_FUNC_INSTANCE(TypeDef)
BIND_ELEMENT_FUNC_INSTANCE(Visibility)

.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Base class for MaterialX elements.
An `Element` is a named object within a `Document`, which may possess any
number of child elements and attributes.
:see: https://materialx.org/docs/api/class_element.html
)docstring";
)docstring");

py::class_<mx::TypedElement, mx::TypedElementPtr, mx::Element>(mod, "TypedElement")
.def("setType", &mx::TypedElement::setType)
Expand All @@ -139,11 +141,11 @@ void bindPyElement(py::module& mod)
.def("isMultiOutputType", &mx::TypedElement::isMultiOutputType)
.def("getTypeDef", &mx::TypedElement::getTypeDef)
.def_readonly_static("TYPE_ATTRIBUTE", &mx::TypedElement::TYPE_ATTRIBUTE)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Base class for typed elements.
:see: https://materialx.org/docs/api/class_typed_element.html
)docstring";
)docstring");

py::class_<mx::ValueElement, mx::ValueElementPtr, mx::TypedElement>(mod, "ValueElement")
.def("setValueString", &mx::ValueElement::setValueString)
Expand Down Expand Up @@ -200,51 +202,51 @@ void bindPyElement(py::module& mod)
BIND_VALUE_ELEMENT_FUNC_INSTANCE(floatarray, mx::FloatVec)
BIND_VALUE_ELEMENT_FUNC_INSTANCE(stringarray, mx::StringVec)

.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Base class for elements that support typed values.
:see: https://materialx.org/docs/api/class_value_element.html
)docstring";
)docstring");

py::class_<mx::Token, mx::TokenPtr, mx::ValueElement>(mod, "Token")
.def_readonly_static("CATEGORY", &mx::Token::CATEGORY)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
A token element representing a string value.
Token elements are used to define input and output values for string
substitutions in image filenames.
:see: https://materialx.org/docs/api/class_token.html
)docstring";
)docstring");

py::class_<mx::CommentElement, mx::CommentElementPtr, mx::Element>(mod, "CommentElement")
.def_readonly_static("CATEGORY", &mx::CommentElement::CATEGORY)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing a block of descriptive text within a `Document`,
which will be stored a comment when the document is written out.
The comment text may be accessed with the methods `Element.getDocString()`
and `Element.setDocString()`.
:see: https://materialx.org/docs/api/class_comment_element.html
)docstring";
)docstring");

py::class_<mx::NewlineElement, mx::NewlineElementPtr, mx::Element>(mod, "NewlineElement")
.def_readonly_static("CATEGORY", &mx::NewlineElement::CATEGORY)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing a newline within a `Document`.
:see: https://materialx.org/docs/api/class_newline_element.html
)docstring";
)docstring");

py::class_<mx::GenericElement, mx::GenericElementPtr, mx::Element>(mod, "GenericElement")
.def_readonly_static("CATEGORY", &mx::GenericElement::CATEGORY)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
A generic element subclass, for instantiating elements with unrecognized
categories.
:see: https://materialx.org/docs/api/class_generic_element.html
)docstring";
)docstring");

py::class_<mx::StringResolver, mx::StringResolverPtr>(mod, "StringResolver")
.def("setFilePrefix", &mx::StringResolver::setFilePrefix)
Expand All @@ -258,7 +260,7 @@ void bindPyElement(py::module& mod)
.def("setGeomNameSubstitution", &mx::StringResolver::setGeomNameSubstitution)
.def("getGeomNameSubstitutions", &mx::StringResolver::getGeomNameSubstitutions)
.def("resolve", &mx::StringResolver::resolve)
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
A helper class for applying string modifiers to data values in the context
of a specific element and geometry.
Expand All @@ -273,35 +275,36 @@ void bindPyElement(py::module& mod)
stored string modifiers before calling `StringResolver.resolve()`.
:see: https://materialx.org/docs/api/class_string_resolver.html
)docstring";
)docstring");

py::class_<mx::ElementPredicate>(mod, "ElementPredicate")
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
Class representing a function that takes an `Element` and returns a `bool`,
to check whether some criteria has passed.
)docstring";
)docstring");

py::register_exception<mx::ExceptionOrphanedElement>(mod, "ExceptionOrphanedElement")
.doc() = R"docstring(
.doc() = PYMATERIALX_DOCSTRING(R"docstring(
A type of exception that is raised when an `Element` is used after its owning
`Document` has gone out of scope.
:see: https://materialx.org/docs/api/class_exception_orphaned_element.html
)docstring";
)docstring");

mod.def("targetStringsMatch", &mx::targetStringsMatch,
py::arg("target1"),
py::arg("target2"),
R"docstring(
PYMATERIALX_DOCSTRING(R"docstring(
Given two target strings, each containing a string array of target names,
return `True` if they have any targets in common.
An empty target string matches all targets.
)docstring");
)docstring"));

mod.def("prettyPrint", &mx::prettyPrint,
py::arg("element"),
R"docstring(
PYMATERIALX_DOCSTRING(R"docstring(
Pretty-print the given `element` tree, calling `Element.asString()`
recursively on each element in depth-first order.
)docstring");
)docstring"));
}
4 changes: 2 additions & 2 deletions source/PyMaterialX/PyMaterialXCore/PyException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ namespace mx = MaterialX;
void bindPyException(py::module& mod)
{
static py::exception<mx::Exception> pyException(mod, "Exception");
pyException.doc() = R"docstring(
pyException.doc() = PYMATERIALX_DOCSTRING(R"docstring(
The base class for exceptions that are propagated from the MaterialX library
to the client application.
:see: https://materialx.org/docs/api/class_exception.html
)docstring";
)docstring");

py::register_exception_translator(
[](std::exception_ptr errPtr)
Expand Down
Loading

0 comments on commit 26a972f

Please sign in to comment.