As of January 1, 2020 this library no longer supports Python 2 on the latest released version.
Library versions released prior to that date will continue to be available. For more information please
visit Python 2 support on Google Cloud.
Source code for google.cloud.spanner_v1.keyset
# Copyright 2016 Google LLC All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Wrap representation of Spanner keys / ranges."""
from google.cloud.spanner_v1 import KeyRangePB
from google.cloud.spanner_v1 import KeySetPB
from google.cloud.spanner_v1._helpers import _make_list_value_pb
from google.cloud.spanner_v1._helpers import _make_list_value_pbs
[docs]class KeyRange(object):
"""Identify range of table rows via start / end points.
Specify either a `start_open` or `start_closed` key, or defaults to
`start_closed = []`. Specify either an `end_open` or `end_closed` key,
or defaults to `end_closed = []`. However, at least one key has to be
specified. If no keys are specified, ValueError is raised.
:type start_open: list of scalars
:param start_open: keys identifying start of range (this key excluded)
:type start_closed: list of scalars
:param start_closed: keys identifying start of range (this key included)
:type end_open: list of scalars
:param end_open: keys identifying end of range (this key excluded)
:type end_closed: list of scalars
:param end_closed: keys identifying end of range (this key included)
:raises ValueError: if no keys are specified
"""
def __init__(
self, start_open=None, start_closed=None, end_open=None, end_closed=None
):
if not any([start_open, start_closed, end_open, end_closed]):
raise ValueError("Must specify at least a start or end row.")
if start_open and start_closed:
raise ValueError("Specify one of 'start_open' / 'start_closed'.")
elif start_open is None and start_closed is None:
start_closed = []
if end_open and end_closed:
raise ValueError("Specify one of 'end_open' / 'end_closed'.")
elif end_open is None and end_closed is None:
end_closed = []
self.start_open = start_open
self.start_closed = start_closed
self.end_open = end_open
self.end_closed = end_closed
def _to_pb(self):
"""Construct a KeyRange protobuf.
:rtype: :class:`~google.cloud.spanner_v1.types.KeyRange`
:returns: protobuf corresponding to this instance.
"""
kwargs = {}
if self.start_open is not None:
kwargs["start_open"] = _make_list_value_pb(self.start_open)
if self.start_closed is not None:
kwargs["start_closed"] = _make_list_value_pb(self.start_closed)
if self.end_open is not None:
kwargs["end_open"] = _make_list_value_pb(self.end_open)
if self.end_closed is not None:
kwargs["end_closed"] = _make_list_value_pb(self.end_closed)
return KeyRangePB(**kwargs)
def _to_dict(self):
"""Return the state of the keyrange as a dict.
:rtype: dict
:returns: state of this instance.
"""
mapping = {}
if self.start_open:
mapping["start_open"] = self.start_open
if self.start_closed:
mapping["start_closed"] = self.start_closed
if self.end_open:
mapping["end_open"] = self.end_open
if self.end_closed:
mapping["end_closed"] = self.end_closed
return mapping
[docs] def __eq__(self, other):
"""Compare by serialized state."""
if not isinstance(other, self.__class__):
return NotImplemented
return self._to_dict() == other._to_dict()
[docs]class KeySet(object):
"""Identify table rows via keys / ranges.
:type keys: list of list of scalars
:param keys: keys identifying individual rows within a table.
:type ranges: list of :class:`KeyRange`
:param ranges: ranges identifying rows within a table.
:type all_: boolean
:param all_: if True, identify all rows within a table
"""
def __init__(self, keys=(), ranges=(), all_=False):
if all_ and (keys or ranges):
raise ValueError("'all_' is exclusive of 'keys' / 'ranges'.")
self.keys = list(keys)
self.ranges = list(ranges)
self.all_ = all_
def _to_pb(self):
"""Construct a KeySet protobuf.
:rtype: :class:`~google.cloud.spanner_v1.types.KeySet`
:returns: protobuf corresponding to this instance.
"""
if self.all_:
return KeySetPB(all_=True)
kwargs = {}
if self.keys:
kwargs["keys"] = _make_list_value_pbs(self.keys)
if self.ranges:
kwargs["ranges"] = [krange._to_pb() for krange in self.ranges]
return KeySetPB(**kwargs)
def _to_dict(self):
"""Return the state of the keyset as a dict.
The result can be used to serialize the instance and reconstitute
it later using :meth:`_from_dict`.
:rtype: dict
:returns: state of this instance.
"""
if self.all_:
return {"all": True}
return {
"keys": self.keys,
"ranges": [keyrange._to_dict() for keyrange in self.ranges],
}
[docs] def __eq__(self, other):
"""Compare by serialized state."""
if not isinstance(other, self.__class__):
return NotImplemented
return self._to_dict() == other._to_dict()
@classmethod
def _from_dict(cls, mapping):
"""Create an instance from the corresponding state mapping.
:type mapping: dict
:param mapping: the instance state.
"""
if mapping.get("all"):
return cls(all_=True)
r_mappings = mapping.get("ranges", ())
ranges = [KeyRange(**r_mapping) for r_mapping in r_mappings]
return cls(keys=mapping.get("keys", ()), ranges=ranges)