'When specs are parsed, any dependencies specified are hanging off
the root, and ONLY the ones that were explicitly provided are there.
Normalization turns a partial flat spec into a DAG, where:
1. Known dependencies of the root package are in the DAG.
2. Each node\'s dependencies dict only contains its known direct
deps.
3. There is only ONE unique spec for each package in the DAG.
* This includes virtual packages.  If there a non-virtual
package that provides a virtual package that is in the spec,
then we replace the virtual package with the non-virtual one.
TODO: normalize should probably implement some form of cycle
detection, to ensure that the spec is actually a DAG.'

def normalize(self, force=False):

    if (not self.name):
        raise SpecError('Attempting    to    normalize    anonymous    spec')
    if (self._normal and (not force)):
        return False
    if force:
        self._mark_concrete(False)
    self.validate_or_raise()
    spec_deps = self.flat_dependencies(copy=False, deptype_query=alldeps)
    provider_index = ProviderIndex([s for s in spec_deps.values()], restrict=True)
    visited = set()
    any_change = self._normalize_helper(visited, spec_deps, provider_index)
    extra = set(spec_deps.keys()).difference(visited)
    if extra:
        raise InvalidDependencyError(((self.name + '    does    not    depend    on    ') + comma_or(extra)))
    self._normal = True
    return any_change
