This is a pure Python package implementing client for etcd.
This package is forked from the now-dead python-etcd3 - it is based on the last released version of the python-etcd3 which is 0.12.0; the AUTHORS lists all committers to the original package.
- No functional changes
- Move to protobuf 5.27.1
- Gencode used in buf.build locked on 5.27.1
- Runtime code >= 5.27.1
- Move to grpcio >= 1.59
- First grpcio version to support Python 3.12
- Gencode used in buf.build locked on 1.59
- Runtime code >= 1.59
- Enhance WatchResponse with method to count events by type
- Done without materialization of event classes
- Useful especially for clients which analyze possibly large incoming event batches and look for those that only describe DELETEs.
- Enhance WatchResponse to allow lazy event materialization
- Old implementation read and created instances of
Event
for all events in the response - With large watch responses, this can contribute to memory usage spikes
- The response now allows iterating events via generator, accessing events by index and determining number of events without the eager materialization
- Old implementation read and created instances of
- Refactored Event and KVMetadata classes to not eagerly access fields from etcd response
- Fix for paged gets: do not send any sorting parameters as the default is already key-ascending order
- Allow
limit
argument on get_* calls- The value specified in
limit
is passed to etcd server; limiting happens server side
- The value specified in
- Add support for paged gets of range of keys and keys starting with a prefix
- This can be useful for clients that do stream processing on large number of key-value pairs
- Without paging, the response from etcd can be quite large and lead to memory spikes in the client
- With paging, results are obtained in smaller pages, so these memory spikes are not so significant.
- The paged results are still presented as a single, continuous stream of key-value pairs
- Reduce memory usage for watches and events
- Watch internals now use classes with slots for objects with high cardinality
- Switched to lazy get of value / prev_kv value in events
- Allow
timeout_override
on all calls- The timeout specified when client is created is used by default for all calls
- On per-call basis, it is possible to override this and use different value
- You may find this useful if you normally keep the timeouts low and aggressive but then have a few outlier calls that are expected to take longer.
- Allow
get
calls on particular revision- This is enabled on all get calls including
get
done in transactions usingTransactionBuilder
- Compaction errors are propagated as-is without additional wrapping
- This is enabled on all get calls including
- API Improvements - running transactions
- Added new API to run transactions. The
txn()
method can be used to run transactions specified usingTransactionBuilder
- The
TransactionBuilder
provides fluent APIs through which code can incrementally build the transaction - specify compares, success and failure operations as necessary - The
TransactionResponse
is returned by thetxn()
. This is a facade that allows for a type-safe way to access responses for particular operations
- Added new API to run transactions. The
-
BREAKING changes
- Dropped support for Python 2
- Supports Python 3.9, 3.10 and 3.11 only; older versions of Python 3 are not supported
- Works only with the last version of protobuf v3 (3.20.0); works with protobuf v4
- Removed the locks module
- Client methods no longer use **kwargs. Use of kwargs was replaced by having all supported parameters coded explicitly. This should not be a breaking change for typical usage. May be room for breakage in some more obscure usage patterns.
- All custom objects returned by the client are now read-only. The read-only API is compatible with 0.12.0, however updates are not possible where they previously were possible
- the Member object no longer contains manipulation methods (remove, update); it is a pure read-only data class. Methods on the client class still exist.
- KVMetadata, Event, PutEvent and DeleteEvent classes use slots; your code may be broken if you added custom attributes to them
- The client.watch_once() now returns all events from the first-encountered WatchResponse - as a List of events. As opposed to returning only single Event - the first one found in the WatchResponse
- put_if_not_exists() now returns a
Tuple[bool, Optional[etcdrpc.PutResponse]]
. The bool is success indicator. If the operation succeeds, a tuple of True and the PutResponse is returned. Else False and None response are returned. - replace() now returns a
Tuple[bool, Optional[etcdrpc.PutResponse]
. The bool is success indicator. If the operation succeeds, a tuple of True and the PutResponse is returned. Else False and None response are returned. - delete() now returns a
Tuple[bool, Optional[etcdrpc.DeleteRangeReponse]
. The bool is success indicator. If the operation succeeds, a tuple of True and DeleteRangeResponse is returned. Else False and None response are returned.
-
API Improvements
- Events now include
kv_meta
andprev_kv_meta
withKVMetadata
objects - All code that forms public API is now re-exported
- All client methods are explicitly typed and there is no use of opaque kwargs anywhere
- Events now include
-
FIXES
- Default call to
transaction
was failing due to success and failure being None - Sending
filter
towatch
methods did not work - Not all gRPC timeouts were converted to etcd3.ConnectionTimedOut. gRPC error with status UNKNOWN and 'context deadline exceeded' slipped through
- Default call to
-
Modernization on top of 0.12.0
- Changed how protobufs are generated; now uses buf.build
- Generated protobufs can be consumed by latest version of protobuf (v4)
- Adopted mypy
- Reworked tests; now uses fully dockerized test environment (via pytest-docker)
After you clone the repository, make sure to initialize the development environment using make dev
. This will set
up virtual environment for the project with all the dependencies installed. If you use direnv tool, do direnv allow
to auto-activate the virtual environment - otherwise activate manually using source .envrc
.
With virtual environment activated, you can:
- Run tests using
make test
or usingpytest
. - Run static type checks using
make mypy
- Force run all pre-commit checks using
make fix-all
(they are otherwise done automatically during pre-commit hook)
If you want to start an etcd3 cluster for some ad-hoc dev testing, you can navigate to the tests
directory and do
docker compose up -d
. Just keep in mind that you have to bring this cluster down (docker compose down -v
) before
you run the automated tests.
Apache License 2.0. See LICENSE.