Skip to content

Commit

Permalink
Implement MDGModifier::renameAttribute binding
Browse files Browse the repository at this point in the history
  • Loading branch information
yantor3d committed Jun 6, 2021
1 parent 18dca1a commit 79f223a
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 3 deletions.
34 changes: 32 additions & 2 deletions src/MDGModifier.inl
Original file line number Diff line number Diff line change
Expand Up @@ -472,8 +472,38 @@ There should be no function sets attached to the attribute at the time of the ca
throw std::logic_error{"Function not yet implemented."};
}, R"pbdoc(Adds an operation to the modifier to remove an element of a multi (array) plug.)pbdoc")

.def("renameAttribute", [](MDGModifier & self, MObject node, MObject attribute, MString shortName, MString longName) {
throw std::logic_error{"Function not yet implemented."};
.def("renameAttribute", [](MDGModifier & self, MObject node, MObject attribute, std::string shortName, std::string longName) {
if (node.isNull())
{
throw std::invalid_argument("Cannot rename an attribute from a null node.");
} else if (!node.hasFn(MFn::kDependencyNode)) {
MString error_msg("Cannot rename attribute - node must be a 'node' object , not a '^1s' object.");
error_msg.format(error_msg, node.apiTypeStr());
throw pybind11::type_error(error_msg.asChar());
}

if (attribute.isNull())
{
throw std::invalid_argument("Cannot rename a null attribute.");
} else if (!attribute.hasFn(MFn::kAttribute)) {
MString error_msg("Cannot rename attribute - 'attribute' must be a 'kAttribute' object, not a(n) '^1s' object.");
error_msg.format(error_msg, attribute.apiTypeStr());
throw pybind11::type_error(error_msg.asChar());
}

if (shortName.empty() || longName.empty())
{
throw std::invalid_argument("Cannot rename an attribute to an empty string.");
}

// TODO: When MFnAttribute is implement, raise a TypeError if `attribute` is not dynamic.
// TODO: Regex to restrict names to [a-zA-Z0-9_]?
// TODO: Do short/long name have length constraints?

MStatus status = self.renameAttribute(node, attribute, MString(shortName.c_str()), MString(longName.c_str()));

CHECK_STATUS(status)

}, R"pbdoc(Adds an operation to the modifer that renames a dynamic attribute on the given dependency node.)pbdoc")

.def("renameNode", [](MDGModifier & self, MObject node, std::string newName) {
Expand Down
56 changes: 55 additions & 1 deletion tests/test_MDGModifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ def test_removeAttribute_fail():
[TypeError, "a non-node object", (plug.attribute(), null)],
[TypeError, "a non-attribute object", (plug.node(), plug.node())],
):
test_removeAttribute_fail.__doc__ = """Test MDGModifier::removeAttribute raises an error if with {}.""".format(doc)
test_removeAttribute_fail.__doc__ = """Test MDGModifier::removeAttribute raises an error if called with {}.""".format(doc)

yield _removeAttribute_fail, exc, node, attr

Expand All @@ -398,6 +398,60 @@ def test_removeExtensionAttribute_pass():



@nose.with_setup(teardown=new_scene)
def test_renameAttribute():
"""Test MDGModfifier::renameAttribute binding."""

node = cmds.createNode('network')

cmds.addAttr(node, ln='fizz')

plug = as_plug(node + '.fizz')

node_obj = plug.node()
attr_obj = plug.attribute()
null_obj = cmdc.Object()

mod = cmdc.DGModifier()
mod.renameAttribute(node_obj, attr_obj, 'buzz', 'buzz')

mod.doIt()
assert plug.name() == node + '.buzz', 'DGModifier.renameAttribute doIt failed'

mod.undoIt()
assert plug.name() == node + '.fizz', 'DGModifier.renameAttribute undo failed'


@nose.with_setup(teardown=new_scene)
def test_renameAttribute_fail():
"""Test MDGModfifier::renameAttribute binding error handling."""

node = cmds.createNode('network')
cmds.addAttr(node, ln='fizz')
plug = as_plug(node + '.fizz')

node_obj = plug.node()
attr_obj = plug.attribute()
null_obj = cmdc.Object()

for exception, doc, (node, attr, short_name, long_name) in (
[ValueError, "a null node", (null_obj, attr_obj, '', '')],
[ValueError, "a null attribute", (node_obj, null_obj, '', '')],
[ValueError, "an empty short name", (node_obj, attr_obj, '', '')],
[ValueError, "an empty long name", (node_obj, attr_obj, 'buzz', '')],
):
test_renameAttribute_fail.__doc__ = """Test MDGModifier::renameAttribute raises an error if called with {}.""".format(doc)
yield _renameAttribute_fail, exception, node, attr, short_name, long_name


def _renameAttribute_fail(exception, node_obj, attr_obj, short_name, long_name):
nose.tools.assert_raises(
exception,
cmdc.DGModifier().renameAttribute,
node_obj, attr_obj, short_name, long_name
)


@nose.with_setup(teardown=new_scene)
def test_renameNode():
"""Test MDGModfifier::renameNode binding."""
Expand Down

0 comments on commit 79f223a

Please sign in to comment.