zope.annotation-3.6.0/bootstrap.py0000644000000000000000000000337312121566406015374 0ustar 00000000000000############################################################################## # # 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 126741 2012-06-11 17:44:56Z 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.annotation-3.6.0/buildout.cfg0000644000000000000000000000034612121566406015312 0ustar 00000000000000[buildout] develop = . parts = test pydev [test] recipe = zc.recipe.testrunner eggs = zope.annotation [test] [ctags] recipe = z3c.recipe.tag:tags eggs = zope.annotation [pydev] recipe = pb.recipes.pydev eggs = zope.annotation zope.annotation-3.6.0/CHANGES.txt0000644000000000000000000000205712121566440014612 0ustar 00000000000000======= CHANGES ======= 3.6.0 (2013-03-18) ------------------ - Don't make AttributeAnnotations available as a view. 3.5.0 (2009-09-07) ------------------ - Add ZODB3 to install_requires, because it's a true requirement of this package, not just a testing requirement, as BTrees are in use. - Fix one test that was inactive because it's function was overriden by a mistake. 3.4.2 (2009-03-09) ------------------ - Clean up package description and documentation a bit. - Change mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Remove old zpkg-related files. 3.4.1 (2008-08-26) ------------------ - Annotation factories take care not to store proxies in the database, so adapting an object wrapped in a ``LocationProxy`` works correctly. Fixes https://bugs.launchpad.net/zope3/+bug/261620 3.4.0 (2007-08-29) ------------------ - Annotation factories are no longer containing the factored object. Instead the objects are located using ``zope.location``. This removes a dependency to ``zope.app.container``. zope.annotation-3.6.0/COPYRIGHT.txt0000644000000000000000000000004012121566406015102 0ustar 00000000000000Zope Foundation and Contributorszope.annotation-3.6.0/LICENSE.txt0000644000000000000000000000402612121566406014624 0ustar 00000000000000Zope 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. zope.annotation-3.6.0/PKG-INFO0000644000000000000000000002063312121566626014104 0ustar 00000000000000Metadata-Version: 1.1 Name: zope.annotation Version: 3.6.0 Summary: Object annotation mechanism Home-page: http://pypi.python.org/pypi/zope.annotation Author: Zope Corporation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ================== Object Annotations ================== This package provides a mechanism to store additional information about objects without need to modify object class. Annotation factories -------------------- There is more to document about annotations, but we'll just sketch out a scenario on how to use the annotation factory for now. This is one of the easiest ways to use annotations -- basically you can see them as persistent, writable adapters. First, let's make a persistent object we can create annotations for: >>> from zope import interface >>> class IFoo(interface.Interface): ... pass >>> from zope.annotation.interfaces import IAttributeAnnotatable >>> from persistent import Persistent >>> class Foo(Persistent): ... interface.implements(IFoo, IAttributeAnnotatable) We directly say that Foo implements IAttributeAnnotatable here. In practice this is often done in ZCML, using the `implements` subdirective of the `content` or `class` directive. Now let's create an annotation for this: >>> class IBar(interface.Interface): ... a = interface.Attribute('A') ... b = interface.Attribute('B') >>> from zope import component >>> class Bar(Persistent): ... interface.implements(IBar) ... component.adapts(IFoo) ... def __init__(self): ... self.a = 1 ... self.b = 2 Note that the annotation implementation does not expect any arguments to its `__init__`. Otherwise it's basically an adapter. Now, we'll register the annotation as an adapter. To do this we use the `factory` function provided by `zope.annotation`: >>> from zope.annotation import factory >>> component.provideAdapter(factory(Bar)) Note that we do not need to specify what the adapter provides or what it adapts - we already do this on the annotation class itself. Now let's make an instance of `Foo`, and make an annotation for it. >>> foo = Foo() >>> bar = IBar(foo) >>> bar.a 1 >>> bar.b 2 We'll change `a` and get the annotation again. Our change is still there: >>> bar.a = 3 >>> IBar(foo).a 3 Of course it's still different for another instance of `Foo`: >>> foo2 = Foo() >>> IBar(foo2).a 1 What if our annotation does not provide what it adapts with `component.adapts`? It will complain: >>> class IQux(interface.Interface): ... pass >>> class Qux(Persistent): ... interface.implements(IQux) >>> component.provideAdapter(factory(Qux)) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Missing 'zope.component.adapts' on annotation It's possible to provide an annotation with an explicit key. (If the key is not supplied, the key is deduced from the annotation's dotted name, provided it is a class.) >>> class IHoi(interface.Interface): ... pass >>> class Hoi(Persistent): ... interface.implements(IHoi) ... component.adapts(IFoo) >>> component.provideAdapter(factory(Hoi, 'my.unique.key')) >>> isinstance(IHoi(foo), Hoi) True Location -------- Annotation factories are put into the location hierarchy with their parent pointing to the annotated object and the name to the dotted name of the annotation's class (or the name the adapter was registered under): >>> foo3 = Foo() >>> new_hoi = IHoi(foo3) >>> new_hoi.__parent__ >>> new_hoi.__name__ 'my.unique.key' >>> import zope.location.interfaces >>> zope.location.interfaces.ILocation.providedBy(new_hoi) True Please notice, that our Hoi object does not implement ILocation, so a location proxy will be used. This has to be re-established every time we retrieve the object (Guard against former bug: proxy wasn't established when the annotation existed already.) >>> old_hoi = IHoi(foo3) >>> old_hoi.__parent__ >>> old_hoi.__name__ 'my.unique.key' >>> zope.location.interfaces.ILocation.providedBy(old_hoi) True LocationProxies --------------- Suppose your annotation proxy provides ILocation. >>> class IPolloi(interface.Interface): ... pass >>> class Polloi(Persistent): ... interface.implements(IPolloi, zope.location.interfaces.ILocation) ... component.adapts(IFoo) ... __name__ = __parent__ = 0 >>> component.provideAdapter(factory(Polloi, 'my.other.key')) Sometimes you're adapting an object wrapped in a LocationProxy. >>> foo4 = Foo() >>> import zope.location.location >>> wrapped_foo4 = zope.location.location.LocationProxy(foo4, None, 'foo4') >>> located_polloi = IPolloi(wrapped_foo4) At first glance it looks as if located_polloi is located under wrapped_foo4. >>> located_polloi.__parent__ is wrapped_foo4 True >>> located_polloi.__name__ 'my.other.key' but that's because we received a LocationProxy >>> print type(located_polloi).__name__ LocationProxy If we unwrap located_polloi and look at it directly, we'll see it stores a reference to the real Foo object >>> from zope.proxy import removeAllProxies >>> removeAllProxies(located_polloi).__parent__ is foo4 True >>> removeAllProxies(located_polloi).__name__ 'my.other.key' ======= CHANGES ======= 3.6.0 (2013-03-18) ------------------ - Don't make AttributeAnnotations available as a view. 3.5.0 (2009-09-07) ------------------ - Add ZODB3 to install_requires, because it's a true requirement of this package, not just a testing requirement, as BTrees are in use. - Fix one test that was inactive because it's function was overriden by a mistake. 3.4.2 (2009-03-09) ------------------ - Clean up package description and documentation a bit. - Change mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Remove old zpkg-related files. 3.4.1 (2008-08-26) ------------------ - Annotation factories take care not to store proxies in the database, so adapting an object wrapped in a ``LocationProxy`` works correctly. Fixes https://bugs.launchpad.net/zope3/+bug/261620 3.4.0 (2007-08-29) ------------------ - Annotation factories are no longer containing the factored object. Instead the objects are located using ``zope.location``. This removes a dependency to ``zope.app.container``. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable 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: Topic :: Software Development zope.annotation-3.6.0/README.txt0000644000000000000000000000004412121566406014473 0ustar 00000000000000See src/zope/annotation/README.txt. zope.annotation-3.6.0/setup.cfg0000644000000000000000000000007312121566626014624 0ustar 00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.annotation-3.6.0/setup.py0000644000000000000000000000414112121566544014514 0ustar 00000000000000############################################################################## # # Copyright (c) 2006-2007 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.annotation package $Id: setup.py 130138 2013-03-18 19:33:06Z davisagli $ """ 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.annotation', version='3.6.0', url='http://pypi.python.org/pypi/zope.annotation', license='ZPL 2.1', description='Object annotation mechanism', author='Zope Corporation and Contributors', author_email='zope-dev@zope.org', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Natural Language :: English', 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Software Development', ], long_description= \ read('src', 'zope', 'annotation', 'README.txt') + '\n\n' + read('CHANGES.txt'), packages=find_packages('src'), package_dir={'': 'src'}, namespace_packages=['zope',], install_requires=['setuptools', 'zope.interface', 'zope.component', 'zope.location', 'zope.proxy', 'ZODB3', ], extras_require=dict( test=['zope.testing'], ), include_package_data=True, zip_safe=False, ) zope.annotation-3.6.0/src/zope/__init__.py0000644000000000000000000000007012121566406016651 0ustar 00000000000000__import__('pkg_resources').declare_namespace(__name__) zope.annotation-3.6.0/src/zope/annotation/__init__.py0000644000000000000000000000156712121566406021037 0ustar 00000000000000############################################################################## # # Copyright (c) 2004 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. # ############################################################################## """Annotation (meta data) support $Id: __init__.py 126741 2012-06-11 17:44:56Z tseaver $ """ from zope.annotation.interfaces import IAttributeAnnotatable from zope.annotation.interfaces import IAnnotations from zope.annotation.factory import factory zope.annotation-3.6.0/src/zope/annotation/attribute.py0000644000000000000000000000475612121566406021306 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 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. # ############################################################################## """Attribute Annotations implementation $Id: attribute.py 126741 2012-06-11 17:44:56Z tseaver $ """ __docformat__ = 'restructuredtext' from UserDict import DictMixin from BTrees.OOBTree import OOBTree from zope import component, interface from zope.annotation import interfaces class AttributeAnnotations(DictMixin): """Store annotations on an object Store annotations in the `__annotations__` attribute on a `IAttributeAnnotatable` object. """ interface.implements(interfaces.IAnnotations) component.adapts(interfaces.IAttributeAnnotatable) def __init__(self, obj, context=None): self.obj = obj def __nonzero__(self): return bool(getattr(self.obj, '__annotations__', 0)) def get(self, key, default=None): """See zope.annotation.interfaces.IAnnotations""" annotations = getattr(self.obj, '__annotations__', None) if not annotations: return default return annotations.get(key, default) def __getitem__(self, key): annotations = getattr(self.obj, '__annotations__', None) if annotations is None: raise KeyError(key) return annotations[key] def keys(self): annotations = getattr(self.obj, '__annotations__', None) if annotations is None: return [] return annotations.keys() def __setitem__(self, key, value): """See zope.annotation.interfaces.IAnnotations""" try: annotations = self.obj.__annotations__ except AttributeError: annotations = self.obj.__annotations__ = OOBTree() annotations[key] = value def __delitem__(self, key): """See zope.app.interfaces.annotation.IAnnotations""" try: annotation = self.obj.__annotations__ except AttributeError: raise KeyError(key) del annotation[key] zope.annotation-3.6.0/src/zope/annotation/configure.zcml0000644000000000000000000000033712121566440021566 0ustar 00000000000000 zope.annotation-3.6.0/src/zope/annotation/factory.py0000644000000000000000000000432712121566406020744 0ustar 00000000000000############################################################################## # # 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. # ############################################################################## """Annotation factory helper $Id: factory.py 126741 2012-06-11 17:44:56Z tseaver $ """ import zope.component import zope.interface import zope.location.location import zope.location.interfaces import zope.proxy import zope.annotation.interfaces def factory(factory, key=None): """Adapter factory to help create annotations easily. """ # if no key is provided, # we'll determine the unique key based on the factory's dotted name if key is None: key = factory.__module__ + '.' + factory.__name__ adapts = zope.component.adaptedBy(factory) if adapts is None: raise TypeError("Missing 'zope.component.adapts' on annotation") @zope.component.adapter(list(adapts)[0]) @zope.interface.implementer(list(zope.component.implementedBy(factory))[0]) def getAnnotation(context): annotations = zope.annotation.interfaces.IAnnotations(context) try: result = annotations[key] except KeyError: result = factory() annotations[key] = result if zope.location.interfaces.ILocation.providedBy(result): zope.location.location.locate(result, zope.proxy.removeAllProxies(context), key) if not (zope.location.interfaces.ILocation.providedBy(result) and result.__parent__ is context and result.__name__ == key): result = zope.location.location.LocationProxy(result, context, key) return result # Convention to make adapter introspectable, used by apidoc getAnnotation.factory = factory return getAnnotation zope.annotation-3.6.0/src/zope/annotation/interfaces.py0000644000000000000000000000537612121566406021425 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 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. # ############################################################################## """Annotations store arbitrary application data under package-unique keys. $Id: interfaces.py 126741 2012-06-11 17:44:56Z tseaver $ """ __docformat__ = 'restructuredtext' from zope.interface import Interface class IAnnotatable(Interface): """Marker interface for objects that support storing annotations. This interface says "There exists an adapter to an IAnnotations for an object that implements `IAnnotatable`". Classes should not directly declare that they implement this interface. Instead they should implement an interface derived from this one, which details how the annotations are to be stored, such as `IAttributeAnnotatable`. """ class IAnnotations(IAnnotatable): """Stores arbitrary application data under package-unique keys. By "package-unique keys", we mean keys that are are unique by virtue of including the dotted name of a package as a prefix. A package name is used to limit the authority for picking names for a package to the people using that package. For example, when implementing annotations for storing Zope Dublin-Core meta-data, we use the key:: "zope.app.dublincore.ZopeDublinCore" """ def __nonzero__(): """Test whether there are any annotations """ def __getitem__(key): """Return the annotation stored under key. Raises KeyError if key not found. """ def get(key, default=None): """Return the annotation stored under key, or default if not found. """ def __setitem__(key, value): """Store annotation under key. In order to avoid key collisions, users of this interface must use their dotted package name as part of the key name. """ def __delitem__(key): """Removes the annotation stored under key. Raises a KeyError if the key is not found. """ class IAttributeAnnotatable(IAnnotatable): """Marker indicating that annotations can be stored on an attribute. This is a marker interface giving permission for an `IAnnotations` adapter to store data in an attribute named `__annotations__`. """ zope.annotation-3.6.0/src/zope/annotation/README.txt0000644000000000000000000001202312121566406020411 0ustar 00000000000000================== Object Annotations ================== This package provides a mechanism to store additional information about objects without need to modify object class. Annotation factories -------------------- There is more to document about annotations, but we'll just sketch out a scenario on how to use the annotation factory for now. This is one of the easiest ways to use annotations -- basically you can see them as persistent, writable adapters. First, let's make a persistent object we can create annotations for: >>> from zope import interface >>> class IFoo(interface.Interface): ... pass >>> from zope.annotation.interfaces import IAttributeAnnotatable >>> from persistent import Persistent >>> class Foo(Persistent): ... interface.implements(IFoo, IAttributeAnnotatable) We directly say that Foo implements IAttributeAnnotatable here. In practice this is often done in ZCML, using the `implements` subdirective of the `content` or `class` directive. Now let's create an annotation for this: >>> class IBar(interface.Interface): ... a = interface.Attribute('A') ... b = interface.Attribute('B') >>> from zope import component >>> class Bar(Persistent): ... interface.implements(IBar) ... component.adapts(IFoo) ... def __init__(self): ... self.a = 1 ... self.b = 2 Note that the annotation implementation does not expect any arguments to its `__init__`. Otherwise it's basically an adapter. Now, we'll register the annotation as an adapter. To do this we use the `factory` function provided by `zope.annotation`: >>> from zope.annotation import factory >>> component.provideAdapter(factory(Bar)) Note that we do not need to specify what the adapter provides or what it adapts - we already do this on the annotation class itself. Now let's make an instance of `Foo`, and make an annotation for it. >>> foo = Foo() >>> bar = IBar(foo) >>> bar.a 1 >>> bar.b 2 We'll change `a` and get the annotation again. Our change is still there: >>> bar.a = 3 >>> IBar(foo).a 3 Of course it's still different for another instance of `Foo`: >>> foo2 = Foo() >>> IBar(foo2).a 1 What if our annotation does not provide what it adapts with `component.adapts`? It will complain: >>> class IQux(interface.Interface): ... pass >>> class Qux(Persistent): ... interface.implements(IQux) >>> component.provideAdapter(factory(Qux)) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Missing 'zope.component.adapts' on annotation It's possible to provide an annotation with an explicit key. (If the key is not supplied, the key is deduced from the annotation's dotted name, provided it is a class.) >>> class IHoi(interface.Interface): ... pass >>> class Hoi(Persistent): ... interface.implements(IHoi) ... component.adapts(IFoo) >>> component.provideAdapter(factory(Hoi, 'my.unique.key')) >>> isinstance(IHoi(foo), Hoi) True Location -------- Annotation factories are put into the location hierarchy with their parent pointing to the annotated object and the name to the dotted name of the annotation's class (or the name the adapter was registered under): >>> foo3 = Foo() >>> new_hoi = IHoi(foo3) >>> new_hoi.__parent__ >>> new_hoi.__name__ 'my.unique.key' >>> import zope.location.interfaces >>> zope.location.interfaces.ILocation.providedBy(new_hoi) True Please notice, that our Hoi object does not implement ILocation, so a location proxy will be used. This has to be re-established every time we retrieve the object (Guard against former bug: proxy wasn't established when the annotation existed already.) >>> old_hoi = IHoi(foo3) >>> old_hoi.__parent__ >>> old_hoi.__name__ 'my.unique.key' >>> zope.location.interfaces.ILocation.providedBy(old_hoi) True LocationProxies --------------- Suppose your annotation proxy provides ILocation. >>> class IPolloi(interface.Interface): ... pass >>> class Polloi(Persistent): ... interface.implements(IPolloi, zope.location.interfaces.ILocation) ... component.adapts(IFoo) ... __name__ = __parent__ = 0 >>> component.provideAdapter(factory(Polloi, 'my.other.key')) Sometimes you're adapting an object wrapped in a LocationProxy. >>> foo4 = Foo() >>> import zope.location.location >>> wrapped_foo4 = zope.location.location.LocationProxy(foo4, None, 'foo4') >>> located_polloi = IPolloi(wrapped_foo4) At first glance it looks as if located_polloi is located under wrapped_foo4. >>> located_polloi.__parent__ is wrapped_foo4 True >>> located_polloi.__name__ 'my.other.key' but that's because we received a LocationProxy >>> print type(located_polloi).__name__ LocationProxy If we unwrap located_polloi and look at it directly, we'll see it stores a reference to the real Foo object >>> from zope.proxy import removeAllProxies >>> removeAllProxies(located_polloi).__parent__ is foo4 True >>> removeAllProxies(located_polloi).__name__ 'my.other.key' zope.annotation-3.6.0/src/zope/annotation/tests/__init__.py0000644000000000000000000000001712121566404022164 0ustar 00000000000000# Import this. zope.annotation-3.6.0/src/zope/annotation/tests/annotations.py0000644000000000000000000000522712121566404022772 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 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. # ############################################################################## """General Annotations Tests All objects implementing 'IAnnotations' should pass these tests. They might be used as base tests for real implementations. $Id: annotations.py 126741 2012-06-11 17:44:56Z tseaver $ """ import unittest from zope.interface.verify import verifyObject from zope.annotation.interfaces import IAnnotations class AnnotationsTest(unittest.TestCase): """Test the IAnnotations interface. The test case class expects the 'IAnnotations' implementer to be in 'self.annotations'. """ def setUp(self): self.obj = {1:2, 3:4} def test_nonzero(self): self.failIf(self.annotations) self.annotations['unittest'] = self.obj self.failUnless(self.annotations) del self.annotations['unittest'] self.failIf(self.annotations) def testInterfaceVerifies(self): verifyObject(IAnnotations, self.annotations) def testStorage(self): # test __getitem__ self.annotations['unittest'] = self.obj res = self.annotations['unittest'] self.failUnlessEqual(self.obj, res) def testGetitemException(self): # test __getitem__ raises exception on unknown key self.assertRaises(KeyError, self.annotations.__getitem__,'randomkey') def testGet(self): # test get self.annotations['unittest'] = self.obj res = self.annotations.get('unittest') self.failUnlessEqual(self.obj, res) def testGetNoSet(self): # test get with no set res = self.annotations.get('randomkey') self.failUnlessEqual(None, res) def testGetDefault(self): # test get returns default res = self.annotations.get('randomkey', 'default') self.failUnlessEqual('default', res) def testDel(self): self.annotations['unittest'] = self.obj del self.annotations['unittest'] self.failUnlessEqual(None, self.annotations.get('unittest')) def testDelRaisesKeyError(self): self.assertRaises(KeyError, self.annotations.__delitem__, 'unittest') zope.annotation-3.6.0/src/zope/annotation/tests/test_attributeannotations.py0000644000000000000000000000342512121566404025753 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 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. # ############################################################################## """Tests the 'AttributeAnnotations' adapter. Also test the annotation factory. $Id: test_attributeannotations.py 126741 2012-06-11 17:44:56Z tseaver $ """ import unittest, doctest from zope.testing import cleanup from zope.interface import implements from zope import component from zope.annotation.tests.annotations import AnnotationsTest from zope.annotation.attribute import AttributeAnnotations from zope.annotation.interfaces import IAttributeAnnotatable class Dummy(object): implements(IAttributeAnnotatable) class AttributeAnnotationsTest(AnnotationsTest, cleanup.CleanUp): def setUp(self): self.annotations = AttributeAnnotations(Dummy()) super(AttributeAnnotationsTest, self).setUp() def setUp(test=None): cleanup.setUp() component.provideAdapter(AttributeAnnotations) def tearDown(test=None): cleanup.tearDown() def test_suite(): return unittest.TestSuite(( unittest.makeSuite(AttributeAnnotationsTest), doctest.DocFileSuite('../README.txt', setUp=setUp, tearDown=tearDown, optionflags=doctest.ELLIPSIS) )) if __name__=='__main__': unittest.main(defaultTest='test_suite') zope.annotation-3.6.0/src/zope.annotation.egg-info/dependency_links.txt0000644000000000000000000000000112121566626024460 0ustar 00000000000000 zope.annotation-3.6.0/src/zope.annotation.egg-info/namespace_packages.txt0000644000000000000000000000000512121566626024740 0ustar 00000000000000zope zope.annotation-3.6.0/src/zope.annotation.egg-info/not-zip-safe0000644000000000000000000000000112121566622022634 0ustar 00000000000000 zope.annotation-3.6.0/src/zope.annotation.egg-info/PKG-INFO0000644000000000000000000002063312121566626021513 0ustar 00000000000000Metadata-Version: 1.1 Name: zope.annotation Version: 3.6.0 Summary: Object annotation mechanism Home-page: http://pypi.python.org/pypi/zope.annotation Author: Zope Corporation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ================== Object Annotations ================== This package provides a mechanism to store additional information about objects without need to modify object class. Annotation factories -------------------- There is more to document about annotations, but we'll just sketch out a scenario on how to use the annotation factory for now. This is one of the easiest ways to use annotations -- basically you can see them as persistent, writable adapters. First, let's make a persistent object we can create annotations for: >>> from zope import interface >>> class IFoo(interface.Interface): ... pass >>> from zope.annotation.interfaces import IAttributeAnnotatable >>> from persistent import Persistent >>> class Foo(Persistent): ... interface.implements(IFoo, IAttributeAnnotatable) We directly say that Foo implements IAttributeAnnotatable here. In practice this is often done in ZCML, using the `implements` subdirective of the `content` or `class` directive. Now let's create an annotation for this: >>> class IBar(interface.Interface): ... a = interface.Attribute('A') ... b = interface.Attribute('B') >>> from zope import component >>> class Bar(Persistent): ... interface.implements(IBar) ... component.adapts(IFoo) ... def __init__(self): ... self.a = 1 ... self.b = 2 Note that the annotation implementation does not expect any arguments to its `__init__`. Otherwise it's basically an adapter. Now, we'll register the annotation as an adapter. To do this we use the `factory` function provided by `zope.annotation`: >>> from zope.annotation import factory >>> component.provideAdapter(factory(Bar)) Note that we do not need to specify what the adapter provides or what it adapts - we already do this on the annotation class itself. Now let's make an instance of `Foo`, and make an annotation for it. >>> foo = Foo() >>> bar = IBar(foo) >>> bar.a 1 >>> bar.b 2 We'll change `a` and get the annotation again. Our change is still there: >>> bar.a = 3 >>> IBar(foo).a 3 Of course it's still different for another instance of `Foo`: >>> foo2 = Foo() >>> IBar(foo2).a 1 What if our annotation does not provide what it adapts with `component.adapts`? It will complain: >>> class IQux(interface.Interface): ... pass >>> class Qux(Persistent): ... interface.implements(IQux) >>> component.provideAdapter(factory(Qux)) # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: Missing 'zope.component.adapts' on annotation It's possible to provide an annotation with an explicit key. (If the key is not supplied, the key is deduced from the annotation's dotted name, provided it is a class.) >>> class IHoi(interface.Interface): ... pass >>> class Hoi(Persistent): ... interface.implements(IHoi) ... component.adapts(IFoo) >>> component.provideAdapter(factory(Hoi, 'my.unique.key')) >>> isinstance(IHoi(foo), Hoi) True Location -------- Annotation factories are put into the location hierarchy with their parent pointing to the annotated object and the name to the dotted name of the annotation's class (or the name the adapter was registered under): >>> foo3 = Foo() >>> new_hoi = IHoi(foo3) >>> new_hoi.__parent__ >>> new_hoi.__name__ 'my.unique.key' >>> import zope.location.interfaces >>> zope.location.interfaces.ILocation.providedBy(new_hoi) True Please notice, that our Hoi object does not implement ILocation, so a location proxy will be used. This has to be re-established every time we retrieve the object (Guard against former bug: proxy wasn't established when the annotation existed already.) >>> old_hoi = IHoi(foo3) >>> old_hoi.__parent__ >>> old_hoi.__name__ 'my.unique.key' >>> zope.location.interfaces.ILocation.providedBy(old_hoi) True LocationProxies --------------- Suppose your annotation proxy provides ILocation. >>> class IPolloi(interface.Interface): ... pass >>> class Polloi(Persistent): ... interface.implements(IPolloi, zope.location.interfaces.ILocation) ... component.adapts(IFoo) ... __name__ = __parent__ = 0 >>> component.provideAdapter(factory(Polloi, 'my.other.key')) Sometimes you're adapting an object wrapped in a LocationProxy. >>> foo4 = Foo() >>> import zope.location.location >>> wrapped_foo4 = zope.location.location.LocationProxy(foo4, None, 'foo4') >>> located_polloi = IPolloi(wrapped_foo4) At first glance it looks as if located_polloi is located under wrapped_foo4. >>> located_polloi.__parent__ is wrapped_foo4 True >>> located_polloi.__name__ 'my.other.key' but that's because we received a LocationProxy >>> print type(located_polloi).__name__ LocationProxy If we unwrap located_polloi and look at it directly, we'll see it stores a reference to the real Foo object >>> from zope.proxy import removeAllProxies >>> removeAllProxies(located_polloi).__parent__ is foo4 True >>> removeAllProxies(located_polloi).__name__ 'my.other.key' ======= CHANGES ======= 3.6.0 (2013-03-18) ------------------ - Don't make AttributeAnnotations available as a view. 3.5.0 (2009-09-07) ------------------ - Add ZODB3 to install_requires, because it's a true requirement of this package, not just a testing requirement, as BTrees are in use. - Fix one test that was inactive because it's function was overriden by a mistake. 3.4.2 (2009-03-09) ------------------ - Clean up package description and documentation a bit. - Change mailing list address to zope-dev at zope.org, as zope3-dev at zope.org is now retired. - Remove old zpkg-related files. 3.4.1 (2008-08-26) ------------------ - Annotation factories take care not to store proxies in the database, so adapting an object wrapped in a ``LocationProxy`` works correctly. Fixes https://bugs.launchpad.net/zope3/+bug/261620 3.4.0 (2007-08-29) ------------------ - Annotation factories are no longer containing the factored object. Instead the objects are located using ``zope.location``. This removes a dependency to ``zope.app.container``. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable 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: Topic :: Software Development zope.annotation-3.6.0/src/zope.annotation.egg-info/requires.txt0000644000000000000000000000013412121566626023010 0ustar 00000000000000setuptools zope.interface zope.component zope.location zope.proxy ZODB3 [test] zope.testingzope.annotation-3.6.0/src/zope.annotation.egg-info/SOURCES.txt0000644000000000000000000000134612121566626022302 0ustar 00000000000000CHANGES.txt COPYRIGHT.txt LICENSE.txt README.txt bootstrap.py buildout.cfg setup.py src/zope/__init__.py src/zope.annotation.egg-info/PKG-INFO src/zope.annotation.egg-info/SOURCES.txt src/zope.annotation.egg-info/dependency_links.txt src/zope.annotation.egg-info/namespace_packages.txt src/zope.annotation.egg-info/not-zip-safe src/zope.annotation.egg-info/requires.txt src/zope.annotation.egg-info/top_level.txt src/zope/annotation/README.txt src/zope/annotation/__init__.py src/zope/annotation/attribute.py src/zope/annotation/configure.zcml src/zope/annotation/factory.py src/zope/annotation/interfaces.py src/zope/annotation/tests/__init__.py src/zope/annotation/tests/annotations.py src/zope/annotation/tests/test_attributeannotations.pyzope.annotation-3.6.0/src/zope.annotation.egg-info/top_level.txt0000644000000000000000000000000512121566626023137 0ustar 00000000000000zope