def _clean_hosting_info(self):
        """Clean the hosting service information.

        If using a hosting service, this will validate that the data
        provided is valid on that hosting service. Then it will create an
        account and link it, if necessary, with the hosting service.
        """
        hosting_type = self.cleaned_data['hosting_type']

        if hosting_type == self.NO_HOSTING_SERVICE_ID:
            self.data['hosting_account'] = None
            self.cleaned_data['hosting_account'] = None
            return

        # This should have been caught during validation, so we can assume
        # it's fine.
        hosting_service_cls = get_hosting_service(hosting_type)
        assert hosting_service_cls

        # Validate that the provided tool is valid for the hosting service.
        tool_name = self.cleaned_data['tool'].name

        if tool_name not in hosting_service_cls.supported_scmtools:
            self.errors['tool'] = self.error_class([
                _('This tool is not supported on the given hosting service')
            ])
            return

        # Now make sure all the account info is correct.
        hosting_account = self.cleaned_data['hosting_account']
        username = self.cleaned_data['hosting_account_username']
        password = self.cleaned_data['hosting_account_password']

        if hosting_service_cls.self_hosted:
            hosting_url = self.cleaned_data['hosting_url'] or None
        else:
            hosting_url = None

        if hosting_service_cls.supports_two_factor_auth:
            two_factor_auth_code = \
                self.cleaned_data['hosting_account_two_factor_auth_code']
        else:
            two_factor_auth_code = None

        if hosting_account and hosting_account.hosting_url != hosting_url:
            self.errors['hosting_account'] = self.error_class([
                _('This account is not compatible with this hosting service '
                  'configuration'),
            ])
            return
        elif hosting_account and not username:
            username = hosting_account.username
        elif not hosting_account and not username:
            self.errors['hosting_account'] = self.error_class([
                _('An account must be linked in order to use this hosting '
                  'service'),
            ])
            return

        if not hosting_account:
            # See if this account with the supplied credentials already
            # exists. If it does, we don't want to create a new entry.
            try:
                hosting_account = HostingServiceAccount.objects.get(
                    service_name=hosting_type,
                    username=username,
                    hosting_url=hosting_url,
                    local_site=self.local_site)
            except HostingServiceAccount.DoesNotExist:
                # That's fine. We're just going to create it later.
                pass

        plan = self.cleaned_data['repository_plan'] or self.DEFAULT_PLAN_ID

        # Set the main repository fields (Path, Mirror Path, etc.) based on
        # the field definitions in the hosting service.
        #
        # This will take into account the hosting service's form data for
        # the given repository plan, the main form data, and the hosting
        # account information.
        #
        # It's expected that the required fields will have validated by now.
        repository_form = self.repository_forms[hosting_type][plan]
        field_vars = repository_form.cleaned_data.copy()
        field_vars.update(self.cleaned_data)

        # If the hosting account needs to authorize and link with an external
        # service, attempt to do so and watch for any errors.
        #
        # If it doesn't need to link with it, we'll just create an entry
        # with the username and save it.
        if not hosting_account:
            hosting_account = HostingServiceAccount(
                service_name=hosting_type,
                username=username,
                hosting_url=hosting_url,
                local_site=self.local_site)

        if (hosting_service_cls.needs_authorization and
            not hosting_account.is_authorized):
            # Attempt to authorize the account.
            hosting_service = None
            plan = None

            if hosting_service_cls:
                hosting_service = hosting_service_cls(hosting_account)

                if hosting_service:
                    plan = (self.cleaned_data['repository_plan'] or
                            self.DEFAULT_PLAN_ID)

            repository_extra_data = self._build_repository_extra_data(
                hosting_service, hosting_type, plan)

            try:
                hosting_account.service.authorize(
                    username, password,
                    hosting_url=hosting_url,
                    two_factor_auth_code=two_factor_auth_code,
                    tool_name=tool_name,
                    local_site_name=self.local_site_name,
                    **repository_extra_data)
            except TwoFactorAuthCodeRequiredError as e:
                self.errors['hosting_account'] = \
                    self.error_class([six.text_type(e)])
                hosting_info = self.hosting_service_info[hosting_type]
                hosting_info['needs_two_factor_auth_code'] = True
                return
            except AuthorizationError as e:
                self.errors['hosting_account'] = self.error_class([
                    _('Unable to link the account: %s') % e,
                ])
                return
            except Exception as e:
                self.errors['hosting_account'] = self.error_class([
                    _('Unknown error when linking the account: %s') % e,
                ])
                return

        if hosting_account:
            # Flag that we've linked the account. If there are any
            # validation errors, and this flag is set, we tell the user
            # that we successfully linked and they don't have to do it
            # again.
            self.hosting_account_linked = True
            hosting_account.save()

        self.data['hosting_account'] = hosting_account
        self.cleaned_data['hosting_account'] = hosting_account

        try:
            self.cleaned_data.update(hosting_service_cls.get_repository_fields(
                username=hosting_account.username,
                hosting_url=hosting_account.hosting_url,
                plan=plan,
                tool_name=tool_name,
                field_vars=field_vars))
        except __HOLE__ as e:
            raise ValidationError([six.text_type(e)])
dataset/ETHPy150Open reviewboard/reviewboard/reviewboard/scmtools/forms.py/RepositoryForm._clean_hosting_info