python-etcd3-async 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. python_etcd3_async-0.1.0/.coverage +0 -0
  2. python_etcd3_async-0.1.0/.gitignore +17 -0
  3. python_etcd3_async-0.1.0/.pylintrc +29 -0
  4. python_etcd3_async-0.1.0/.python-version +1 -0
  5. python_etcd3_async-0.1.0/AGENTS.md +138 -0
  6. python_etcd3_async-0.1.0/CLAUDE.md +257 -0
  7. python_etcd3_async-0.1.0/PKG-INFO +328 -0
  8. python_etcd3_async-0.1.0/README.md +318 -0
  9. python_etcd3_async-0.1.0/README_CN.md +318 -0
  10. python_etcd3_async-0.1.0/SKILL.md +105 -0
  11. python_etcd3_async-0.1.0/docs/assets/stylesheets/extra.css +53 -0
  12. python_etcd3_async-0.1.0/docs/en/getting-started/installation.md +35 -0
  13. python_etcd3_async-0.1.0/docs/en/guide/advanced_queries.md +43 -0
  14. python_etcd3_async-0.1.0/docs/en/guide/configuration.md +88 -0
  15. python_etcd3_async-0.1.0/docs/en/guide/usage.md +142 -0
  16. python_etcd3_async-0.1.0/docs/en/index.md +69 -0
  17. python_etcd3_async-0.1.0/docs/en/operations/async_error_handling.md +468 -0
  18. python_etcd3_async-0.1.0/docs/en/operations/auto_reconnection.md +34 -0
  19. python_etcd3_async-0.1.0/docs/en/operations/error_handling.md +37 -0
  20. python_etcd3_async-0.1.0/docs/en/operations/failover.md +54 -0
  21. python_etcd3_async-0.1.0/docs/en/operations/monitoring.md +67 -0
  22. python_etcd3_async-0.1.0/docs/en/operations/observability.md +225 -0
  23. python_etcd3_async-0.1.0/docs/en/resources/authors.md +13 -0
  24. python_etcd3_async-0.1.0/docs/en/resources/contributing.md +38 -0
  25. python_etcd3_async-0.1.0/docs/en/resources/history.md +18 -0
  26. python_etcd3_async-0.1.0/docs/zh/getting-started/installation.md +35 -0
  27. python_etcd3_async-0.1.0/docs/zh/guide/advanced_queries.md +43 -0
  28. python_etcd3_async-0.1.0/docs/zh/guide/configuration.md +88 -0
  29. python_etcd3_async-0.1.0/docs/zh/guide/usage.md +142 -0
  30. python_etcd3_async-0.1.0/docs/zh/index.md +69 -0
  31. python_etcd3_async-0.1.0/docs/zh/operations/async_error_handling.md +458 -0
  32. python_etcd3_async-0.1.0/docs/zh/operations/auto_reconnection.md +34 -0
  33. python_etcd3_async-0.1.0/docs/zh/operations/error_handling.md +37 -0
  34. python_etcd3_async-0.1.0/docs/zh/operations/failover.md +54 -0
  35. python_etcd3_async-0.1.0/docs/zh/operations/monitoring.md +67 -0
  36. python_etcd3_async-0.1.0/docs/zh/operations/observability.md +225 -0
  37. python_etcd3_async-0.1.0/docs/zh/resources/authors.md +13 -0
  38. python_etcd3_async-0.1.0/docs/zh/resources/contributing.md +38 -0
  39. python_etcd3_async-0.1.0/docs/zh/resources/history.md +18 -0
  40. python_etcd3_async-0.1.0/etcd3/__init__.py +90 -0
  41. python_etcd3_async-0.1.0/etcd3/async_client.py +1495 -0
  42. python_etcd3_async-0.1.0/etcd3/async_client_extensions.py +878 -0
  43. python_etcd3_async-0.1.0/etcd3/async_endpoint.py +140 -0
  44. python_etcd3_async-0.1.0/etcd3/async_managers.py +498 -0
  45. python_etcd3_async-0.1.0/etcd3/async_monitor.py +16 -0
  46. python_etcd3_async-0.1.0/etcd3/async_watch.py +462 -0
  47. python_etcd3_async-0.1.0/etcd3/client.py +2021 -0
  48. python_etcd3_async-0.1.0/etcd3/endpoint.py +79 -0
  49. python_etcd3_async-0.1.0/etcd3/events.py +40 -0
  50. python_etcd3_async-0.1.0/etcd3/exceptions.py +47 -0
  51. python_etcd3_async-0.1.0/etcd3/exporters/__init__.py +18 -0
  52. python_etcd3_async-0.1.0/etcd3/exporters/prometheus.py +365 -0
  53. python_etcd3_async-0.1.0/etcd3/leases.py +106 -0
  54. python_etcd3_async-0.1.0/etcd3/locks.py +593 -0
  55. python_etcd3_async-0.1.0/etcd3/log.py +146 -0
  56. python_etcd3_async-0.1.0/etcd3/log_formatters.py +228 -0
  57. python_etcd3_async-0.1.0/etcd3/log_sampling.py +221 -0
  58. python_etcd3_async-0.1.0/etcd3/members.py +44 -0
  59. python_etcd3_async-0.1.0/etcd3/observability.py +431 -0
  60. python_etcd3_async-0.1.0/etcd3/shared.py +486 -0
  61. python_etcd3_async-0.1.0/etcd3/trace.py +231 -0
  62. python_etcd3_async-0.1.0/etcd3/trace_attributes.py +434 -0
  63. python_etcd3_async-0.1.0/etcd3/transactions.py +280 -0
  64. python_etcd3_async-0.1.0/etcd3/utils.py +158 -0
  65. python_etcd3_async-0.1.0/etcd3/watch.py +270 -0
  66. python_etcd3_async-0.1.0/etcdrpc/__init__.py +16 -0
  67. python_etcd3_async-0.1.0/etcdrpc/auth.proto +49 -0
  68. python_etcd3_async-0.1.0/etcdrpc/kv.proto +43 -0
  69. python_etcd3_async-0.1.0/etcdrpc/rpc.proto +924 -0
  70. python_etcd3_async-0.1.0/examples/leader_election.py +285 -0
  71. python_etcd3_async-0.1.0/examples/leader_election_sync.py +300 -0
  72. python_etcd3_async-0.1.0/examples/service_discovery.py +204 -0
  73. python_etcd3_async-0.1.0/examples/service_discovery_sync.py +229 -0
  74. python_etcd3_async-0.1.0/examples/service_registration.py +226 -0
  75. python_etcd3_async-0.1.0/examples/service_registration_sync.py +195 -0
  76. python_etcd3_async-0.1.0/gen_protos.py +69 -0
  77. python_etcd3_async-0.1.0/mkdocs.yml +95 -0
  78. python_etcd3_async-0.1.0/pyproject.toml +50 -0
  79. python_etcd3_async-0.1.0/tests/__init__.py +0 -0
  80. python_etcd3_async-0.1.0/tests/test_async_client.py +394 -0
  81. python_etcd3_async-0.1.0/tests/test_async_error_handling.py +208 -0
  82. python_etcd3_async-0.1.0/tests/test_async_managers.py +88 -0
  83. python_etcd3_async-0.1.0/tests/test_batch_operations.py +466 -0
  84. python_etcd3_async-0.1.0/tests/test_client.py +117 -0
  85. python_etcd3_async-0.1.0/tests/test_events.py +252 -0
  86. python_etcd3_async-0.1.0/tests/test_kv_operations.py +523 -0
  87. python_etcd3_async-0.1.0/tests/test_lease_keepalive_retry.py +434 -0
  88. python_etcd3_async-0.1.0/tests/test_leases.py +242 -0
  89. python_etcd3_async-0.1.0/tests/test_leases_integration.py +229 -0
  90. python_etcd3_async-0.1.0/tests/test_locks.py +356 -0
  91. python_etcd3_async-0.1.0/tests/test_locks_integration.py +147 -0
  92. python_etcd3_async-0.1.0/tests/test_log_formatters.py +234 -0
  93. python_etcd3_async-0.1.0/tests/test_log_sampling.py +180 -0
  94. python_etcd3_async-0.1.0/tests/test_members.py +200 -0
  95. python_etcd3_async-0.1.0/tests/test_observability_integration.py +205 -0
  96. python_etcd3_async-0.1.0/tests/test_trace_attributes.py +311 -0
  97. python_etcd3_async-0.1.0/tests/test_transactions.py +240 -0
  98. python_etcd3_async-0.1.0/tests/test_transactions_integration.py +320 -0
  99. python_etcd3_async-0.1.0/tests/test_utils.py +280 -0
  100. python_etcd3_async-0.1.0/tests/test_watch.py +142 -0
  101. python_etcd3_async-0.1.0/usage_guide.md +223 -0
  102. python_etcd3_async-0.1.0/uv.lock +911 -0
