python-etcd3-async 0.1.5__py3-none-any.whl → 0.1.6__py3-none-any.whl
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.
- etcd3/__init__.py +1 -1
- etcd3/async_client_extensions.py +2 -2
- etcd3/async_managers.py +7 -2
- etcd3/async_multi_client.py +36 -9
- etcd3/errors.py +85 -18
- etcd3/multi_client.py +24 -17
- etcd3/shared.py +14 -12
- etcd3/sync_cluster_operations.py +7 -2
- {python_etcd3_async-0.1.5.dist-info → python_etcd3_async-0.1.6.dist-info}/METADATA +1 -1
- {python_etcd3_async-0.1.5.dist-info → python_etcd3_async-0.1.6.dist-info}/RECORD +11 -11
- {python_etcd3_async-0.1.5.dist-info → python_etcd3_async-0.1.6.dist-info}/WHEEL +1 -1
etcd3/__init__.py
CHANGED
etcd3/async_client_extensions.py
CHANGED
|
@@ -730,9 +730,9 @@ class AsyncClusterOperations:
|
|
|
730
730
|
def __init__(self, client):
|
|
731
731
|
self.client = client
|
|
732
732
|
|
|
733
|
-
async def add_member(self, urls):
|
|
733
|
+
async def add_member(self, urls, is_learner=False):
|
|
734
734
|
"""Add a member into the cluster."""
|
|
735
|
-
return await self.client.cluster_manager.add_member(urls)
|
|
735
|
+
return await self.client.cluster_manager.add_member(urls, is_learner)
|
|
736
736
|
|
|
737
737
|
async def remove_member(self, member_id):
|
|
738
738
|
"""Remove an existing member from the cluster."""
|
etcd3/async_managers.py
CHANGED
|
@@ -224,14 +224,19 @@ class AsyncClusterManager:
|
|
|
224
224
|
def __init__(self, etcd_client):
|
|
225
225
|
self.etcd_client = etcd_client
|
|
226
226
|
|
|
227
|
-
async def add_member(self, urls):
|
|
227
|
+
async def add_member(self, urls, is_learner=False):
|
|
228
228
|
"""
|
|
229
229
|
Add a member into the cluster.
|
|
230
230
|
|
|
231
|
+
:param urls: peer URLs the member will advertise to the cluster
|
|
232
|
+
:param is_learner: add as a non-voting learner, which does not
|
|
233
|
+
affect quorum on an existing cluster
|
|
231
234
|
:returns: new member
|
|
232
235
|
:rtype: :class:`.Member`
|
|
233
236
|
"""
|
|
234
|
-
member_add_request = etcdrpc.MemberAddRequest(
|
|
237
|
+
member_add_request = etcdrpc.MemberAddRequest(
|
|
238
|
+
peerURLs=urls, isLearner=is_learner
|
|
239
|
+
)
|
|
235
240
|
|
|
236
241
|
# Create cluster stub directly
|
|
237
242
|
channel = await self.etcd_client._get_channel()
|
etcd3/async_multi_client.py
CHANGED
|
@@ -19,7 +19,6 @@ from etcd3.shared import (
|
|
|
19
19
|
EXCEPTIONS_BY_CODE,
|
|
20
20
|
FAILED_EP_CODES,
|
|
21
21
|
Transactions,
|
|
22
|
-
EtcdTokenCallCredentials,
|
|
23
22
|
RequestBuilder,
|
|
24
23
|
)
|
|
25
24
|
from etcd3.async_managers import (
|
|
@@ -161,8 +160,14 @@ class AsyncMultiEndpointEtcd3Client:
|
|
|
161
160
|
self.transactions = Transactions()
|
|
162
161
|
self.auth = AsyncAuthOperations(self)
|
|
163
162
|
|
|
164
|
-
async def _init_auth(self):
|
|
165
|
-
"""Initialize authentication asynchronously.
|
|
163
|
+
async def _init_auth(self, channel=None):
|
|
164
|
+
"""Initialize authentication asynchronously.
|
|
165
|
+
|
|
166
|
+
:param channel: Channel to run Authenticate on. Callers from
|
|
167
|
+
``_get_channel`` pass the channel they are about to return —
|
|
168
|
+
re-acquiring here could rebuild (close) that channel.
|
|
169
|
+
:type channel: grpc.aio.Channel, optional
|
|
170
|
+
"""
|
|
166
171
|
if self._auth_done:
|
|
167
172
|
return
|
|
168
173
|
|
|
@@ -172,7 +177,8 @@ class AsyncMultiEndpointEtcd3Client:
|
|
|
172
177
|
|
|
173
178
|
if self._user and self._password:
|
|
174
179
|
# Create auth stub with auto-reconnection
|
|
175
|
-
channel
|
|
180
|
+
if channel is None:
|
|
181
|
+
channel = await self._acquire_channel()
|
|
176
182
|
auth_stub = etcdrpc.AuthStub(channel)
|
|
177
183
|
|
|
178
184
|
auth_request = etcdrpc.AuthenticateRequest(
|
|
@@ -180,10 +186,11 @@ class AsyncMultiEndpointEtcd3Client:
|
|
|
180
186
|
)
|
|
181
187
|
|
|
182
188
|
resp = await auth_stub.Authenticate(auth_request, timeout=self.timeout)
|
|
189
|
+
# Token is attached via self.metadata on every call. Do not
|
|
190
|
+
# create grpc call credentials here: grpc.aio rejects them on
|
|
191
|
+
# insecure channels ("call credentials are only valid on
|
|
192
|
+
# secure channels") and the metadata token works everywhere.
|
|
183
193
|
self.metadata = (("token", resp.token),)
|
|
184
|
-
self.call_credentials = grpc.metadata_call_credentials(
|
|
185
|
-
EtcdTokenCallCredentials(resp.token)
|
|
186
|
-
)
|
|
187
194
|
|
|
188
195
|
self._auth_done = True
|
|
189
196
|
|
|
@@ -280,11 +287,28 @@ class AsyncMultiEndpointEtcd3Client:
|
|
|
280
287
|
"""Try to rebuild the channel, return True on success, False on failure."""
|
|
281
288
|
try:
|
|
282
289
|
await endpoint.rebuild_channel()
|
|
290
|
+
# A rebuilt channel may talk to a restarted server whose
|
|
291
|
+
# token seed changed; force re-authentication on next use.
|
|
292
|
+
self._auth_done = False
|
|
283
293
|
return True
|
|
284
294
|
except Exception:
|
|
285
295
|
return False
|
|
286
296
|
|
|
287
297
|
async def _get_channel(self):
|
|
298
|
+
"""Get an available channel, authenticating first when credentials exist.
|
|
299
|
+
|
|
300
|
+
Lazy auth: when the client was created with user/password and no
|
|
301
|
+
token is held yet (initial use or after a channel rebuild), the
|
|
302
|
+
Authenticate RPC runs before the channel is handed out. All call
|
|
303
|
+
sites read ``self.metadata`` after ``_get_channel()``, so the
|
|
304
|
+
token is always attached.
|
|
305
|
+
"""
|
|
306
|
+
channel = await self._acquire_channel()
|
|
307
|
+
if self._user and self._password and not self._auth_done:
|
|
308
|
+
await self._init_auth(channel)
|
|
309
|
+
return channel
|
|
310
|
+
|
|
311
|
+
async def _acquire_channel(self):
|
|
288
312
|
"""Get an available channel with automatic reconnection support.
|
|
289
313
|
|
|
290
314
|
Uses two-phase locking strategy:
|
|
@@ -969,14 +993,17 @@ class AsyncMultiEndpointEtcd3Client:
|
|
|
969
993
|
"""
|
|
970
994
|
return await self.lock_ops.lock(name, ttl=ttl)
|
|
971
995
|
|
|
972
|
-
async def add_member(self, urls):
|
|
996
|
+
async def add_member(self, urls, is_learner=False):
|
|
973
997
|
"""
|
|
974
998
|
Add a member into the cluster.
|
|
975
999
|
|
|
1000
|
+
:param urls: peer URLs the member will advertise to the cluster
|
|
1001
|
+
:param is_learner: add as a non-voting learner, which does not
|
|
1002
|
+
affect quorum on an existing cluster
|
|
976
1003
|
:returns: new member
|
|
977
1004
|
:rtype: :class:`.Member`
|
|
978
1005
|
"""
|
|
979
|
-
return await self.cluster_ops.add_member(urls)
|
|
1006
|
+
return await self.cluster_ops.add_member(urls, is_learner)
|
|
980
1007
|
|
|
981
1008
|
async def remove_member(self, member_id):
|
|
982
1009
|
"""
|
etcd3/errors.py
CHANGED
|
@@ -26,6 +26,79 @@ _FAILED_EP_CODES = [
|
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
def _is_invalid_auth_token(exc):
|
|
30
|
+
"""Check if an RPC error means the server rejected our auth token."""
|
|
31
|
+
try:
|
|
32
|
+
return exc.code() == grpc.StatusCode.UNAUTHENTICATED
|
|
33
|
+
except Exception:
|
|
34
|
+
return False
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def _try_reauth(client_or_ops):
|
|
38
|
+
"""Re-authenticate after the server rejected our token.
|
|
39
|
+
|
|
40
|
+
etcd rotates its token seed on restart, so an existing channel can be
|
|
41
|
+
fully healthy while the stored token is dead. Drop the token and let
|
|
42
|
+
the lazy-auth path in ``_get_channel`` mint a fresh one.
|
|
43
|
+
|
|
44
|
+
:return: True when a new token was obtained, False when re-auth does
|
|
45
|
+
not apply (no credentials or non-authenticating client object)
|
|
46
|
+
"""
|
|
47
|
+
client = getattr(client_or_ops, "client", client_or_ops)
|
|
48
|
+
if not (
|
|
49
|
+
getattr(client, "_user", None)
|
|
50
|
+
and getattr(client, "_password", None)
|
|
51
|
+
and hasattr(client, "_get_channel")
|
|
52
|
+
):
|
|
53
|
+
return False
|
|
54
|
+
client._auth_done = False
|
|
55
|
+
await client._get_channel()
|
|
56
|
+
return True
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
async def _call_with_auth_retry(payload, self, args, kwargs, error_handler_func):
|
|
60
|
+
"""Run payload; on an invalid-token error re-authenticate and retry once.
|
|
61
|
+
|
|
62
|
+
The retry attempt is safe: an UNAUTHENTICATED call never reached the
|
|
63
|
+
state machine, so the operation was not applied server-side.
|
|
64
|
+
"""
|
|
65
|
+
try:
|
|
66
|
+
return await payload(self, *args, **kwargs)
|
|
67
|
+
except grpc.RpcError as exc:
|
|
68
|
+
if _is_invalid_auth_token(exc) and await _try_reauth(self):
|
|
69
|
+
try:
|
|
70
|
+
return await payload(self, *args, **kwargs)
|
|
71
|
+
except grpc.RpcError as retry_exc:
|
|
72
|
+
exc = retry_exc
|
|
73
|
+
error_handler_func(self, exc)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _try_reauth_sync(client_or_ops):
|
|
77
|
+
"""Sync counterpart of :func:`_try_reauth` (see above)."""
|
|
78
|
+
client = getattr(client_or_ops, "client", client_or_ops)
|
|
79
|
+
if not (
|
|
80
|
+
getattr(client, "_user", None)
|
|
81
|
+
and getattr(client, "_password", None)
|
|
82
|
+
and hasattr(client, "_authenticate")
|
|
83
|
+
):
|
|
84
|
+
return False
|
|
85
|
+
client._authenticate()
|
|
86
|
+
return True
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _call_with_auth_retry_sync(payload, self, args, kwargs, error_handler_func):
|
|
90
|
+
"""Sync counterpart of :func:`_call_with_auth_retry` (see above)."""
|
|
91
|
+
try:
|
|
92
|
+
return payload(self, *args, **kwargs)
|
|
93
|
+
except grpc.RpcError as exc:
|
|
94
|
+
if _is_invalid_auth_token(exc) and _try_reauth_sync(self):
|
|
95
|
+
try:
|
|
96
|
+
return payload(self, *args, **kwargs)
|
|
97
|
+
except grpc.RpcError as retry_exc:
|
|
98
|
+
exc = retry_exc
|
|
99
|
+
error_handler_func(self, exc)
|
|
100
|
+
|
|
101
|
+
|
|
29
102
|
def _make_async_handle_errors_with_tracing(error_handler_func, operation_name: str):
|
|
30
103
|
"""Factory to create async error handlers with tracing."""
|
|
31
104
|
|
|
@@ -34,15 +107,13 @@ def _make_async_handle_errors_with_tracing(error_handler_func, operation_name: s
|
|
|
34
107
|
async def handler(self, *args, **kwargs):
|
|
35
108
|
tracer = get_tracer()
|
|
36
109
|
if tracer is None:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
error_handler_func(self, exc)
|
|
110
|
+
return await _call_with_auth_retry(
|
|
111
|
+
payload, self, args, kwargs, error_handler_func
|
|
112
|
+
)
|
|
41
113
|
with create_span(operation_name, {"operation": operation_name}):
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
error_handler_func(self, exc)
|
|
114
|
+
return await _call_with_auth_retry(
|
|
115
|
+
payload, self, args, kwargs, error_handler_func
|
|
116
|
+
)
|
|
46
117
|
|
|
47
118
|
return handler
|
|
48
119
|
|
|
@@ -100,17 +171,13 @@ def _make_sync_handle_errors_with_tracing(error_handler_func, operation_name: st
|
|
|
100
171
|
def handler(self, *args, **kwargs):
|
|
101
172
|
tracer = get_tracer()
|
|
102
173
|
if tracer is None:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
error_handler_func(self, exc)
|
|
107
|
-
return
|
|
174
|
+
return _call_with_auth_retry_sync(
|
|
175
|
+
payload, self, args, kwargs, error_handler_func
|
|
176
|
+
)
|
|
108
177
|
with create_span(operation_name, {"operation": operation_name}):
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
error_handler_func(self, exc)
|
|
113
|
-
return
|
|
178
|
+
return _call_with_auth_retry_sync(
|
|
179
|
+
payload, self, args, kwargs, error_handler_func
|
|
180
|
+
)
|
|
114
181
|
|
|
115
182
|
return handler
|
|
116
183
|
|
etcd3/multi_client.py
CHANGED
|
@@ -164,21 +164,17 @@ class MultiEndpointEtcd3Client:
|
|
|
164
164
|
cred_params = [c is not None for c in (user, password)]
|
|
165
165
|
|
|
166
166
|
if all(cred_params):
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
auth_stub = etcdrpc.AuthStub(self.channel)
|
|
171
|
-
resp = auth_stub.Authenticate(auth_request, self.timeout)
|
|
172
|
-
self.metadata = (("token", resp.token),)
|
|
173
|
-
self.call_credentials = grpc.metadata_call_credentials(
|
|
174
|
-
self._get_etcd_token_call_credentials(resp.token)
|
|
175
|
-
)
|
|
176
|
-
|
|
167
|
+
self._user = user
|
|
168
|
+
self._password = password
|
|
169
|
+
self._authenticate()
|
|
177
170
|
elif any(cred_params):
|
|
178
|
-
raise
|
|
171
|
+
raise ValueError(
|
|
179
172
|
"if using authentication credentials both user and password "
|
|
180
173
|
"must be specified."
|
|
181
174
|
)
|
|
175
|
+
else:
|
|
176
|
+
self._user = None
|
|
177
|
+
self._password = None
|
|
182
178
|
|
|
183
179
|
# Import here to avoid circular dependency
|
|
184
180
|
from etcd3.shared import Transactions
|
|
@@ -206,11 +202,19 @@ class MultiEndpointEtcd3Client:
|
|
|
206
202
|
|
|
207
203
|
self.maintenance = SyncMaintenanceOperations(self)
|
|
208
204
|
|
|
209
|
-
def
|
|
210
|
-
"""
|
|
211
|
-
from etcd3.shared import EtcdTokenCallCredentials
|
|
205
|
+
def _authenticate(self):
|
|
206
|
+
"""Obtain an auth token on the current channel (metadata-only).
|
|
212
207
|
|
|
213
|
-
|
|
208
|
+
The token rides in ``self.metadata`` on every call. Do not create
|
|
209
|
+
grpc call credentials here: they are rejected on insecure channels
|
|
210
|
+
and the metadata token works everywhere, matching the async client.
|
|
211
|
+
"""
|
|
212
|
+
auth_request = etcdrpc.AuthenticateRequest(
|
|
213
|
+
name=self._user, password=self._password
|
|
214
|
+
)
|
|
215
|
+
auth_stub = etcdrpc.AuthStub(self.channel)
|
|
216
|
+
resp = auth_stub.Authenticate(auth_request, self.timeout)
|
|
217
|
+
self.metadata = (("token", resp.token),)
|
|
214
218
|
|
|
215
219
|
@property
|
|
216
220
|
def _current_endpoint_label(self):
|
|
@@ -1159,14 +1163,17 @@ class MultiEndpointEtcd3Client:
|
|
|
1159
1163
|
"""
|
|
1160
1164
|
return self.lock_ops.lock(name, ttl=ttl)
|
|
1161
1165
|
|
|
1162
|
-
def add_member(self, urls):
|
|
1166
|
+
def add_member(self, urls, is_learner=False):
|
|
1163
1167
|
"""
|
|
1164
1168
|
Add a member into the cluster.
|
|
1165
1169
|
|
|
1170
|
+
:param urls: peer URLs the member will advertise to the cluster
|
|
1171
|
+
:param is_learner: add as a non-voting learner, which does not
|
|
1172
|
+
affect quorum on an existing cluster
|
|
1166
1173
|
:returns: new member
|
|
1167
1174
|
:rtype: :class:`.Member`
|
|
1168
1175
|
"""
|
|
1169
|
-
return self.cluster.add_member(urls)
|
|
1176
|
+
return self.cluster.add_member(urls, is_learner)
|
|
1170
1177
|
|
|
1171
1178
|
def remove_member(self, member_id):
|
|
1172
1179
|
"""
|
etcd3/shared.py
CHANGED
|
@@ -9,7 +9,16 @@ import functools
|
|
|
9
9
|
import grpc
|
|
10
10
|
import etcdrpc
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
# For backward compatibility, expose error handler factories
|
|
13
|
+
from etcd3.errors import (
|
|
14
|
+
_make_sync_handle_errors_with_tracing,
|
|
15
|
+
_make_sync_handle_generator_errors_with_tracing,
|
|
16
|
+
_make_async_handle_errors_with_tracing as _make_async_handle_errors_with_tracing,
|
|
17
|
+
_make_async_handle_generator_errors_with_tracing as _make_async_handle_generator_errors_with_tracing,
|
|
18
|
+
_EXCEPTIONS_BY_CODE,
|
|
19
|
+
_FAILED_EP_CODES,
|
|
20
|
+
)
|
|
21
|
+
|
|
13
22
|
import etcd3.transactions as transactions
|
|
14
23
|
import etcd3.utils as utils
|
|
15
24
|
|
|
@@ -299,16 +308,6 @@ class RequestBuilder:
|
|
|
299
308
|
return delete_request
|
|
300
309
|
|
|
301
310
|
|
|
302
|
-
# For backward compatibility, expose error handler factories
|
|
303
|
-
from etcd3.errors import (
|
|
304
|
-
_make_sync_handle_errors_with_tracing,
|
|
305
|
-
_make_sync_handle_generator_errors_with_tracing,
|
|
306
|
-
_make_async_handle_errors_with_tracing,
|
|
307
|
-
_make_async_handle_generator_errors_with_tracing,
|
|
308
|
-
_EXCEPTIONS_BY_CODE,
|
|
309
|
-
_FAILED_EP_CODES,
|
|
310
|
-
)
|
|
311
|
-
|
|
312
311
|
# Re-export for compatibility
|
|
313
312
|
EXCEPTIONS_BY_CODE = _EXCEPTIONS_BY_CODE
|
|
314
313
|
FAILED_EP_CODES = _FAILED_EP_CODES
|
|
@@ -324,7 +323,10 @@ def _init_sync_error_handlers(error_handler_func):
|
|
|
324
323
|
|
|
325
324
|
This must be called after client module is fully loaded.
|
|
326
325
|
"""
|
|
327
|
-
global
|
|
326
|
+
global \
|
|
327
|
+
_sync_handle_errors, \
|
|
328
|
+
_sync_handle_generator_errors, \
|
|
329
|
+
_sync_handle_keepalive_errors
|
|
328
330
|
_sync_handle_errors = _make_sync_handle_errors_with_tracing(
|
|
329
331
|
error_handler_func, "etcd3.operation"
|
|
330
332
|
)
|
etcd3/sync_cluster_operations.py
CHANGED
|
@@ -43,14 +43,19 @@ class SyncClusterOperations:
|
|
|
43
43
|
return self.client.metadata
|
|
44
44
|
|
|
45
45
|
@_sync_handle_errors
|
|
46
|
-
def add_member(self, urls):
|
|
46
|
+
def add_member(self, urls, is_learner=False):
|
|
47
47
|
"""
|
|
48
48
|
Add a member into the cluster.
|
|
49
49
|
|
|
50
|
+
:param urls: peer URLs the member will advertise to the cluster
|
|
51
|
+
:param is_learner: add as a non-voting learner, which does not
|
|
52
|
+
affect quorum on an existing cluster
|
|
50
53
|
:returns: new member
|
|
51
54
|
:rtype: :class:`.Member`
|
|
52
55
|
"""
|
|
53
|
-
member_add_request = etcdrpc.MemberAddRequest(
|
|
56
|
+
member_add_request = etcdrpc.MemberAddRequest(
|
|
57
|
+
peerURLs=urls, isLearner=is_learner
|
|
58
|
+
)
|
|
54
59
|
|
|
55
60
|
# Create cluster stub directly
|
|
56
61
|
cluster_stub = etcdrpc.ClusterStub(self.channel)
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
etcd3/__init__.py,sha256=
|
|
1
|
+
etcd3/__init__.py,sha256=SB6RBboBlNB86OdfisuMJIAgdpq87uez2JrUGfhLL4E,3353
|
|
2
2
|
etcd3/async_client.py,sha256=r10DHsJP6rWD55N5iq28ONRcU3VgWQozTJiLbFnKUEs,1499
|
|
3
|
-
etcd3/async_client_extensions.py,sha256
|
|
3
|
+
etcd3/async_client_extensions.py,sha256=-L6FYftLfwzxWNKMZZCgu0SILBLLtSwsLUZ8Np8ixOY,34214
|
|
4
4
|
etcd3/async_config.py,sha256=tjGR_SP25uYpC0wI9LoHxKgPuL7yaSHWtUQrcPrx0uQ,3530
|
|
5
5
|
etcd3/async_endpoint.py,sha256=pXlMaV7acNQPFohYV3eCWfVTDSgvZlbwy42z0tx3rm4,4595
|
|
6
|
-
etcd3/async_managers.py,sha256=
|
|
6
|
+
etcd3/async_managers.py,sha256=qEDED9SbYy8xrMn180fK3FdlVzJnqV_Rs_5wvDLYnYA,18391
|
|
7
7
|
etcd3/async_monitor.py,sha256=iZPac3Pqn5bI0ONguJJctQsi4b2ft4hWPknug6jj5RY,453
|
|
8
|
-
etcd3/async_multi_client.py,sha256=
|
|
8
|
+
etcd3/async_multi_client.py,sha256=N_FbfIHxCIKltdcJx7P0n14bLVwtdvZnpYl8jWk31yQ,46709
|
|
9
9
|
etcd3/async_single_client.py,sha256=VO-ct-x6jPnqf2tPUlMYeitftxvgJTrM5KzyV7WaRhI,4506
|
|
10
10
|
etcd3/async_watch.py,sha256=m6I2BAoI54J-ZPVVMxao6XJQXvVyQ88Hp2QeauD9z20,15962
|
|
11
11
|
etcd3/auth.py,sha256=gWd6Cl2CMe4P6i4SsLQ_9UMv9bNSCs_QAMqyOVfKQ3k,21896
|
|
12
12
|
etcd3/client.py,sha256=KXC7IwVOQlgky5GBg2Qmf-pNBwHlgR27rzKe-7tBSD4,1332
|
|
13
13
|
etcd3/config.py,sha256=3Jm6Nbpdp-hiToR_FtM6cgktV5vB_5Da3S-aENtAtYU,6069
|
|
14
14
|
etcd3/endpoint.py,sha256=aSMBmEitAADW0ABAZhc8L7jPYsQo8amEWKv6LJbsmC4,2589
|
|
15
|
-
etcd3/errors.py,sha256=
|
|
15
|
+
etcd3/errors.py,sha256=kCy_vXTC8pInVv4UZqyGgc6LLcEevw1pWMlapWZCr4I,9084
|
|
16
16
|
etcd3/events.py,sha256=TBWIiw6c_PcdAaBv_-jEqbOZNWTzTkZfDbHrYCkR9n0,903
|
|
17
17
|
etcd3/exceptions.py,sha256=mkCdJAyWIJiVwHnT7PvDQ8aJTN3d8mW4KXs_V91Lr74,1093
|
|
18
18
|
etcd3/leases.py,sha256=pkJVfYWCZ_uBXSjla5TXFfNf_D6yoTJnkntefOaPRrk,2788
|
|
@@ -21,11 +21,11 @@ etcd3/log.py,sha256=sMo6av48x9Nf_YDIWdSv8R-VUeVXi1n17wGDAAaFnlM,4282
|
|
|
21
21
|
etcd3/log_formatters.py,sha256=weWgMQjuI_cZFBEUORGCgkFJQIPvDUaiCLJN64t7s9o,7304
|
|
22
22
|
etcd3/log_sampling.py,sha256=7PhNz-HOZ6sHdBiXS29YJ3baHY_L1VwJaq4NZt2yX78,6692
|
|
23
23
|
etcd3/members.py,sha256=4t71YSzPfoEzyNMIRGFuJQXoydfHUwlk_JDxTM8moeg,1325
|
|
24
|
-
etcd3/multi_client.py,sha256=
|
|
24
|
+
etcd3/multi_client.py,sha256=FiI85nMgc2Atni6GgEPW67kXVtjllS6c6W6uRf8HRck,44550
|
|
25
25
|
etcd3/observability.py,sha256=BLOUMs1H2icF-tEWB_RoZFKoCNoXZt1ZZERGfckesW4,14215
|
|
26
|
-
etcd3/shared.py,sha256=
|
|
26
|
+
etcd3/shared.py,sha256=RGzbc7SNprvC-QFODVfP9HR2hD1oAc9tVaNwVQ6GGmI,10999
|
|
27
27
|
etcd3/single_client.py,sha256=sG3tna7i_1y5u_XuwvsH0BeMQIj6uaKL5XgOYRpratI,5014
|
|
28
|
-
etcd3/sync_cluster_operations.py,sha256=
|
|
28
|
+
etcd3/sync_cluster_operations.py,sha256=YgJGjqdSEhzp-0A1QIwXJtZNw-IbjDnxTDCiZKJydIE,4319
|
|
29
29
|
etcd3/sync_kv_operations.py,sha256=yMeq6sLvcY-DbMIZGyzDxOyU_4mT5FEse7rGaJJUqA8,22150
|
|
30
30
|
etcd3/sync_lock_operations.py,sha256=XkezEM0lDGKhj3BPiMtmfFteWatm-XbZewAtjcreuwM,1091
|
|
31
31
|
etcd3/sync_maintenance_operations.py,sha256=oDXRfrMsTYvpMKbvD0K1k1nwgzyYcnjmqO8jZ3QZfUI,8397
|
|
@@ -49,6 +49,6 @@ etcdrpc/rpc.proto,sha256=UD4vXbdPUNHSLSx7K_UltWqJjWswHBKSs0t9aNMA4qg,31351
|
|
|
49
49
|
etcdrpc/rpc_pb2.py,sha256=8qhnULNr8jym0qyivDVqJB86H_u1Rb_K8iY8FNT9e0s,30252
|
|
50
50
|
etcdrpc/rpc_pb2.pyi,sha256=TfPtHXIluO_D1rchVMVfoSgZTPQLk-YNhmcJBIt9XIk,35473
|
|
51
51
|
etcdrpc/rpc_pb2_grpc.py,sha256=HOifyKL0X3BmLkS1r0tWTMfyfChBiy76O6Ys12kT5n8,73810
|
|
52
|
-
python_etcd3_async-0.1.
|
|
53
|
-
python_etcd3_async-0.1.
|
|
54
|
-
python_etcd3_async-0.1.
|
|
52
|
+
python_etcd3_async-0.1.6.dist-info/METADATA,sha256=WBABRd9BOnhf7XzvTGViH3mGsym5srfDLgXo5cN9aWg,8723
|
|
53
|
+
python_etcd3_async-0.1.6.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
54
|
+
python_etcd3_async-0.1.6.dist-info/RECORD,,
|