Пример #1
0
def test_ndb_context():
    assert _runstate.states.current() is None

    with _runstate.ndb_context():
        one = _runstate.current()

        with _runstate.ndb_context():
            two = _runstate.current()
            assert one is not two
            two.eventloop = unittest.mock.Mock(spec=("run", ))
            two.eventloop.run.assert_not_called()

        assert _runstate.current() is one
        two.eventloop.run.assert_called_once_with()

    assert _runstate.states.current() is None
Пример #2
0
def _get_read_options(options):
    """Get the read options for a request.

    Args:
        options (Dict[str, Any]): The options for the request. For example,
            ``{"read_consistency": EVENTUAL}``. May contain options unrelated
            to creating a :class:`datastore_pb2.ReadOptions` instance, which
            will be ignored.

    Returns:
        datastore_pb2.ReadOptions: The options instance for passing to the
            Datastore gRPC API.

    Raises:
        ValueError: When ``read_consistency`` is set to ``EVENTUAL`` and there
            is a transaction.
    """
    state = _runstate.current()
    transaction = options.get("transaction", state.transaction)

    read_consistency = options.get("read_consistency")
    if read_consistency is None:
        read_consistency = options.get("read_policy")  # Legacy NDB

    if transaction is not None and read_consistency is EVENTUAL:
        raise ValueError(
            "read_consistency must be EVENTUAL when in transaction")

    return datastore_pb2.ReadOptions(read_consistency=read_consistency,
                                     transaction=transaction)
Пример #3
0
def _get_batch(batch_cls, options):
    """Gets a data structure for storing batched calls to Datastore Lookup.

    The batch data structure is stored in the current run state. If there is
    not already a batch started, a new structure is created and an idle
    callback is added to the current event loop which will eventually perform
    the batch look up.

    Args:
        batch_cls (type): Class representing the kind of operation being
            batched.
        options (Dict[str, Any]): The options for the request. For example,
            ``{"read_consistency": EVENTUAL}``. Calls with different options
            will be placed in different batches.

    Returns:
        batch_cls: An instance of the batch class.
    """
    state = _runstate.current()
    batches = state.batches.get(batch_cls)
    if batches is None:
        state.batches[batch_cls] = batches = {}

    options_key = tuple(sorted(options.items()))
    batch = batches.get(options_key)
    if batch is not None:
        return batch

    def idle():
        batch = batches.pop(options_key)
        batch.idle_callback()

    batches[options_key] = batch = _LookupBatch(options)
    _eventloop.add_idle(idle)
    return batch
Пример #4
0
def _datastore_commit(mutations, transaction):
    """Call Commit on Datastore.

    Args:
        mutations (List[datastore_pb2.Mutation]): The changes to persist to
            Datastore.
        transaction (Union[bytes, NoneType]): The identifier for the
            transaction for this commit, or :data:`None` if no transaction is
            being used.

    Returns:
        grpc.Future: A future for
            :class:`google.cloud.datastore_v1.datastore_pb2.CommitResponse`
    """
    if transaction is None:
        mode = datastore_pb2.CommitRequest.NON_TRANSACTIONAL
    else:
        mode = datastore_pb2.CommitRequest.TRANSACTIONAL

    client = _runstate.current().client
    request = datastore_pb2.CommitRequest(
        project_id=client.project,
        mode=mode,
        mutations=mutations,
        transaction=transaction,
    )

    api = stub()
    return api.Commit.future(request)
Пример #5
0
def test_ndb_context():
    assert _runstate.states.current() is None

    with _runstate.ndb_context():
        one = _runstate.current()

        with _runstate.ndb_context():
            two = _runstate.current()
            assert one is not two
            two.eventloop = unittest.mock.Mock(spec=("run",))
            two.eventloop.run.assert_not_called()

        assert _runstate.current() is one
        two.eventloop.run.assert_called_once_with()

    assert _runstate.states.current() is None
Пример #6
0
def stub():
    """Get the stub for the `Google Datastore` API.

    Gets the stub from the current context.

    Returns:
        :class:`~google.cloud.datastore_v1.proto.datastore_pb2_grpc.DatastoreStub`:
            The stub instance.
    """
    state = _runstate.current()
    return state.stub
def test_state_context():
    assert _runstate.states.current() is None

    client1 = object()
    client2 = object()
    with _runstate.state_context(client1):
        one = _runstate.current()
        assert one.client is client1

        with _runstate.state_context(client2):
            two = _runstate.current()
            assert two.client is client2
            assert one is not two
            two.eventloop = unittest.mock.Mock(spec=("run", ))
            two.eventloop.run.assert_not_called()

        assert _runstate.current() is one
        two.eventloop.run.assert_called_once_with()

    assert _runstate.states.current() is None
Пример #8
0
def get_event_loop():
    """Get the current event loop.

    This function should be called within a context established by
    :func:`~google.cloud.ndb.ndb_context`.

    Returns:
        EventLoop: The event loop for the current context.
    """
    context = _runstate.current()
    return context.eventloop
