예제 #1
0
    def _normalize_cursor(cursor, orders):
        """Helper: convert cursor to a list of values based on orders."""
        if cursor is None:
            return

        if not orders:
            raise ValueError(_NO_ORDERS_FOR_CURSOR)

        document_fields, before = cursor

        order_keys = [order.field.field_path for order in orders]

        if isinstance(document_fields, dict):
            # Transform to list using orders
            values = []
            data = document_fields
            for order_key in order_keys:
                try:
                    values.append(_helpers.get_nested_value(order_key, data))
                except KeyError:
                    msg = _MISSING_ORDER_BY.format(order_key, data)
                    raise ValueError(msg)
            document_fields = values

        if len(document_fields) != len(orders):
            msg = _MISMATCH_CURSOR_W_ORDER_BY.format(document_fields, order_keys)
            raise ValueError(msg)

        _transform_bases = (transforms.Sentinel, transforms._ValueList)
        for field in document_fields:
            if isinstance(field, _transform_bases):
                msg = _INVALID_CURSOR_TRANSFORM
                raise ValueError(msg)

        return document_fields, before
예제 #2
0
    def get(self, field_path):
        """Get a value from the snapshot data.

        If the data is nested, for example:

        .. code-block:: python

           >>> snapshot.to_dict()
           {
               'top1': {
                   'middle2': {
                       'bottom3': 20,
                       'bottom4': 22,
                   },
                   'middle5': True,
               },
               'top6': b'\x00\x01 foo',
           }

        a **field path** can be used to access the nested data. For
        example:

        .. code-block:: python

           >>> snapshot.get('top1')
           {
               'middle2': {
                   'bottom3': 20,
                   'bottom4': 22,
               },
               'middle5': True,
           }
           >>> snapshot.get('top1.middle2')
           {
               'bottom3': 20,
               'bottom4': 22,
           }
           >>> snapshot.get('top1.middle2.bottom3')
           20

        See :meth:`~.firestore_v1beta1.client.Client.field_path` for
        more information on **field paths**.

        A copy is returned since the data may contain mutable values,
        but the data stored in the snapshot must remain immutable.

        Args:
            field_path (str): A field path (``.``-delimited list of
                field names).

        Returns:
            Any: (A copy of) the value stored for the ``field_path``.

        Raises:
            KeyError: If the ``field_path`` does not match nested data
                in the snapshot.
        """
        nested_data = _helpers.get_nested_value(field_path, self._data)
        return copy.deepcopy(nested_data)
예제 #3
0
def _cursor_pb(cursor_pair, orders):
    """Convert a cursor pair to a protobuf.

    If ``cursor_pair`` is :data:`None`, just returns :data:`None`.

    Args:
        cursor_pair (Optional[Tuple[dict, bool]]): Two-tuple of

            * a mapping of fields. Any field that is present in this mapping
              must also be present in ``orders``
            * a ``before`` flag

        orders (Tuple[google.cloud.proto.firestore.v1beta1.\
            query_pb2.StructuredQuery.Order, ...]]): The "order by" entries
            to use for a query. (We use this rather than a list of field path
            strings just because it is how a query stores calls
            to ``order_by``.)

    Returns:
        Optional[google.cloud.firestore_v1beta1.types.Cursor]: A
        protobuf cursor corresponding to the values.

    Raises:
        ValueError: If ``cursor_pair`` is not :data:`None`, but there are
            no ``orders``.
        ValueError: If one of the field paths in ``orders`` is not contained
            in the ``data`` (i.e. the first component of ``cursor_pair``).
    """
    if cursor_pair is None:
        return None

    if len(orders) == 0:
        raise ValueError(_NO_ORDERS_FOR_CURSOR)

    data, before = cursor_pair
    value_pbs = []
    for order in orders:
        field_path = order.field.field_path
        try:
            value = _helpers.get_nested_value(field_path, data)
        except KeyError:
            msg = _MISSING_ORDER_BY.format(field_path, data)
            raise ValueError(msg)

        value_pb = _helpers.encode_value(value)
        value_pbs.append(value_pb)

    return query_pb2.Cursor(values=value_pbs, before=before)
예제 #4
0
    def _normalize_cursor(self, cursor, orders):
        """Helper: convert cursor to a list of values based on orders."""
        if cursor is None:
            return

        if not orders:
            raise ValueError(_NO_ORDERS_FOR_CURSOR)

        document_fields, before = cursor

        order_keys = [order.field.field_path for order in orders]

        if isinstance(document_fields, dict):
            # Transform to list using orders
            values = []
            data = document_fields
            for order_key in order_keys:
                try:
                    values.append(_helpers.get_nested_value(order_key, data))
                except KeyError:
                    msg = _MISSING_ORDER_BY.format(order_key, data)
                    raise ValueError(msg)
            document_fields = values

        if len(document_fields) != len(orders):
            msg = _MISMATCH_CURSOR_W_ORDER_BY.format(document_fields,
                                                     order_keys)
            raise ValueError(msg)

        _transform_bases = (transforms.Sentinel, transforms._ValueList)

        for index, key_field in enumerate(zip(order_keys, document_fields)):
            key, field = key_field

            if isinstance(field, _transform_bases):
                msg = _INVALID_CURSOR_TRANSFORM
                raise ValueError(msg)

            if key == "__name__" and "/" not in field:
                document_fields[index] = "{}/{}/{}".format(
                    self._client._database_string,
                    "/".join(self._parent._path), field)

        return document_fields, before
예제 #5
0
    def get(self, field_path):
        """Get a value from the snapshot data.

        If the data is nested, for example:

        .. code-block:: python

           >>> snapshot.to_dict()
           {
               'top1': {
                   'middle2': {
                       'bottom3': 20,
                       'bottom4': 22,
                   },
                   'middle5': True,
               },
               'top6': b'\x00\x01 foo',
           }

        a **field path** can be used to access the nested data. For
        example:

        .. code-block:: python

           >>> snapshot.get('top1')
           {
               'middle2': {
                   'bottom3': 20,
                   'bottom4': 22,
               },
               'middle5': True,
           }
           >>> snapshot.get('top1.middle2')
           {
               'bottom3': 20,
               'bottom4': 22,
           }
           >>> snapshot.get('top1.middle2.bottom3')
           20

        See :meth:`~.firestore_v1beta1.client.Client.field_path` for
        more information on **field paths**.

        A copy is returned since the data may contain mutable values,
        but the data stored in the snapshot must remain immutable.

        Args:
            field_path (str): A field path (``.``-delimited list of
                field names).

        Returns:
            Any or None:
                (A copy of) the value stored for the ``field_path`` or
                None if snapshot document does not exist.

        Raises:
            KeyError: If the ``field_path`` does not match nested data
                in the snapshot.
        """
        if not self._exists:
            return None
        nested_data = _helpers.get_nested_value(field_path, self._data)
        return copy.deepcopy(nested_data)
    def _call_fut(field_path, data):
        from google.cloud.firestore_v1beta1._helpers import get_nested_value

        return get_nested_value(field_path, data)