Tries to select a version of a required package.

        Returns the name of the package whose incompatibilities should be
        propagated by _propagate(), or None indicating that version solving is
        complete and a solution has been found.

def _choose_package_version(self):  # type: () -> Union[str, None]
        """
        Tries to select a version of a required package.

        Returns the name of the package whose incompatibilities should be
        propagated by _propagate(), or None indicating that version solving is
        complete and a solution has been found.
        """
        unsatisfied = self._solution.unsatisfied
        if not unsatisfied:
            return

        # Prefer packages with as few remaining versions as possible,
        # so that if a conflict is necessary it's forced quickly.
        def _get_min(dependency):
            if dependency.name in self._use_latest:
                # If we're forced to use the latest version of a package, it effectively
                # only has one version to choose from.
                return 1

            if dependency.name in self._locked:
                return 1

            try:
                return len(self._provider.search_for(dependency))
            except ValueError:
                return 0

        if len(unsatisfied) == 1:
            dependency = unsatisfied[0]
        else:
            dependency = min(*unsatisfied, key=_get_min)

        locked = self._get_locked(dependency.name)
        if locked is None or not dependency.constraint.allows(locked.version):
            try:
                packages = self._provider.search_for(dependency)
            except ValueError as e:
                self._add_incompatibility(
                    Incompatibility([Term(dependency, True)], PackageNotFoundCause(e))
                )
                return dependency.name

            try:
                version = packages[0]
            except IndexError:
                version = None
        else:
            version = locked

        if version is None:
            # If there are no versions that satisfy the constraint,
            # add an incompatibility that indicates that.
            self._add_incompatibility(
                Incompatibility([Term(dependency, True)], NoVersionsCause())
            )

            return dependency.name

        version = self._provider.complete_package(version)

        conflict = False
        for incompatibility in self._provider.incompatibilities_for(version):
            self._add_incompatibility(incompatibility)

            # If an incompatibility is already satisfied, then selecting version
            # would cause a conflict.
            #
            # We'll continue adding its dependencies, then go back to
            # unit propagation which will guide us to choose a better version.
            conflict = conflict or all(
                [
                    term.dependency.name == dependency.name
                    or self._solution.satisfies(term)
                    for term in incompatibility.terms
                ]
            )

        if not conflict:
            self._solution.decide(version)
            self._log(
                "selecting {} ({})".format(version.name, version.full_pretty_version)
            )

        return dependency.name