{ "info": { "author": "Chris Rossi, Archimedean Company", "author_email": "pylons-devel@googlegroups.com", "bugtrack_url": null, "classifiers": [ "Framework :: Pylons", "Intended Audience :: Developers", "License :: Repoze Public License", "Programming Language :: Python" ], "description": "===========\nLimone ZODB\n===========\n\n`Limone ZODB` is an extension of `Limone`_ which generates content types that\nare persistable via ZODB. Usage is the same as `Limone` except that the\ndecorators and `make_content_type` function are imported from the `limone_zodb`\npackage instead of the `limone` package::\n\n import colander\n import limone_zodb\n import persistent\n\n class Friend(colander.TupleSchema):\n rank = colander.SchemaNode(colander.Int(),\n validator=colander.Range(0, 9999))\n name = colander.SchemaNode(colander.String())\n\n class Phone(colander.MappingSchema):\n location = colander.SchemaNode(colander.String(),\n validator=colander.OneOf(['home', 'work']))\n number = colander.SchemaNode(colander.String())\n\n class Friends(colander.SequenceSchema):\n friend = Friend()\n\n class Phones(colander.SequenceSchema):\n phone = Phone()\n\n @limone_zodb.content_schema\n class Person(colander.MappingSchema):\n name = colander.SchemaNode(colander.String())\n age = colander.SchemaNode(colander.Int(),\n validator=colander.Range(0, 200))\n friends = Friends()\n phones = Phones()\n\n jake = Person(name='Jake', age=21)\n assert isinstance(jake, persistent.Persistent)\n\n.. _`Limone`: http://pypi.python.org/pypi/limone\n\n\nRationale\n---------\n\nNaively, one might presume that using `persistent.Persistent` as a base class\nfor the content type would be sufficient. What can happen, though, is you can\nfind that certain changes to a content object fail to persist. For example,\nwithout using `limone_zodb` we might have just done something more like::\n\n import limone\n import persistent\n\n @limone.content_type(Person)\n class PersistentPerson(persistent.Persistent):\n pass\n\n jake = PersistentPerson(name='Jake', age=21)\n\nThan, later, in another transaction::\n\n jake.age = 22 # This will persist just fine\n\nWhile this will work fine if you only change direct attributes of the content\nobject, if you change deep attributes, like `friends` or `phones` in the\nexample above, those won't necessarily persist automatically. This is not due\nto anything particular to `Limone`. This behavior can be observed with any\nobject containing nested data structures. Let's take a look at this example\nwhich doesn't use `Limone`::\n\n import persistent\n\n class C(persistent.Persistent):\n def __init__(self):\n self.foo = 'Hello'\n self.bars = ['tiki', 'biker']\n\n o = C()\n\nAssuming we have stored the instance `o` in the ZODB and retrieved it another\ntransaction, we could try to modify it. If we change the value of `o.foo` and\ncommit our transactoin, a new copy of `o` will be written to the ZODB and our\nchange will have been saved::\n\n import transaction\n\n o.foo = 'Howdy' # This change will persist\n transaction.commit()\n\nIf, on the other hand, we add a new value to `o.bars`, then this change alone\nwill not be sufficient to cause a new value of `o` to be written to the ZODB\nand the change will not be persisted when the transaction is committed::\n\n o.bars.append('lesbian') # Change does not persist\n transaction.commit()\n\nThe reason for this lies in how `persistent.Persistent` object work.\n`persistent.Persistent` overrides the `__setattr__` method of `object` so that\nwhen an attribute is set on a persistent object, that object is advertised to\nthe transaction as having been changed, and a new copy is written when the\ntransaction is committed. `bars`, though, is just a regular old Python list\nthat doesn't know anything about persistence. Mutating that list does not\nadvertise the change to the transaction, so the ZODB doesn't know that there is\nanything new to be written to the database.\n\nFor this exact same reason, changes to a `Limone` content object that only\ninvolve a nested data structure, will fail to advertise to the transaction\nthat a change has occurred. If these are the only changes to an object, that\nobject's new state will not be written to the database when the transaction is\ncommitted.\n\n`Limone ZODB` gets around this problem by passing a metaclass into the normal\n`Limone` content type generation process which makes sure that making any\nchange to a `Limone ZODB` content object, at any level of the content\nstructure, will cause the change to be persisted automatically, without any\nhoops to be jumped through by the developer.\n\n\nChangelog for Limone ZODB\n-------------------------\n\n0.1a2 (2011-08-09)\n++++++++++++++++++\n\n- Changed the method resolution order of _MappingNode to make sure that\n limone's __setattr__ is called on attribute assignment.\n\n0.1a1 (2011-07-16)\n++++++++++++++++++\n\n- Initial alpha release.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://pylonsproject.org", "keywords": "", "license": "BSD-derived (http://www.repoze.org/LICENSE.txt)", "maintainer": null, "maintainer_email": null, "name": "limone_zodb", "package_url": "https://pypi.org/project/limone_zodb/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/limone_zodb/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://pylonsproject.org" }, "release_url": "https://pypi.org/project/limone_zodb/0.1a2/", "requires_dist": null, "requires_python": null, "summary": "ZODB persistence for Limone content types.", "version": "0.1a2" }, "last_serial": 794203, "releases": { "0.1a1": [ { "comment_text": "", "digests": { "md5": "92942fb0116b7c0c653d48d078b7a269", "sha256": "485750f354312418381fe9760ebe623ad64db0c58337c400d11dbb0b2f5d2afd" }, "downloads": -1, "filename": "limone_zodb-0.1a1.tar.gz", "has_sig": false, "md5_digest": "92942fb0116b7c0c653d48d078b7a269", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4423, "upload_time": "2011-07-16T20:38:22", "url": "https://files.pythonhosted.org/packages/41/27/37524c36248399881f8c3cd4ec7f21739fefb20e4c1d0b112b981a443f86/limone_zodb-0.1a1.tar.gz" } ], "0.1a2": [ { "comment_text": "", "digests": { "md5": "346a124450b4c7f09f9ad693bce65b85", "sha256": "a83719c525c2303ef2da5c303f94a2dc509d0132aad22a340c12ba777fb6f53f" }, "downloads": -1, "filename": "limone_zodb-0.1a2.tar.gz", "has_sig": false, "md5_digest": "346a124450b4c7f09f9ad693bce65b85", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4479, "upload_time": "2011-08-09T18:21:23", "url": "https://files.pythonhosted.org/packages/b9/25/850d2faf16c028eb17bfcd54c768f5d6ea249d61a480f9510fa3a79fa68b/limone_zodb-0.1a2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "346a124450b4c7f09f9ad693bce65b85", "sha256": "a83719c525c2303ef2da5c303f94a2dc509d0132aad22a340c12ba777fb6f53f" }, "downloads": -1, "filename": "limone_zodb-0.1a2.tar.gz", "has_sig": false, "md5_digest": "346a124450b4c7f09f9ad693bce65b85", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4479, "upload_time": "2011-08-09T18:21:23", "url": "https://files.pythonhosted.org/packages/b9/25/850d2faf16c028eb17bfcd54c768f5d6ea249d61a480f9510fa3a79fa68b/limone_zodb-0.1a2.tar.gz" } ] }