Reads rows from the database using key lookups and scans, as a simple
        key/value style alternative to ``ExecuteSql``. This method cannot be
        used to return a result set larger than 10 MiB; if the read matches more
        data than that, the read fails with a ``FAILED_PRECONDITION`` error.

        Reads inside read-write transactions might return ``ABORTED``. If this
        occurs, the application should restart the transaction from the
        beginning. See ``Transaction`` for more details.

        Larger result sets can be yielded in streaming fashion by calling
        ``StreamingRead`` instead.

        Example:
            >>> from google.cloud import spanner_v1
            >>>
            >>> client = spanner_v1.SpannerClient()
            >>>
            >>> session = client.session_path('[PROJECT]', '[INSTANCE]', '[DATABASE]', '[SESSION]')
            >>>
            >>> # TODO: Initialize `table`:
            >>> table = ''
            >>>
            >>> # TODO: Initialize `columns`:
            >>> columns = []
            >>>
            >>> # TODO: Initialize `key_set`:
            >>> key_set = {}
            >>>
            >>> response = client.read(session, table, columns, key_set)

        Args:
            session (str): Required. The session in which the read should be performed.
            table (str): Required. The name of the table in the database to be read.
            columns (list[str]): The columns of ``table`` to be returned for each row matching this
                request.
            key_set (Union[dict, ~google.cloud.spanner_v1.types.KeySet]): Required. ``key_set`` identifies the rows to be yielded. ``key_set``
                names the primary keys of the rows in ``table`` to be yielded, unless
                ``index`` is present. If ``index`` is present, then ``key_set`` instead
                names index keys in ``index``.

                If the ``partition_token`` field is empty, rows are yielded in table
                primary key order (if ``index`` is empty) or index key order (if
                ``index`` is non-empty). If the ``partition_token`` field is not empty,
                rows will be yielded in an unspecified order.

                It is not an error for the ``key_set`` to name rows that do not exist in
                the database. Read yields nothing for nonexistent rows.

                If a dict is provided, it must be of the same form as the protobuf
                message :class:`~google.cloud.spanner_v1.types.KeySet`
            transaction (Union[dict, ~google.cloud.spanner_v1.types.TransactionSelector]): The transaction to use. If none is provided, the default is a
                temporary read-only transaction with strong concurrency.

                If a dict is provided, it must be of the same form as the protobuf
                message :class:`~google.cloud.spanner_v1.types.TransactionSelector`
            index (str): If non-empty, the name of an index on ``table``. This index is used
                instead of the table primary key when interpreting ``key_set`` and
                sorting result rows. See ``key_set`` for further information.
            limit (long): If greater than zero, only the first ``limit`` rows are yielded. If
                ``limit`` is zero, the default is no limit. A limit cannot be specified
                if ``partition_token`` is set.
            resume_token (bytes): If this request is resuming a previously interrupted read,
                ``resume_token`` should be copied from the last ``PartialResultSet``
                yielded before the interruption. Doing this enables the new read to
                resume where the last read left off. The rest of the request parameters
                must exactly match the request that yielded this token.
            partition_token (bytes): If present, results will be restricted to the specified partition
                previously created using PartitionRead(). There must be an exact match
                for the values of fields common to this message and the
                PartitionReadRequest message used to create this partition\_token.
            retry (Optional[google.api_core.retry.Retry]):  A retry object used
                to retry requests. If ``None`` is specified, requests will not
                be retried.
            timeout (Optional[float]): The amount of time, in seconds, to wait
                for the request to complete. Note that if ``retry`` is
                specified, the timeout applies to each individual attempt.
            metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata
                that is provided to the method.

        Returns:
            A :class:`~google.cloud.spanner_v1.types.ResultSet` instance.

        Raises:
            google.api_core.exceptions.GoogleAPICallError: If the request
                    failed for any reason.
            google.api_core.exceptions.RetryError: If the request failed due
                    to a retryable error and retry attempts failed.
            ValueError: If the parameters are invalid.

