<commit_before>import abc

from uuid import UUID

from typing import *

from .options import OptionBlock, forward_args, OptionBlockDeriv
from .bucket import BucketOptions, Bucket, CoreBucket
from couchbase_core.cluster import Cluster as SDK2Cluster, Authenticator as SDK2Authenticator
from .exceptions import SearchException
T=TypeVar('T')


class QueryMetrics(object):
    pass


class IQueryResult:
    def request_id(self):
        # type: (...) ->UUID
        pass

    def client_context_id(self):
        # type: (...)->str
        pass

    def signature(self):
        # type: (...)->Any
        pass

    def rows(self):
        # type: (...)->List[T]
        pass

    def warnings(self):
        # type: (...)->List[Warning]
        pass

    def metrics(self):
        # type: (...)->QueryMetrics
        pass


CallableOnOptionBlock = Callable[[OptionBlockDeriv, Any], Any]


def options_to_func(orig,  # type: U
                    verb  # type: CallableOnOptionBlock
                    ):
    class invocation:
        # type: (...)->Callable[[T,Tuple[OptionBlockDeriv,...],Any],Any]
        def __init__(self,  # type: T
                       *options,  # type: OptionBlockDeriv
                       **kwargs  # type: Any
                       ):
            # type: (...)->None
            self.orig=orig
            self.options=options
            self.kwargs=kwargs

        def __call__(self, *args, **kwargs):
            # type: (...)->Callable[[T,Tuple[OptionBlockDeriv,...],Any],Any]
            def invocator(self, *options, **kwargs):
                return verb(self, forward_args(kwargs, *options))
            return invocator

    return invocation(orig)


class QueryOptions(OptionBlock, IQueryResult):
    @property
    @abc.abstractmethod
    def is_live(self):
        return False

    def __init__(self, statement=None, parameters=None, timeout=None):

        """
        Executes a N1QL query against the remote cluster returning a IQueryResult with the results of the query.
        :param statement: N1QL query
        :param options: the optional parameters that the Query service takes. See The N1QL Query API for details or a SDK 2.0 implementation for detail.
        :return: An IQueryResult object with the results of the query or error message if the query failed on the server.
        :except Any exceptions raised by the underlying platform - HTTP_TIMEOUT for example.
        :except ServiceNotFoundException - service does not exist or cannot be located.

        """
        super(QueryOptions, self).__init__(statement=statement, parameters=parameters, timeout=timeout)


