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)
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))
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()
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
def cursor_after(self): """Implements :meth:`QueryIterator.cursor_after`.""" raise exceptions.BadArgumentError("Can't have cursors with OR filter")
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