Skip to content

Commit

Permalink
Implementing query.Parameter.
Browse files Browse the repository at this point in the history
  • Loading branch information
dhermes committed Oct 17, 2018
1 parent 2ae5be5 commit bcf836e
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 4 deletions.
64 changes: 62 additions & 2 deletions ndb/src/google/cloud/ndb/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

"""High-level wrapper for datastore queries."""

from google.cloud.ndb import _exceptions


__all__ = [
"Cursor",
Expand Down Expand Up @@ -64,8 +66,66 @@ def __ne__(self, other):


class Parameter(ParameterizedThing):
def __init__(self, *args, **kwargs):
raise NotImplementedError
"""Represents a bound variable in a GQL query.
``Parameter(1)`` corresponds to a slot labeled ``:1`` in a GQL query.
``Parameter('xyz')`` corresponds to a slot labeled ``:xyz``.
The value must be set (bound) separately by calling :meth:`set`.
Args:
key (Union[str, int]): The parameter key.
Raises:
TypeError: If the ``key`` is not a string or integer.
"""

def __init__(self, key):
if not isinstance(key, (int, str, bytes)):
raise TypeError(
"Parameter key must be an integer or string, not {}".format(
key
)
)
self._key = key

def __repr__(self):
return "{}({!r})".format(self.__class__.__name__, self._key)

def __eq__(self, other):
if not isinstance(other, Parameter):
return NotImplemented

return self._key == other._key

@property
def key(self):
"""Retrieve the key."""
return self._key

def resolve(self, bindings, used):
"""Resolve the current parameter from the parameter bindings.
Args:
bindings (dict): A mapping of parameter bindings.
used (Dict[Union[str, int], bool]): A mapping of already used
parameters. This will be modified if the current parameter
is in ``bindings``.
Returns:
Any: The bound value for the current parameter.
Raises:
.BadArgumentError: If the current parameter is not in ``bindings``.
"""
key = self._key
if key not in bindings:
raise _exceptions.BadArgumentError(
"Parameter :{} is not bound.".format(key)
)
value = bindings[key]
used[key] = True
return value


class ParameterizedFunction(ParameterizedThing):
Expand Down
60 changes: 58 additions & 2 deletions ndb/tests/unit/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest.mock

import pytest

from google.cloud.ndb import _exceptions
from google.cloud.ndb import query
import tests.unit.utils

Expand Down Expand Up @@ -57,8 +60,61 @@ def test___ne__():
class TestParameter:
@staticmethod
def test_constructor():
with pytest.raises(NotImplementedError):
query.Parameter()
for key in (88, b"abc", "def"):
parameter = query.Parameter(key)
assert parameter._key == key

@staticmethod
def test_constructor_invalid():
with pytest.raises(TypeError):
query.Parameter(None)

@staticmethod
def test___repr__():
parameter = query.Parameter("ghi")
assert repr(parameter) == "Parameter('ghi')"

@staticmethod
def test___eq__():
parameter1 = query.Parameter("yep")
parameter2 = query.Parameter("nope")
parameter3 = unittest.mock.sentinel.parameter
assert parameter1 == parameter1
assert not parameter1 == parameter2
assert not parameter1 == parameter3

@staticmethod
def test___ne__():
parameter1 = query.Parameter("yep")
parameter2 = query.Parameter("nope")
parameter3 = unittest.mock.sentinel.parameter
assert not parameter1 != parameter1
assert parameter1 != parameter2
assert parameter1 != parameter3

@staticmethod
def test_key():
parameter = query.Parameter(9000)
assert parameter.key == 9000

@staticmethod
def test_resolve():
key = 9000
bound_value = "resoolt"
parameter = query.Parameter(key)
used = {}
result = parameter.resolve({key: bound_value}, used)
assert result == bound_value
assert used == {key: True}

@staticmethod
def test_resolve_missing_key():
parameter = query.Parameter(9000)
used = {}
with pytest.raises(_exceptions.BadArgumentError):
parameter.resolve({}, used)

assert used == {}


class TestParameterizedFunction:
Expand Down

0 comments on commit bcf836e

Please sign in to comment.