{ "info": { "author": "Zope Corporation and Contributors", "author_email": "zope-dev@zope.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Zope3", "Intended Audience :: Developers", "License :: OSI Approved :: Zope Public License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP" ], "description": "This package provides a framework for object locking. The implementation\nis intended to provide a simple general-purpose locking architecture upon\nwhich other locking applications can be built (WebDAV locking, for example).\n\n\nDetailed Dcoumentation\n----------------------\n\n\n==============\nObject Locking\n==============\n\nThis package provides a framework for object locking. The implementation\nis intended to provide a simple general-purpose locking architecture upon\nwhich other locking applications can be built (WebDAV locking, for example).\n\nThe locking system is purely *advisory* - it provides a way to associate a\nlock with an object, but it does not enforce locking in any way. It is up\nto application-level code to ensure that locked objects are restricted in\na way appropriate to the application.\n\nThe Zope 3 locking model defines interfaces and a default implementation\nthat:\n\n - allows for a single lock on an object, owned by a specific principal\n\n - does not necessarily impose inherent semantic meaning (exclusive\n vs. non-exclusive, write vs. read) on locks, though it will\n provide fields that higher-level application components can use\n to implement and enforce such semantics\n\n - can potentially be used to build more ambitious locking\n mechanisms (such as WebDAV locking equivalent to Zope 2)\n\n - supports common use cases that have been uncovered in several years\n of development of real-world applications (such as reporting all of\n the objects locked by a given user)\n\n\nThe Zope3 locking architecture defines an `ILockable` interface and\nprovides a default adapter implementation that requires only that an\nobject be adaptable to `IKeyReference`. All persistent objects can be\nadapted to this interface by default in Zope 3, so in practice all\npersistent objects are lockable.\n\nThe default `ILockable` adapter implementation provides support for:\n\n - locking and unlocking an object\n\n - breaking an existing lock on an object\n\n - obtaining the lock information for an object\n\n\nLocking operations (lock, unlock, break lock) fire events that may be\nhandled by applications or other components to interact with the locking\nsystem in a loosely-coupled way.\n\nLock information is accessible through an object that supports the\n`ILockInfo` interface. The `ILockInfo` interface implies `IAnnotatable`,\nso that other locking implementations (superseding or complementing the\ndefault implementation) can store more information if needed to support\nextended locking semantics.\n\nThe locking architecture also supports an efficient method of lock tracking\nthat allows you to determine what locks are held on objects. The default\nimplementation provides an `ILockTracker` utility that can be used by\napplications to quickly find all objects locked by a particular principal.\n\n\nLocking essentials\n------------------\n\nNormally, locking is provided by the default locking implementation. In\nthis example, we'll create a simple content class. The content class\nis persistent, which allows us to use the default locking adapters and\nutilities.\n\n >>> import persistent\n\n >>> class Content(persistent.Persistent):\n ... \"\"\"A sample content object\"\"\"\n ...\n ... def __init__(self, value):\n ... self.value = value\n ...\n ... def __call__(self):\n ... return self\n ...\n ... def __hash__(self):\n ... return self.value\n ...\n ... def __cmp__(self, other):\n ... return cmp(self.value, other.value)\n\n\nNow we will create a few sample objects to work with:\n\n >>> item1 = Content(\"item1\")\n >>> item1.__name__ = \"item1\"\n\n >>> item2 = Content(\"item2\")\n >>> item2.__name__ = \"item2\"\n\n >>> item3 = Content(\"item3\")\n >>> item3.__name__ = \"item3\"\n\n\nIt is possible to test whether an object supports locking by attempting\nto adapt it to the ILockable interface:\n\n >>> from zope.app.locking.interfaces import ILockable\n >>> from zope.app.locking.interfaces import ILockInfo\n\n >>> ILockable(item1, None)\n >> ILockable(42, None)\n\n\nThere must be an active interaction to use locking, to allow the framework\nto determine the principal performing locking operations. This example sets\nup some sample principals and a helper to switch principals for further\nexamples:\n\n >>> class FauxPrincipal:\n ... def __init__(self, id):\n ... self.id = id\n\n >>> britney = FauxPrincipal('britney')\n >>> tim = FauxPrincipal('tim')\n\n >>> class FauxParticipation:\n ... interaction = None\n ... def __init__(self, principal):\n ... self.principal = principal\n\n >>> import zope.security.management\n >>> def set_principal(principal):\n ... if zope.security.management.queryInteraction():\n ... zope.security.management.endInteraction()\n ... participation = FauxParticipation(principal)\n ... zope.security.management.newInteraction(participation)\n\n >>> set_principal(britney)\n\n\nNow, let's look at basic locking. To perform locking operations, we first\nhave to adapt an object to `ILockable`:\n\n >>> obj = ILockable(item1)\n >>> from zope.interface.verify import verifyObject\n >>> verifyObject(ILockable, obj)\n True\n\nWe can ask if the object is locked:\n\n >>> obj.locked()\n False\n\n\nIf it were locked, we could get the id of the principal that owns the\nlock. Since it is not locked, this will return `None`:\n\n >>> obj.locker()\n\n\nNow let's lock the object. Note that the lock method return an instance\nof an object that implements `ILockInfo` on success:\n\n >>> info = obj.lock()\n >>> verifyObject(ILockInfo, info)\n True\n\n >>> obj.locked()\n True\n\n >>> obj.locker()\n 'britney'\n\n\nMethods are provided to check whether the current principal already has\nthe lock on an object and whether the lock is already owned by a different\nprincipal:\n\n >>> obj.ownLock()\n True\n\n >>> obj.isLockedOut()\n False\n\n\nIf we switch principals, we see that the answers reflect the current\nprincipal:\n\n >>> set_principal(tim)\n >>> obj.ownLock()\n False\n\n >>> obj.isLockedOut()\n True\n\n\nA principal can only release his or her own locks:\n\n >>> obj.unlock()\n Traceback (most recent call last):\n ...\n LockingError: Principal is not lock owner\n\n\nIf we switch back to the original principal, we see that the original\nprincipal can unlock the object:\n\n >>> set_principal(britney)\n >>> obj.unlock()\n\n\nThere is a mechanism for breaking locks that does not take the current\nprincipal into account. This will break any existing lock on an object:\n\n >>> obj.lock()\n <...LockInfo...>\n\n >>> set_principal(tim)\n >>> obj.locked()\n True\n\n >>> obj.breaklock()\n >>> obj.locked()\n False\n\n\nLocks can be created with an optional timeout. If a timeout is provided,\nit should be an integer number of seconds from the time the lock is\ncreated.\n\n >>> # fake time function to avoid a time.sleep in tests!\n >>> import time\n >>> def faketime():\n ... return time.time() + 3600.0\n\n >>> obj.lock(timeout=10)\n <...LockInfo...>\n\n >>> obj.locked()\n True\n\n >>> import zope.app.locking.storage\n >>> zope.app.locking.storage.timefunc = faketime\n >>> obj.locked()\n False\n\n(Note that we undo our time hack in the tearDown of this module.)\n\nFinally, it is possible to explicitly get an `ILockInfo` object that\ncontains the lock information for the object. Note that locks that do\nnot have a timeout set have a timeout value of `None`.\n\n >>> obj = ILockable(item2)\n >>> obj.lock()\n <...LockInfo...>\n\n >>> info = obj.getLockInfo()\n >>> info.principal_id\n 'tim'\n >>> info.timeout\n\n\nIt is possible to get the object associated with a lock directly from\nan `ILockInfo` instance:\n\n >>> target = info.target\n >>> target.__name__ == 'item2'\n True\n\n\nThe `ILockInfo` interface extends the IMapping interface, so application\ncode can store extra information on locks if necessary. It is recommended\nthat keys for extra data use qualified names following the convention that\nis commonly used for annotations:\n\n >>> info['my.namespace.extra'] = 'spam'\n >>> info['my.namespace.extra']\n 'spam'\n >>> obj.unlock()\n >>> obj.locked()\n False\n\n\nLock tracking\n-------------\n\nIt is often desirable to be able to report on the currently held locks in\na system (particularly on a per-user basis), without requiring an expensive\nbrute-force search. An `ILockTracker` utility allows an application to get\nthe current locks for a principal, or all current locks:\n\n >>> set_principal(tim)\n >>> obj = ILockable(item2)\n >>> obj.lock()\n <...LockInfo...>\n\n >>> set_principal(britney)\n >>> obj = ILockable(item3)\n >>> obj.lock()\n <...LockInfo...>\n\n >>> from zope.app.locking.interfaces import ILockTracker\n >>> from zope.component import getUtility\n >>> util = getUtility(ILockTracker)\n >>> verifyObject(ILockTracker, util)\n True\n\n >>> items = util.getLocksForPrincipal('britney')\n >>> len(items) == 1\n True\n\n >>> items = util.getAllLocks()\n >>> len(items) >= 2\n True\n\n\nThese methods allow an application to create forms and other code that\nperforms unlocking or breaking of locks on sets of objects:\n\n >>> items = util.getAllLocks()\n >>> for item in items:\n ... obj = ILockable(item.target)\n ... obj.breaklock()\n\n >>> items = util.getAllLocks()\n >>> len(items)\n 0\n\nThe lock storage utility provides further capabilities, and is a part of the\nstandard lock adapter implementation, but the ILockable interface does not\ndepend on ILockStorage. Other implementations of ILockable may not use\nILockStorage. However, if used by the adapter, it provides useful\ncapabilties.\n\n >>> from zope.app.locking.interfaces import ILockStorage\n >>> util = getUtility(ILockStorage)\n >>> verifyObject(ILockStorage, util)\n True\n\nLocking events\n--------------\n\nLocking operations (lock, unlock, break lock) fire events that can be used\nby applications. Note that expiration of a lock *does not* fire an event\n(because the current implementation uses a lazy expiration approach).\n\n >>> import zope.event\n\n >>> def log_event(event):\n ... print event\n\n >>> zope.event.subscribers.append(log_event)\n\n >>> obj = ILockable(item2)\n >>> obj.lock()\n LockedEvent ...\n\n >>> obj.unlock()\n UnlockedEvent ...\n\n >>> obj.lock()\n LockedEvent ...\n\n >>> obj.breaklock()\n BreakLockEvent ...\n\n\nTALES conditions based on locking\n---------------------------------\n\nTALES expressions can use a named path adapter to get information\nabout the lock status for an object, including whether or not the\nobject can be locked. The default registration for this adapter uses\nthe name \"locking\", so a condition might be expressed like\n\"context/locking:ownLock\", for example.\n\nFor objects that aren't lockable, the adapter provides information\nthat makes sense::\n\n >>> from zope.component import getAdapter\n >>> from zope.traversing.interfaces import IPathAdapter\n\n >>> ns = getAdapter(42, IPathAdapter, \"locking\")\n >>> ns.lockable\n False\n\n >>> ns.locked\n False\n\n >>> ns.lockedOut\n False\n\n >>> ns.ownLock\n False\n\nUsing an object that's lockable, but unlocked, also gives the expected\nresults::\n\n >>> ns = getAdapter(item1, IPathAdapter, \"locking\")\n >>> ns.lockable\n True\n\n >>> ns.locked\n False\n\n >>> ns.lockedOut\n False\n\n >>> ns.ownLock\n False\n\nIf we lock the object, the adapter indicates that the object is locked\nand that we own it::\n\n >>> ob = ILockable(item1)\n >>> ob.lock()\n LockedEvent for ...\n\n >>> ns.lockable\n True\n\n >>> ns.locked\n True\n\n >>> ns.lockedOut\n False\n\n >>> ns.ownLock\n True\n\n\n=======\nCHANGES\n=======\n\n3.5.0 (2009-02-01)\n------------------\n\n- Use ``zope.site`` instead of ``zope.app.folder`` in test.\n\n- Remove usage of deprecated ``zope.app.zapi``.\n\n3.4.0 (2007-10-25)\n------------------\n\n- Initial release independent of the main Zope tree.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://pypi.python.org/pypi/zope.app.locking", "keywords": "zope3 object locking", "license": "ZPL 2.1", "maintainer": null, "maintainer_email": null, "name": "zope.app.locking", "package_url": "https://pypi.org/project/zope.app.locking/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/zope.app.locking/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://pypi.python.org/pypi/zope.app.locking" }, "release_url": "https://pypi.org/project/zope.app.locking/3.5.0/", "requires_dist": null, "requires_python": null, "summary": "Simple Object Locking Framework for Zope 3 applications", "version": "3.5.0" }, "last_serial": 805213, "releases": { "3.4.0": [ { "comment_text": "", "digests": { "md5": "1bc1133e4372f0b50d97b93877dc0726", "sha256": "953f683e9114153673e0354a0501354832e2e990a21c16c9ea8c24160f501326" }, "downloads": -1, "filename": "zope.app.locking-3.4.0.tar.gz", "has_sig": false, "md5_digest": "1bc1133e4372f0b50d97b93877dc0726", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15737, "upload_time": "2007-10-25T15:52:19", "url": "https://files.pythonhosted.org/packages/48/ca/3b0df843f5de7e93de7f19d0ca4523b8061c0f3b20f6fc1771f17c0bb7cd/zope.app.locking-3.4.0.tar.gz" } ], "3.5.0": [ { "comment_text": "", "digests": { "md5": "4edce1ba26f6c56b0eb79f703d8a80fe", "sha256": "ba80727cb453e64458c4423efc9309ea8af44432a68a8d6808994da4f3a33a73" }, "downloads": -1, "filename": "zope.app.locking-3.5.0.tar.gz", "has_sig": false, "md5_digest": "4edce1ba26f6c56b0eb79f703d8a80fe", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17991, "upload_time": "2009-02-01T16:23:35", "url": "https://files.pythonhosted.org/packages/e3/9c/4d3ca57731327826c2d3e200ba47248510fe72a6febbd6a8e258578710c3/zope.app.locking-3.5.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "4edce1ba26f6c56b0eb79f703d8a80fe", "sha256": "ba80727cb453e64458c4423efc9309ea8af44432a68a8d6808994da4f3a33a73" }, "downloads": -1, "filename": "zope.app.locking-3.5.0.tar.gz", "has_sig": false, "md5_digest": "4edce1ba26f6c56b0eb79f703d8a80fe", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17991, "upload_time": "2009-02-01T16:23:35", "url": "https://files.pythonhosted.org/packages/e3/9c/4d3ca57731327826c2d3e200ba47248510fe72a6febbd6a8e258578710c3/zope.app.locking-3.5.0.tar.gz" } ] }