def rget(self, key, replica_index=None, quiet=None): """Get an item from a replica node :param string key: The key to fetch :param int replica_index: The replica index to fetch. If this is ``None`` then this method will return once any replica responds. Use :attr:`configured_replica_count` to figure out the upper bound for this parameter. The value for this parameter must be a number between 0 and the value of :attr:`configured_replica_count`-1. :param boolean quiet: Whether to suppress errors when the key is not found This method (if `replica_index` is not supplied) functions like the :meth:`get` method that has been passed the `replica` parameter:: c.get(key, replica=True) .. seealso:: :meth:`get` :meth:`rget_multi` """ if replica_index is not None: return _Base._rgetix(self, key, replica=replica_index, quiet=quiet) else: return _Base._rget(self, key, quiet=quiet)
def rget_multi(self, keys, replica_index=None, quiet=None): if replica_index is not None: return _Base._rgetix_multi(self, keys, replica=replica_index, quiet=quiet) else: return _Base._rget_multi(self, keys, quiet=quiet)
def get_and_lock(self, id, # type: str expiration, # type: int *options, # type: GetAndLockOptions **kwargs ): # type: (...)->GetResult final_options=forward_args(kwargs, *options) x = _Base.get(self.bucket, id, expiration, **final_options) _Base.lock(self.bucket, id, options) return ResultPrecursor(x, options)
def endure_multi(self, keys, persist_to=-1, replicate_to=-1, timeout=5.0, interval=0.010, check_removed=False): """Check durability requirements for multiple keys :param keys: The keys to check The type of keys may be one of the following: * Sequence of keys * A :class:`~couchbase_core.result.MultiResult` object * A ``dict`` with CAS values as the dictionary value * A sequence of :class:`~couchbase_core.result.Result` objects :return: A :class:`~.MultiResult` object of :class:`~.OperationResult` items. .. seealso:: :meth:`endure` """ if not _LCB.PYCBC_ENDURE: raise NotImplementedInV3("Standalone endure") return _Base.endure_multi(self, keys, persist_to=persist_to, replicate_to=replicate_to, timeout=timeout, interval=interval, check_removed=check_removed)
def unlock_multi( self, # type: Client keys # type: Iterable[str] ): # type: (...)->Result """Unlock multiple keys. Multi variant of :meth:`unlock` :param dict keys: the keys to unlock :return: a :class:`~couchbase_core.result.MultiResult` object The value of the ``keys`` argument should be either the CAS, or a previously returned :class:`Result` object from a :meth:`lock` call. Effectively, this means you may pass a :class:`~.MultiResult` as the ``keys`` argument. Thus, you can do something like :: keys = (....) rvs = cb.lock_multi(keys, ttl=5) # do something with rvs cb.unlock_multi(rvs) .. seealso:: :meth:`unlock` """ return _Base.unlock_multi(self, keys)
def touch_multi( self, # type: Client keys, # type: Iterable[str] ttl=0, # type: int durability_level=Durability.NONE # type: Durability ): # type: (...)->Result """Touch multiple keys. Multi variant of :meth:`touch` :param keys: the keys to touch :type keys: :ref:`iterable<argtypes>`. ``keys`` can also be a dictionary with values being integers, in which case the value for each key will be used as the TTL instead of the global one (i.e. the one passed to this function) :param int ttl: The new expiration time :param Durability durability_level: Sync replication durability level. :return: A :class:`~.MultiResult` object Update three keys to expire in 10 seconds :: cb.touch_multi(("key1", "key2", "key3"), ttl=10) Update three keys with different expiration times :: cb.touch_multi({"foo" : 1, "bar" : 5, "baz" : 10}) .. seealso:: :meth:`touch` """ return _Base.touch_multi(self, keys, ttl=ttl, durability_level=durability_level)
def append_multi( self, # type: Client keys, # type: Mapping[str,Any] ttl=0, # type: int format=None, # type: int persist_to=0, # type: int replicate_to=0 # type: int ): # type: (...)->Result """Append to multiple keys. Multi variant of :meth:`append`. .. warning:: If using the `Item` interface, use the :meth:`append_items` and :meth:`prepend_items` instead, as those will automatically update the :attr:`.Item.value` property upon successful completion. .. seealso:: :meth:`append`, :meth:`upsert_multi`, :meth:`upsert` """ return _Base.append_multi(self, keys, format=format, persist_to=persist_to, replicate_to=replicate_to)
def replace_multi( self, # type: Bucket keys, # type: Mapping[str, Any] ttl=0, format=None, persist_to=0, replicate_to=0): """ Replace multiple keys. Multi variant of :meth:`replace` :param dict keys: replacement entries :param int ttl: If specified, sets the expiration value for all keys :param int format: If specified, this is the conversion format which will be used for _all_ the keys. :param int persist_to: Durability constraint for persistence. Note that it is more efficient to use :meth:`endure_multi` on the returned :class:`~couchbase_core.result.MultiResult` than using these parameters for a high volume of keys. Using these parameters however does save on latency as the constraint checking for each item is performed as soon as it is successfully stored. :param int replicate_to: Durability constraints for replication. See notes on the `persist_to` parameter for usage. :return: .. seealso:: :meth:`replace`, :meth:`upsert_multi`, :meth:`upsert` """ return _Base.replace_multi(self, keys, ttl=ttl, format=format, persist_to=persist_to, replicate_to=replicate_to)
def append(self, id, # type: str value, # type: str *options, # type: Any **kwargs # type: Any ): # type: (...)->ResultPrecursor """Append a string to an existing value in Couchbase. :param string value: The data to append to the existing value. Other parameters follow the same conventions as :meth:`upsert`. The `format` argument must be one of :const:`~couchbase_core.FMT_UTF8` or :const:`~couchbase_core.FMT_BYTES`. If not specified, it will be :const:`~.FMT_UTF8` (overriding the :attr:`default_format` attribute). This is because JSON or Pickle formats will be nonsensical when random data is appended to them. If you wish to modify a JSON or Pickle encoded object, you will need to retrieve it (via :meth:`get`), modify it, and then store it again (using :meth:`upsert`). Additionally, you must ensure the value (and flags) for the current value is compatible with the data to be appended. For an example, you may append a :const:`~.FMT_BYTES` value to an existing :const:`~couchbase_core.FMT_JSON` value, but an error will be thrown when retrieving the value using :meth:`get` (you may still use the :attr:`data_passthrough` to overcome this). :raise: :exc:`.NotStoredError` if the key does not exist """ x = _Base.append(self.bucket, id, value, forward_args(kwargs, *options)) return ResultPrecursor(x, options)
def touch(self, id, # type: str *options, # type: TouchOptions **kwargs): # type: (...)->MutationResult """Update a key's expiration time :param string key: The key whose expiration time should be modified :param int timeout: The new expiration time. If the expiration time is `0` then the key never expires (and any existing expiration is removed) :return: :class:`.OperationResult` Update the expiration time of a key :: cb.upsert("key", expiration=Seconds(100)) # expires in 100 seconds cb.touch("key", expiration=Seconds(0)) # key should never expire now :raise: The same things that :meth:`get` does .. seealso:: :meth:`get` - which can be used to get *and* update the expiration """ return _Base.touch(self.bucket, id, **forward_args(kwargs, *options))
def get_multi( self, # type: Client keys, # type: Iterable[str] ttl=0, # type: int quiet=None, # type: bool replica=False, # type: bool no_format=False # type: bool ): # type: (...)->Result """Get multiple keys. Multi variant of :meth:`get` :param keys: keys the keys to fetch :type keys: :ref:`iterable<argtypes>` :param int ttl: Set the expiration for all keys when retrieving :param boolean replica: Whether the results should be obtained from a replica instead of the master. See :meth:`get` for more information about this parameter. :param Durability durability_level: Sync replication durability level. :return: A :class:`~.MultiResult` object. This is a dict-like object and contains the keys (passed as) `keys` as the dictionary keys, and :class:`~.Result` objects as values """ return _Base.get_multi(self, keys, ttl=ttl, quiet=quiet, replica=replica, no_format=no_format)
def remove(self, key, cas=0, quiet=None, persist_to=0, replicate_to=0): """Remove the key-value entry for a given key in Couchbase. :param key: A string which is the key to remove. The format and type of the key follows the same conventions as in :meth:`upsert` :type key: string, dict, or tuple/list :param int cas: The CAS to use for the removal operation. If specified, the key will only be removed from the server if it has the same CAS as specified. This is useful to remove a key only if its value has not been changed from the version currently visible to the client. If the CAS on the server does not match the one specified, an exception is thrown. :param boolean quiet: Follows the same semantics as `quiet` in :meth:`get` :param int persist_to: If set, wait for the item to be removed from the storage of at least these many nodes :param int replicate_to: If set, wait for the item to be removed from the cache of at least these many nodes (excluding the master) :raise: :exc:`.DocumentNotFoundException` if the key does not exist. :raise: :exc:`.DocumentExistsException` if a CAS was specified, but the CAS on the server had changed :return: A :class:`~.Result` object. Simple remove:: ok = cb.remove("key").success Don't complain if key does not exist:: ok = cb.remove("key", quiet=True) Only remove if CAS matches our version:: rv = cb.get("key") cb.remove("key", cas=rv.cas) Remove multiple keys:: oks = cb.remove_multi(["key1", "key2", "key3"]) Remove multiple keys with CAS:: oks = cb.remove({ "key1" : cas1, "key2" : cas2, "key3" : cas3 }) .. seealso:: :meth:`remove_multi`, :meth:`endure` for more information on the ``persist_to`` and ``replicate_to`` options. """ return _Base.remove(self, key, cas=cas, quiet=quiet, persist_to=persist_to, replicate_to=replicate_to)
def counter(self, key, delta=1, initial=None, ttl=0): """Increment or decrement the numeric value of an item. This method instructs the server to treat the item stored under the given key as a numeric counter. Counter operations require that the stored value exists as a string representation of a number (e.g. ``123``). If storing items using the :meth:`upsert` family of methods, and using the default :const:`couchbase_v2.FMT_JSON` then the value will conform to this constraint. :param string key: A key whose counter value is to be modified :param int delta: an amount by which the key should be modified. If the number is negative then this number will be *subtracted* from the current value. :param initial: The initial value for the key, if it does not exist. If the key does not exist, this value is used, and `delta` is ignored. If this parameter is `None` then no initial value is used :type initial: int or `None` :param int ttl: The lifetime for the key, after which it will expire :raise: :exc:`.DocumentNotFoundException` if the key does not exist on the bucket (and `initial` was `None`) :raise: :exc:`.DeltaBadvalException` if the key exists, but the existing value is not numeric :return: A :class:`.Result` object. The current value of the counter may be obtained by inspecting the return value's `value` attribute. Simple increment:: rv = cb.counter("key") rv.value # 42 Increment by 10:: rv = cb.counter("key", delta=10) Decrement by 5:: rv = cb.counter("key", delta=-5) Increment by 20, set initial value to 5 if it does not exist:: rv = cb.counter("key", delta=20, initial=5) Increment three keys:: kv = cb.counter_multi(["foo", "bar", "baz"]) for key, result in kv.items(): print "Key %s has value %d now" % (key, result.value) .. seealso:: :meth:`counter_multi` """ return _Base.counter(self, key, delta=delta, initial=initial, ttl=ttl)
def upsert_multi( self, # type: Client keys, # type: Mapping[str,Any] ttl=0, # type: int format=None, # type: int persist_to=0, # type: int replicate_to=0, # type: int durability_level=Durability.NONE # type: Durability ): # type: (...)->Result """ Write multiple items to the cluster. Multi version of :meth:`upsert` :param dict keys: A dictionary of keys to set. The keys are the keys as they should be on the server, and the values are the values for the keys to be stored. `keys` may also be a :class:`~.ItemCollection`. If using a dictionary variant for item collections, an additional `ignore_cas` parameter may be supplied with a boolean value. If not specified, the operation will fail if the CAS value on the server does not match the one specified in the `Item`'s `cas` field. :param int ttl: If specified, sets the expiration value for all keys :param int format: If specified, this is the conversion format which will be used for _all_ the keys. :param int persist_to: Durability constraint for persistence. Note that it is more efficient to use :meth:`endure_multi` on the returned :class:`~couchbase_core.result.MultiResult` than using these parameters for a high volume of keys. Using these parameters however does save on latency as the constraint checking for each item is performed as soon as it is successfully stored. :param int replicate_to: Durability constraints for replication. See notes on the `persist_to` parameter for usage. :param Durability durability_level: Sync replication durability level. You should either use this or the old-style durability params above, but not both. :return: A :class:`~.MultiResult` object, which is a `dict`-like object The multi methods are more than just a convenience, they also save on network performance by batch-scheduling operations, reducing latencies. This is especially noticeable on smaller value sizes. .. seealso:: :meth:`upsert` """ return _Base.upsert_multi(self, keys, ttl=ttl, format=format, persist_to=persist_to, replicate_to=replicate_to, durability_level=durability_level)
def prepend_multi(self, keys, format=None, persist_to=0, replicate_to=0): """Prepend to multiple keys. Multi variant of :meth:`prepend` .. seealso:: :meth:`prepend`, :meth:`upsert_multi`, :meth:`upsert` """ return _Base.prepend_multi(self, keys, format=format, persist_to=persist_to, replicate_to=replicate_to)
def decrement(self, id, # type: str delta, # type: DeltaValue *options, # type: CounterOptions **kwargs ): # type: (...)->ResultPrecursor """Decrement the numeric value of an item. This method instructs the server to treat the item stored under the given key as a numeric counter. Counter operations require that the stored value exists as a string representation of a number (e.g. ``123``). If storing items using the :meth:`upsert` family of methods, and using the default :const:`couchbase_core.FMT_JSON` then the value will conform to this constraint. :param string key: A key whose counter value is to be modified :param DeltaValue delta: an amount by which the key should be decremented. :param couchbase.options.SignedInt64 initial: The initial value for the key, if it does not exist. If the key does not exist, this value is used, and `delta` is ignored. If this parameter is `None` then no initial value is used :param SignedInt64 initial: :class:`couchbase.options.SignedInt64` or `None` :param Seconds expiration: The lifetime for the key, after which it will expire :raise: :exc:`.NotFoundError` if the key does not exist on the bucket (and `initial` was `None`) :raise: :exc:`.DeltaBadvalError` if the key exists, but the existing value is not numeric :return: A :class:`couchbase.result.MutationResult` object. Simple decrement:: rv = cb.decrement("key") cb.get("key").content_as[int] # 42 Decrement by 10:: rv = cb.decrement("key", DeltaValue(10)) Decrement by 20, set initial value to 5 if it does not exist:: rv = cb.decrement("key", DeltaValue(20), initial=SignedInt64(5)) """ final_opts = self._check_delta_initial(kwargs, *options) final_opts = self._check_delta_initial(kwargs, *options) x = _Base.counter(self.bucket, id, delta=-int(DeltaValue.verified(delta)), **final_opts) return ResultPrecursor(x, final_opts)
def counter_multi(self, kvs, initial=None, delta=1, ttl=0, durability_level=Durability.NONE): """Perform counter operations on multiple items :param kvs: Keys to operate on. See below for more options :param initial: Initial value to use for all keys. :param delta: Delta value for all keys. :param ttl: Expiration value to use for all keys :param Durability durability_level: Sync replication durability level. :return: A :class:`~.MultiResult` containing :class:`~.ValueResult` values The `kvs` can be a: - Iterable of keys .. code-block:: python cb.counter_multi((k1, k2)) - A dictionary mapping a key to its delta .. code-block:: python cb.counter_multi({ k1: 42, k2: 99 }) - A dictionary mapping a key to its additional options .. code-block:: python cb.counter_multi({ k1: {'delta': 42, 'initial': 9, 'ttl': 300}, k2: {'delta': 99, 'initial': 4, 'ttl': 700} }) When using a dictionary, you can override settings for each key on a per-key basis (for example, the initial value). Global settings (global here means something passed as a parameter to the method) will take effect for those values which do not have a given option specified. """ return _Base.counter_multi(self, kvs, initial=initial, delta=delta, ttl=ttl, durability_level=durability_level)
def lock_multi(self, keys, ttl=0): """Lock multiple keys. Multi variant of :meth:`lock` :param keys: the keys to lock :type keys: :ref:`iterable<argtypes>` :param int ttl: The lock timeout for all keys :return: a :class:`~.MultiResult` object .. seealso:: :meth:`lock` """ return _Base.lock_multi(self, keys, ttl=ttl)
def remove_multi(self, kvs, quiet=None): """Remove multiple items from the cluster :param kvs: Iterable of keys to delete from the cluster. If you wish to specify a CAS for each item, then you may pass a dictionary of keys mapping to cas, like `remove_multi({k1:cas1, k2:cas2}`) :param quiet: Whether an exception should be raised if one or more items were not found :return: A :class:`~.MultiResult` containing :class:`~.OperationResult` values. """ return _Base.remove_multi(self, kvs, quiet=quiet)
def prepend(self, id, # type: str value, # type: str *options, # type: PrependOptions **kwargs # type: Any ): # type: (...)->ResultPrecursor """Prepend a string to an existing value in Couchbase. .. seealso:: :meth:`append` """ x = _Base.prepend(self.bucket, id, value, **forward_args(kwargs, *options)) return ResultPrecursor(x, options)
def _cntl(self, *args, **kwargs): """Low-level interface to the underlying C library's settings. via ``lcb_cntl()``. This method accepts an opcode and an optional value. Constants are intentionally not defined for the various opcodes to allow saner error handling when an unknown opcode is not used. .. warning:: If you pass the wrong parameters to this API call, your application may crash. For this reason, this is not a public API call. Nevertheless it may be used sparingly as a workaround for settings which may have not yet been exposed directly via a supported API :param int op: Type of cntl to access. These are defined in libcouchbase's ``cntl.h`` header file :param value: An optional value to supply for the operation. If a value is not passed then the operation will return the current value of the cntl without doing anything else. otherwise, it will interpret the cntl in a manner that makes sense. If the value is a float, it will be treated as a timeout value and will be multiplied by 1000000 to yield the microsecond equivalent for the library. If the value is a boolean, it is treated as a C ``int`` :param value_type: String indicating the type of C-level value to be passed to ``lcb_cntl()``. The possible values are: * ``"string"`` - NUL-terminated `const char`. Pass a Python string * ``"int"`` - C ``int`` type. Pass a Python int * ``"uint32_t"`` - C ``lcb_uint32_t`` type. Pass a Python int * ``"unsigned"`` - C ``unsigned int`` type. Pass a Python int * ``"float"`` - C ``float`` type. Pass a Python float * ``"timeout"`` - The number of seconds as a float. This is converted into microseconds within the extension library. :return: If no `value` argument is provided, retrieves the current setting (per the ``value_type`` specification). Otherwise this function returns ``None``. """ return _Base._cntl(self, *args, **kwargs)
def insert_multi(self, keys, ttl=0, format=None, persist_to=0, replicate_to=0): """Add multiple keys. Multi variant of :meth:`insert` .. seealso:: :meth:`insert`, :meth:`upsert_multi`, :meth:`upsert` """ return _Base.insert_multi(self, keys, ttl=ttl, format=format, persist_to=persist_to, replicate_to=replicate_to)
def _get_generic(self, key, kwargs, options): options = forward_args(kwargs, *options) options.pop('key', None) spec = options.pop('spec', []) project = options.pop('project', None) if project: if len(project) <= CBCollection.MAX_GET_OPS: spec = gen_projection_spec(project) else: raise couchbase.exceptions.ArgumentError( "Project only accepts {} operations or less".format(CBCollection.MAX_GET_OPS)) if not project: x = _Base.get(self.bucket, key, **options) else: x = self.bucket.lookup_in(key, *spec, **options) return ResultPrecursor(x, options)
def remove(self, # type: CBCollection id, # type: str *options, # type: RemoveOptions **kwargs ): # type: (...)->MutationResult """Remove the key-value entry for a given key in Couchbase. :param key: A string which is the key to remove. The format and type of the key follows the same conventions as in :meth:`upsert` :type key: string, dict, or tuple/list :param int cas: The CAS to use for the removal operation. If specified, the key will only be removed from the server if it has the same CAS as specified. This is useful to remove a key only if its value has not been changed from the version currently visible to the client. If the CAS on the server does not match the one specified, an exception is thrown. :param boolean quiet: Follows the same semantics as `quiet` in :meth:`get` :param int persist_to: If set, wait for the item to be removed from the storage of at least these many nodes :param int replicate_to: If set, wait for the item to be removed from the cache of at least these many nodes (excluding the master) :raise: :exc:`.NotFoundError` if the key does not exist. :raise: :exc:`.KeyExistsError` if a CAS was specified, but the CAS on the server had changed :return: A :class:`~.Result` object. Simple remove:: ok = cb.remove("key").success Don't complain if key does not exist:: ok = cb.remove("key", quiet=True) Only remove if CAS matches our version:: rv = cb.get("key") cb.remove("key", cas=rv.cas) """ final_options = forward_args(kwargs, *options) return ResultPrecursor(_Base.remove(self.bucket, id, **final_options), final_options)
def observe(self, key, master_only=False): """Return storage information for a key. It returns a :class:`.ValueResult` object with the ``value`` field set to a list of :class:`~.ObserveInfo` objects. Each element in the list responds to the storage status for the key on the given node. The length of the list (and thus the number of :class:`~.ObserveInfo` objects) are equal to the number of online replicas plus the master for the given key. :param string key: The key to inspect :param bool master_only: Whether to only retrieve information from the master node. .. seealso:: :ref:`observe_info` """ return _Base.observe(self, key, master_only=master_only)
def unlock(self, key, cas): """Unlock a Locked Key in Couchbase. This unlocks an item previously locked by :meth:`lock` :param key: The key to unlock :param cas: The cas returned from :meth:`lock`'s :class:`.Result` object. See :meth:`lock` for an example. :raise: :exc:`.TemporaryFailException` if the CAS supplied does not match the CAS on the server (possibly because it was unlocked by previous call). .. seealso:: :meth:`lock` :meth:`unlock_multi` """ return _Base.unlock(self, key, cas=cas)
def prepend_multi( self, # type: Client keys, # type: Mapping[str,Any] ttl=0, # type: int format=None, # type: int persist_to=0, # type: int replicate_to=0 # type: int ): # type: (...)->Result """Prepend to multiple keys. Multi variant of :meth:`prepend` .. seealso:: :meth:`prepend`, :meth:`upsert_multi`, :meth:`upsert` """ return _Base.prepend_multi(self, keys, format=format, persist_to=persist_to, replicate_to=replicate_to)
def replace(self, id, # type: str value, # type: Any *options, **kwargs ): # type: (...)->MutationResult """Store an object in Couchbase only if it already exists. Follows the same conventions as :meth:`upsert`, but the value is stored only if a previous value already exists. :raise: :exc:`.NotFoundError` if the key does not exist .. seealso:: :meth:`upsert` """ final_options = forward_args(kwargs, *options) return ResultPrecursor(_Base.replace(self.bucket, id, value, **final_options), final_options)
def insert(self, key, value, *options, **kwargs): # type: (...)->ResultPrecursor """Store an object in Couchbase unless it already exists. Follows the same conventions as :meth:`upsert` but the value is stored only if it does not exist already. Conversely, the value is not stored if the key already exists. Notably missing from this method is the `cas` parameter, this is because `insert` will only succeed if a key does not already exist on the server (and thus can have no CAS) :raise: :exc:`.KeyExistsError` if the key already exists .. seealso:: :meth:`upsert` """ final_options = forward_args(kwargs, *options) return ResultPrecursor(_Base.insert(self.bucket, key, value, **final_options), final_options)
def _cntlstr(self, key, value): """ Low-level interface to the underlying C library's settings. via ``lcb_cntl_string()``. This method accepts a key and a value. It can modify the same sort of settings as the :meth:`~._cntl` method, but may be a bit more convenient to follow in code. .. warning:: See :meth:`~._cntl` for warnings. :param string key: The setting key :param string value: The setting value See the API documentation for libcouchbase for a list of acceptable setting keys. """ return _Base._cntlstr(self, key, value)