{ "info": { "author": "Jim Fulton", "author_email": "jim@zope.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6" ], "description": "Generational Sets\n*****************\n\nGenerational sets (GSets) are designed to facilitate data synchronization\nbetween a server and clients.\n\nGoals:\n\n- Make synchronization simple by sending all updates for a tree of sets\n at once.\n\n- Allow clients to be updated very quickly.\n\n- Reduce data-transfer volume by sending only changes.\n\n- Avoid conflict resolution.\n\nAssumptions:\n\n- Disconnected data updates aren't needed.\n\n- Clients mirror server data.\n\n This implies that the server data, or more specifically, the user's\n view of the server data, aren't too large to store on the client.\n\nGSets track state by generation. A client presents a generation and\nis sent updates made since the presented generation. GSets can be\ngrouped into trees with a shared generation. A client can present a\nsingle generation and be sent updates for all of the sets making up a\ndatabase.\n\nThis implementation of generational sets uses `ZODB\n`_ to store data on the server.\n\nHigh-level usage pattern\n========================\n\n- Define a tree of sets representing the data in an application.\n This may be user specific.\n\n- Clients make updates via REST calls to a server. They don't make\n local changes except in response to server updates.\n\n- Client requests include their data generation.\n\n- Most (JSON) responses to server calls have optional updates property\n that contains generational updates since the generation provided by\n the client. When the client gets updates, which include the new\n generation, it applies the updates to it's internal data store.\n\n- For native apps, the server sends push notifications when there are\n updates for a user and, in response, the client polls for the\n updates. This allows updates to be extremely timely without\n constant polling.\n\nNote that this package only provides the data structure\nimplementation. Wrapping the data structure in a REST interface or\nsending notifications is up to applications.\n\nAPI\n===\n\nEvery object in a GSet must have an id. By default, this is provided\nby an ``id`` attribute, but you can configure a GSet to use another\nattribute or some other mechanism to get an id for an object.\n\nWhen an object is added to a GSet, call the\n``add`` method on the Gset with the object::\n\n >>> from zc.generationalset import GSet\n >>> things = GSet()\n >>> athing = Thing(42)\n >>> things.add(athing)\n\nWhen an object is changed, call the ``changed`` method on the Gset\nwith the object. If object is not present in the Gset, update will\nraise a KeyError::\n\n >>> things.changed(athing)\n >>> things.changed(Thing(43))\n Traceback (most recent call last):\n ...\n KeyError: 43\n\n >>> things.generational_updates(0)\n {'generation': 3, 'adds': [Thing(42)]}\n\nTo remove an object, call\nthe ``remove`` method with the object::\n\n >>> things.remove(athing)\n\nTo get updates to a set since a given generation, call\n``generational_updates``, passing a generation::\n\n >>> things.generational_updates(0)\n {'generation': 4, 'removals': [42]}\n\n >>> things.add(Thing(1))\n >>> things.generational_updates(0)\n {'generation': 5, 'removals': [42], 'adds': [Thing(1)]}\n >>> things.generational_updates(3)\n {'generation': 5, 'adds': [Thing(1)]}\n\nNote that generations start at 1.\n\nThe result of calling ``generational_updates`` is a dictionary with\nkeys:\n\ngeneration\n The current generation of the set\n\nadds\n Objects added since the given generation.\n\nremovals\n Ids of objects removed since the given generation.\n\ncontents\n All of the object in the set.\n\n ``contents`` are returned when there have been many removals since\n the given generation. A generational set only keeps track of a\n limited number (99 by default, but configurable) of removals. If a\n client is too out of date for the set to have relevant removals, it\n returns the entire contents, instead of returning adds and removals.\n\nGSets support iteration, and querying length and containment. They\ndon't currently support set operations, like intersection and\nunion. You can also retrieve an item from a GSet using its id::\n\n >>> len(things)\n 1\n >>> list(things)\n [Thing(1)]\n >>> Thing(1) in things\n True\n >>> things[1]\n Thing(1)\n\nNested sets\n-----------\n\nTo define nested sets:\n\n- Define a parent set::\n\n >>> parent = GSet(superset=True)\n\n Note the use of the ``superset`` parameter.\n\n- Define child sets, and add them to the parent:\n\n >>> messages = GSet(\"messages\", parent)\n >>> parent.add(messages)\n\n When defining child sets, specify an id and the parent.\n\nWe haven't tested more than one level of nesting.\n\nWhen asking for generational updates on parent sets, the adds and\ncontents contain the generational updates for subsets, with ids, but\nwithout subset generations:\n\n >>> messages.add(Thing(42))\n >>> parent.generational_updates(0)\n {'generation': 3, 'adds': [{'id': 'messages', 'adds': [Thing(42)]}]}\n\n\nChanges\n*******\n\n0.4.0 (2017-06-20)\n==================\n\n- Python 3 support\n\n- When asking for updates from generation 0, only adds are sent. Never\n removals, making this common case more efficient.\n\n0.3.0 (2014-08-28)\n==================\n\n- Added a ``changed`` method to make intent clear when simply recording changes.\n\n- Fixed: exceptions were raised when objects added to generational\n sets quacked a little like generational sets.\n\n0.2.0 (2014-08-10)\n==================\n\n- Improved subset APIs:\n\n - No longer need to specify superset flag.\n\n - Can have set and non-set children.\n\n - A subset can be created without a parent and the parent will be\n set when it's added to a containing set.\n\n0.1.2 (2014-06-09)\n==================\n\nFixed: Internal data structures were misshandled when there were more\n than the maximum number of removals.\n\n(Release 0.1.1 was made in error.)\n\n0.1.0 (2014-06-08)\n==================\n\nInitial release", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/zc/generationalset", "keywords": "real-time UI,ZODB", "license": "ZPL 2.1", "maintainer": "", "maintainer_email": "", "name": "zc.generationalset", "package_url": "https://pypi.org/project/zc.generationalset/", "platform": "", "project_url": "https://pypi.org/project/zc.generationalset/", "project_urls": { "Homepage": "https://bitbucket.org/zc/generationalset" }, "release_url": "https://pypi.org/project/zc.generationalset/0.4.0/", "requires_dist": null, "requires_python": "", "summary": "*****************", "version": "0.4.0" }, "last_serial": 2963135, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "2a1a18a2bbbba1866dbb39c565135395", "sha256": "add85bec30d99c6480be0d8489ae7d281a46142a55a3ea59d73fb5ea3eff0f17" }, "downloads": -1, "filename": "zc.generationalset-0.1.0.tar.gz", "has_sig": false, "md5_digest": "2a1a18a2bbbba1866dbb39c565135395", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9170, "upload_time": "2014-06-08T19:20:14", "url": "https://files.pythonhosted.org/packages/3a/20/3b5a5be2c66f08c1d4817d1748b01cb2b2e8cb94ee909c2f97395f27ef60/zc.generationalset-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "2fee789cdf347ccf42f1358ecf7994c6", "sha256": "87e5a7c73adc3df285cd7c77f958d58995593820457938cf497f5a714a2de2c9" }, "downloads": -1, "filename": "zc.generationalset-0.1.1.tar.gz", "has_sig": false, "md5_digest": "2fee789cdf347ccf42f1358ecf7994c6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9305, "upload_time": "2014-06-09T13:44:09", "url": "https://files.pythonhosted.org/packages/ca/68/1670acef00afcef51abc364282d78d378ef3c447c96e43ac16a2b7975bba/zc.generationalset-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "dc65e959488eee3b18acea0092464ecd", "sha256": "2993d21b1075d7c33ebf8b27e4c9d1d5e5256cfcea59a5a38b64bd121e1151d5" }, "downloads": -1, "filename": "zc.generationalset-0.1.2.tar.gz", "has_sig": false, "md5_digest": "dc65e959488eee3b18acea0092464ecd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9389, "upload_time": "2014-06-09T13:52:50", "url": "https://files.pythonhosted.org/packages/4c/24/5fdc9692e228a13ca8a86d6312682e3a057ca642bc7fc74c2da06bd48e4f/zc.generationalset-0.1.2.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "ca08bcea2a7aa339062cac268f398d35", "sha256": "2245d373df506a32da608fcd1a614142435b19f7efb03eebcd4779c4e01ea821" }, "downloads": -1, "filename": "zc.generationalset-0.2.0.tar.gz", "has_sig": false, "md5_digest": "ca08bcea2a7aa339062cac268f398d35", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9989, "upload_time": "2014-08-10T21:26:35", "url": "https://files.pythonhosted.org/packages/0c/d1/26c7f801181701a0901026d8390fb13faf7b4fc9f369a63703c91c871eaa/zc.generationalset-0.2.0.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "9a8d027bb5bd0716c1730938b5ca4b0c", "sha256": "cd2ed755c78238f8d0b486fbe2d83f17b0f99d90ba5b835b5aa9b6be54d9282e" }, "downloads": -1, "filename": "zc.generationalset-0.3.0.tar.gz", "has_sig": false, "md5_digest": "9a8d027bb5bd0716c1730938b5ca4b0c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10669, "upload_time": "2014-08-28T17:20:11", "url": "https://files.pythonhosted.org/packages/de/6f/ca49b07279cf826a7b0bd197d460f1555bd9e32e9939e4fc2c31c012d68f/zc.generationalset-0.3.0.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "d7d62b69eff62c9231f923cc9db5d1ed", "sha256": "829c71ad4596dda3358ff8c7bbe15bb1494320a7df83326ab816406ed4ffebf2" }, "downloads": -1, "filename": "zc.generationalset-0.4.0.tar.gz", "has_sig": false, "md5_digest": "d7d62b69eff62c9231f923cc9db5d1ed", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13118, "upload_time": "2017-06-20T20:32:50", "url": "https://files.pythonhosted.org/packages/12/db/73b5434843ba1c39c1f2b40d8ae0a9558bc2f102e4e62722d8fe393c2aa6/zc.generationalset-0.4.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "d7d62b69eff62c9231f923cc9db5d1ed", "sha256": "829c71ad4596dda3358ff8c7bbe15bb1494320a7df83326ab816406ed4ffebf2" }, "downloads": -1, "filename": "zc.generationalset-0.4.0.tar.gz", "has_sig": false, "md5_digest": "d7d62b69eff62c9231f923cc9db5d1ed", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13118, "upload_time": "2017-06-20T20:32:50", "url": "https://files.pythonhosted.org/packages/12/db/73b5434843ba1c39c1f2b40d8ae0a9558bc2f102e4e62722d8fe393c2aa6/zc.generationalset-0.4.0.tar.gz" } ] }