def _updateFromTroveSetGraph(self, uJob, troveSet, troveCache,
                            split = True, fromChangesets = [],
                            criticalUpdateInfo=None, applyCriticalOnly = False,
                            restartInfo = None, callback = None,
                            ignoreMissingDeps = False):
        """
        Populates an update job based on a set of trove update and erase
        operations.If self.cfg.autoResolve is set, dependencies
        within the job are automatically closed. Returns a mapping with
        suggestions for possible dependency resolutions.

        @param uJob: A L{conary.local.database.UpdateJob} object
        @type uJob: L{conary.local.database.UpdateJob}
        @param split: Split large update operations into separate jobs.
                      This must be true (False broke how we
                      handle users and groups, which requires info- packages
                      to be installed first and in separate jobs) if you
                      intend to install the job. We allow False here because
                      we don't need to do these calculations when the jobs
                      are being constructed for other reasons.
        @type split: bool
        @param fromChangesets: When specified, this list of
        L{changeset.ChangeSetFromFile} objects is used as the source of troves,
        instead of the repository.
        @type fromChangesets: list
        @param criticalUpdateInfo: Settings and data needed for critical
        updates
        @type criticalUpdateInfo: L{CriticalUpdateInfo}
        @param applyCriticalOnly: apply only the critical update.
        @type applyCriticalOnly: bool
        @param restartInfo: If specified, overrides itemList. It specifies the
        location where the rest of an update job run was stored (after
        applying the critical update).
        @type restartInfo: string
        @param ignoreMissingDeps: Do not raise DepResolutionFailure on
        unresolved dependencies
        @tye ignoreMissingDeps: bool
        @rtype: dict

        @raise ConaryError: if a C{sync} operation was requested, and
            relative changesets were specified.

        @raise DepResolutionFailure: could not resolve dependencies

        @raise InternalConaryError: if a jobset was inconsistent.

        @raise UpdateError: Generic update error.

        @raise MissingTrovesError: if one of the requested troves could not
            be found.

        @raise other: Callbacks may generate exceptions on their own. See
            L{update.ClientUpdate.applyUpdateJob} for an explanation of
            the behavior of exceptions within callbacks.
        """

        def _updateJob(job, addedTroves):
            for newTup in addedTroves:
                # First look for an exact erase or update in the old job that
                # would remove this trove
                erases = [x for x in job
                        if (x[0], x[1][0], x[1][1]) == newTup]
                if erases:
                    if len(erases) > 1 or erases[0][2][0] is not None:
                        # Corner case, fall back to doing a full diff
                        return False
                    # We're adding back a trove that the job would have erased
                    # and the two annihilate each other
                    job.remove(erases[0])
                    continue

                # Then look for a name-only match against an erase
                erases = [x for x in job
                        if x[0] == newTup[0] and x[2][0] is None]
                if erases:
                    if len(erases) > 1:
                        # Corner case
                        return False
                    # Convert this erasure into an update
                    job.remove(erases[0])
                    oldVF = erases[0][1]
                    job.append( (newTup[0], oldVF, newTup[1:3], False) )
                    continue

                # No match, it's a new install
                job.append( (newTup[0], (None, None), newTup[1:3], True) )
            return True

        if criticalUpdateInfo is None:
            criticalUpdateInfo = update.CriticalUpdateInfo()

        searchPath = troveSet.searchPath

        if callback:
            callback.executingSystemModel()

        #depSearch = CMLSearchPath([ preFetch, searchPath ],
                                               #graph = preFetch.g)
        depSearch = searchPath
        troveSet.g.realize(CMLActionData(troveCache,
                                              self.cfg.flavor[0],
                                              self.repos, self.cfg))

        existsTrv = trove.Trove("@model", versions.NewVersion(),
                                deps.Flavor(), None)
        targetTrv = trove.Trove("@model", versions.NewVersion(),
                                deps.Flavor(), None)

        pins = set()
        phantomsByName = {}
        for tup, pinned in self.db.iterAllTroves(withPins = True):
            existsTrv.addTrove(*tup)
            if pinned:
                pins.add(tup)
                targetTrv.addTrove(*tup)
            if tup[1].onPhantomLabel():
                phantomsByName.setdefault(tup[0], set()).add(tup)

        for tup, inInstall, explicit in \
                                troveSet._walk(troveCache, recurse = True):
            if inInstall and tup[0:3] not in pins:
                targetTrv.addTrove(*tup[0:3])

        self._closePackages(troveCache, targetTrv)

        if phantomsByName or self.cfg.syncCapsuleDatabase == 'update':
            # Allow phantom troves to be updated to a real trove, but preserve
            # ones that would be erased outright.
            for tup in targetTrv.iterTroveList(strongRefs=True):
                name = tup[0]
                if existsTrv.hasTrove(*tup):
                    # This particular trove is not replacing anything
                    continue
                if name in phantomsByName:
                    # Could be replacing a phantom trove, so keep the latter in
                    # the old set so it will be updated.
                    del phantomsByName[name]
            # Discard any unmatched phantom troves from the old set so that
            # they will be left alone.
            for tups in phantomsByName.itervalues():
                for tup in tups:
                    existsTrv.delTrove(missingOkay=False, *tup)

        job = targetTrv.diff(existsTrv, absolute = False)[2]

        if callback:
            callback.resolvingDependencies()

        # don't resolve against local troves (we can do this because either
        # they're installed and show up in the unresolveable list or they
        # aren't installed and we don't know about them) or troves which are
        # in the install set (since they're already in the install set,
        # adding them to the install set won't help)
        depDb = deptable.DependencyDatabase()
        depResolveSource = depSearch._getResolveSource(
                        depDb = depDb,
                        filterFn = lambda n, v, f :
                            (v.isOnLocalHost() or
                             targetTrv.isStrongReference(n,v,f)))
        resolveMethod = depResolveSource.getResolveMethod()

        uJob.setSearchSource(self.getSearchSource())
        # this is awful
        jobTroveSource = uJob.getTroveSource()
        jobTroveSource.addChangeSets(fromChangesets,
                                     includesFileContents = True)

        pathHashCache = {}

        resolveDeps = split = True
        if resolveDeps or split:
            check = self.db.getDepStateClass(troveCache,
               findOrdering = split,
               ignoreDepClasses = self.cfg.ignoreDependencies)

            linkedJobs = self._findOverlappingJobs(job, troveCache,
                                      pathHashCache = pathHashCache)

            criticalJobs = criticalUpdateInfo.findCriticalJobs(job)
            finalJobs = criticalUpdateInfo.findFinalJobs(job)
            criticalOnly = criticalUpdateInfo.isCriticalOnlyUpdate()

            log.info("resolving dependencies")
            result = check.depCheck(job,
                                    linkedJobs = linkedJobs,
                                    criticalJobs = criticalJobs,
                                    finalJobs = finalJobs,
                                    criticalOnly = criticalOnly)

            suggMap = {}
            while True:
                added = set()
                for (needingTup, neededDeps, neededTupList) in \
                                                result.unresolveableList:
                    for neededTup in neededTupList:
                        if (neededTup not in added and
                                searchPath.hasOptionalTrove(neededTup)):
                            log.info("keeping installed trove for deps %s",
                                     neededTup)
                            added.add(neededTup)

                if not added:
                    unsatisfied = result.unsatisfiedList
                    unsatisfied += [ x[0:2] for x in result.unresolveableList ]

                    while (resolveMethod.prepareForResolution(unsatisfied) and
                           not added):
                        sugg = resolveMethod.resolveDependencies()
                        newJob = resolveMethod.filterSuggestions(
                                            result.unsatisfiedList, sugg, suggMap)
                        for (name, oldInfo, newInfo, isAbsolute) in newJob:
                            assert(isAbsolute)
                            log.info("adding for dependency %s", name)
                            added.add((name, newInfo[0], newInfo[1]))

                if not added:
                    break

                for troveTup in added:
                    targetTrv.addTrove(*troveTup)

                added.update(self._closePackages(troveCache, targetTrv,
                                                 newTroves = added))

                # try to avoid a diff here
                if not _updateJob(job, added):
                    job = targetTrv.diff(existsTrv, absolute = False)[2]

                log.info("resolving dependencies (job length %d)", len(job))
                criticalJobs = criticalUpdateInfo.findCriticalJobs(job)
                finalJobs = criticalUpdateInfo.findFinalJobs(job)
                criticalOnly = criticalUpdateInfo.isCriticalOnlyUpdate()

                linkedJobs = self._findOverlappingJobs(job, troveCache,
                                          pathHashCache = pathHashCache)

                result = check.depCheck(job,
                                        linkedJobs = linkedJobs,
                                        criticalJobs = criticalJobs,
                                        finalJobs = finalJobs,
                                        criticalOnly = criticalOnly)

            check.done()
            log.info("job dependency closed; %s jobs resulted", len(job))

            # if any of the things we're about to install or remove use
            # capsules we cannot split the job
            if not split:
                splitJob = [ job ]
                criticalUpdates = []
            else:
                splitJob = result.getChangeSetList()
                criticalUpdates = [ splitJob[x] for x in
                                        result.getCriticalUpdates() ]

            if result.unsatisfiedList and (not ignoreMissingDeps):
                raise update.DepResolutionFailure(
                            self.cfg, result.unsatisfiedList,
                            suggMap, result.unresolveableList, splitJob,
                            criticalUpdates)
            elif result.unresolveableList and (not ignoreMissingDeps):
                # this can't happen because dep resolution empties
                # the unresolveableList into the unsatisfiedList to try
                # and find matches
                assert(0)
        else:
            (depList, suggMap, cannotResolve, splitJob, keepList,
             criticalUpdates) = ( [], {}, [], [ job ], [], [] )

        # this prevents us from using the changesetList as a searchSource
        log.info("processing job list")
        self._processCMLJobList(job, uJob, troveCache)
        log.info("gathering group defined path conflicts")
        self._findAcceptablePathConflicts(job, uJob, troveCache)
        log.info("combining jobs")
        self._combineJobs(uJob, splitJob, criticalUpdates)
        uJob.reorderPreScripts(criticalUpdateInfo)
        uJob.setTransactionCounter(self.db.getTransactionCounter())

        # remove things from the suggMap which are in the already installed
        # set
        for neededSet in suggMap.itervalues():
            for troveTup in set(neededSet):
                if existsTrv.hasTrove(*troveTup):
                    neededSet.remove(troveTup)

        for needingTroveTup, neededSet in suggMap.items():
            if not neededSet:
                del suggMap[needingTroveTup]

        if callback:
            callback.done()

        return suggMap
dataset/ETHPy150Open sassoftware/conary/conary/conaryclient/modelupdate.py/CMLClient._updateFromTroveSetGraph/operator `and` -> `or`