/usr/share/pyshared/zope/principalannotation/README.txt is in python-zope.principalannotation 3.6.1-0ubuntu4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | =====================
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)
<zope.principalannotation.utility.Annotations object at 0x...>
Or using principal id::
>>> util.getAnnotationsById(nadako.id)
<zope.principalannotation.utility.Annotations object at 0x...>
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
<zope.principalannotation.utility.Annotations object at 0x...>
>>> 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
|