'Apply an inheriting view (a descendant of the base view)
Apply to a source architecture all the spec nodes (i.e. nodes
describing where and what changes to apply to some parent
architecture) given by an inheriting view.
:param Element source: a parent architecture to modify
:param Elepect specs_tree: a modifying architecture in an inheriting view
:param inherit_id: the database id of specs_arch
:return: a modified source where the specs are applied
:rtype: Element'

@api.model
def apply_inheritance_specs(self, source, specs_tree, inherit_id):

    specs = [specs_tree]
    while len(specs):
        spec = specs.pop(0)
        if isinstance(spec, SKIPPED_ELEMENT_TYPES):
            continue
        if (spec.tag == 'data'):
            specs += [c for c in spec]
            continue
        node = self.locate_node(source, spec)
        if (node is not None):
            pos = spec.get('position', 'inside')
            if (pos == 'replace'):
                for loc in spec.xpath(".//*[text()='$0']"):
                    loc.text = ''
                    loc.append(copy.deepcopy(node))
                if (node.getparent() is None):
                    source = copy.deepcopy(spec[0])
                else:
                    for child in spec:
                        node.addprevious(child)
                    node.getparent().remove(node)
            elif (pos == 'attributes'):
                for child in spec.getiterator('attribute'):
                    attribute = child.get('name')
                    value = (child.text or '')
                    if (child.get('add') or child.get('remove')):
                        assert (not child.text)
                        separator = child.get('separator', ',')
                        if (separator == '    '):
                            separator = None
                        to_add = filter(bool, map(str.strip, child.get('add', '').split(separator)))
                        to_remove = map(str.strip, child.get('remove', '').split(separator))
                        values = map(str.strip, node.get(attribute, '').split(separator))
                        value = (separator or '    ').join((filter((lambda s: (s not in to_remove)), values) + to_add))
                    if value:
                        node.set(attribute, value)
                    elif (attribute in node.attrib):
                        del node.attrib[attribute]
            else:
                sib = node.getnext()
                for child in spec:
                    if (pos == 'inside'):
                        node.append(child)
                    elif (pos == 'after'):
                        if (sib is None):
                            node.addnext(child)
                            node = child
                        else:
                            sib.addprevious(child)
                    elif (pos == 'before'):
                        node.addprevious(child)
                    else:
                        self.raise_view_error((_("Invalid    position    attribute:    '%s'") % pos), inherit_id)
        else:
            attrs = ''.join([('    %s="%s"' % (attr, spec.get(attr))) for attr in spec.attrib if (attr != 'position')])
            tag = ('<%s%s>' % (spec.tag, attrs))
            self.raise_view_error((_("Element    '%s'    cannot    be    located    in    parent    view") % tag), inherit_id)
    return source
