diff --git a/cmdx.py b/cmdx.py index d592474..024829b 100644 --- a/cmdx.py +++ b/cmdx.py @@ -512,6 +512,8 @@ class Node(object): >>> transform["tx"] = 5 >>> transform["worldMatrix"][0] >> decompose["inputMatrix"] >>> decompose["outputTranslate"] + cmdx.Plug("decompose", "outputTranslate") == (5.0, 0.0, 0.0) + >>> decompose["outputTranslate"].read() (5.0, 0.0, 0.0) """ @@ -548,7 +550,8 @@ def __str__(self): return self.name(namespace=True) def __repr__(self): - return self.name(namespace=True) + cls_name = '{}.{}'.format(__name__, self.__class__.__name__) + return '{}("{}")'.format(cls_name, self.name(namespace=True)) def __add__(self, other): """Support legacy + '.attr' behavior @@ -576,9 +579,12 @@ def __getitem__(self, key): optionally pass tuple to include unit. Example: + >>> _new() >>> node = createNode("transform") >>> node["translate"] = (1, 1, 1) >>> node["translate", Meters] + cmdx.Plug("transform1", "translate") == (0.01, 0.01, 0.01) + >>> node["translate", Meters].read() (0.01, 0.01, 0.01) """ @@ -625,6 +631,8 @@ def __setitem__(self, key, value): >>> node["rotateX", Degrees] = 1.0 >>> node["rotateX"] = Degrees(1) >>> node["rotateX", Degrees] + cmdx.Plug("myNode", "rotateX") == 1.0 + >>> node["rotateX", Degrees].read() 1.0 >>> node["myDist"] = Distance() >>> node["myDist"] = node["translateX"] @@ -645,6 +653,13 @@ def __setitem__(self, key, value): ... else: ... assert False >>> + >>> node["myString"] = String() + >>> node["myString"] + cmdx.Plug("myNode", "myString") == "" + >>> node["myString"] = "Hello, world!" + >>> node["myString"] + cmdx.Plug("myNode", "myString") == "Hello, world!" + >>> >>> delete(node) """ @@ -978,9 +993,12 @@ def update(self, attrs): attrs (dict): Key/value pairs of name and attribute Examples: + >>> _new() >>> node = createNode("transform") >>> node.update({"tx": 5.0, ("ry", Degrees): 30.0}) >>> node["tx"] + cmdx.Plug("transform1", "translateX") == 5.0 + >>> node["tx"].read() 5.0 """ @@ -996,16 +1014,23 @@ def clear(self): values, freeing up memory at the expense of performance. Example: + >>> _new() >>> node = createNode("transform") >>> node["translateX"] = 5 >>> node["translateX"] + cmdx.Plug("transform1", "translateX") == 5.0 + >>> node["translateX"].read() 5.0 >>> # Plug was reused >>> node["translateX"] + cmdx.Plug("transform1", "translateX") == 5.0 + >>> node["translateX"].read() 5.0 >>> # Value was reused >>> node.clear() >>> node["translateX"] + cmdx.Plug("transform1", "translateX") == 5.0 + >>> node["translateX"].read() 5.0 >>> # Plug and value was recomputed @@ -1513,7 +1538,8 @@ def __str__(self): return self.path() def __repr__(self): - return self.path() + cls_name = '{}.{}'.format(__name__, self.__class__.__name__) + return '{}("{}")'.format(cls_name, self.name()) def __or__(self, other): """Syntax sugar for finding a child @@ -1521,14 +1547,24 @@ def __or__(self, other): Examples: >>> _new() >>> parent = createNode("transform", "parent") - >>> child = createNode("transform", "child", parent) + >>> child = createNode("transform", "child", parent) >>> parent | "child" - |parent|child + cmdx.DagNode("child") + >>> (parent | "child").path() in ( + ... '|parent|child', + ... u'|parent|child' + ... ) + True # Stackable too - >>> grand = createNode("transform", "grand", child) + >>> grand = createNode("transform", "grand", child) >>> parent | "child" | "grand" - |parent|child|grand + cmdx.DagNode("grand") + >>> (parent | "child" | "grand").path() in ( + ... '|parent|child|grand', + ... u'|parent|child|grand' + ... ) + True """ @@ -2302,7 +2338,13 @@ def flatten(self, type=None): >>> parent = cmds.sets([cc, c], name="parent") >>> mainset = encode(parent) >>> sorted(mainset.flatten(), key=lambda n: n.name()) - [|a, |b, |c] + [cmdx.DagNode("a"), cmdx.DagNode("b"), cmdx.DagNode("c")] + >>> result = sorted([n.name() for n in mainset.flatten()]) + >>> result in ( + ... ['a', 'b', 'c'], + ... [u'a', u'b', u'c'] + ... ) + True """ @@ -2558,11 +2600,16 @@ def __add__(self, other): than adding to longName, e.g. node["translate"] + "X" Example: + >>> _new() >>> node = createNode("transform") >>> node["tx"] = 5 >>> node["translate"] + "X" + cmdx.Plug("transform1", "translateX") == 5.0 + >>> (node["translate"] + "X").read() 5.0 >>> node["t"] + "x" + cmdx.Plug("transform1", "translateX") == 5.0 + >>> (node["t"] + "x").read() 5.0 >>> try: ... node["t"] + node["r"] @@ -2591,6 +2638,7 @@ def __iadd__(self, other): """Support += operator, for .append() Example: + >>> _new() >>> node = createNode("transform") >>> node["myArray"] = Double(array=True) >>> node["myArray"].append(1.0) @@ -2598,10 +2646,16 @@ def __iadd__(self, other): >>> node["myArray"] += 5.1 >>> node["myArray"] += [1.1, 2.3, 999.0] >>> node["myArray"][0] + cmdx.Plug("transform1", "myArray[0]") == 1.0 + >>> node["myArray"][0].read() 1.0 >>> node["myArray"][6] + cmdx.Plug("transform1", "myArray[6]") == 999.0 + >>> node["myArray"][6].read() 999.0 >>> node["myArray"][-1] + cmdx.Plug("transform1", "myArray[6]") == 999.0 + >>> node["myArray"][-1].read() 999.0 """ @@ -2627,7 +2681,24 @@ def __str__(self): return str(self.read()) def __repr__(self): - return str(self.read()) + cls_name = '{}.{}'.format(__name__, self.__class__.__name__) + msg = '{}("{}", "{}")'.format(cls_name, + self.node().name(), + self.name()) + + if not all((self.isCompound, self.isArray)): + # Delegate and include the value result from __str__ + read_result = str(self) + attr = self._mplug.attribute() + typ = attr.apiType() + if typ == om.MFn.kTypedAttribute: + typ = om.MFnTypedAttribute(attr).attrType() + if typ == om.MFnData.kString: + # Add surrounding quotes, indicating it is a string + read_result = '"{}"'.format(read_result) + msg += ' == {}'.format(read_result) + + return msg def __rshift__(self, other): """Support connecting attributes via A >> B""" @@ -2796,9 +2867,12 @@ def __setitem__(self, index, value): """Write to child of array or compound plug Example: + >>> _new() >>> node = createNode("transform") >>> node["translate"][0] = 5 >>> node["tx"] + cmdx.Plug("transform1", "translateX") == 5.0 + >>> node["tx"].read() 5.0 """ @@ -3170,12 +3244,17 @@ def extend(self, values): If cmdx.Plug's, create a new entry and connect it. Example: + >>> _new() >>> node = createNode("transform") >>> node["myArray"] = Double(array=True) >>> node["myArray"].extend([1.0, 2.0, 3.0]) >>> node["myArray"][0] + cmdx.Plug("transform1", "myArray[0]") == 1.0 + >>> node["myArray"][0].read() 1.0 >>> node["myArray"][-1] + cmdx.Plug("transform1", "myArray[2]") == 3.0 + >>> node["myArray"][-1].read() 3.0 """ @@ -4102,6 +4181,8 @@ def connections(self, >>> b["ihi"].connection() == a True >>> a["ihi"] + cmdx.Plug("A", "isHistoricallyInteresting") == 2 + >>> a["ihi"].read() 2 >>> b["arrayAttr"] = Long(array=True) >>> b["arrayAttr"][0] >> a["ihi"] @@ -6351,7 +6432,13 @@ def connect(self, src, dst, force=True): ... mod.connect(tm["sx"], tm["tx"]) ... >>> tm["tx"].connection() - |myTransform + cmdx.DagNode("myTransform") + >>> tm["tx"].connection().path() in ( + ... '|myTransform', + ... u'|myTransform' + ... ) + True + >>> cmds.undo() >>> tm["tx"].connection() is None True @@ -6359,7 +6446,12 @@ def connect(self, src, dst, force=True): # Connect without undo >>> tm["tx"] << tx["output"] >>> tm["tx"].connection() - myAnimCurve + cmdx.AnimCurve("myAnimCurve") + >>> tm["tx"].connection().name() in ( + ... 'myAnimCurve', + ... u'myAnimCurve' + ... ) + True # Disconnect without undo >>> tm["tx"] // tx["output"] @@ -6445,11 +6537,21 @@ def connectAttr(self, srcPlug, dstNode, dstAttr): ... mod.connectAttr(newNode["newAttr"], otherNode, otherAttr) ... >>> newNode["newAttr"].connection() - |otherNode + cmdx.DagNode("otherNode") + >>> newNode["newAttr"].connection().path() in ( + ... '|otherNode', + ... u'|otherNode' + ... ) + True >>> cmds.undo() >>> newNode["newAttr"].connection() - |newNode + cmdx.DagNode("newNode") + >>> newNode["newAttr"].connection().path() in ( + ... '|newNode', + ... u'|newNode' + ... ) + True """ @@ -6760,6 +6862,7 @@ class DagModifier(_BaseModifier): """Modifier for DAG nodes Example: + >>> _new() >>> with DagModifier() as mod: ... node1 = mod.createNode("transform") ... node2 = mod.createNode("transform", parent=node1) @@ -6769,8 +6872,12 @@ class DagModifier(_BaseModifier): >>> getAttr(node1 + ".translateX") 1.0 >>> node2["translate"][0] + cmdx.Plug("transform2", "translateX") == 1.0 + >>> node2["translate"][0].read() 1.0 >>> node2["translate"][1] + cmdx.Plug("transform2", "translateY") == 2.0 + >>> node2["translate"][1].read() 2.0 >>> with DagModifier() as mod: ... node1 = mod.createNode("transform") @@ -6779,8 +6886,12 @@ class DagModifier(_BaseModifier): ... node1["translate"] >> node2["translate"] ... >>> node2["translate"][0] + cmdx.Plug("transform4", "translateX") == 5.0 + >>> node2["translate"][0].read() 5.0 >>> node2["translate"][1] + cmdx.Plug("transform4", "translateY") == 6.0 + >>> node2["translate"][1].read() 6.0 Example, without context manager: @@ -7721,7 +7832,8 @@ def __hash__(self): def __repr__(self): """Avoid repr depicting the full contents of this dict""" - return self["name"] + cls_name = '{}.{}'.format(__name__, self.__class__.__name__) + return 'cmdx.{}("{}")'.format(cls_name, self["name"]) def __new__(cls, *args, **kwargs): """Support for using name of assignment diff --git a/tests.py b/tests.py index 73ccac6..3a327b6 100644 --- a/tests.py +++ b/tests.py @@ -383,8 +383,9 @@ def test_nodeoperators(): node = cmdx.createNode(cmdx.tTransform, name="myNode") assert_equals(node, "|myNode") + assert_equals(repr(node), 'cmdx.DagNode("myNode")') assert_not_equals(node, "|NotEquals") - assert_equals(str(node), repr(node)) + assert_not_equals(str(node), repr(node)) @with_setup(new_scene)