Edit - made a mistake, details below…
Hi,
What code are you doing to connect the remapHsv.outColorR attribute to the specRoughness?- I tested both the connection editor and via code successfully:
import maya.cmds as cmds
# Create the nodes
base_shader_node = cmds.createNode("aiStandardSurface")
remap_hsv_node_01 = cmds.createNode("remapHsv")
cmds.connectAttr(
"{0}.outColorR".format(remap_hsv_node_01),
"{0}.specularRoughness".format(base_shader_node))
remap_hsv_node_02 = cmds.createNode("remapHsv")
cmds.connectAttr(
"{0}.outColor".format(remap_hsv_node_02),
"{0}.color".format(remap_hsv_node_01))
file_node_01 = cmds.createNode("file")
cmds.connectAttr(
"{0}.outColor".format(file_node_01),
"{0}.color".format(remap_hsv_node_02))
place_2d_node_01 = cmds.createNode("place2dTexture")
cmds.connectAttr(
"{0}.coverage".format(place_2d_node_01),
"{0}.coverage".format(file_node_01))
Ack! - I made a mistake! - i forgot to call the get_nodes code inside itself (the recursive part) and was only calling the traverse once - this is fixed now:
import maya.cmds as cmds
def _traverse(node, children):
connections = cmds.listConnections(
node,
source=True,
destination=False,
skipConversionNodes=True) or {}
for child in connections:
children[child] = {}
def get_nodes(node, children):
_traverse(node, children)
for child in children:
get_nodes(child, children[child])
children = {}
get_nodes("aiStandardSurface1", children)
print children
# >> {u'remapHsv1': {u'remapHsv2': {u'file1': {u'place2dTexture1': {}, u'defaultColorMgtGlobals': {}}}}}
So i have a traverse function _traverse - which basically gets child nodes plugged into a give node. We supply a children argument as essentially a ‘by reference’ to basically pass data to it - specifically mutable data - that is data that is changeable.
Function scope is inherent to whats inside it - so you need a way to change external data given to it. Its why if you have a variable at the base scope of a module - (a python file) functions within are able to access it (essentially because they inherit the outer scope):
a = 10
def myFunc():
return a
print myFunc()
# >> 10
…but crucially cannot change it:
a = 10
def myFunc():
a = 20
myFunc()
print a
# >> 10
A is immutable and doesn’t have any mutability - i.e. we can’t change it within the internal scope. In classes this changes a little basically your binding the class instance with the self which references variables of the instance. So what is a mutable type? Things like lists, and dictionaries - they can be appended. So something like this will work:
a = []
def myFunc(val):
val.append(20)
myFunc(a)
print a
# >> [20]
When we call the get_nodes on itself - we’re passing in the children dict into itself indefinitely - take a hierarchy like so:
a
b c
de fg
When we call the get nodes on a we pass the children dictionary to it - because its mutable we collect b and c into it. Because children is a dictionary, b and c become keys added to the dictionary and there values are dictionaries themselves!:
{"b": {}, "c": {}}
Now crucially in our loop we call this code:
for child in children:
get_nodes(child, children[child])
So what were doing is for each child in the children dictionary we’ll run the function itself again on - ie. we call get_nodes on b and c. But instead of passing our children dictionary we’ll pass the dictionaries of its children i.e. children[b]:
note* calling dict[key] will return the value of the key.
So when we call get_nodes(child, children[child]) - what we’re really saying is get_nodes(“b”, {}} - So b’s value becomes the new children dictionary i.e the mutable value we’re adding too!
{"b": {"d":{}, "e": {}}, "c": {"f":{}, "g": {}}
Because b and c values are dictionaries - we then keep continuing to call the function.
I.e. Pass a mutable variable to the function and for each child of the viable call the function.
The Fibonacci sequence is a perfect example of this - its basically a recurve function adding the last value to create the next - creating a number sequence that can reflect nature:
1 1 2 3 5 8 13 21 …
1 + 0 = new 1
new 1 + previous 1 = new 2
new 2 + previous 1 = new 3
new 3 + previous 2 = new 5
…
Hope this helps - It can be tricky to distill scope knowledge 
-c