Binary file
@@ -0,0 +1,17 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+ etcdrpc/*_pb2.py
9
+ etcdrpc/*_pb2_grpc.py
10
+ etcdrpc/*_pb2.pyi
11
+ .trae/documents/*
12
+ .pytest_cache/
13
+ .ruff_cache/
14
+ htmlcov/
15
+ # Virtual environments
16
+ .venv
17
+ /site
@@ -0,0 +1,29 @@
1
+ # Pylint configuration file
2
+
3
+ [MASTER]
4
+
5
+ # Specify a score threshold to be exceeded before program exits with error.
6
+ score=no
7
+
8
+
9
+ [MESSAGES CONTROL]
10
+
11
+ # Disable specific messages
12
+ #disable=all
13
+ #enable=unused-import,unused-variable
14
+ ; disable=C0302,R0902,R0913,R0917,C0116,W0212,R0914,R0904,R0903,E0202,W0718
15
+
16
+
17
+ [BASIC]
18
+
19
+ # Maximum line length.
20
+ max-line-length=100
21
+
22
+
23
+ [TYPECHECK]
24
+
25
+ # List of module names for which member attributes should not be checked
26
+ # (useful for modules/projects where namespaces are manipulated during runtime
27
+ # and thus existing member attributes cannot be deduced by static analysis).
28
+ # It supports qualified module names, as well as Unix pattern matching.
29
+ ignored-modules=etcdrpc
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,138 @@
1
+ # AGENTS.md - python-etcd3-async
2
+
3
+ AI coding agent guidelines for the python-etcd3-async project.
4
+
5
+ ## Project Overview
6
+ - **Name**: python-etcd3-async
7
+ - **Python**: 3.12+
8
+ - **Package Manager**: uv
9
+ - **License**: Apache 2.0
10
+
11
+ ## Build & Development Commands
12
+
13
+ ### Setup
14
+ ```bash
15
+ uv sync # Install dependencies
16
+ uv sync --extra dev # Install with dev dependencies
17
+ uv pip install -e . # Editable install
18
+ ```
19
+
20
+ ### Testing (requires ETCD_ENDPOINT)
21
+ ```bash
22
+ ETCD_ENDPOINT=192.168.31.15:12379 uv run pytest
23
+ ETCD_ENDPOINT=192.168.31.15:12379 uv run pytest tests/test_async_client.py::TestAsyncClient::test_client_init -v
24
+ ETCD_ENDPOINT=192.168.31.15:12379 uv run pytest --cov=etcd3 --cov=etcdrpc
25
+ ```
26
+
27
+ ### Linting
28
+ ```bash
29
+ uv run ruff check etcd3/ etcdrpc/ # Check
30
+ uv run ruff format etcd3/ etcdrpc/ # Format
31
+ pylint etcd3/ # Static/ etcdrpc analysis
32
+ ```
33
+
34
+ ### Other
35
+ ```bash
36
+ uv run python gen_protos.py # Regenerate protobuf
37
+ uv run mkdocs serve # Serve docs
38
+ ```
39
+
40
+ ## Code Style
41
+
42
+ ### Formatting
43
+ - **Max line length**: 100 characters
44
+ - **Formatter**: ruff
45
+ - Follow PEP 8
46
+
47
+ ### Naming
48
+ - Classes: `PascalCase` (e.g., `AsyncEtcd3Client`)
49
+ - Functions/Methods: `snake_case` (e.g., `async_client()`, `get_prefix()`)
50
+ - Constants: `UPPER_CASE` (e.g., `FILTER_PUT`)
51
+ - Private: `_leading_underscore` (e.g., `_get_channel()`)
52
+
53
+ ### Imports (3 groups, sorted)
54
+ 1. Standard library
55
+ 2. Third-party (grpc, etcdrpc, pytest)
56
+ 3. Internal modules
57
+
58
+ ### Type Hints
59
+ - Use type hints for all parameters and returns
60
+ - Use `Optional[]` for nullable types, `Literal[]` for enums
61
+
62
+ ### Docstrings
63
+ - Google-style
64
+ - Document all public methods/classes
65
+ - Include type info
66
+
67
+ ### Error Handling
68
+ - Use custom exceptions from `etcd3/exceptions.py`:
69
+ - `Etcd3Exception` (base), `ConnectionFailedError`, `ConnectionTimeoutError`
70
+ - `RevisionCompactedError`, `LockReleaseError`, `BatchOperationError`
71
+ - Decorators: `_handle_errors`, `_async_handle_errors`
72
+
73
+ ## Architecture
74
+
75
+ ### Dual Client Design
76
+ - **Sync**: `Etcd3Client`, `MultiEndpointEtcd3Client` in `etcd3/client.py`
77
+ - **Async**: `AsyncEtcd3Client`, `AsyncMultiEndpointEtcd3Client` in `etcd3/async_client.py`
78
+ - Factory: `async_client()` function
79
+
80
+ ### Extension Pattern (`etcd3/async_client_extensions.py`)
81
+ - `AsyncKVOperations`, `AsyncLeaseOperations`, `AsyncLockOperations`
82
+ - `AsyncClusterOperations`, `AsyncMaintenanceOperations`, `AsyncWatchOperations`
83
+
84
+ ### Load Balancing
85
+ - `LoadBalancerStrategy` enum: `PRIORITY`, `ROUND_ROBIN`, `RANDOM`, `STICKY`
86
+
87
+ ## Observability (Environment Variables)
88
+
89
+ All prefixed with `ETCD_OBS_`:
90
+
91
+ | Variable | Default | Description |
92
+ |----------|---------|-------------|
93
+ | `ETCD_OBS_AUTO_INIT` | true | Auto-init on client create |
94
+ | `ETCD_OBS_LOG_LEVEL` | INFO | DEBUG/INFO/WARNING/ERROR |
95
+ | `ETCD_OBS_LOG_FORMAT` | text | text/json/colored |
96
+ | `ETCD_OBS_LOG_SAMPLE_RATE` | 1.0 | 0.0-1.0 |
97
+ | `ETCD_OBS_LOG_SAMPLE_STRATEGY` | always | always/rate/dynamic/level_based |
98
+ | `ETCD_OBS_TRACING_ENABLED` | true | Enable OpenTelemetry |
99
+ | `ETCD_OBS_TRACING_SERVICE_NAME` | etcd3-client | Service name |
100
+ | `ETCD_OBS_TRACING_SAMPLE_RATE` | 1.0 | Trace sampling |
101
+ | `ETCD_OBS_OTLP_ENDPOINT` | - | OTLP collector endpoint |
102
+ | `ETCD_OBS_PROMETHEUS_ENABLED` | false | Enable Prometheus |
103
+
104
+ ## Testing
105
+ - Tests require `ETCD_ENDPOINT` env var
106
+ - Unit tests: no etcd needed
107
+ - Integration tests: require running etcd server
108
+ - Test files: `tests/test_*.py`
109
+
110
+ ## Common Patterns
111
+ ```python
112
+ # Async client (auto-initializes observability)
113
+ from etcd3 import async_client
114
+ etcd = await async_client(host='localhost', port=2379)
115
+
116
+ # Sync client
117
+ from etcd3 import client
118
+ etcd = client(host='localhost', port=2379)
119
+
120
+ # Manual observability config
121
+ from etcd3 import ObservabilityConfig, configure_from_env
122
+ config = configure_from_env()
123
+ config.apply()
124
+
125
+ # Context tracking
126
+ from etcd3 import get_request_context
127
+ async with etcd.context(operation="batch_put", source="worker_1"):
128
+ await etcd.kv.batch_put(items)
129
+ ```
130
+
131
+ ## Security
132
+ - TLS, username/password, token-based auth supported
133
+ - Never commit credentials
134
+
135
+ ## References
136
+ - [python-etcd3](https://github.com/kragniz/python-etcd3)
137
+ - [Go etcd client v3](https://pkg.go.dev/go.etcd.io/etcd/client/v3)
138
+ - [etcd docs](https://etcd.io/docs/)
@@ -0,0 +1,257 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ python-etcd3-async is an async Python client library for the etcd v3 API using `grpc.aio`. It provides both synchronous and asynchronous clients with full support for etcd operations including key-value operations, leases, locks, watches, transactions, and cluster management.
8
+
9
+ ## Commands
10
+
11
+ ### Development Setup
12
+ ```bash
13
+ # Install dependencies
14
+ uv sync
15
+
16
+ # Install dev dependencies
17
+ uv sync --extra dev
18
+
19
+ # Run Python commands
20
+ uv run python <script.py>
21
+
22
+ # Install package in dev mode
23
+ uv pip install -e .
24
+ ```
25
+
26
+ ### Testing
27
+ ```bash
28
+ # Run all tests (requires ETCD_ENDPOINT environment variable)
29
+ ETCD_ENDPOINT=192.168.31.15:12379 uv run pytest
30
+
31
+ # Run a single test file
32
+ ETCD_ENDPOINT=192.168.31.15:12379 uv run pytest tests/test_async_client.py
33
+
34
+ # Run a specific test method
35
+ ETCD_ENDPOINT=192.168.31.15:12379 uv run pytest tests/test_locks.py::TestAsyncLock::test_lock_acquire -v
36
+
37
+ # Run with coverage
38
+ ETCD_ENDPOINT=192.168.31.15:12379 uv run pytest --cov=etcd3 --cov=etcdrpc
39
+
40
+ # Run with verbose output
41
+ ETCD_ENDPOINT=192.168.31.15:12379 uv run pytest -v
42
+ ```
43
+
44
+ ### Linting & Formatting
45
+ ```bash
46
+ # Check with ruff
47
+ uv run ruff check etcd3/ etcdrpc/
48
+
49
+ # Format with ruff
50
+ uv run ruff format etcd3/ etcdrpc/
51
+
52
+ # Run pylint
53
+ pylint etcd3/ etcdrpc/
54
+ ```
55
+
56
+ ### Protobuf Generation
57
+ ```bash
58
+ # Protobuf files are auto-generated during build via hatchling hook
59
+ # To manually regenerate:
60
+ uv run python gen_protos.py
61
+ ```
62
+
63
+ ### Environment Variables
64
+ | Variable | Description |
65
+ |----------|-------------|
66
+ | `ETCD3_LOG_LEVEL` | Set logging level (DEBUG, INFO, WARNING, ERROR) |
67
+ | `ETCD_ENDPOINT` | etcd server address for testing (e.g., 192.168.31.15:12379) |
68
+
69
+ ## Project Rules
70
+
71
+ 1. Use `uv` for Python environment management, `hatchling` as build tool
72
+ 2. Use `uv run python` to execute Python commands
73
+ 3. Follow PEP8规范, use `pylint` for static analysis
74
+ 4. Use `pytest` and `pytest-asyncio` for sync and async tests
75
+ 5. Use context7 MCP to query official documentation
76
+
77
+ ## Architecture
78
+
79
+ ### Core Client Classes
80
+
81
+ **Sync client (`etcd3/client.py`):**
82
+ - `MultiEndpointEtcd3Client` - Base class with multiple endpoints and failover support
83
+ - `Etcd3Client` - Single endpoint client, inherits from `MultiEndpointEtcd3Client`
84
+ - `Endpoint` - Single etcd cluster endpoint with gRPC channel
85
+
86
+ **Async client (`etcd3/async_client.py`):**
87
+ - `AsyncMultiEndpointEtcd3Client` - Main async client with failover support
88
+ - `AsyncEtcd3Client` - Alias for backward compatibility
89
+ - `async_client()` - Factory function
90
+
91
+ ### Configuration Classes
92
+
93
+ **`RangeRequestConfig`** - Dataclass for range query options (limit, revision, sort_order, etc.)
94
+
95
+ **`ClientConfig`** / **`AsyncClientConfig`** - Client connection configuration (host, port, timeout, TLS, auth)
96
+
97
+ **`AsyncMultiEndpointConfig`** - Multi-endpoint failover configuration
98
+
99
+ ### Async Operation Extensions (`etcd3/async_client_extensions.py`)
100
+
101
+ Operation classes that wrap async functionality with error handling decorators:
102
+ - `AsyncKVOperations` - Key-value CRUD operations
103
+ - `AsyncLeaseOperations` - Lease creation, revocation, refresh
104
+ - `AsyncLockOperations` - Distributed lock operations
105
+ - `AsyncClusterOperations` - Cluster operations
106
+ - `AsyncMaintenanceOperations` - Maintenance operations
107
+ - `AsyncWatchOperations` - Watch operations
108
+
109
+ ### Async Managers (`etcd3/async_managers.py`)
110
+
111
+ - `AsyncWatchManager` - Watch operations with callbacks and prefixes
112
+ - `AsyncClusterManager` - Cluster membership operations
113
+ - `AsyncMaintenanceManager` - Status, defragmentation, alarms, snapshots
114
+
115
+ ### Endpoint Pattern
116
+
117
+ **`etcd3/endpoint.py`** - Base endpoint with shared logic:
118
+ - `BaseEndpoint` - Common endpoint functionality (fail state, health check)
119
+
120
+ **`etcd3/async_endpoint.py`** (async `AsyncEndpoint` class):
121
+ - Async gRPC channel with `is_healthy()` and `rebuild_channel()`
122
+
123
+ **`etcd3/client.py`** (sync `Endpoint` class):
124
+ - Sync gRPC channel with `is_healthy()` and `rebuild_channel()`
125
+
126
+ ### Shared Components
127
+
128
+ **`etcd3/shared.py`:**
129
+ - `Transactions` - Transaction operation builders
130
+ - `KVMetadata` - Key-value metadata wrapper
131
+ - `Status`, `Alarm` - Status information classes
132
+ - `EtcdTokenCallCredentials` - Authentication credentials
133
+ - `RequestBuilder` - gRPC request builder utility
134
+ - `_handle_errors` / `_async_handle_errors` - Error handling decorators
135
+ - `_make_sync_handle_generator_errors_with_tracing` - Generator error decorator with `propagate_errors` support
136
+
137
+ **`etcd3/trace.py`:** Request tracing and monitoring utilities
138
+
139
+ **`etcd3/monitor.py` / `etcd3/async_monitor.py`:** Request monitoring decorators
140
+
141
+ **`etcd3/exceptions.py`:** Exception classes (`Etcd3Exception` and subclasses)
142
+
143
+ **`etcd3/utils.py`:** Key encoding, prefix ranges, lease conversion utilities, filter constants, load balancer strategies
144
+
145
+ **`etcd3/transactions.py`:** Transaction comparison and operation classes
146
+
147
+ **`etcd3/async_client_extensions.py`:**
148
+ - `get_request_context()` / `set_request_context()` - Context variable utilities for request tracking
149
+ - `AsyncKVOperations` - KV operations with `batch_put()`, `batch_delete()`, `put_many()` methods
150
+
151
+ **`etcd3/async_client.py`:**
152
+ - `client.context()` - Context manager for request tracking with `asyncio.Semaphore` concurrency control
153
+
154
+ **`etcd3/leases.py`:** `Lease` and `AsyncLease` classes
155
+
156
+ **`etcd3/locks.py`:** `Lock` and `AsyncLock` classes
157
+
158
+ **`etcd3/events.py`:** Watch event classes
159
+
160
+ **`etcd3/watch.py`** / **`etcd3/async_watch.py`:** Watch builder and iterator implementations
161
+
162
+ **`etcd3/members.py`:** `Member` class for cluster representation
163
+
164
+ ### Protobuf Layer (`etcdrpc/`)
165
+
166
+ Generated gRPC/Python bindings from etcd proto files:
167
+ - `rpc_pb2.py`, `rpc_pb2_grpc.py` - Main RPC definitions
168
+ - `kv_pb2.py`, `kv_pb2_grpc.py` - Key-value service
169
+ - `auth_pb2.py`, `auth_pb2_grpc.py` - Authentication service
170
+
171
+ Compiled during build via `gen_protos.py` (hatchling build hook).
172
+
173
+ ### Examples (`examples/`)
174
+
175
+ | File | Description |
176
+ |------|-------------|
177
+ | `leader_election.py` | Async leader election with lease-based lock |
178
+ | `leader_election_sync.py` | Sync version using threading |
179
+ | `service_registration.py` | Async service registration with auto-renewal |
180
+ | `service_registration_sync.py` | Sync version using threads |
181
+ | `service_discovery.py` | Async service discovery with watch callbacks |
182
+ | `service_discovery_sync.py` | Sync version using polling |
183
+
184
+ ## Key Design Patterns
185
+
186
+ 1. **Dual sync/async implementations:** Same API for sync (`client.py`) and async (`async_client.py`)
187
+
188
+ 2. **Error handling decorators:**
189
+ - `_handle_errors` / `_async_handle_errors` - Standard error handling
190
+ - `_sync_handle_keepalive_errors` / `_async_handle_keepalive_errors` - Lease keepalive with `propagate_errors=True`
191
+
192
+ 3. **Endpoint failover:** `MultiEndpointEtcd3Client` tracks failed endpoints with retry on `failover=True`
193
+
194
+ 4. **Load balancing:** Multiple strategies supported via `LoadBalancerStrategy`:
195
+ - `PRIORITY` (default): Keep current endpoint if healthy, failover on failure
196
+ - `ROUND_ROBIN`: Cycle through endpoints sequentially
197
+ - `RANDOM`: Random endpoint selection
198
+ - `STICKY`: Maintain connection to the same endpoint
199
+
200
+ 5. **Auto-reconnection:** Async has `_get_channel()`, sync has matching implementation with health check
201
+
202
+ 6. **Lazy authentication:** Async uses `_init_auth()` with `asyncio.Lock()`, sync initializes in `__init__`
203
+
204
+ 7. **Watch pattern:** Iterator + cancel function returns for both sync and async
205
+
206
+ 8. **Request context tracking:** Use `client.context()` to track operations across async tasks:
207
+ ```python
208
+ async with etcd.context(operation="batch_put", source="worker_1"):
209
+ await etcd.kv.batch_put(items)
210
+ ctx = get_request_context() # Get context in callbacks
211
+ ```
212
+
213
+ ## Common Operations
214
+
215
+ ```python
216
+ # KV Operations
217
+ client.get(key), client.put(key, value), client.delete(key)
218
+ client.get_prefix(prefix), client.get_range(start, end), client.get_all()
219
+
220
+ # Batch Operations (async only)
221
+ await client.kv.batch_put([('/key1', 'value1'), ('/key2', 'value2')])
222
+ await client.kv.batch_delete(['/key1', '/key2'])
223
+ await client.kv.put_many({'/key1': 'value1', '/key2': 'value2'})
224
+
225
+ # Watch with filters (only receive PUT events)
226
+ from etcd3 import FILTER_DELETE
227
+ events, cancel = await client.watch('/key', filters=[FILTER_DELETE])
228
+
229
+ # Leases
230
+ lease = client.lease(ttl)
231
+ async for response in lease.refresh(): pass
232
+ lease.revoke()
233
+
234
+ # Locks
235
+ lock = client.lock('/name', ttl=ttl)
236
+ await lock.acquire() / lock.release()
237
+ # or use context manager
238
+
239
+ # Watches
240
+ events_iter, cancel = client.watch(key)
241
+ async for event in events_iter: pass
242
+ cancel()
243
+
244
+ # Transactions
245
+ client.transaction(
246
+ compare=[client.transactions.value('/key') == 'expected'],
247
+ success=[client.transactions.put('/key', 'new')],
248
+ failure=[]
249
+ )
250
+
251
+ # Cluster
252
+ members = client.members()
253
+ client.add_member(urls), client.remove_member(id), client.update_member(id, urls)
254
+
255
+ # Maintenance
256
+ client.status(), client.compact(revision), client.defragment()
257
+ ```