{ "info": { "author": "Renjie Cai", "author_email": "revol.cai@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "# etcd3-py\n\n[![pypi](https://img.shields.io/pypi/v/etcd3-py.svg)](https://pypi.python.org/pypi/etcd3-py)\n[![travis](https://travis-ci.org/Revolution1/etcd3-py.svg?branch=master)](https://travis-ci.org/Revolution1/etcd3-py)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/9448814cd66b4a568365bc050d88270c)](https://www.codacy.com/app/revol/etcd3-py?utm_source=github.com&utm_medium=referral&utm_content=Revolution1/etcd3-py&utm_campaign=Badge_Grade)\n[![codecov](https://codecov.io/gh/Revolution1/etcd3-py/branch/master/graph/badge.svg)](https://codecov.io/gh/Revolution1/etcd3-py)\n[![doc](https://readthedocs.org/projects/etcd3-py/badge/?version=latest)](http://etcd3-py.readthedocs.io/en/latest/?badge=latest)\n[![updates](https://pyup.io/repos/github/Revolution1/etcd3-py/shield.svg)](https://pyup.io/repos/github/Revolution1/etcd3-py/)\n[![python3](https://pyup.io/repos/github/Revolution1/etcd3-py/python-3-shield.svg)](https://pyup.io/repos/github/Revolution1/etcd3-py/)\n\nPython client for etcd v3 (Using gRPC-JSON-Gateway)\n\n* Free software: Apache Software License 2.0\n* Source Code: https://github.com/Revolution1/etcd3-py\n* Documentation: https://etcd3-py.readthedocs.io.\n* etcd version required: v3.2.2+\n\nNotice: The authentication header through gRPC-JSON-Gateway only supported in [etcd v3.3.0+](https://github.com/coreos/etcd/pull/7999)\n\n## Features\n\n* [x] Support python2.7 and python3.5+ (aiohttp requires python3.5.2+)\n* [x] Sync client based on requests\n* [x] Async client based on aiohttp\n* [x] TLS Connection\n* [x] support APIs\n * [x] Auth\n * [x] KV\n * [x] Watch\n * [x] Cluster\n * [x] Lease\n * [x] Lock\n * [x] Maintenance\n * [x] Extra APIs\n* [x] stateful utilities\n * [x] Watch\n * [x] Lease\n * [x] Transaction\n * [x] Lock\n\n## Quick Start\n\n**Install**\n```bash\n$ pip install etcd3-py\n```\n\n**Sync Client**\n```python\n>>> from etcd3 import Client\n>>> client = Client('127.0.0.1', 2379, cert=(CERT_PATH, KEY_PATH), verify=CA_PATH)\n>>> client.version()\nEtcdVersion(etcdserver='3.3.0-rc.4', etcdcluster='3.3.0')\n>>> client.put('foo', 'bar')\netcdserverpbPutResponse(header=etcdserverpbResponseHeader(cluster_id=11588568905070377092, member_id=128088275939295631, revision=15433, raft_term=4))\n>>> client.range('foo').kvs\n[mvccpbKeyValue(key=b'foo', create_revision=15429, mod_revision=15433, version=5, value=b'bar')]\n```\n\n**Async Client (Python3.5+)**\n```python\n>>> import asyncio\n>>> from etcd3 import AioClient\n>>> client = AioClient('127.0.0.1', 2379)\n>>> async def getFoo():\n... await client.put('foo', 'bar')\n... r = await client.range('foo')\n... print('key:', r.kvs[0].key, 'value:', r.kvs[0].value)\n>>> loop = asyncio.get_event_loop()\n>>> loop.run_until_complete(getFoo())\nkey: b'foo' value: b'bar'\n```\n\n**Transaction Util**\n```python\n>>> from etcd3 import Client\n>>> txn = Client().Txn()\n>>> txn.compare(txn.key('foo').value == 'bar')\n>>> txn.success(txn.put('foo', 'bra'))\n>>> txn.commit()\netcdserverpbTxnResponse(header=etcdserverpbResponseHeader(cluster_id=11588568905070377092, member_id=128088275939295631, revision=15656, raft_term=4), succeeded=True, responses=[etcdserverpbResponseOp(response_put=etcdserverpbPutResponse(header=etcdserverpbResponseHeader(revision=15656)))])\n```\n\n**Lease Util**\n```python\n>>> from etcd3 import Client\n>>> client = Client()\n>>> with client.Lease(ttl=5) as lease:\n... client.put('foo', 'bar', lease=lease.ID)\n... client.put('fizz', 'buzz', lease=lease.ID)\n... r = lease.time_to_live(keys=True)\n... assert set(r.keys) == {b'foo', b'fizz'}\n... assert lease.alive()\n```\n\n**Watch Util**\n```python\n>>> from etcd3 import Client\n>>> client = Client()\n>>> watcher = c.Watcher(all=True, progress_notify=True, prev_kv=True)\n>>> w.onEvent('f.*', lambda e: print(e.key, e.value))\n>>> w.runDaemon()\n>>> # etcdctl put foo bar\n>>> # etcdctl put foz bar\nb'foo' b'bar'\nb'foz' b'bar'\n>>> w.stop()\n```\n\n**Lock Util**\n```python\n>>> import time\n>>> from threading import Thread\n>>> from etcd3 import Client\n>>> client = Client()\n>>> name = 'lock_name'\n>>> def user1():\n... with client.Lock(name, lock_ttl=5):\n... print('user1 got the lock')\n... time.sleep(5)\n... print('user1 releasing the lock')\n>>> def user2():\n... with client.Lock(name, lock_ttl=5):\n... print('user2 got the lock')\n... time.sleep(5)\n... print('user2 releasing the lock')\n>>> t1 = Thread(target=user1, daemon=True)\n>>> t2 = Thread(target=user2, daemon=True)\n>>> t1.start()\n>>> t2.start()\n>>> t1.join()\n>>> t2.join()\nuser1 got the lock\nuser1 releasing the lock\nuser2 got the lock\nuser2 releasing the lock\n```\n\n**Start a single-node etcd using docker**\n```bash\nexport NODE1=0.0.0.0\nexport ETCD_VER=v3.3\ndocker run -d \\\n-p 2379:2379 \\\n-p 2380:2380 \\\n--volume=/tmp/etcd3-data:/etcd-data \\\n--name etcd3 quay.io/coreos/etcd:$ETCD_VER \\\n/usr/local/bin/etcd \\\n--data-dir=/etcd-data --name node1 \\\n--initial-advertise-peer-urls http://${NODE1}:2380 --listen-peer-urls http://${NODE1}:2380 \\\n--advertise-client-urls http://${NODE1}:2379 --listen-client-urls http://${NODE1}:2379 \\\n--initial-cluster node1=http://${NODE1}:2380\n```\n\n## FAQ\n\n**Q:** authentication seems not working? Try calling api of a auth-enabled etcd server returned error \"ErrUserEmpty error:'etcdserver: user name is empty'\"\n\n**A:** Take a look at [#41](https://github.com/Revolution1/etcd3-py/issues/41), currently etcd3-py dose not authenticate automatically, you need to call client.auth() by yourself.\n\n## TODO\n\n- [ ] human friendly middle level apis\n- [ ] able to expose json or raw response to user\n- [ ] add election api\n- [ ] benchmark\n- [ ] python-etcd(etcd v2) compatible client\n- [ ] etcd browser\n- [ ] support etcd v3.4.x\n\n\n# History\n\n## 0.1.6 (2019-05-9)\n\n- merge pull request [#90](https://github.com/Revolution1/etcd3-py/pull/90) Fix lease util keeping problems\n- merge pull request [#89](https://github.com/Revolution1/etcd3-py/pull/89) Add range end and lease to txn\n- merge pull request [#87](https://github.com/Revolution1/etcd3-py/pull/87) Add handel null value as gogoproto does while modelizing response data\n- merge pull request [#82](https://github.com/Revolution1/etcd3-py/pull/82) Fix watch util issue #18 and #78\n- merge pull request [#79](https://github.com/Revolution1/etcd3-py/pull/79) Improve etcd comapabitity of multiple versions\n- merge pull request [#51](https://github.com/Revolution1/etcd3-py/pull/51) Add a base EtcdModel to all dynamic created model\n- merge pull request [#42](https://github.com/Revolution1/etcd3-py/pull/42) Improve etcd comapabitity of multiple versions\n\n## 0.1.5 (2018-07-4)\n\n- merge pull request [#34](https://github.com/Revolution1/etcd3-py/pull/34) enum34 only where it's needed\n\n## 0.1.4 (2018-03-30)\n\n- better code quality\n- support etcd v3.2.2+\n\n## 0.1.3 (2018-03-21)\n\n- finished lock util\n\n## 0.1.2 (2018-03-20)\n\n- Add more test\n- Add watcher, transaction and lease util\n\nYou can try it at dev environment\n\n## 0.1.0 (2018-03-19)\n\n- Implemented all APIs of etcd3's gRPC-JSON-Gateway\n- Stateful utils (Watcher Lease Lock Transaction) are in progress\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/revolution1/etcd3-py", "keywords": "etcd3", "license": "Apache Software License 2.0", "maintainer": "", "maintainer_email": "", "name": "etcd3-py", "package_url": "https://pypi.org/project/etcd3-py/", "platform": "", "project_url": "https://pypi.org/project/etcd3-py/", "project_urls": { "Homepage": "https://github.com/revolution1/etcd3-py" }, "release_url": "https://pypi.org/project/etcd3-py/0.1.6/", "requires_dist": [ "six (>=1.11.0)", "requests (>=2.10.0)", "semantic-version (>=2.6.0)", "pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "enum34 (>=1.1.6) ; python_version < \"3.4\"", "aiohttp ; python_version >= \"3.5\"" ], "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "summary": "Python client for etcd v3 (Using gRPC-JSON-Gateway)", "version": "0.1.6" }, "last_serial": 5246542, "releases": { "0.1.1": [ { "comment_text": "", "digests": { "md5": "4ee4a620c16faaf9777a7a0350e0de7e", "sha256": "6e3e38e592948d72fe9ab4a12d261a8545f685577c339ce2c1c75998c78210cc" }, "downloads": -1, "filename": "etcd3_py-0.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4ee4a620c16faaf9777a7a0350e0de7e", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 46647, "upload_time": "2018-03-18T17:59:15", "url": "https://files.pythonhosted.org/packages/bb/70/281ef389c8e97d605cfff2ed0017f51114baae8cb215053791178f676fea/etcd3_py-0.1.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b15aa2a07f7a41cc94ac65c43ce5355c", "sha256": "c01df607825d8b24628c14c29144938120feb4325dc5efad336d8da132d19244" }, "downloads": -1, "filename": "etcd3-py-0.1.1.tar.gz", "has_sig": false, "md5_digest": "b15aa2a07f7a41cc94ac65c43ce5355c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 67472, "upload_time": "2018-03-18T17:59:10", "url": "https://files.pythonhosted.org/packages/47/41/a1dc8504ebc877bd98314b76a335ae59a8dd3233aeff1e5bd17371e0d0a1/etcd3-py-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "0fc2ce6b48482ed22874a474add62523", "sha256": "eaa2a69b044ae5533e0e4d6f9b8958e321c89c86d64dfd3f26c256880852de30" }, "downloads": -1, "filename": "etcd3_py-0.1.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "0fc2ce6b48482ed22874a474add62523", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 58196, "upload_time": "2018-03-20T11:42:53", "url": "https://files.pythonhosted.org/packages/64/42/0f95ab0303be3f0a7f30f567a2670cc782d2b0cddc3f650e1711000b2ad8/etcd3_py-0.1.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7ac84dd644795f92dbff9c3a6136f3cf", "sha256": "e2be20f164b70e5726eb99d3f179a8332dcb96a7a369464f50354778a7416d87" }, "downloads": -1, "filename": "etcd3-py-0.1.2.tar.gz", "has_sig": false, "md5_digest": "7ac84dd644795f92dbff9c3a6136f3cf", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 78378, "upload_time": "2018-03-20T11:42:42", "url": "https://files.pythonhosted.org/packages/dd/15/06a42d91770af7de3302dfac8687671444fcae4f6b236889bbe753ad908f/etcd3-py-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "68b3567d6044334c68c3ae20d8de16bb", "sha256": "42e3635c53385bbadc2aa8df5e4ecc7babd1251f7992599ba0cf4a515befb033" }, "downloads": -1, "filename": "etcd3_py-0.1.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "68b3567d6044334c68c3ae20d8de16bb", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 61043, "upload_time": "2018-03-21T13:09:17", "url": "https://files.pythonhosted.org/packages/3d/47/b38a7ed4a737c5776780786b1d2ba8e2d432acb65a7489401c2121cfb841/etcd3_py-0.1.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9e8e60d13fdb7258b2cb2d3cbb64a75e", "sha256": "ba27dc36f7ffc614b289001468117ba59562924c0da4ab04973c94258d77618b" }, "downloads": -1, "filename": "etcd3-py-0.1.3.tar.gz", "has_sig": false, "md5_digest": "9e8e60d13fdb7258b2cb2d3cbb64a75e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 81695, "upload_time": "2018-03-21T13:09:12", "url": "https://files.pythonhosted.org/packages/63/70/1d61fb42da9915282f15629a2323be922416c7db8ed57f2213c08c7eb783/etcd3-py-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "43dd2b3361255e949a1668153edd76fa", "sha256": "6fbe444d00831d300533cc8265f5f456c4ee236b40d9bfdb26577ccfc1613e60" }, "downloads": -1, "filename": "etcd3_py-0.1.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "43dd2b3361255e949a1668153edd76fa", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "size": 61784, "upload_time": "2018-05-30T09:26:23", "url": "https://files.pythonhosted.org/packages/46/7a/92964588c724372b9a121bc08d861a3edbbf73d93b7a2c30c70ab3a945f5/etcd3_py-0.1.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "3776de26ad92694c941afd3b81865807", "sha256": "1c891f3bbafde8686be9699525a6d72e4c07a60f0b7896b5a3b8daacb3f68054" }, "downloads": -1, "filename": "etcd3-py-0.1.4.tar.gz", "has_sig": false, "md5_digest": "3776de26ad92694c941afd3b81865807", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "size": 84258, "upload_time": "2018-05-30T09:26:24", "url": "https://files.pythonhosted.org/packages/84/50/afb5adb7bf7b581a96ad85437ca9486e17f9067e05dc3e71836453d0f214/etcd3-py-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "2eb1c546f29954fbd41e8e4bbb4f8b9d", "sha256": "f653c6f4d16dc6a8b7a07adf66bbe22a9429f94c0af6d6e69985de845a3bf6ca" }, "downloads": -1, "filename": "etcd3_py-0.1.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "2eb1c546f29954fbd41e8e4bbb4f8b9d", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 86602, "upload_time": "2018-07-04T15:38:35", "url": "https://files.pythonhosted.org/packages/6f/20/f96e5c6df257b457726265e9f30673689414f5031716f950ff8ecb14f4be/etcd3_py-0.1.5-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a107db6be2bdfa7b9497c1712f973068", "sha256": "82cd609c4a7638dfc5366dd50ec145aa5bb92f57f16dbf8177d556386b407ffa" }, "downloads": -1, "filename": "etcd3-py-0.1.5.tar.gz", "has_sig": false, "md5_digest": "a107db6be2bdfa7b9497c1712f973068", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 90125, "upload_time": "2018-07-04T15:38:38", "url": "https://files.pythonhosted.org/packages/4e/8e/9b2efa2427cd7acf94536d51c4fdb8a7926307650602e0b238330d88b6c1/etcd3-py-0.1.5.tar.gz" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "df3e204e4876decccb3e5ac7c2378dc7", "sha256": "3882eee3e6b9b834abc26d962eff35bc58212c34ea11c0adf4aa22f663d4e8cf" }, "downloads": -1, "filename": "etcd3_py-0.1.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "df3e204e4876decccb3e5ac7c2378dc7", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "size": 102102, "upload_time": "2019-05-09T09:37:44", "url": "https://files.pythonhosted.org/packages/b6/b8/7777a6363e1ea7a6d8b4cb2a4ad7be62502881e504d9aba6fbbbb980adb8/etcd3_py-0.1.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e5cc368f9d652c8009f6662168ecff1c", "sha256": "087f9f2a84f60466a87dd996a8f7e60862f0200e486d5d20fc2d989f12b2be83" }, "downloads": -1, "filename": "etcd3-py-0.1.6.tar.gz", "has_sig": false, "md5_digest": "e5cc368f9d652c8009f6662168ecff1c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "size": 121835, "upload_time": "2019-05-09T09:37:49", "url": "https://files.pythonhosted.org/packages/ff/aa/6080c340e04ef452d8c0a6053303a1e165dc4666ec48e693b908231c8c71/etcd3-py-0.1.6.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "df3e204e4876decccb3e5ac7c2378dc7", "sha256": "3882eee3e6b9b834abc26d962eff35bc58212c34ea11c0adf4aa22f663d4e8cf" }, "downloads": -1, "filename": "etcd3_py-0.1.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "df3e204e4876decccb3e5ac7c2378dc7", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "size": 102102, "upload_time": "2019-05-09T09:37:44", "url": "https://files.pythonhosted.org/packages/b6/b8/7777a6363e1ea7a6d8b4cb2a4ad7be62502881e504d9aba6fbbbb980adb8/etcd3_py-0.1.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e5cc368f9d652c8009f6662168ecff1c", "sha256": "087f9f2a84f60466a87dd996a8f7e60862f0200e486d5d20fc2d989f12b2be83" }, "downloads": -1, "filename": "etcd3-py-0.1.6.tar.gz", "has_sig": false, "md5_digest": "e5cc368f9d652c8009f6662168ecff1c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", "size": 121835, "upload_time": "2019-05-09T09:37:49", "url": "https://files.pythonhosted.org/packages/ff/aa/6080c340e04ef452d8c0a6053303a1e165dc4666ec48e693b908231c8c71/etcd3-py-0.1.6.tar.gz" } ] }