Пример #9
0
def _perform_batch_lookup():
    """Perform a Datastore Lookup on all batched Lookup requests.

    Meant to be used as an idle callback, so that calls to lookup entities can
    be batched into a single request to the back end service as soon as running
    code has need of one of the results.
    """
    state = _runstate.current()
    batch = state.batches.pop(_BATCH_LOOKUP, None)
    if batch is None:
        return

    rpc = _datastore_lookup(batch.keys())
    _eventloop.queue_rpc(rpc, BatchLookupCallback(batch))
Пример #10
0
def _get_transaction(options):
    """Get the transaction for a request.

    If specified, this will return the transaction from ``options``. Otherwise,
    it will return the transaction for the current context.

    Args:
        options (Dict[str, Any]): The options for the request. Only
            ``transaction`` will have any bearing here.

    Returns:
        Union[bytes, NoneType]: The transaction identifier, or :data:`None`.
    """
    state = _runstate.current()
    return options.get("transaction", state.transaction)
Пример #11
0
def get_event_loop():
    """Get the current event loop.

    This function should be called within a context established by
    :func:`~google.cloud.ndb.ndb_context`.

    Returns:
        EventLoop: The event loop for the current context.
    """
    state = _runstate.current()

    # Be lazy and avoid circular dependency with _runstate
    if state.eventloop is None:
        state.eventloop = EventLoop()

    return state.eventloop
Пример #12
0
def get_event_loop():
    """Get the current event loop.

    This function should be called within a context established by
    :func:`~google.cloud.ndb.ndb_context`.

    Returns:
        EventLoop: The event loop for the current context.
    """
    state = _runstate.current()

    # Be lazy and avoid circular dependency with _runstate
    if state.eventloop is None:
        state.eventloop = EventLoop()

    return state.eventloop
Пример #13
0
def _datastore_lookup(keys):
    """Issue a Lookup call to Datastore using gRPC.

    Args:
        keys (Iterable[datastore_v1.proto.entity_pb2.Key]): The entity keys to look up.

    Returns:
        :class:`grpc.Future`: Future object for eventual result of lookup.
    """
    client = _runstate.current().client
    request = datastore_pb2.LookupRequest(
        project_id=client.project, keys=[key for key in keys]
    )

    api = stub()
    return api.Lookup.future(request)
Пример #14
0
def _get_lookup_batch():
    """Gets a data structure for storing batched calls to Datastore Lookup.

    The batch data structure is stored in the current run state. If there is
    not already a batch started, a new structure is created and an idle
    callback is added to the current event loop which will eventually perform
    the batch look up.

    Returns:
        Dict[~datastore_v1.proto.entity_pb2.Key, List[~tasklets.Future]]
    """
    state = _runstate.current()
    batch = state.batches.get(_BATCH_LOOKUP)
    if batch is not None:
        return batch

    state.batches[_BATCH_LOOKUP] = batch = {}
    _eventloop.add_idle(_perform_batch_lookup)
    return batch
Пример #15
0
def _datastore_lookup(keys, read_options):
    """Issue a Lookup call to Datastore using gRPC.

    Args:
        keys (Iterable[entity_pb2.Key]): The entity keys to
            look up.
        read_options (Union[datastore_pb2.ReadOptions, NoneType]): Options for
            the request.

    Returns:
        :class:`grpc.Future`: Future object for eventual result of lookup.
    """
    client = _runstate.current().client
    request = datastore_pb2.LookupRequest(
        project_id=client.project,
        keys=[key for key in keys],
        read_options=read_options,
    )

    api = stub()
    return api.Lookup.future(request)
Пример #16
0
def _project_from_app(app, allow_empty=False):
    """Convert a legacy Google App Engine app string to a project.

    Args:
        app (str): The application value to be used. If the caller passes
            :data:`None` and ``allow_empty`` is :data:`False`, then this will
            use the project set by the current client context. (See
            :meth:`~client.Client.context`.)
        allow_empty (bool): Flag determining if an empty (i.e. :data:`None`)
            project is allowed. Defaults to :data:`False`.

    Returns:
        str: The cleaned project.
    """
    if app is None:
        if allow_empty:
            return None
        client = _runstate.current().client
        app = client.project

    # NOTE: This is the same behavior as in the helper
    #       ``google.cloud.datastore.key._clean_app()``.
    parts = app.split("~", 1)
    return parts[-1]
Пример #17
0
def stub():
    """Get the stub for the `Google Datastore` API.

    Gets the stub from the current context, creating one if there isn't one
    already.

    Returns:
        :class:`~google.cloud.datastore_v1.proto.datastore_pb2_grpc.DatastoreStub`:
            The stub instance.
    """
    state = _runstate.current()

    if state.stub is None:
        client = state.client
        if client.secure:
            channel = _helpers.make_secure_channel(client._credentials,
                                                   _http.DEFAULT_USER_AGENT,
                                                   client.host)
        else:
            channel = grpc.insecure_channel(client.host)

        state.stub = datastore_pb2_grpc.DatastoreStub(channel)

    return state.stub
Пример #18
0
 def test_assert_as_context_manager(self):
     context = self._make_one()
     with context:
         assert _runstate.current() is context
     with pytest.raises(exceptions.ContextError):
         _runstate.current()