class Cluster:
    class ClusterOptions(OptionBlock):
        pass

    def __init__(self,
                 connection_string=None,  # type: str
                 *options  # type: ClusterOptions
                 ):
        cluster_opts=forward_args(None, *options)
        cluster_opts.update(bucket_class=lambda connstr, bname=None, **kwargs: Bucket(connstr,bname, BucketOptions(**kwargs)))
        self._cluster = SDK2Cluster(connection_string, **cluster_opts)  # type: SDK2Cluster

    def authenticate(self,
                     authenticator=None,  # type: SDK2Authenticator
                     username=None,  # type: str
                     password=<PASSWORD>  # type: str
                     ):
        self._cluster.authenticate(authenticator, username, password)

    def bucket(self,
               name,  # type: str,
               *options,  # type: BucketOptions
               **kwargs
               ):
        # type: (...)->Bucket
        args=forward_args(kwargs,*options)
        args.update(bname=name)
        return self._cluster.open_bucket(name, **args)

    class QueryParameters(OptionBlock):
        def __init__(self, *args, **kwargs):
            super(Cluster.QueryParameters, self).__init__(*args, **kwargs)

    @overload
    def query(self,
              statement,
              parameters=None,
              timeout=None):
        pass

    @overload
    def query(self,
              statement,  # type: str,
              *options  # type: QueryOptions
              ):
        # type: (...)->IQueryResult
        pass

    def query_real(self,
                   statement,
                   *options, **kwargs):
        # type: (str, Any, Any) -> IQueryResult
        result = self._cluster.n1ql_query(statement, forward_args(kwargs, *options))
        return result

    @options_to_func(QueryOptions, query_real)
    class query:
        __doc__ = QueryOptions.__doc__

    def _operate_on_first_bucket(self, verb, failtype, *args, **kwargs):
        first_bucket = next(iter(self._cluster._buckets), None)  # type: Optional[couchbase.CoreBucket]
        if not first_bucket:
            raise failtype("Need at least one bucket active to perform search")
        return verb(first_bucket, *args, **kwargs)

    def analytics_query(self,
                        statement,  # type: str,
                        *options,  # type: AnalyticsOptions
                        **kwargs
                        ):
        # type: (...)->IAnalyticsResult
        """
        Executes an Analytics query against the remote cluster and returns a IAnalyticsResult with the results of the query.
        :param statement: the analytics statement to execute
        :param options: the optional parameters that the Analytics service takes based on the Analytics RFC.
        :return: An IAnalyticsResult object with the results of the query or error message if the query failed on the server.
        Throws Any exceptions raised by the underlying platform - HTTP_TIMEOUT for example.
        :except ServiceNotFoundException - service does not exist or cannot be located.<commit_msg>PYCBC-541: Correct cluster query syntax/docs<commit_after>import abc

from uuid import UUID

from typing import *

from .options import OptionBlock, forward_args, OptionBlockDeriv
from .bucket import BucketOptions, Bucket, CoreBucket
from couchbase_core.cluster import Cluster as SDK2Cluster, Authenticator as SDK2Authenticator
from .exceptions import SearchException
T=TypeVar('T')


class QueryMetrics(object):
    pass


class IQueryResult:
    def request_id(self):
        # type: (...) ->UUID
        pass

    def client_context_id(self):
        # type: (...)->str
        pass

    def signature(self):
        # type: (...)->Any
        pass

    def rows(self):
        # type: (...)->List[T]
        pass

    def warnings(self):
        # type: (...)->List[Warning]
        pass

    def metrics(self):
        # type: (...)->QueryMetrics
        pass


CallableOnOptionBlock = Callable[[OptionBlockDeriv, Any], Any]


def options_to_func(orig,  # type: U
                    verb  # type: CallableOnOptionBlock
                    ):
    class invocation:
        # type: (...)->Callable[[T,Tuple[OptionBlockDeriv,...],Any],Any]
        def __init__(self,  # type: T
                       *options,  # type: OptionBlockDeriv
                       **kwargs  # type: Any
                       ):
            # type: (...)->None
            self.orig=orig
            self.options=options
            self.kwargs=kwargs

        def __call__(self, *args, **kwargs):
            # type: (...)->Callable[[T,Tuple[OptionBlockDeriv,...],Any],Any]
            def invocator(self, *options, **kwargs):
                return verb(self, forward_args(kwargs, *options))
            return invocator

    return invocation(orig)


class QueryOptions(OptionBlock, IQueryResult):
    @property
    @abc.abstractmethod
    def is_live(self):
        return False

    def __init__(self, statement=None, parameters=None, timeout=None):

        """
        Executes a N1QL query against the remote cluster returning a IQueryResult with the results of the query.
        :param statement: N1QL query
        :param options: the optional parameters that the Query service takes. See The N1QL Query API for details or a SDK 2.0 implementation for detail.
        :return: An IQueryResult object with the results of the query or error message if the query failed on the server.
        :except Any exceptions raised by the underlying platform - HTTP_TIMEOUT for example.
        :except ServiceNotFoundException - service does not exist or cannot be located.

        """
        super(QueryOptions, self).__init__(statement=statement, parameters=parameters, timeout=timeout)


class Cluster:
    class ClusterOptions(OptionBlock):
        pass

    def __init__(self,
                 connection_string=None,  # type: str
                 *options  # type: ClusterOptions
                 ):
        cluster_opts=forward_args(None, *options)
        cluster_opts.update(bucket_class=lambda connstr, bname=None, **kwargs: Bucket(connstr,bname, BucketOptions(**kwargs)))
        self._cluster = SDK2Cluster(connection_string, **cluster_opts)  # type: SDK2Cluster

    def authenticate(self,
                     authenticator=None,  # type: SDK2Authenticator
                     username=None,  # type: str
                     password=<PASSWORD>  # type: str
                     ):
        self._cluster.authenticate(authenticator, username, password)

    def bucket(self,
               name,  # type: str,
               *options,  # type: BucketOptions
               **kwargs
               ):
        # type: (...)->Bucket
        args=forward_args(kwargs,*options)
        args.update(bname=name)
        return self._cluster.open_bucket(name, **args)

    class QueryParameters(OptionBlock):
        def __init__(self, *args, **kwargs):
            super(Cluster.QueryParameters, self).__init__(*args, **kwargs)

    @overload
    def query(self,
              statement,
              parameters=None,
              timeout=None):
        pass

    @overload
    def query(self,
              statement,  # type: str,
              *options  # type: QueryOptions
              ):
        # type: (...)->IQueryResult
        pass

    def query(self,
              statement,
              *options,  # type: QueryOptions
              **kwargs):
        # type: (str, Any, Any) -> IQueryResult
        """

        :param str statement: the N1QL query statement to execute
        :param QueryOptions options: the optional parameters that the Query service takes.
            See The N1QL Query API for details or a SDK 2.0 implementation for detail.

        :return: An :class:`IQueryResult` object with the results of the query or error message
        if the query failed on the server.

        """
        result = self._cluster.n1ql_query(statement, forward_args(kwargs, *options))
        return result

    def _operate_on_first_bucket(self, verb, failtype, *args, **kwargs):
        first_bucket = next(iter(self._cluster._buckets), None)  # type: Optional[couchbase.CoreBucket]
        if not first_bucket:
            raise failtype("Need at least one bucket active to perform search")
        return verb(first_bucket, *args, **kwargs)

    def analytics_query(self,
                        statement,  # type: str,
                        *options,  # type: AnalyticsOptions
                        **kwargs
                        ):
        # type: (...)->IAnalyticsResult
        """
        Executes an Analytics query against the remote cluster and returns a IAnalyticsResult with the results of the query.
        :param statement: the analytics statement to execute
        :param options: the optional parameters that the Analytics service takes based on the Analytics RFC.
        :return: An IAnalyticsResult object with the results of the query or error message if the query failed on the server.
        Throws Any exceptions raised by the underlying platform - HTTP_TIMEOUT for example.
        :except ServiceNotFoundException - service does not exist or cannot be located.
{'fraction_non_alphanumeric': 0.09172146349688079, 'fraction_numerical': 0.0024447816557073006, 'mean_word_length': 2.150863213811421, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1161373', 'n_tokens_mistral': 3136, 'n_tokens_neox': 3006, 'n_words': 953}