'Flexible mechanism for inheriting content from an external course/library/etc.
Will copy all of the XBlocks whose keys are passed as `source_course` so that they become
children of the XBlock whose key is `dest_usage`. Any previously existing children of
`dest_usage` that haven\'t been replaced/updated by this copy_from_template operation will
be deleted.
Unlike `copy()`, this does not care whether the resulting blocks are positioned similarly
in their new course/library. However, the resulting blocks will be in the same relative
order as `source_keys`.
If any of the blocks specified already exist as children of the destination block, they
will be updated rather than duplicated or replaced. If they have Scope.settings field values
overriding inherited default values, those overrides will be preserved.
IMPORTANT: This method does not preserve block_id - in other words, every block that is
copied will be assigned a new block_id. This is because we assume that the same source block
may be copied into one course in multiple places. However, it *is* guaranteed that every
time this method is called for the same source block and dest_usage, the same resulting
block id will be generated.
:param source_keys: a list of BlockUsageLocators. Order is preserved.
:param dest_usage: The BlockUsageLocator that will become the parent of an inherited copy
of all the xblocks passed in `source_keys`.
:param user_id: The user who will get credit for making this change.'

@contract(source_keys='list(BlockUsageLocator)', dest_usage=BlockUsageLocator)
def copy_from_template(self, source_keys, dest_usage, user_id, head_validation=True):

    source_structures = {}
    for key in source_keys:
        course_key = key.course_key
        if (course_key.branch is None):
            raise ItemNotFoundError('branch    is    required    for    all    source    keys    when    using    copy_from_template')
        if (course_key not in source_structures):
            with self.bulk_operations(course_key):
                source_structures[course_key] = self._lookup_course(course_key, head_validation=head_validation).structure
    destination_course = dest_usage.course_key
    with self.bulk_operations(destination_course):
        index_entry = self.get_course_index(destination_course)
        if (index_entry is None):
            raise ItemNotFoundError(destination_course)
        dest_structure = self._lookup_course(destination_course).structure
        old_dest_structure_version = dest_structure['_id']
        dest_structure = self.version_structure(destination_course, dest_structure, user_id)
        block_key = BlockKey(dest_usage.block_type, dest_usage.block_id)
        orig_descendants = set(self.descendants(dest_structure['blocks'], block_key, depth=None, descendent_map={}))
        orig_descendants.remove(block_key)
        new_descendants = self._copy_from_template(source_structures, source_keys, dest_structure, block_key, user_id, head_validation)
        dest_info = dest_structure['blocks'][block_key]
        dest_info.edit_info.previous_version = dest_info.edit_info.update_version
        dest_info.edit_info.update_version = old_dest_structure_version
        dest_info.edit_info.edited_by = user_id
        dest_info.edit_info.edited_on = datetime.datetime.now(UTC)
        orphans = (orig_descendants - new_descendants)
        for orphan in orphans:
            del dest_structure['blocks'][orphan]
        self.update_structure(destination_course, dest_structure)
        self._update_head(destination_course, index_entry, destination_course.branch, dest_structure['_id'])
    return [destination_course.make_usage_key(*k) for k in dest_structure['blocks'][block_key].fields['children']]
