zope.principalannotation-3.6.1/0000755000175000017500000000000011370376165016466 5ustar tseavertseaverzope.principalannotation-3.6.1/buildout.cfg0000644000175000017500000000110711370376125020771 0ustar tseavertseaver[buildout] develop = . parts = test coverage-test coverage-report docs [test] recipe = zc.recipe.testrunner eggs = zope.principalannotation [test] [coverage-test] recipe = zc.recipe.testrunner eggs = zope.principalannotation [test] defaults = ['--coverage', '../../coverage'] [coverage-report] recipe = zc.recipe.egg eggs = z3c.coverage scripts = coverage=coverage-report arguments = ('coverage', 'coverage/report') [docs] recipe = z3c.recipe.sphinxdoc eggs = zope.principalannotation [docs] build-dir = ${buildout:directory}/docs index-doc = README default.css = layout.html = zope.principalannotation-3.6.1/COPYRIGHT.txt0000644000175000017500000000004011370376125020565 0ustar tseavertseaverZope Foundation and Contributorszope.principalannotation-3.6.1/CHANGES.txt0000644000175000017500000000127711370376125020302 0ustar tseavertseaver======= CHANGES ======= 3.6.1 (2010-05-05) ------------------ - Fixed a test failure in nested local site manager setup. - Removed dependency on zope.container. 3.6.0 (2009-03-09) ------------------ Initial release. This package was splitted off zope.app.principalannotation to remove its dependencies on "zope 3 application server" components. In addition, the following changes were made after split off: - The IAnnotations implementation was fixed to look in the higher-level utility not only on ``__getitem__``, but also on ``get`` and ``__nonzero``. - Tests was reworked into the README.txt doctest. - Added a buildout part that generates Sphinx documentation from the README.txt zope.principalannotation-3.6.1/setup.cfg0000644000175000017500000000007311370376165020307 0ustar tseavertseaver[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.principalannotation-3.6.1/README.txt0000644000175000017500000000032011370376125020153 0ustar tseavertseaverThis package implements annotations for zope.security principals. Common annotation techniques, like AttributeAnnotations cannot be applied to principals, since they are created on the fly for every request. zope.principalannotation-3.6.1/PKG-INFO0000644000175000017500000002256511370376165017575 0ustar tseavertseaverMetadata-Version: 1.0 Name: zope.principalannotation Version: 3.6.1 Summary: Annotations for Zope Principals Home-page: http://pypi.python.org/pypi/zope.principalannotation Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ===================== Principal Annotations ===================== This package implements annotations for zope.security principals. To make it clear, the `principal` here is the object that provides ``zope.security.interfaces.IPrincipal`` interface and `annotations` is the object providing ``zope.annotation.interfaces.IAnnotations``. The problem is that principals is dynamic, non-persistent objects created on the fly for every security participation (request or something), so common annotation techniques, like AttributeAnnotations cannot be applied to them. This package provides a persistent storage of principal annotations, storing annotations by principal ID as well as an adapter from IPrincipal to IAnnotations. PrincipalAnnotationUtility -------------------------- The core of this package is the ``PrincipalAnnotationUtility`` class that stores annotations for principals and allows to get them easily. It provides the IPrincipalAnnotationUtility interface:: >>> from zope.principalannotation.interfaces import IPrincipalAnnotationUtility >>> from zope.principalannotation.utility import PrincipalAnnotationUtility >>> from zope.interface.verify import verifyObject >>> util = PrincipalAnnotationUtility() >>> verifyObject(IPrincipalAnnotationUtility, util) True It provides three methods: ``getAnnotations``, ``getAnnotationsById`` and ``hasAnnotations``. Let's create a testing principal and check out these methods:: >>> from zope.security.testing import Principal >>> nadako = Principal('nadako') >>> nadako.id 'nadako' We can check if our principal has any annotations. Of course, it currently doesn't have any:: >>> util.hasAnnotations(nadako) False We can get ``IAnnotations`` object using principal object itself:: >>> util.getAnnotations(nadako) Or using principal id:: >>> util.getAnnotationsById(nadako.id) Let's get the ``IAnnotations`` object for our principal and play with it:: >>> annots = util.getAnnotations(nadako) >>> from zope.interface.verify import verifyObject >>> from zope.annotation.interfaces import IAnnotations >>> verifyObject(IAnnotations, annots) True Let's check the ``IAnnotation`` contract:: >>> bool(annots) False >>> annots['not.here'] Traceback (most recent call last): ... KeyError: 'not.here' >>> annots.get('not.here') is None True >>> annots.get('not.here', 42) 42 Note, that the ``IAnnotations`` object gets stored in the utility only when we set a key for it. This is a simple optimization that allows us not to store any data when all we do is simply checking for presense of annotation. The ``hasAnnotations`` method will return ``True`` after storing a key in the annotations:: >>> util.hasAnnotations(nadako) False >>> annots['its.here'] = 'some info' >>> util.hasAnnotations(nadako) True We can also delete the existing key:: >>> del annots['its.here'] But we can't delete the key that is (no more) existant:: >>> del annots['its.here'] Traceback (most recent call last): ... KeyError: 'its.here' Multiple annotation utilities ----------------------------- Imagine that your application has a root ``site`` object with its component registry (a.k.a. site manager) and that object has a sub-site object with its own component registry, and that component registry has the root's component registry as its base. In that case, we want the ``IAnnotations`` object to be available to retrieve annotations from higher-level utilities. Let's register our utility in the root site and create a sub-site with its own IPrincipalAnnotationUtility:: >>> root['util'] = util >>> rootsm = root.getSiteManager() >>> rootsm.registerUtility(util, IPrincipalAnnotationUtility) >>> from zope.site.folder import Folder >>> from zope.site.site import LocalSiteManager >>> subsite = Folder() >>> root['subsite'] = subsite >>> subsm = LocalSiteManager(subsite) >>> subsm.__bases__ = (rootsm,) >>> subsite.setSiteManager(subsm) >>> util2 = PrincipalAnnotationUtility() >>> subsite['util2'] = util2 >>> subsm.registerUtility(util2, IPrincipalAnnotationUtility) Now, let's create a key in the IAnnotations, provided by root utility:: >>> annots = util.getAnnotations(nadako) >>> annots['root.number'] = 42 The subsite utility should get the annotation successfully:: >>> annots2 = util2.getAnnotations(nadako) >>> bool(annots2) True >>> annots2['root.number'] 42 If we have the key both in higher-level annotations and lower-level ones, the lower-level will have priority, but higher-level won't be deleted or overriden:: >>> annots['another.number'] = 1 >>> annots2['another.number'] = 42 >>> annots['another.number'] 1 >>> annots2['another.number'] 42 If we'll delete the key from lower-level, it will not be deleted from a higher level utility:: >>> del annots2['another.number'] >>> annots['another.number'] 1 >>> annots2['another.number'] 1 IPrincipal -> IAnnotations adapter ---------------------------------- Of course, the most nice feature is that we can simply adapt our principal object to IAnnotations and get those annotations using standard way documented in ``zope.annotation`` package. >>> annots = IAnnotations(nadako) >>> annots >>> annots['root.number'] 42 By default, the IAnnotation adapter uses the current site's utility:: >>> IAnnotations(nadako) is util.getAnnotations(nadako) True >>> from zope.site.hooks import setSite >>> setSite(subsite) >>> IAnnotations(nadako) is util2.getAnnotations(nadako) True Howerver, we can use a binary multi-adapter to IAnnotations to specify some context object from which to get the annotations utility:: >>> from zope.component import getMultiAdapter >>> annots = getMultiAdapter((nadako, root), IAnnotations) >>> annots is util.getAnnotations(nadako) True >>> annots = getMultiAdapter((nadako, subsite), IAnnotations) >>> annots is util2.getAnnotations(nadako) True ======= CHANGES ======= 3.6.1 (2010-05-05) ------------------ - Fixed a test failure in nested local site manager setup. - Removed dependency on zope.container. 3.6.0 (2009-03-09) ------------------ Initial release. This package was splitted off zope.app.principalannotation to remove its dependencies on "zope 3 application server" components. In addition, the following changes were made after split off: - The IAnnotations implementation was fixed to look in the higher-level utility not only on ``__getitem__``, but also on ``get`` and ``__nonzero``. - Tests was reworked into the README.txt doctest. - Added a buildout part that generates Sphinx documentation from the README.txt Keywords: zope security principal annotation Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.principalannotation-3.6.1/bootstrap.py0000644000175000017500000000337311370376125021057 0ustar tseavertseaver############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Bootstrap a buildout-based project Simply run this script in a directory containing a buildout.cfg. The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. $Id: bootstrap.py 112036 2010-05-05 19:10:45Z tseaver $ """ import os, shutil, sys, tempfile, urllib2 tmpeggs = tempfile.mkdtemp() ez = {} exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' ).read() in ez ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) import pkg_resources cmd = 'from setuptools.command.easy_install import main; main()' if sys.platform == 'win32': cmd = '"%s"' % cmd # work around spawn lamosity on windows ws = pkg_resources.working_set assert os.spawnle( os.P_WAIT, sys.executable, sys.executable, '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout', dict(os.environ, PYTHONPATH= ws.find(pkg_resources.Requirement.parse('setuptools')).location ), ) == 0 ws.add_entry(tmpeggs) ws.require('zc.buildout') import zc.buildout.buildout zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap']) shutil.rmtree(tmpeggs) zope.principalannotation-3.6.1/setup.py0000644000175000017500000000465711370376125020210 0ustar tseavertseaver############################################################################## # # Copyright (c) 2009 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Setup for zope.principalannotation package $Id: setup.py 112068 2010-05-05 23:14:35Z tseaver $ """ import os from setuptools import setup, find_packages def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read() setup(name='zope.principalannotation', version = '3.6.1', author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', description='Annotations for Zope Principals', long_description=( read('src', 'zope', 'principalannotation', 'README.txt') + '\n\n' + read('CHANGES.txt') ), keywords = "zope security principal annotation", classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Natural Language :: English', 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP', 'Framework :: Zope3'], url='http://pypi.python.org/pypi/zope.principalannotation', license='ZPL 2.1', packages=find_packages('src'), package_dir = {'': 'src'}, namespace_packages=['zope'], extras_require = dict(test=['zope.testing', 'zope.site[test]'], docs=['z3c.recipe.sphinxdoc',]), install_requires=['setuptools', 'ZODB3', 'zope.annotation', 'zope.component', 'zope.interface', 'zope.location', 'zope.security', 'zope.site', ], include_package_data = True, zip_safe = False, ) zope.principalannotation-3.6.1/src/0000755000175000017500000000000011370376165017255 5ustar tseavertseaverzope.principalannotation-3.6.1/src/zope.principalannotation.egg-info/0000755000175000017500000000000011370376165025777 5ustar tseavertseaverzope.principalannotation-3.6.1/src/zope.principalannotation.egg-info/SOURCES.txt0000644000175000017500000000132111370376165027660 0ustar tseavertseaverCHANGES.txt COPYRIGHT.txt LICENSE.txt README.txt bootstrap.py buildout.cfg setup.py src/zope/__init__.py src/zope.principalannotation.egg-info/PKG-INFO src/zope.principalannotation.egg-info/SOURCES.txt src/zope.principalannotation.egg-info/dependency_links.txt src/zope.principalannotation.egg-info/namespace_packages.txt src/zope.principalannotation.egg-info/not-zip-safe src/zope.principalannotation.egg-info/requires.txt src/zope.principalannotation.egg-info/top_level.txt src/zope/principalannotation/README.txt src/zope/principalannotation/__init__.py src/zope/principalannotation/configure.zcml src/zope/principalannotation/interfaces.py src/zope/principalannotation/tests.py src/zope/principalannotation/utility.pyzope.principalannotation-3.6.1/src/zope.principalannotation.egg-info/dependency_links.txt0000644000175000017500000000000111370376165032045 0ustar tseavertseaver zope.principalannotation-3.6.1/src/zope.principalannotation.egg-info/top_level.txt0000644000175000017500000000000511370376165030524 0ustar tseavertseaverzope zope.principalannotation-3.6.1/src/zope.principalannotation.egg-info/namespace_packages.txt0000644000175000017500000000000511370376165032325 0ustar tseavertseaverzope zope.principalannotation-3.6.1/src/zope.principalannotation.egg-info/requires.txt0000644000175000017500000000024611370376165030401 0ustar tseavertseaversetuptools ZODB3 zope.annotation zope.component zope.interface zope.location zope.security zope.site [test] zope.testing zope.site[test] [docs] z3c.recipe.sphinxdoczope.principalannotation-3.6.1/src/zope.principalannotation.egg-info/PKG-INFO0000644000175000017500000002256511370376165027106 0ustar tseavertseaverMetadata-Version: 1.0 Name: zope.principalannotation Version: 3.6.1 Summary: Annotations for Zope Principals Home-page: http://pypi.python.org/pypi/zope.principalannotation Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ===================== Principal Annotations ===================== This package implements annotations for zope.security principals. To make it clear, the `principal` here is the object that provides ``zope.security.interfaces.IPrincipal`` interface and `annotations` is the object providing ``zope.annotation.interfaces.IAnnotations``. The problem is that principals is dynamic, non-persistent objects created on the fly for every security participation (request or something), so common annotation techniques, like AttributeAnnotations cannot be applied to them. This package provides a persistent storage of principal annotations, storing annotations by principal ID as well as an adapter from IPrincipal to IAnnotations. PrincipalAnnotationUtility -------------------------- The core of this package is the ``PrincipalAnnotationUtility`` class that stores annotations for principals and allows to get them easily. It provides the IPrincipalAnnotationUtility interface:: >>> from zope.principalannotation.interfaces import IPrincipalAnnotationUtility >>> from zope.principalannotation.utility import PrincipalAnnotationUtility >>> from zope.interface.verify import verifyObject >>> util = PrincipalAnnotationUtility() >>> verifyObject(IPrincipalAnnotationUtility, util) True It provides three methods: ``getAnnotations``, ``getAnnotationsById`` and ``hasAnnotations``. Let's create a testing principal and check out these methods:: >>> from zope.security.testing import Principal >>> nadako = Principal('nadako') >>> nadako.id 'nadako' We can check if our principal has any annotations. Of course, it currently doesn't have any:: >>> util.hasAnnotations(nadako) False We can get ``IAnnotations`` object using principal object itself:: >>> util.getAnnotations(nadako) Or using principal id:: >>> util.getAnnotationsById(nadako.id) Let's get the ``IAnnotations`` object for our principal and play with it:: >>> annots = util.getAnnotations(nadako) >>> from zope.interface.verify import verifyObject >>> from zope.annotation.interfaces import IAnnotations >>> verifyObject(IAnnotations, annots) True Let's check the ``IAnnotation`` contract:: >>> bool(annots) False >>> annots['not.here'] Traceback (most recent call last): ... KeyError: 'not.here' >>> annots.get('not.here') is None True >>> annots.get('not.here', 42) 42 Note, that the ``IAnnotations`` object gets stored in the utility only when we set a key for it. This is a simple optimization that allows us not to store any data when all we do is simply checking for presense of annotation. The ``hasAnnotations`` method will return ``True`` after storing a key in the annotations:: >>> util.hasAnnotations(nadako) False >>> annots['its.here'] = 'some info' >>> util.hasAnnotations(nadako) True We can also delete the existing key:: >>> del annots['its.here'] But we can't delete the key that is (no more) existant:: >>> del annots['its.here'] Traceback (most recent call last): ... KeyError: 'its.here' Multiple annotation utilities ----------------------------- Imagine that your application has a root ``site`` object with its component registry (a.k.a. site manager) and that object has a sub-site object with its own component registry, and that component registry has the root's component registry as its base. In that case, we want the ``IAnnotations`` object to be available to retrieve annotations from higher-level utilities. Let's register our utility in the root site and create a sub-site with its own IPrincipalAnnotationUtility:: >>> root['util'] = util >>> rootsm = root.getSiteManager() >>> rootsm.registerUtility(util, IPrincipalAnnotationUtility) >>> from zope.site.folder import Folder >>> from zope.site.site import LocalSiteManager >>> subsite = Folder() >>> root['subsite'] = subsite >>> subsm = LocalSiteManager(subsite) >>> subsm.__bases__ = (rootsm,) >>> subsite.setSiteManager(subsm) >>> util2 = PrincipalAnnotationUtility() >>> subsite['util2'] = util2 >>> subsm.registerUtility(util2, IPrincipalAnnotationUtility) Now, let's create a key in the IAnnotations, provided by root utility:: >>> annots = util.getAnnotations(nadako) >>> annots['root.number'] = 42 The subsite utility should get the annotation successfully:: >>> annots2 = util2.getAnnotations(nadako) >>> bool(annots2) True >>> annots2['root.number'] 42 If we have the key both in higher-level annotations and lower-level ones, the lower-level will have priority, but higher-level won't be deleted or overriden:: >>> annots['another.number'] = 1 >>> annots2['another.number'] = 42 >>> annots['another.number'] 1 >>> annots2['another.number'] 42 If we'll delete the key from lower-level, it will not be deleted from a higher level utility:: >>> del annots2['another.number'] >>> annots['another.number'] 1 >>> annots2['another.number'] 1 IPrincipal -> IAnnotations adapter ---------------------------------- Of course, the most nice feature is that we can simply adapt our principal object to IAnnotations and get those annotations using standard way documented in ``zope.annotation`` package. >>> annots = IAnnotations(nadako) >>> annots >>> annots['root.number'] 42 By default, the IAnnotation adapter uses the current site's utility:: >>> IAnnotations(nadako) is util.getAnnotations(nadako) True >>> from zope.site.hooks import setSite >>> setSite(subsite) >>> IAnnotations(nadako) is util2.getAnnotations(nadako) True Howerver, we can use a binary multi-adapter to IAnnotations to specify some context object from which to get the annotations utility:: >>> from zope.component import getMultiAdapter >>> annots = getMultiAdapter((nadako, root), IAnnotations) >>> annots is util.getAnnotations(nadako) True >>> annots = getMultiAdapter((nadako, subsite), IAnnotations) >>> annots is util2.getAnnotations(nadako) True ======= CHANGES ======= 3.6.1 (2010-05-05) ------------------ - Fixed a test failure in nested local site manager setup. - Removed dependency on zope.container. 3.6.0 (2009-03-09) ------------------ Initial release. This package was splitted off zope.app.principalannotation to remove its dependencies on "zope 3 application server" components. In addition, the following changes were made after split off: - The IAnnotations implementation was fixed to look in the higher-level utility not only on ``__getitem__``, but also on ``get`` and ``__nonzero``. - Tests was reworked into the README.txt doctest. - Added a buildout part that generates Sphinx documentation from the README.txt Keywords: zope security principal annotation Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.principalannotation-3.6.1/src/zope.principalannotation.egg-info/not-zip-safe0000644000175000017500000000000111370376140030216 0ustar tseavertseaver zope.principalannotation-3.6.1/src/zope/0000755000175000017500000000000011370376165020232 5ustar tseavertseaverzope.principalannotation-3.6.1/src/zope/principalannotation/0000755000175000017500000000000011370376165024306 5ustar tseavertseaverzope.principalannotation-3.6.1/src/zope/principalannotation/interfaces.py0000644000175000017500000000272011370376125027000 0ustar tseavertseaver############################################################################## # # Copyright (c) 2009 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Utility for storing `IAnnotations` for principals. $Id: interfaces.py 112036 2010-05-05 19:10:45Z tseaver $ """ __docformat__ = 'restructuredtext' from zope.interface import Interface class IPrincipalAnnotationUtility(Interface): """Stores `IAnnotations` for `IPrinicipals`.""" def getAnnotations(principal): """Return object implementing `IAnnotations` for the given `IPrinicipal`. If there is no `IAnnotations` it will be created and then returned. """ def getAnnotationsById(principalId): """Return object implementing `IAnnotations` for the given `prinicipalId`. If there is no `IAnnotations` it will be created and then returned. """ def hasAnnotations(principal): """Return boolean indicating if given `IPrincipal` has `IAnnotations`.""" zope.principalannotation-3.6.1/src/zope/principalannotation/README.txt0000644000175000017500000001407311370376125026005 0ustar tseavertseaver===================== Principal Annotations ===================== This package implements annotations for zope.security principals. To make it clear, the `principal` here is the object that provides ``zope.security.interfaces.IPrincipal`` interface and `annotations` is the object providing ``zope.annotation.interfaces.IAnnotations``. The problem is that principals is dynamic, non-persistent objects created on the fly for every security participation (request or something), so common annotation techniques, like AttributeAnnotations cannot be applied to them. This package provides a persistent storage of principal annotations, storing annotations by principal ID as well as an adapter from IPrincipal to IAnnotations. PrincipalAnnotationUtility -------------------------- The core of this package is the ``PrincipalAnnotationUtility`` class that stores annotations for principals and allows to get them easily. It provides the IPrincipalAnnotationUtility interface:: >>> from zope.principalannotation.interfaces import IPrincipalAnnotationUtility >>> from zope.principalannotation.utility import PrincipalAnnotationUtility >>> from zope.interface.verify import verifyObject >>> util = PrincipalAnnotationUtility() >>> verifyObject(IPrincipalAnnotationUtility, util) True It provides three methods: ``getAnnotations``, ``getAnnotationsById`` and ``hasAnnotations``. Let's create a testing principal and check out these methods:: >>> from zope.security.testing import Principal >>> nadako = Principal('nadako') >>> nadako.id 'nadako' We can check if our principal has any annotations. Of course, it currently doesn't have any:: >>> util.hasAnnotations(nadako) False We can get ``IAnnotations`` object using principal object itself:: >>> util.getAnnotations(nadako) Or using principal id:: >>> util.getAnnotationsById(nadako.id) Let's get the ``IAnnotations`` object for our principal and play with it:: >>> annots = util.getAnnotations(nadako) >>> from zope.interface.verify import verifyObject >>> from zope.annotation.interfaces import IAnnotations >>> verifyObject(IAnnotations, annots) True Let's check the ``IAnnotation`` contract:: >>> bool(annots) False >>> annots['not.here'] Traceback (most recent call last): ... KeyError: 'not.here' >>> annots.get('not.here') is None True >>> annots.get('not.here', 42) 42 Note, that the ``IAnnotations`` object gets stored in the utility only when we set a key for it. This is a simple optimization that allows us not to store any data when all we do is simply checking for presense of annotation. The ``hasAnnotations`` method will return ``True`` after storing a key in the annotations:: >>> util.hasAnnotations(nadako) False >>> annots['its.here'] = 'some info' >>> util.hasAnnotations(nadako) True We can also delete the existing key:: >>> del annots['its.here'] But we can't delete the key that is (no more) existant:: >>> del annots['its.here'] Traceback (most recent call last): ... KeyError: 'its.here' Multiple annotation utilities ----------------------------- Imagine that your application has a root ``site`` object with its component registry (a.k.a. site manager) and that object has a sub-site object with its own component registry, and that component registry has the root's component registry as its base. In that case, we want the ``IAnnotations`` object to be available to retrieve annotations from higher-level utilities. Let's register our utility in the root site and create a sub-site with its own IPrincipalAnnotationUtility:: >>> root['util'] = util >>> rootsm = root.getSiteManager() >>> rootsm.registerUtility(util, IPrincipalAnnotationUtility) >>> from zope.site.folder import Folder >>> from zope.site.site import LocalSiteManager >>> subsite = Folder() >>> root['subsite'] = subsite >>> subsm = LocalSiteManager(subsite) >>> subsm.__bases__ = (rootsm,) >>> subsite.setSiteManager(subsm) >>> util2 = PrincipalAnnotationUtility() >>> subsite['util2'] = util2 >>> subsm.registerUtility(util2, IPrincipalAnnotationUtility) Now, let's create a key in the IAnnotations, provided by root utility:: >>> annots = util.getAnnotations(nadako) >>> annots['root.number'] = 42 The subsite utility should get the annotation successfully:: >>> annots2 = util2.getAnnotations(nadako) >>> bool(annots2) True >>> annots2['root.number'] 42 If we have the key both in higher-level annotations and lower-level ones, the lower-level will have priority, but higher-level won't be deleted or overriden:: >>> annots['another.number'] = 1 >>> annots2['another.number'] = 42 >>> annots['another.number'] 1 >>> annots2['another.number'] 42 If we'll delete the key from lower-level, it will not be deleted from a higher level utility:: >>> del annots2['another.number'] >>> annots['another.number'] 1 >>> annots2['another.number'] 1 IPrincipal -> IAnnotations adapter ---------------------------------- Of course, the most nice feature is that we can simply adapt our principal object to IAnnotations and get those annotations using standard way documented in ``zope.annotation`` package. >>> annots = IAnnotations(nadako) >>> annots >>> annots['root.number'] 42 By default, the IAnnotation adapter uses the current site's utility:: >>> IAnnotations(nadako) is util.getAnnotations(nadako) True >>> from zope.site.hooks import setSite >>> setSite(subsite) >>> IAnnotations(nadako) is util2.getAnnotations(nadako) True Howerver, we can use a binary multi-adapter to IAnnotations to specify some context object from which to get the annotations utility:: >>> from zope.component import getMultiAdapter >>> annots = getMultiAdapter((nadako, root), IAnnotations) >>> annots is util.getAnnotations(nadako) True >>> annots = getMultiAdapter((nadako, subsite), IAnnotations) >>> annots is util2.getAnnotations(nadako) True zope.principalannotation-3.6.1/src/zope/principalannotation/configure.zcml0000644000175000017500000000105211370376125027150 0ustar tseavertseaver zope.principalannotation-3.6.1/src/zope/principalannotation/utility.py0000644000175000017500000001072211370376125026361 0ustar tseavertseaver############################################################################## # # Copyright (c) 2009 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Implementation of IPrincipalAnnotationUtility $Id: utility.py 104798 2009-10-05 15:01:13Z tlotze $ """ __docformat__ = 'restructuredtext' from BTrees.OOBTree import OOBTree from persistent import Persistent from persistent.dict import PersistentDict from zope import interface, component from zope.annotation.interfaces import IAnnotations from zope.location import Location from zope.location.interfaces import IContained from zope.security.interfaces import IPrincipal from zope.site.next import queryNextUtility from zope.principalannotation.interfaces import IPrincipalAnnotationUtility # TODO: register utility as adapter for IAnnotations on utility activation. class PrincipalAnnotationUtility(Persistent): """Stores `IAnnotations` for `IPrinicipals`. The utility ID is 'PrincipalAnnotation'. """ interface.implements(IPrincipalAnnotationUtility, IContained) __parent__ = None __name__ = None def __init__(self): self.annotations = OOBTree() def getAnnotations(self, principal): """Return object implementing IAnnotations for the given principal. If there is no `IAnnotations` it will be created and then returned. """ return self.getAnnotationsById(principal.id) def getAnnotationsById(self, principalId): """Return object implementing `IAnnotations` for the given principal. If there is no `IAnnotations` it will be created and then returned. """ annotations = self.annotations.get(principalId) if annotations is None: annotations = Annotations(principalId, store=self.annotations) annotations.__parent__ = self annotations.__name__ = principalId return annotations def hasAnnotations(self, principal): """Return boolean indicating if given principal has `IAnnotations`.""" return principal.id in self.annotations class Annotations(Persistent, Location): """Stores annotations.""" interface.implements(IAnnotations) def __init__(self, principalId, store=None): self.principalId = principalId self.data = PersistentDict() # We don't really expect that many # _v_store is used to remember a mapping object that we should # be saved in if we ever change self._v_store = store def __nonzero__(self): nz = bool(self.data) if not nz: # maybe higher-level utility's annotations will be non-zero next = queryNextUtility(self, IPrincipalAnnotationUtility) if next is not None: annotations = next.getAnnotationsById(self.principalId) return bool(next) return nz def __getitem__(self, key): try: return self.data[key] except KeyError: # We failed locally: delegate to a higher-level utility. next = queryNextUtility(self, IPrincipalAnnotationUtility) if next is not None: annotations = next.getAnnotationsById(self.principalId) return annotations[key] raise def get(self, key, default=None): try: return self[key] except KeyError: return default def __setitem__(self, key, value): if getattr(self, '_v_store', None) is not None: # _v_store is used to remember a mapping object that we should # be saved in if we ever change self._v_store[self.principalId] = self del self._v_store self.data[key] = value def __delitem__(self, key): del self.data[key] @component.adapter(IPrincipal) @interface.implementer(IAnnotations) def annotations(principal, context=None): utility = component.getUtility(IPrincipalAnnotationUtility, context=context) return utility.getAnnotations(principal) zope.principalannotation-3.6.1/src/zope/principalannotation/tests.py0000644000175000017500000000262011370376125026016 0ustar tseavertseaver############################################################################## # # Copyright (c) 2009 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Principal Annotation Tests $Id: tests.py 112036 2010-05-05 19:10:45Z tseaver $ """ import unittest from zope.component import provideAdapter from zope.testing import doctest from zope.interface import Interface from zope.security.interfaces import IPrincipal from zope.site.testing import siteSetUp, siteTearDown from zope.principalannotation.utility import annotations def setUp(test): site = siteSetUp(site=True) test.globs['root'] = site provideAdapter(annotations) provideAdapter(annotations, (IPrincipal, Interface)) def tearDown(test): siteTearDown() def test_suite(): return unittest.TestSuite(( doctest.DocFileSuite( 'README.txt', setUp=setUp, tearDown=tearDown, optionflags=doctest.ELLIPSIS) )) zope.principalannotation-3.6.1/src/zope/principalannotation/__init__.py0000644000175000017500000000001711370376125026411 0ustar tseavertseaver# i'm a packagezope.principalannotation-3.6.1/src/zope/__init__.py0000644000175000017500000000031011370376125022331 0ustar tseavertseaver# this is a namespace package try: import pkg_resources pkg_resources.declare_namespace(__name__) except ImportError: import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) zope.principalannotation-3.6.1/LICENSE.txt0000644000175000017500000000402611370376125020307 0ustar tseavertseaverZope Public License (ZPL) Version 2.1 A copyright notice accompanies this license document that identifies the copyright holders. This license has been certified as open source. It has also been designated as GPL compatible by the Free Software Foundation (FSF). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source code must retain the accompanying copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the accompanying copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Names of the copyright holders must not be used to endorse or promote products derived from this software without prior written permission from the copyright holders. 4. The right to distribute this software or to use it for any purpose does not give you the right to use Servicemarks (sm) or Trademarks (tm) of the copyright holders. Use of them is covered by separate agreement with the copyright holders. 5. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. Disclaimer THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.