def read(
        self,
        session,
        table,
        columns,
        key_set,
        transaction=None,
        index=None,
        limit=None,
        resume_token=None,
        partition_token=None,
        retry=google.api_core.gapic_v1.method.DEFAULT,
        timeout=google.api_core.gapic_v1.method.DEFAULT,
        metadata=None,
    ):
        """
        Reads rows from the database using key lookups and scans, as a simple
        key/value style alternative to ``ExecuteSql``. This method cannot be
        used to return a result set larger than 10 MiB; if the read matches more
        data than that, the read fails with a ``FAILED_PRECONDITION`` error.

        Reads inside read-write transactions might return ``ABORTED``. If this
        occurs, the application should restart the transaction from the
        beginning. See ``Transaction`` for more details.

        Larger result sets can be yielded in streaming fashion by calling
        ``StreamingRead`` instead.

        Example:
            >>> from google.cloud import spanner_v1
            >>>
            >>> client = spanner_v1.SpannerClient()
            >>>
            >>> session = client.session_path('[PROJECT]', '[INSTANCE]', '[DATABASE]', '[SESSION]')
            >>>
            >>> # TODO: Initialize `table`:
            >>> table = ''
            >>>
            >>> # TODO: Initialize `columns`:
            >>> columns = []
            >>>
            >>> # TODO: Initialize `key_set`:
            >>> key_set = {}
            >>>
            >>> response = client.read(session, table, columns, key_set)

        Args:
            session (str): Required. The session in which the read should be performed.
            table (str): Required. The name of the table in the database to be read.
            columns (list[str]): The columns of ``table`` to be returned for each row matching this
                request.
            key_set (Union[dict, ~google.cloud.spanner_v1.types.KeySet]): Required. ``key_set`` identifies the rows to be yielded. ``key_set``
                names the primary keys of the rows in ``table`` to be yielded, unless
                ``index`` is present. If ``index`` is present, then ``key_set`` instead
                names index keys in ``index``.

                If the ``partition_token`` field is empty, rows are yielded in table
                primary key order (if ``index`` is empty) or index key order (if
                ``index`` is non-empty). If the ``partition_token`` field is not empty,
                rows will be yielded in an unspecified order.

                It is not an error for the ``key_set`` to name rows that do not exist in
                the database. Read yields nothing for nonexistent rows.

                If a dict is provided, it must be of the same form as the protobuf
                message :class:`~google.cloud.spanner_v1.types.KeySet`
            transaction (Union[dict, ~google.cloud.spanner_v1.types.TransactionSelector]): The transaction to use. If none is provided, the default is a
                temporary read-only transaction with strong concurrency.

                If a dict is provided, it must be of the same form as the protobuf
                message :class:`~google.cloud.spanner_v1.types.TransactionSelector`
            index (str): If non-empty, the name of an index on ``table``. This index is used
                instead of the table primary key when interpreting ``key_set`` and
                sorting result rows. See ``key_set`` for further information.
            limit (long): If greater than zero, only the first ``limit`` rows are yielded. If
                ``limit`` is zero, the default is no limit. A limit cannot be specified
                if ``partition_token`` is set.
            resume_token (bytes): If this request is resuming a previously interrupted read,
                ``resume_token`` should be copied from the last ``PartialResultSet``
                yielded before the interruption. Doing this enables the new read to
                resume where the last read left off. The rest of the request parameters
                must exactly match the request that yielded this token.
            partition_token (bytes): If present, results will be restricted to the specified partition
                previously created using PartitionRead(). There must be an exact match
                for the values of fields common to this message and the
                PartitionReadRequest message used to create this partition\_token.
            retry (Optional[google.api_core.retry.Retry]):  A retry object used
                to retry requests. If ``None`` is specified, requests will not
                be retried.
            timeout (Optional[float]): The amount of time, in seconds, to wait
                for the request to complete. Note that if ``retry`` is
                specified, the timeout applies to each individual attempt.
            metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata
                that is provided to the method.

        Returns:
            A :class:`~google.cloud.spanner_v1.types.ResultSet` instance.

        Raises:
            google.api_core.exceptions.GoogleAPICallError: If the request
                    failed for any reason.
            google.api_core.exceptions.RetryError: If the request failed due
                    to a retryable error and retry attempts failed.
            ValueError: If the parameters are invalid.
        """
        # Wrap the transport method to add retry and timeout logic.
        if "read" not in self._inner_api_calls:
            self._inner_api_calls["read"] = google.api_core.gapic_v1.method.wrap_method(
                self.transport.read,
                default_retry=self._method_configs["Read"].retry,
                default_timeout=self._method_configs["Read"].timeout,
                client_info=self._client_info,
            )

        request = spanner_pb2.ReadRequest(
            session=session,
            table=table,
            columns=columns,
            key_set=key_set,
            transaction=transaction,
            index=index,
            limit=limit,
            resume_token=resume_token,
            partition_token=partition_token,
        )
        if metadata is None:
            metadata = []
        metadata = list(metadata)
        try:
            routing_header = [("session", session)]
        except AttributeError:
            pass
        else:
            routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata(
                routing_header
            )
            metadata.append(routing_metadata)

        return self._inner_api_calls["read"](
            request, retry=retry, timeout=timeout, metadata=metadata
        )