<Purpose>
    Recursively compares two commanddicts to see if they have conflicting commands.
    
  <Arguments>
    originaldict: A commanddict to compare.
    comparedict: A commanddict to compare.
    
  <Side Effects>
    None
    
  <Exceptions>
    ModuleConflictError - A command was conflicting.  
        The error detail is the problematic command.
    
  <Returns>
    None

def ensure_no_conflicts_in_commanddicts(originaldict, comparedict):
  """
  <Purpose>
    Recursively compares two commanddicts to see if they have conflicting commands.
    
  <Arguments>
    originaldict: A commanddict to compare.
    comparedict: A commanddict to compare.
    
  <Side Effects>
    None
    
  <Exceptions>
    ModuleConflictError - A command was conflicting.  
        The error detail is the problematic command.
    
  <Returns>
    None
  """
  
  """
  Child nodes are identical if they all of the following are identical: 
    helptext/callback/summary.
     
  There are 3 cases we have to worry about.
  > Shared child node.
    > Child nodes are identical.  Check grandchildren.
    > Only one is defined.  Check grandchildren.
    > Both child nodes are defined and are not identical.  Reject.
  > Node is not shared.  Accept. 
  """
  
  for child in comparedict.keys():
    # Node not shared.
    if child not in originaldict:
      continue
    
    # Shared node
    comparechild_defined = is_commanddictnode_defined(comparedict[child])
    originalchild_defined = is_commanddictnode_defined(originaldict[child])
    
    # Only one is defined, or;
    # both are defined and they are identical
    if ((comparechild_defined ^ originalchild_defined) or
        (comparechild_defined and originalchild_defined and 
         _are_cmd_nodes_same(originaldict[child], comparedict[child]))):
      try:
        ensure_no_conflicts_in_commanddicts(comparedict[child]['children'], originaldict[child]['children'])
      except seash_exceptions.ModuleConflictError, e:
        # Reconstruct the full command recursively
        raise seash_exceptions.ModuleConflictError(child + " " + str(e) + " ("+module_name+")")
      continue
    
    # Not identical.  Conflict found.
    # Also include which module the conflicting module was found from.
    if 'module' in originaldict[child]:
        module_name = originaldict['module'][child]      
    else:
      module_name = "default"
    raise seash_exceptions.ModuleConflictError(child + ' ('+module_name+')')