def node_sub(self, node_self, node_other):
def same_leaf_list(tag):<EOL><INDENT>list_self = [c for c in list(node_self) if c.tag == tag]<EOL>list_other = [c for c in list(node_other) if c.tag == tag]<EOL>s_node = self.device.get_schema_node((list_self + list_other)[<NUM_LIT:0>])<EOL>if s_node.get('<STR_LIT>') == '<STR_LIT:user>':<EOL><INDENT>if [i.text for i in list_self] == [i.text for i in list_other]:<EOL><INDENT>return True<EOL><DEDENT>else:<EOL><INDENT>return False<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if set([i.text for i in list_self]) ==set([i.text for i in list_other]):<EOL><INDENT>return True<EOL><DEDENT>else:<EOL><INDENT>return False<EOL><DEDENT><DEDENT><DEDENT>if self.preferred_replace != '<STR_LIT>':<EOL><INDENT>t_self = [c.tag for c in list(node_self)if self.device.get_schema_node(c).get('<STR_LIT:type>') =='<STR_LIT>']<EOL>t_other = [c.tag for c in list(node_other)if self.device.get_schema_node(c).get('<STR_LIT:type>') =='<STR_LIT>']<EOL>commonalities = set(t_self) & set(t_other)<EOL>for commonality in commonalities:<EOL><INDENT>if not same_leaf_list(commonality):<EOL><INDENT>node_self.set(operation_tag, '<STR_LIT:replace>')<EOL>node_other.set(operation_tag, '<STR_LIT:replace>')<EOL>return<EOL><DEDENT><DEDENT><DEDENT>in_s_not_in_o, in_o_not_in_s, in_s_and_in_o =self._group_kids(node_self, node_other)<EOL>ordered_by_user = {}<EOL>for child_self in in_s_not_in_o:<EOL><INDENT>child_other = etree.Element(child_self.tag,<EOL>{operation_tag: self.preferred_delete},<EOL>nsmap=child_self.nsmap)<EOL>if self.preferred_create != '<STR_LIT>':<EOL><INDENT>child_self.set(operation_tag, self.preferred_create)<EOL><DEDENT>siblings = list(node_other.iterchildren(tag=child_self.tag))<EOL>if siblings:<EOL><INDENT>siblings[-<NUM_LIT:1>].addnext(child_other)<EOL><DEDENT>else:<EOL><INDENT>node_other.append(child_other)<EOL><DEDENT>s_node = self.device.get_schema_node(child_self)<EOL>if s_node.get('<STR_LIT:type>') == '<STR_LIT>':<EOL><INDENT>if s_node.get('<STR_LIT>') == '<STR_LIT:user>' ands_node.tag not in ordered_by_user:<EOL><INDENT>ordered_by_user[s_node.tag] = '<STR_LIT>'<EOL><DEDENT>child_other.text = child_self.text<EOL><DEDENT>elif s_node.get('<STR_LIT:type>') == '<STR_LIT:list>':<EOL><INDENT>keys = self._get_list_keys(s_node)<EOL>if s_node.get('<STR_LIT>') == '<STR_LIT:user>' ands_node.tag not in ordered_by_user:<EOL><INDENT>ordered_by_user[s_node.tag] = keys<EOL><DEDENT>for key in keys:<EOL><INDENT>key_node = child_self.find(key)<EOL>e = etree.SubElement(child_other, key, nsmap=key_node.nsmap)<EOL>e.text = key_node.text<EOL><DEDENT><DEDENT><DEDENT>for child_other in in_o_not_in_s:<EOL><INDENT>child_self = etree.Element(child_other.tag,<EOL>{operation_tag: self.preferred_delete},<EOL>nsmap=child_other.nsmap)<EOL>if self.preferred_create != '<STR_LIT>':<EOL><INDENT>child_other.set(operation_tag, self.preferred_create)<EOL><DEDENT>siblings = list(node_self.iterchildren(tag=child_other.tag))<EOL>if siblings:<EOL><INDENT>siblings[-<NUM_LIT:1>].addnext(child_self)<EOL><DEDENT>else:<EOL><INDENT>node_self.append(child_self)<EOL><DEDENT>s_node = self.device.get_schema_node(child_other)<EOL>if s_node.get('<STR_LIT:type>') == '<STR_LIT>':<EOL><INDENT>if s_node.get('<STR_LIT>') == '<STR_LIT:user>' ands_node.tag not in ordered_by_user:<EOL><INDENT>ordered_by_user[s_node.tag] = '<STR_LIT>'<EOL><DEDENT>child_self.text = child_other.text<EOL><DEDENT>elif s_node.get('<STR_LIT:type>') == '<STR_LIT:list>':<EOL><INDENT>keys = self._get_list_keys(s_node)<EOL>if s_node.get('<STR_LIT>') == '<STR_LIT:user>' ands_node.tag not in ordered_by_user:<EOL><INDENT>ordered_by_user[s_node.tag] = keys<EOL><DEDENT>for key in keys:<EOL><INDENT>key_node = child_other.find(key)<EOL>e = etree.SubElement(child_self, key, nsmap=key_node.nsmap)<EOL>e.text = key_node.text<EOL><DEDENT><DEDENT><DEDENT>for child_self, child_other in in_s_and_in_o:<EOL><INDENT>s_node = self.device.get_schema_node(child_self)<EOL>if s_node.get('<STR_LIT:type>') == '<STR_LIT>':<EOL><INDENT>if child_self.text == child_other.text:<EOL><INDENT>if not s_node.get('<STR_LIT>'):<EOL><INDENT>node_self.remove(child_self)<EOL>node_other.remove(child_other)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>if self.preferred_replace != '<STR_LIT>':<EOL><INDENT>child_self.set(operation_tag, self.preferred_replace)<EOL>child_other.set(operation_tag, self.preferred_replace)<EOL><DEDENT><DEDENT><DEDENT>elif s_node.get('<STR_LIT:type>') == '<STR_LIT>':<EOL><INDENT>if s_node.get('<STR_LIT>') == '<STR_LIT:user>':<EOL><INDENT>if s_node.tag not in ordered_by_user:<EOL><INDENT>ordered_by_user[s_node.tag] = '<STR_LIT>'<EOL><DEDENT><DEDENT>else:<EOL><INDENT>node_self.remove(child_self)<EOL>node_other.remove(child_other)<EOL><DEDENT><DEDENT>elif s_node.get('<STR_LIT:type>') == '<STR_LIT>':<EOL><INDENT>if self._node_le(child_self, child_other) andself._node_le(child_other, child_self):<EOL><INDENT>node_self.remove(child_self)<EOL>node_other.remove(child_other)<EOL><DEDENT>else:<EOL><INDENT>self.node_sub(child_self, child_other)<EOL><DEDENT><DEDENT>elif s_node.get('<STR_LIT:type>') == '<STR_LIT:list>':<EOL><INDENT>if s_node.get('<STR_LIT>') == '<STR_LIT:user>' ands_node.tag not in ordered_by_user:<EOL><INDENT>ordered_by_user[s_node.tag] = self._get_list_keys(s_node)<EOL><DEDENT>if self._node_le(child_self, child_other) andself._node_le(child_other, child_self):<EOL><INDENT>if s_node.get('<STR_LIT>') == '<STR_LIT:user>':<EOL><INDENT>for child in child_self.getchildren():<EOL><INDENT>schema_node = self.device.get_schema_node(child)<EOL>if not schema_node.get('<STR_LIT>'):<EOL><INDENT>child_self.remove(child)<EOL><DEDENT><DEDENT>for child in child_other.getchildren():<EOL><INDENT>schema_node = self.device.get_schema_node(child)<EOL>if not schema_node.get('<STR_LIT>'):<EOL><INDENT>child_other.remove(child)<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>node_self.remove(child_self)<EOL>node_other.remove(child_other)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>self.node_sub(child_self, child_other)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>path = self.device.get_xpath(s_node)<EOL>raise ModelError("<STR_LIT>""<STR_LIT>".format(path, s_node.get('<STR_LIT:type>')))<EOL><DEDENT><DEDENT>for tag in ordered_by_user:<EOL><INDENT>scope_s = in_s_not_in_o + in_s_and_in_o<EOL>scope_o = in_o_not_in_s + in_s_and_in_o<EOL>for sequence in self._get_sequence(scope_s, tag, node_self),self._get_sequence(scope_o, tag, node_other):<EOL><INDENT>for item in sequence:<EOL><INDENT>i = sequence.index(item)<EOL>if i == <NUM_LIT:0>:<EOL><INDENT>item.set(insert_tag, '<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>item.set(insert_tag, '<STR_LIT>')<EOL>precursor = sequence[i - <NUM_LIT:1>]<EOL>if ordered_by_user[tag] == '<STR_LIT>':<EOL><INDENT>item.set(value_tag, precursor.text)<EOL><DEDENT>else:<EOL><INDENT>keys = ordered_by_user[tag]<EOL>key_nodes = {k: precursor.find(k) for k in keys}<EOL>ids = {k: self._url_to_prefix(n, k)for k, n in key_nodes.items()}<EOL>l = ["<STR_LIT>".format(ids[k], key_nodes[k].text)for k in keys]<EOL>item.set(key_tag, '<STR_LIT>'.join(l))<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>
node_sub

        Low-level api: Compute the delta of two configs. This method is
        recursive. Assume two configs are different.

        Parameters
        ----------

        node_self : `Element`
            A config node in a config tree that is being processed. node_self
            cannot be a leaf node.

        node_other : `Element`
            A config node in another config tree that is being processed.

        Returns
        -------

        None
            There is no return of this method.