Clone a Scope.

        This will clone a scope if the client has the right to do so. Sufficient permissions to clone a scope are a
        superuser, a user in the `GG:Configurators` group and a user that is Scope manager of the scope to be
        clone and member of the `GG:Managers` group as well.

        If no additional arguments are provided, the values of the `source_scope` are used for the new scope.

        .. versionadded: 2.6

        :param source_scope: Scope object to be cloned itself
        :type source_scope: :class:`models.Scope`
        :param name: (optional) new name of the scope
        :type name: basestring or None
        :param status: (optional) statis of the new scope
        :type status: one of :class:`enums.ScopeStatus`
        :param tags: (optional) list of new scope tags
        :type tags: list or None
        :param start_date: (optional) start date of the to be cloned scope
        :type start_date: datetime or None
        :param due_date: (optional) due data of the to be cloned scope
        :type due_date: datetime or None
        :param description: (optional) description of the new scope
        :type description: basestring or None
        :param team: (optional) team_id or Team object to assign membership of scope to a team.
        :type team: basestring or :class:`models.Team` or None
        # :param scope_options: (optional) dictionary with scope options (NO EFFECT)
        # :type scope_options: dict or None
        :param asynchronous: (optional) option to use asynchronous cloning of the scope, default to False.
        :type asynchronous: bool or None
        :return: New scope that is cloned
        :rtype: :class:`models.Scope`
        :raises IllegalArgumentError: When the provided arguments are incorrect
        :raises APIError: When the server is unable to clone the scope (eg. permissions)

def clone_scope(self, source_scope, name=None, status=None, start_date=None, due_date=None,
                    description=None, tags=None, team=None, asynchronous=False):
        """
        Clone a Scope.

        This will clone a scope if the client has the right to do so. Sufficient permissions to clone a scope are a
        superuser, a user in the `GG:Configurators` group and a user that is Scope manager of the scope to be
        clone and member of the `GG:Managers` group as well.

        If no additional arguments are provided, the values of the `source_scope` are used for the new scope.

        .. versionadded: 2.6

        :param source_scope: Scope object to be cloned itself
        :type source_scope: :class:`models.Scope`
        :param name: (optional) new name of the scope
        :type name: basestring or None
        :param status: (optional) statis of the new scope
        :type status: one of :class:`enums.ScopeStatus`
        :param tags: (optional) list of new scope tags
        :type tags: list or None
        :param start_date: (optional) start date of the to be cloned scope
        :type start_date: datetime or None
        :param due_date: (optional) due data of the to be cloned scope
        :type due_date: datetime or None
        :param description: (optional) description of the new scope
        :type description: basestring or None
        :param team: (optional) team_id or Team object to assign membership of scope to a team.
        :type team: basestring or :class:`models.Team` or None
        # :param scope_options: (optional) dictionary with scope options (NO EFFECT)
        # :type scope_options: dict or None
        :param asynchronous: (optional) option to use asynchronous cloning of the scope, default to False.
        :type asynchronous: bool or None
        :return: New scope that is cloned
        :rtype: :class:`models.Scope`
        :raises IllegalArgumentError: When the provided arguments are incorrect
        :raises APIError: When the server is unable to clone the scope (eg. permissions)
        """
        if not isinstance(source_scope, Scope):
            raise IllegalArgumentError('`source_scope` should be a `Scope` object')

        data_dict = {'id': source_scope.id, 'async': asynchronous}

        if name is not None:
            if not isinstance(name, (string_types, text_type)):
                raise IllegalArgumentError("`name` should be a string")
            data_dict['name'] = str(name)

        if start_date is not None:
            if isinstance(start_date, datetime.datetime):
                if not start_date.tzinfo:
                    warnings.warn("The duedate '{}' is naive and not timezone aware, use pytz.timezone info. "
                                  "This date is interpreted as UTC time.".format(start_date.isoformat(sep=' ')))
                data_dict['start_date'] = start_date.isoformat(sep='T')
            else:
                raise IllegalArgumentError('Start date should be a datetime.datetime() object')

        if due_date is not None:
            if isinstance(due_date, datetime.datetime):
                if not due_date.tzinfo:
                    warnings.warn("The duedate '{}' is naive and not timezone aware, use pytz.timezone info. "
                                  "This date is interpreted as UTC time.".format(due_date.isoformat(sep=' ')))
                data_dict['due_date'] = due_date.isoformat(sep='T')
            else:
                raise IllegalArgumentError('Due date should be a datetime.datetime() object')

        if description is not None:
            if not isinstance(description, (text_type, string_types)):
                raise IllegalArgumentError("`description` should be a string")
            else:
                data_dict['text'] = description

        if status is not None:
            if status not in ScopeStatus.values():
                raise IllegalArgumentError("`status` should be one of '{}'".format(ScopeStatus.values()))
            else:
                data_dict['status'] = str(status)

        if tags is not None:
            if not isinstance(tags, list):
                raise IllegalArgumentError("'Tags' should be provided as a list, was provided as '{}'".
                                           format(type(tags)))
            if not (all([isinstance(t, (str, text_type)) for t in tags])):
                raise IllegalArgumentError("Each tag in the list of tags should be provided as a string")
            data_dict['tags'] = tags

        if team is not None:
            if isinstance(team, Team):
                team_id = team.id
            elif is_uuid(team):
                team_id = team
            elif isinstance(team, (text_type, string_types)):
                team_id = self.team(name=team).id
            else:
                raise IllegalArgumentError("`team` should be a name of an existing team or UUID of a team")
            data_dict['team'] = team_id

        url = self._build_url('scopes')
        query_params = dict(select_action='clone')
        response = self._request('POST', url,
                                 params=query_params,
                                 json=data_dict)

        if response.status_code != requests.codes.created:  # pragma: no cover
            if response.status_code == requests.codes.forbidden:
                raise ForbiddenError("Could not clone scope, {}: {}".format(str(response), response.content))
            else:
                raise APIError("Could not clone scope, {}: {}".format(str(response), response.content))

        return Scope(response.json()['results'][0], client=source_scope._client)