{ "info": { "author": "Jeff Rhyason", "author_email": "jeff@indelible.systems", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Topic :: Database" ], "description": "This package is a client library for the managed Indelible Logs service.\n\nWhat is Indelible?\n------------------\n\nIndelible is a new managed, persistent storage service, that is:\n* secure by default, end-to-end encrypted, safe, and private - you never have to expose any plaintext data to us. Even for indexes. Did you read that right? Yes, you did: Indelible is a persistent store that provides value without needing access to any of your unencrypted data. This also means that, in the event of a data breach, there's nothing fun to see.\n* versioned - old versions remain readable until you're done with them\n* immutable - new data is put in new versions; old versions never modified == eliminates data races, simplifies processing. This is a big whole thing that shouldn't fit in a bullet point.\n* highly-available - layering atop today's great HA KV stores means 99.999% availability\n* strongly consistent - sanity is more important than throughput\n * reactive - no additional pubsub/event sourcing/CQRS required. Notifications come as pulls containing diffs showing what changed since the last version you saw.\n\nWhy do I want it to use Indelible now?\n--------------------------------------\n* secure by default -> encrypted by client, no plaintext to worry about breaching\n* easy to plumb - diff your data like you diff your software\n* you can build much more easily on a system that does not overwrite data, or make you wade through huge streams (when all you really want is diffs)\n* strongly-consistent with 99.999% availability\n* solves at least 1 of the major problems of computer science: versioning simplifies caching, and cache invalidation\n* simpler idempotency leads to simpler systems\n* immutability will change your life. it'll put back the years on your life that eventual consistency took off.\n* Indelible can eliminate polling -> lowers latency, improves user experience\n\nPython API Tour\n===============\n\nOverview\n--------\n\nThis is a quick tour of the Indelible Log API with Python.\n\nPrerequisites\n-------------\n\n ------------------ ------------------------------------------------------------------------------------\n Indelible apikey Please [sign up](mailto:showmethelogs@indelible.systems) for the Developer Preview\n `Python` Tested with 2.7 and 3.6\n ------------------ ------------------------------------------------------------------------------------\n\nGetting started\n---------------\n\nInstall the package:\n\n``` {#input}\npip install indelible_log\n```\n\nCreate `testprofile.json` for configuration:\n\n {\n \"endpoint_url\": \"https://log.ndlbl.net:8443\",\n \"customer_id\": \"customer-id\",\n \"apikey\": \"api-key\",\n \"master_key_base64\": \"v7RBLmFz5oB+IWOtGBEyfgejHvyYZwMTu+x0bbzZ+/4=\"\n }\n\nStart Python:\n\n``` {#input}\npython\n```\n\n Python 3.6.9 (default, Jul 25 2019, 01:16:08) \n [GCC 4.2.1 Compatible FreeBSD Clang 6.0.0 (tags/RELEASE_600/final 326565)] on freebsd11\n Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n\n >>> from indelible_log import Cmd, Log\n >>> import json\n >>>\n >>> profile = json.loads(open(\"testprofile.js\", \"r\").read())\n >>> log_name = json.dumps([\"walkthrough\", \"Hello, world!\", \"v1\"])\n >>>\n\nCreating a log {#create}\n--------------\n\nLet\\'s create a new log with the defaults.\n\n >>> log = Log(log_name, profile, encrypt=True, key_mode=\"string\", value_mode=\"json\")\n >>> log.create(log_group=\"mykey\")\n >>>\n\nAppending to a log {#upsert}\n------------------\n\n >>> log.update(update_source=\"python\", commands=[\n ... indelible_log.Cmd.Upsert(\"foo\", [1, 2, 3])\n ... ])\n >>>\n\nShowing the contents of a log {#diff}\n-----------------------------\n\nIterate over the log\\'s current entries:\n\n >>> for entry in log:\n ... print(entry)\n {'change': 'Add', 'entry': {'key': 'foo', 'value': [1, 2, 3]}, 'version': 1}\n >>>\n\nA previous version:\n\n >>> diff = log.version_diff(from_version=1)\n >>> for change in diff.changes():\n ... print(change)\n >>>\n\nReactive Logs --- Getting notified about new versions {#longpoll}\n-----------------------------------------------------\n\nIn another window, get this update ready:\n\n >>> log.update(update_source=\"python\", commands=[\n ... Cmd.ExpectVersion(1),\n ... Cmd.Remove(\"foo\", [1, 2, 3]),\n ... Cmd.Insert(\"bar\", [4, 5, 6])\n ... ])\n >>>\n\nBack in your original window, start monitoring, then finish that\n`update()`:\n\n >>> diff = log.version_diff(from_version=1, wait_seconds=60)\n >>> diff.to_version\n 2\n >>> for change in diff.changes():\n ... print(change)\n {'change': 'Remove', 'entry': {'key': 'foo', 'value': [1, 2, 3]}, 'version': 1}\n {'change': 'Add', 'entry': {'key': 'bar', 'value': [4, 5, 6]}, 'version': 2}\n >>>\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://indelible.systems", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "indelible-log", "package_url": "https://pypi.org/project/indelible-log/", "platform": "", "project_url": "https://pypi.org/project/indelible-log/", "project_urls": { "Homepage": "https://indelible.systems" }, "release_url": "https://pypi.org/project/indelible-log/0.4.6/", "requires_dist": [ "requests", "pynacl" ], "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "summary": "client for Indelible managed persistent store and synchronizer", "version": "0.4.6", "yanked": false, "yanked_reason": null }, "last_serial": 6038825, "releases": { "0.4": [ { "comment_text": "", "digests": { "md5": "ead71f7b89fbe07f9215c4129214f847", "sha256": "d57f4a81b3f4353fac2c42c02c15970976dea2536398bdc32cb15a486a54dcd5" }, "downloads": -1, "filename": "indelible_log-0.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ead71f7b89fbe07f9215c4129214f847", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 6832, "upload_time": "2019-09-03T22:14:57", "upload_time_iso_8601": "2019-09-03T22:14:57.278833Z", "url": "https://files.pythonhosted.org/packages/d1/c5/496fca9c82ab50cf3b7ee10e04a80b11b5b1fe5ced44dc3b95939e90fdcb/indelible_log-0.4-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "77d03e69cb8c665ab0611c887cc59096", "sha256": "7ee9f6daa23137dfff716f962b0b8dd446a91f3c3d80911bf6a8e2891fb32463" }, "downloads": -1, "filename": "indelible_log-0.4.tar.gz", "has_sig": false, "md5_digest": "77d03e69cb8c665ab0611c887cc59096", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 5901, "upload_time": "2019-09-03T22:14:59", "upload_time_iso_8601": "2019-09-03T22:14:59.554833Z", "url": "https://files.pythonhosted.org/packages/4e/d1/43c11f8903ad28b735ffc41f10ca0feb346b0647d272ac44385278c37e92/indelible_log-0.4.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "e2b446c3938b9cf0ebbbd4a8c8e4c199", "sha256": "4bb9ad9f8cff616c8e065deb739660a3ad2ef57cde09bc055fc537223ab0362e" }, "downloads": -1, "filename": "indelible_log-0.4.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "e2b446c3938b9cf0ebbbd4a8c8e4c199", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4", "size": 6942, "upload_time": "2019-09-04T20:59:21", "upload_time_iso_8601": "2019-09-04T20:59:21.227983Z", "url": "https://files.pythonhosted.org/packages/1c/cf/37eee7cfb9da6d7118329a3a71b6cf05420ec4eee1ec95108fc041bf5de7/indelible_log-0.4.1-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "69ca68d5dc71251575dc1d40bc64fba7", "sha256": "938afaa4f7913bdda362fde1c9cadce88fe8536332fa726ae713d3ff80368b19" }, "downloads": -1, "filename": "indelible_log-0.4.1.tar.gz", "has_sig": false, "md5_digest": "69ca68d5dc71251575dc1d40bc64fba7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4", "size": 6020, "upload_time": "2019-09-04T20:59:22", "upload_time_iso_8601": "2019-09-04T20:59:22.583728Z", "url": "https://files.pythonhosted.org/packages/e5/9c/86362a6d6b3225ef87b4a4099676214e6442eb9f395bdc76975ef8aa8141/indelible_log-0.4.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.2": [ { "comment_text": "", "digests": { "md5": "7b18491364c8a0c844b696cc44abef01", "sha256": "6d14763b9a4dceaebf42530e8e98458640baf5344a54b75c4ea9658234f389cd" }, "downloads": -1, "filename": "indelible_log-0.4.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "7b18491364c8a0c844b696cc44abef01", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4", "size": 6943, "upload_time": "2019-09-04T22:27:35", "upload_time_iso_8601": "2019-09-04T22:27:35.040898Z", "url": "https://files.pythonhosted.org/packages/db/aa/3e49ae850d91d547d9ecc23e16b679ffa8aaa531b78d60a3abeec11ec668/indelible_log-0.4.2-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "0ef9c75e935169d88db3cedf349761e3", "sha256": "883f2ea7e7b51a6f1e38458aa2edba6e3b190085a8265112bba98692b5e49b28" }, "downloads": -1, "filename": "indelible_log-0.4.2.tar.gz", "has_sig": false, "md5_digest": "0ef9c75e935169d88db3cedf349761e3", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4", "size": 6017, "upload_time": "2019-09-04T22:27:36", "upload_time_iso_8601": "2019-09-04T22:27:36.552604Z", "url": "https://files.pythonhosted.org/packages/ad/82/480642a2c7e583ffbf022f5f9ffc3af77ff4b27142d8ae434eff6154c546/indelible_log-0.4.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.3": [ { "comment_text": "", "digests": { "md5": "d728df840ae54bbcd4de14ea696e1a98", "sha256": "2a5bb28ce0a666e92f60c97bddec1cea8aabcafd228fdfb4dc16cabe090acd7d" }, "downloads": -1, "filename": "indelible_log-0.4.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "d728df840ae54bbcd4de14ea696e1a98", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 8971, "upload_time": "2019-10-24T04:45:49", "upload_time_iso_8601": "2019-10-24T04:45:49.542532Z", "url": "https://files.pythonhosted.org/packages/7b/3e/4bdbed466a3e3062e0aeebec2276507dec2f6f156e0bc1a44ccec5eaa13b/indelible_log-0.4.3-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "8ad106b3e242e8567101069d7bad5116", "sha256": "ae6389f2e15642b06c8e5ac295a87282b2d9510d3210de20c2c1d9dfb79d8aea" }, "downloads": -1, "filename": "indelible_log-0.4.3.tar.gz", "has_sig": false, "md5_digest": "8ad106b3e242e8567101069d7bad5116", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 7974, "upload_time": "2019-10-24T04:45:51", "upload_time_iso_8601": "2019-10-24T04:45:51.061289Z", "url": "https://files.pythonhosted.org/packages/f8/f4/19b783f1ec557dab9cac89ad4887c47bd1dd17501164155349497a678180/indelible_log-0.4.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.4": [ { "comment_text": "", "digests": { "md5": "86476b872259533d2ef4859e3df4ac2c", "sha256": "6c7921c45b92c40295a6cfe0bfbbe3f206874e6ece8acaf1b046abff4376bcbe" }, "downloads": -1, "filename": "indelible_log-0.4.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "86476b872259533d2ef4859e3df4ac2c", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 8974, "upload_time": "2019-10-25T16:55:28", "upload_time_iso_8601": "2019-10-25T16:55:28.963627Z", "url": "https://files.pythonhosted.org/packages/d6/6c/756d63c7d9aa01aedbfb638629d20c66c2ebbc8c64f5b57ac78df9ffb6dc/indelible_log-0.4.4-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "37c700554071fa8f958a8f90e76f696d", "sha256": "889ceae016fe321f0c8f99ced1413ac8fb12737301134718aaf89aaaf01d71d7" }, "downloads": -1, "filename": "indelible_log-0.4.4.tar.gz", "has_sig": false, "md5_digest": "37c700554071fa8f958a8f90e76f696d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 7974, "upload_time": "2019-10-25T16:55:30", "upload_time_iso_8601": "2019-10-25T16:55:30.220801Z", "url": "https://files.pythonhosted.org/packages/44/08/b4ad7c97df2fdedb29edcdc22c249837b8d5793656baa87c107ff26bf0a4/indelible_log-0.4.4.tar.gz", "yanked": false, "yanked_reason": null } ], "0.4.6": [ { "comment_text": "", "digests": { "md5": "61867b5e5ba78c3832703207e5c18dc0", "sha256": "dd04bdae4ff84743647c46b8c866549eafa30057d305313333f62932f87373dc" }, "downloads": -1, "filename": "indelible_log-0.4.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "61867b5e5ba78c3832703207e5c18dc0", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 8988, "upload_time": "2019-10-28T00:36:02", "upload_time_iso_8601": "2019-10-28T00:36:02.736046Z", "url": "https://files.pythonhosted.org/packages/9c/2e/fa6e5cc68607a76d00586eccaa577b2afa839b6d1920902af2543321b6af/indelible_log-0.4.6-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "06568d4cbb5d436bd7a4ff304c231a17", "sha256": "6d55c0222a4efa2eb68fd688db66db0c75eb3f3aa8853fc0b0a20ff64bf1858b" }, "downloads": -1, "filename": "indelible_log-0.4.6.tar.gz", "has_sig": false, "md5_digest": "06568d4cbb5d436bd7a4ff304c231a17", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 7990, "upload_time": "2019-10-28T00:36:04", "upload_time_iso_8601": "2019-10-28T00:36:04.358776Z", "url": "https://files.pythonhosted.org/packages/3b/d1/0f493917e84675e42c7c8afb8ed4a6b50ec1c76e3fdf0af968e348882bea/indelible_log-0.4.6.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "61867b5e5ba78c3832703207e5c18dc0", "sha256": "dd04bdae4ff84743647c46b8c866549eafa30057d305313333f62932f87373dc" }, "downloads": -1, "filename": "indelible_log-0.4.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "61867b5e5ba78c3832703207e5c18dc0", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 8988, "upload_time": "2019-10-28T00:36:02", "upload_time_iso_8601": "2019-10-28T00:36:02.736046Z", "url": "https://files.pythonhosted.org/packages/9c/2e/fa6e5cc68607a76d00586eccaa577b2afa839b6d1920902af2543321b6af/indelible_log-0.4.6-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "06568d4cbb5d436bd7a4ff304c231a17", "sha256": "6d55c0222a4efa2eb68fd688db66db0c75eb3f3aa8853fc0b0a20ff64bf1858b" }, "downloads": -1, "filename": "indelible_log-0.4.6.tar.gz", "has_sig": false, "md5_digest": "06568d4cbb5d436bd7a4ff304c231a17", "packagetype": "sdist", "python_version": "source", "requires_python": ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4", "size": 7990, "upload_time": "2019-10-28T00:36:04", "upload_time_iso_8601": "2019-10-28T00:36:04.358776Z", "url": "https://files.pythonhosted.org/packages/3b/d1/0f493917e84675e42c7c8afb8ed4a6b50ec1c76e3fdf0af968e348882bea/indelible_log-0.4.6.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }