Example #1
0
    def _IN(self, value):
        """For the ``in`` comparison operator.

        The ``in`` operator cannot be overloaded in the way we want
        to, so we define a method. For example:

        .. code-block:: python

            Employee.query(Employee.rank.IN([4, 5, 6]))

        Note that the method is called ``_IN()`` but may normally be invoked
        as ``IN()``; ``_IN()`` is provided for the case that a
        :class:`.StructuredProperty` refers to a model that has a property
        named ``IN``.

        Args:
            value (Iterable[Any]): The set of values that the property value
                must be contained in.

        Returns:
            Union[~google.cloud.ndb.query.DisjunctionNode, \
                ~google.cloud.ndb.query.FilterNode, \
                ~google.cloud.ndb.query.FalseNode]: A node corresponding
            to the desired in filter.

            * If ``value`` is empty, this will return a :class:`.FalseNode`
            * If ``len(value) == 1``, this will return a :class:`.FilterNode`
            * Otherwise, this will return a :class:`.DisjunctionNode`

        Raises:
            ~google.cloud.ndb.exceptions.BadFilterError: If the current
                property is not indexed.
            ~google.cloud.ndb.exceptions.BadArgumentError: If ``value`` is not
                a basic container (:class:`list`, :class:`tuple`, :class:`set`
                or :class:`frozenset`).
        """
        # Import late to avoid circular imports.
        from google.cloud.ndb import query

        if not self._indexed:
            raise exceptions.BadFilterError(
                "Cannot query for unindexed property {}".format(self._name)
            )

        if not isinstance(value, (list, tuple, set, frozenset)):
            raise exceptions.BadArgumentError(
                "Expected list, tuple or set, got {!r}".format(value)
            )

        values = []
        for sub_value in value:
            if sub_value is not None:
                sub_value = self._do_validate(sub_value)
                sub_value = self._call_to_base_type(sub_value)
                sub_value = self._datastore_type(sub_value)
            values.append(sub_value)

        return query.FilterNode(self._name, "in", values)
Example #2
0
    def _to_filter(self, post=False):
        """Helper to convert to low-level filter, or :data:`None`.

        Args:
            post (bool): Indicates if this is a post-filter node.

        Raises:
            .BadArgumentError: Always. This is because this node represents
            a parameter, i.e. no value exists to be filtered on.
        """
        raise exceptions.BadArgumentError("Parameter :{} is not bound.".format(
            self._param.key))
Example #3
0
def _clean_flat_path(flat):
    """Verify and convert the flat path for a key.

    This may modify ``flat`` in place. In particular, if the last element is
    :data:`None` (for a partial key), this will pop it off the end. Also
    if some of the kinds are instance of :class:`.Model`, they will be
    converted to strings in ``flat``.

    Args:
        flat (List[Union[str, int]]): The flattened path as a list.

    Raises:
        TypeError: If the kind in a pair is an invalid type.
        .BadArgumentError: If a key ID is :data:`None` (indicating a partial
           key), but in a pair other than the last one.
        TypeError: If a key ID is not a string or integer.
    """
    # Verify the inputs in ``flat``.
    for i in range(0, len(flat), 2):
        # Make sure the ``kind`` is either a string or a Model.
        kind = flat[i]
        if isinstance(kind, type):
            kind = kind._get_kind()
            flat[i] = kind
        if not isinstance(kind, str):
            raise TypeError(
                "Key kind must be a string or Model class; "
                "received {!r}".format(kind)
            )
        # Make sure the ``id_`` is either a string or int. In the special case
        # of a partial key, ``id_`` can be ``None`` for the last pair.
        id_ = flat[i + 1]
        if id_ is None:
            if i + 2 < len(flat):
                raise exceptions.BadArgumentError(
                    "Incomplete Key entry must be last"
                )
        elif not isinstance(id_, (str, int)):
            raise TypeError(_INVALID_ID_TYPE.format(id_))

    # Remove trailing ``None`` for a partial key.
    if flat[-1] is None:
        flat.pop()
Example #4
0
    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
Example #5
0
 def cursor_after(self):
     """Implements :meth:`QueryIterator.cursor_after`."""
     raise exceptions.BadArgumentError("Can't have cursors with OR filter")
Example #6
0
    def cursor_after(self):
        """Implements :meth:`QueryIterator.cursor_after."""
        if self._cursor_after is None:
            raise exceptions.BadArgumentError("There is no cursor currently")

        return self._cursor_after