def __ValidateDependenciesFor(self, rOrderedDependencyList: List[Package], package: Package, graph: DependencyGraph) -> None: packageNode = graph.Get(package) # TODO: make the get method never return none if packageNode is None: raise Exception( "the package should always have a node in the graph") while len(graph.Nodes) > 0: nodes = graph.RemoveNodesWithNoIncomingDependencies() if len(nodes) <= 0: self.HandleCircularDependencies(graph, packageNode) nodes.sort(key=lambda node: node.Name.lower()) for node in nodes: if node.Package != packageNode: rOrderedDependencyList.append(node.Package)
def HandleCircularDependencies(self, graph: DependencyGraph, packageNode: DependencyGraphNode) -> None: keepRemoving = True while keepRemoving: keepRemoving = len(graph.RemoveNodesWithNoDependencies()) > 0 # check if this package is actually part of the circular dependency or not if not packageNode in graph.Nodes: raise CircularDependencyInDependentModuleException( "'%s' uses a package that has a circular dependency" % (packageNode.Name)) # We are only interested in the dependencies that start at packageNode circularDependencies = [] # type: List[List[DependencyGraphNode]] dependencies = [packageNode] # type: List[DependencyGraphNode] self.BuildDependencyList(circularDependencies, dependencies, packageNode) circularDepStringsSet = set() # Set[str] for circularDep in circularDependencies: circularDepStringsSet.add( self.GetCircularDependencyString(circularDep)) circularDepStrings = list(circularDepStringsSet) circularDepStrings.sort( key=lambda str: (self.__CountArrows(str), str.lower())) raise CircularDependencyException( "Circular dependency detected while validating " + packageNode.Name + ":\n " + "\n ".join(circularDepStrings))
def __ValidateDependencies(self, config: Config, packages: List[Package]) -> None: exceptionList = [] # type: List[Exception] exceptionList2 = [] # type: List[Exception] for package in packages: try: #allDependenciesDict = {} #stack = [package] graph = DependencyGraph(package) #, True) orderedDependencyList = [] # type: List[Package] self.__ValidateDependenciesFor(orderedDependencyList, package, graph) orderedDependencyList.reverse() package.ResolvedBuildOrder = orderedDependencyList # NOTE: we can not filter the dependency list based on 'ExperimentalRecipes' here since we need to resolve it first # package.ResolvedExperimentalRecipeBuildOrder = [entry for entry in orderedDependencyList if not entry.DirectExperimentalRecipe is None] except CircularDependencyException as ex: if config.GroupException: exceptionList.append(ex) else: raise except CircularDependencyInDependentModuleException as ex: if config.GroupException: exceptionList2.append(ex) else: raise if len(exceptionList) > 0: raise GroupedException(exceptionList) # If the below exception is fired we have a internal error # as any entry in exceptionList2 should result in entries in # exceptionList if len(exceptionList2) > 0: raise GroupedException(exceptionList2)
def __init__(self, config: Config, platformName: str, generatorInfo: GeneratorInfo, genFiles: List[XmlGenFile], logVerbosity: int = 1) -> None: super().__init__() # create top level package and resolve build order config.LogPrintVerbose(logVerbosity, "Validating dependencies") packageManager = PackageManager(config, platformName, generatorInfo, genFiles) packages = packageManager.Packages # Build a graph containing all packages graph = DependencyGraph(None) #, True) for package in packages: graph.AddNode(package) graph.Finalize() # Extract the top level nodes nodes = graph.GetNodesWithNoIncomingDependencies() #useFallback = True if len(nodes) > 0: topLevelGenFile = XmlGenFile( config, config.ToolConfig.DefaultPackageLanguage) topLevelGenFile.Name = PackageNameMagicString.TopLevelName topLevelGenFile.SetType(PackageType.TopLevel) for entry in nodes: topLevelGenFile.DirectDependencies.append( FakeXmlGenFileDependency(config, entry.Name, AccessType.Public)) topLevelGenFile.DirectDependencies.sort( key=lambda s: s.Name.lower()) else: # We have circular dependencies and couldnt find any starting nodes # so generate a empty top level node and expect a circular dependency # error to be caught topLevelGenFile = XmlGenFile( config, config.ToolConfig.DefaultPackageLanguage) topLevelGenFile.Name = PackageNameMagicString.TopLevelName topLevelGenFile.SetType(PackageType.TopLevel) topLevelPackage = packageManager.CreatePackage(config, platformName, topLevelGenFile, True) graph.AddNodeAndEdges(topLevelPackage) # Since we need to resolve the build order we might as well verify dependencies at the same time self.__ValidateDependencies(config, packages) self.AllPackages = packages # type: List[Package] self.TopLevelPackage = topLevelPackage self.__ResolveAllPackageDependencies(config, topLevelPackage)