'Removes the block identified by the usage_key and all of its
related data from the block structure.  If descendants of the
removed block are to be kept, the structure\'s relations are
updated to reconnect the block\'s parents with its children.
Note: While the immediate relations of the block are updated
(removed), all descendants of the block will remain in the
structure unless the _prune_unreachable method is called.
Arguments:
usage_key (UsageKey) - Usage key of the block that is to be
removed.
keep_descendants (bool) - If True, the block structure\'s
relations (graph edges) are updated such that the
removed block\'s children become children of the
removed block\'s parents.'

def remove_block(self, usage_key, keep_descendants):

    children = self._block_relations[usage_key].children
    parents = self._block_relations[usage_key].parents
    for child in children:
        self._block_relations[child].parents.remove(usage_key)
    for parent in parents:
        self._block_relations[parent].children.remove(usage_key)
    self._block_relations.pop(usage_key, None)
    self._block_data_map.pop(usage_key, None)
    if keep_descendants:
        for child in children:
            for parent in parents:
                self._add_relation(parent, child)
