{ "info": { "author": "Rufus Pollock (Open Knowledge Foundation)", "author_email": "info@okfn.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "About\n=====\n\nVersioned Domain Model (vdm) is a package which allows you to 'version' your\ndomain model in the same way that source code version control systems such as\nsubversion allow you version your code. In particular, versioned domain model\nversions a complete model and not just individual domain objects (for more on\nthis distinction see below).\n\nAt present the package is provided as an extension to SQLAlchemy (tested\nagainst v0.4-v0.8).\n\nThe library is pretty stable and has been used by the authors in production\nsystems since v0.2 (May 2008).\n\n\nCopyright and License\n=====================\n\nCopyright (c) 2007-2010 The Open Knowledge Foundation\n\nLicensed under the MIT license: http://www.opensource.org/licenses/mit-license.php\n\n\nAuthors\n=======\n\nRufus Pollock (Open Knowledge Foundation) - http://rufuspollock.org/\nhttp://www.okfn.org/\n\n\nA Full Versioned Domain Model\n=============================\n\nTo permit 'atomic' changes involving multiple objects at once as well as to\nfacilitate domain object traversal it is necessary to introduce an explicit\n'Revision' object to represent a single changeset to the domain model.\n\nOne also needs to introduce the concept of 'State'. This allows us to make\n(some) domain objects stateful, in particular those which are to be versioned\n(State is necessary to support delete/undelete functionality as well as to\nimplement versioned many-to-many relationships).\n\nFor each original domain object that comes versioned we end up with 2 domain\nobjects:\n\n * The 'continuity': the original domain object.\n * The 'version/revision': the versions/revisions of that domain object.\n\nOften a user will never need to be concerned (explicitly) with the\nversion/revision object as they will just interact with the original domain\nobject, which will, where necessary, 'proxy' requests down to the\n'version/revision'.\n\nTo give a flavour of all of this here is a pseudo-code example::\n\n # We need a session of some kind to track which objects have been changed\n # In SQLAlchemy can use its Session object\n session = get_session_in_some_way()\n\n # Our Revision object\n rev1 = Revision(author='me')\n # Associate revision with session\n # Any given session will have a single associated revision\n session.revision = rev1\n\n # Book and Author are domain objects which has been made versioned using this library\n # Note the typo!\n b1 = Book(name='warandpeace', title='War and Peacee')\n b2 = Book(name='annakarenina', title='Anna')\n # Note the duplicate!\n b3 = Book(name='warandpeace')\n a1 = Author(name='tolstoy')\n\n # this is just shorthand for ending this revision and saving all changes\n # this may vary depending on the implementation\n rev1.commit()\n timestamp1 = rev1.timestamp\n\n # some time later\n rev2 = Revision(author='me')\n session.revision = rev2\n\n b1 = Book.get(name='warandpeace')\n # correct typo\n b1.title = 'War and Peace'\n # add the author\n a1 = Author.get(name='tolstoy')\n b1.authors.append(a1)\n # duplicate item so delete\n b3.delete()\n rev2.commit()\n\n # some time even later\n rev1 = Revision.get(timestamp=timestamp1)\n b1 = Book.get(name='warandpeace')\n b1 = b1.get_as_of(rev1)\n assert b1.title == 'War and Peacee'\n assert b1.authors == []\n # etc\n\n\nCode in Action\n--------------\n\nTo see some real code in action take a look at, for SQLAlchemy::\n\n vdm/sqlalchemy/demo.py\n vdm/sqlalchemy/demo_test.py\n\n\nGeneral Conceptual Documentation\n================================\n\nA great starting point is Fowler's *Patterns for things that change with time*:\n\n http://martinfowler.com/eaaDev/timeNarrative.html\n\nIn particular Temporal Object:\n\n http://martinfowler.com/eaaDev/TemporalObject.html\n\nTwo possible approaches:\n\n 1. (simpler) Versioned domain objects are versioned independently (like a\n wiki). This is less of a versioned 'domain model' and more of plain\n versioned domain objects.\n 2. (more complex) Have explicit 'Revision' object and multiple objects can be\n changed simultaneously in each revision (atomicity). This is a proper\n versioned *domain model*.\n\nRemark: using the first approach it is:\n\n * Impossible to support versioning of many-to-many links between versioned\n domain objects.\n * Impossible to change multiple objects 'at once' -- that is as part of\n one atomic change\n * Difficult to support domain model traversal, that is the ability to\n navigate around the domain model at a particular 'revision'/point-in-time.\n * More discussions of limitations can be found in this thread [1].\n\n[1]:\n\nThe versioned domain model (vdm) package focuses on supporting the second case\n(this obviously includes the first one as a subcase) -- hence the name.\n\n\nUse Cases\n---------\n\nSA = Implemented in SQLAlchemy\n\n1. (SA) CRUD for a simple versioned object (no references other than HasA)\n\n2. (SA) Versioning of Many-2-Many and many-2-one relationships where one or\nboth of the related objects are versioned.\n\n3. (SA) Undelete for the above.\n\n4. (SA) Purge for the above.\n\n5. (SA) Support for changing multiple objects in a single commit.\n\n6. (SA) Consistent object traversal both at HEAD and \"in the past\"\n\n7. (SA) Diffing support on versioning objects and listing of changes for a\ngiven Revision.\n\n8. Concurrency checking:\n\n 1. Simultaneous edits of different parts of the domain model\n 2. Simultaneous edits of same parts of domain model (conflict resolution or\n locking)\n\n 1. Alice and Bob both get object X\n 2. Bob updates object X and commits (A's X is now out of date)\n 3. Alice updates object X and commits\n 4. Conflict!!\n\n This can be resolved in the following ways:\n\n 1. Locking\n 2. Merging\n\n Rather than summarize all situations just see Fowler on concurrency\n\n9. Support for pending updates (so updates must be approved before being visible)\n\n 1. A non-approved user makes a change\n 2. This change is marked as pending\n 3. This change is notified to a moderator\n 4. A moderator either allows or disallows the change\n", "description_content_type": "", "docs_url": "https://pythonhosted.org/vdm/", "download_url": "https://github.com/okfn/vdm", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://www.okfn.org/vdm/", "keywords": "versioning sqlobject sqlalchemy orm", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "vdm", "package_url": "https://pypi.org/project/vdm/", "platform": "", "project_url": "https://pypi.org/project/vdm/", "project_urls": { "Download": "https://github.com/okfn/vdm", "Homepage": "http://www.okfn.org/vdm/" }, "release_url": "https://pypi.org/project/vdm/0.15/", "requires_dist": null, "requires_python": "", "summary": "A versioned domain model framework.", "version": "0.15" }, "last_serial": 5267262, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "2e42a388c0616a9a8bba770363b72842", "sha256": "e510be70f6d40a3a5d9e51a216a77fe8737159595f8931b37cc38259fff6a803" }, "downloads": -1, "filename": "vdm-0.1-py2.4.egg", "has_sig": false, "md5_digest": "2e42a388c0616a9a8bba770363b72842", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 23775, "upload_time": "2007-03-27T09:23:51", "url": "https://files.pythonhosted.org/packages/cc/59/0c8f372c91e952b8d8c562e2e161f00d383d4b1aed1a2221d7a60eccab9d/vdm-0.1-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "42bc430fdfe379ae0bdb1b9a1acf0bc1", "sha256": "b89db4cef71d67a84afbec9065630bc86bd7af05989f370fbe4e2a96d9de29ff" }, "downloads": -1, "filename": "vdm-0.1.tar.gz", "has_sig": false, "md5_digest": "42bc430fdfe379ae0bdb1b9a1acf0bc1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9111, "upload_time": "2007-03-27T09:23:49", "url": "https://files.pythonhosted.org/packages/cb/57/2a470e611b2fa6368bdb00be2a71aeeab89fe5b7f89d5dd627aa6740b998/vdm-0.1.tar.gz" } ], "0.10": [ { "comment_text": "", "digests": { "md5": "1066a11825bb9be858c6c67e2ba9a91f", "sha256": "8834a0bf0d4c4e89c3246be3b5c6c8051a2ee3a9a9f7eac9ff5a8d289e911141" }, "downloads": -1, "filename": "vdm-0.10.tar.gz", "has_sig": false, "md5_digest": "1066a11825bb9be858c6c67e2ba9a91f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33994, "upload_time": "2011-10-26T19:32:07", "url": "https://files.pythonhosted.org/packages/84/c0/de15579dc8a14654f2a4dc78c054856de7f8ce01c326a24a232faafc8b58/vdm-0.10.tar.gz" } ], "0.11": [ { "comment_text": "", "digests": { "md5": "0a0a0b0bbd6b1e6c3281ea8cd52b3171", "sha256": "cfb24ba3f37a4ea6798a7ef6d202b73bf7672366cb3de8112eebda4228be6f08" }, "downloads": -1, "filename": "vdm-0.11.tar.gz", "has_sig": false, "md5_digest": "0a0a0b0bbd6b1e6c3281ea8cd52b3171", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33368, "upload_time": "2013-04-23T11:34:26", "url": "https://files.pythonhosted.org/packages/1b/94/e3cac9e4a8e4a72a868e6ff8c1db737c1f8ffa6a76e26b2450007eb6c4c5/vdm-0.11.tar.gz" } ], "0.12": [ { "comment_text": "", "digests": { "md5": "c8502c3d063392d70761522833834e21", "sha256": "9ad849366452884f83329ed3667712620cf99d0e0dac1feed8985835f8803d58" }, "downloads": -1, "filename": "vdm-0.12.tar.gz", "has_sig": false, "md5_digest": "c8502c3d063392d70761522833834e21", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33379, "upload_time": "2014-01-20T16:59:33", "url": "https://files.pythonhosted.org/packages/fb/0f/d46b4823d696fb171f7893659e5106067fa693df46994d2d388531842fda/vdm-0.12.tar.gz" } ], "0.13": [ { "comment_text": "", "digests": { "md5": "1fc30de1170c0f7899dc4a7563e5ee18", "sha256": "e624917edaa4de4f995e8390180f0c06168e60cb45decfd11551bae66765afa5" }, "downloads": -1, "filename": "vdm-0.13.tar.gz", "has_sig": false, "md5_digest": "1fc30de1170c0f7899dc4a7563e5ee18", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31477, "upload_time": "2014-08-12T13:37:40", "url": "https://files.pythonhosted.org/packages/c7/24/6dd5b37ec0c0ba760c09f9828dc2c55876f538b40cf0a43b34699ca4caa9/vdm-0.13.tar.gz" } ], "0.14": [ { "comment_text": "", "digests": { "md5": "0047ddc166261f670a3c13e1578f9f28", "sha256": "81bb747b422e68a59a8cbd42ac7fdf5d46cd4c96cca5b9b5dd48a18780b2afda" }, "downloads": -1, "filename": "vdm-0.14.tar.gz", "has_sig": false, "md5_digest": "0047ddc166261f670a3c13e1578f9f28", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30859, "upload_time": "2017-06-27T14:52:40", "url": "https://files.pythonhosted.org/packages/e1/57/1051dfdf32c97feecdc87f0f28b97245ba19b4d6e5930ec6d9bc1623c1f7/vdm-0.14.tar.gz" } ], "0.15": [ { "comment_text": "", "digests": { "md5": "e2f6384d8c03e56c83cdbde28d5e67d6", "sha256": "65b75bb342280114e3c9794fbe5c54b77a9d997fbe07dae50aa303381ccfa26e" }, "downloads": -1, "filename": "vdm-0.15.tar.gz", "has_sig": false, "md5_digest": "e2f6384d8c03e56c83cdbde28d5e67d6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33067, "upload_time": "2019-05-14T12:56:00", "url": "https://files.pythonhosted.org/packages/83/6b/69d14e438f47c88daf0f986b00ddb69c1b3d474ff7199ac673f833a341f0/vdm-0.15.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "c9f59e00dc26c18fdd217ea3e74817ff", "sha256": "9d231f8e50ff2ebbdfb26a2dbd1b4c23f92d12eae3695f929f4f3b8fead5bde7" }, "downloads": -1, "filename": "vdm-0.2-py2.5.egg", "has_sig": false, "md5_digest": "c9f59e00dc26c18fdd217ea3e74817ff", "packagetype": "bdist_egg", "python_version": "2.5", "requires_python": null, "size": 114829, "upload_time": "2008-05-29T16:46:56", "url": "https://files.pythonhosted.org/packages/37/da/367c973fd1d2b2d5acf22cfb679adf7b2e31f342e9b9b47f234a8d7615f5/vdm-0.2-py2.5.egg" }, { "comment_text": "", "digests": { "md5": "147829ba706733973fd607c579247617", "sha256": "39255c55849f806ba06cccf2d937b16bd7f3b01fd96ca5fb56a43a2cb55d64cf" }, "downloads": -1, "filename": "vdm-0.2.tar.gz", "has_sig": false, "md5_digest": "147829ba706733973fd607c579247617", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 36971, "upload_time": "2008-05-29T16:46:50", "url": "https://files.pythonhosted.org/packages/9a/e9/bc68be8022480319a313cecee9046e6caf6536ce1b4a7de8b9462a148c8e/vdm-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "25b49981b637efe4fba6e66fde28d735", "sha256": "7d0d5115c3cc95c353e984d24a69ea3775516e6e40614c017d1a73db3cbbcd31" }, "downloads": -1, "filename": "vdm-0.3-py2.5.egg", "has_sig": false, "md5_digest": "25b49981b637efe4fba6e66fde28d735", "packagetype": "bdist_egg", "python_version": "2.5", "requires_python": null, "size": 87305, "upload_time": "2008-10-31T08:44:08", "url": "https://files.pythonhosted.org/packages/e0/eb/8b785a99b2e4047a3fd70b2e8e74bb51ad59d8655da5d4c69fd77881c04a/vdm-0.3-py2.5.egg" }, { "comment_text": "", "digests": { "md5": "4b3c263febc2770d32dc1cf4d95cb650", "sha256": "7e60fb196b074b3b43149cda2d172dafc36b682c85018bd41fa21449cfbc480b" }, "downloads": -1, "filename": "vdm-0.3.tar.gz", "has_sig": false, "md5_digest": "4b3c263febc2770d32dc1cf4d95cb650", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29890, "upload_time": "2008-10-31T08:44:04", "url": "https://files.pythonhosted.org/packages/5f/0f/adc06e82e882b5bed5d3870a47fd1aaafa9d9d05c4f0e64ace394f863fec/vdm-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "cedf80750b85cfef3c8fc296f2a63b4f", "sha256": "040cbdfd7564b9d52a97c1ab42667e96e890f214722f15c8af644ff22c378ac4" }, "downloads": -1, "filename": "vdm-0.4.tar.gz", "has_sig": false, "md5_digest": "cedf80750b85cfef3c8fc296f2a63b4f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32647, "upload_time": "2009-05-07T18:33:42", "url": "https://files.pythonhosted.org/packages/59/ca/5ee3db52a7f6aa10a9eccd3467e61d3f1fced9dcd505d18d0cc02cad3e2a/vdm-0.4.tar.gz" } ], "0.5": [ { "comment_text": "", "digests": { "md5": "a90e686a110aca48f43d42df345278e3", "sha256": "ef503f9993129aac5ee8315d1e13a93baf4689071d8922a7e3d430cab407d1d2" }, "downloads": -1, "filename": "vdm-0.5.tar.gz", "has_sig": false, "md5_digest": "a90e686a110aca48f43d42df345278e3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 34758, "upload_time": "2009-10-25T19:21:54", "url": "https://files.pythonhosted.org/packages/fe/4b/7bcd0e34bb72804445dccb390703eb1cca639c4915f86598feef0f6dfdd3/vdm-0.5.tar.gz" } ], "0.6": [ { "comment_text": "", "digests": { "md5": "6995fe98cdaf2c75a3b3d92536b67407", "sha256": "d201caae3191ca7dd699d2067804ad1fc512a1f4dd293b12d8f62eeb4c874ac9" }, "downloads": -1, "filename": "vdm-0.6.tar.gz", "has_sig": false, "md5_digest": "6995fe98cdaf2c75a3b3d92536b67407", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 35993, "upload_time": "2010-02-11T13:55:06", "url": "https://files.pythonhosted.org/packages/66/a8/f7dfba76b68411d16ff28442581fa941e480d0bbe9166d548f0b3aaef28e/vdm-0.6.tar.gz" } ], "0.7": [ { "comment_text": "", "digests": { "md5": "ddeb6be74a402aca000050f024a25f8f", "sha256": "03b32c9793c8ef5ce3898dc95e9f6d77f9374501e259982b78c818dc90119f17" }, "downloads": -1, "filename": "vdm-0.7.tar.gz", "has_sig": false, "md5_digest": "ddeb6be74a402aca000050f024a25f8f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 41682, "upload_time": "2010-05-11T20:23:52", "url": "https://files.pythonhosted.org/packages/0a/8a/1b28d5121fd50c7e15875ec4663957771fafb51710e338e05da14dfe7602/vdm-0.7.tar.gz" } ], "0.8": [], "0.9": [ { "comment_text": "", "digests": { "md5": "d3630848c580731b7bc5423bee920718", "sha256": "1d6123b3e7d8a079a276dbb4d508829e91e8ff587d0f00fae85658bce13cd4f4" }, "downloads": -1, "filename": "vdm-0.9.tar.gz", "has_sig": false, "md5_digest": "d3630848c580731b7bc5423bee920718", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33886, "upload_time": "2011-01-11T17:24:52", "url": "https://files.pythonhosted.org/packages/6f/06/9ee3d10fe7bfe417842014cb620f22137c16c3d46e555d210d0d946d5f33/vdm-0.9.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e2f6384d8c03e56c83cdbde28d5e67d6", "sha256": "65b75bb342280114e3c9794fbe5c54b77a9d997fbe07dae50aa303381ccfa26e" }, "downloads": -1, "filename": "vdm-0.15.tar.gz", "has_sig": false, "md5_digest": "e2f6384d8c03e56c83cdbde28d5e67d6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33067, "upload_time": "2019-05-14T12:56:00", "url": "https://files.pythonhosted.org/packages/83/6b/69d14e438f47c88daf0f986b00ddb69c1b3d474ff7199ac673f833a341f0/vdm-0.15.tar.gz" } ] }