Run upgrade pre-checks prior to applying upgrades.

        Pre-checks should
        in general be fast to execute. Pre-checks may the use the wait_for_user
        function, to query the user for confirmation, but should respect the
        --yes-i-know option to run unattended.

        All pre-checks will be executed even if one fails, however if one pre-
        check fails, the upgrade process will be stopped and the user warned.

        :param upgrades: List of upgrades sorted in topological order.

def pre_upgrade_checks(self, upgrades):
        """Run upgrade pre-checks prior to applying upgrades.

        Pre-checks should
        in general be fast to execute. Pre-checks may the use the wait_for_user
        function, to query the user for confirmation, but should respect the
        --yes-i-know option to run unattended.

        All pre-checks will be executed even if one fails, however if one pre-
        check fails, the upgrade process will be stopped and the user warned.

        :param upgrades: List of upgrades sorted in topological order.
        """
        errors = []

        for check in self.global_pre_upgrade:
            self._setup_log_prefix(plugin_id=check.__name__)
            try:
                check()
            except RuntimeError as e:
                errors.append((check.__name__, e.args))

        for u in upgrades:
            self._setup_log_prefix(plugin_id=u.name)
            try:
                u.pre_upgrade()
            except RuntimeError as e:
                errors.append((u.name, e.args))

        self._teardown_log_prefix()

        self._check_errors(errors, "Pre-upgrade check for %s failed with the"
                           " following errors:")