Stereotypes
===========
"Yes, they're stereotypes." - Blur
.;lxxo,
.lONWKkxXWd .;;.
.0M0' .OM0. ,O;;lx.
.0WkxKNWM0; .lc:cx' ,kl.
.:. 'NMNl..lKWK: .xWNx'
.:dONMK. :NWd :OX; 'OWXNNx'
.,lkKWMMMMMWk 'co.:NN: . .oNXl..ok, '.
.,cxKNMMMMMMNOo;..':dOXWWXc .. l:. 'dXNo. ,c :OWNk'
lWMMMMMWMMMMX' cOXMMWKxc' .x0l. l0o. dN' .cKMMXNWWx'
dWXxl,.OMMMMK.lWMM0, .'. .c. oolXx. :dl:dWc .cKMMXl..oNMNd.
' .0MMMMd lWMWdlOXWd .o0olXk' .,:lxKK: ;KMMMMXc. 'KMMx
.0MMMWc cNMMMXko, .cx, ;x:;kWW0cc0WWXo,,0MMk
.0MMMNc :NMMx .cxKX: .dNK; ,kNMMMMNd.
.lk0XNNXNMMMMN; :NMWx:dKWMMNOc .. .dXx' .;cc,.
.oNMMMMMMMMMMMMMX, cNMMMMXkl,. .oNMMMWk,
.kMMMWKkxkOKWMMMMMX, ;Oxc' .:KMMMNNMMW0c.
;WMMM0. .lXMMMNx. .lXMMMXl..dNMMMK;
'XMMMWk:. .oc,. cKMMMMMK: .oXMMW0:
:NMMMMMWKkc'. :0WMMWKNMMWKc. .lXMWO.
.o0WMMMMMMMNk:. .lKWMMNk, .dXMWk' .c,
.;lkKWMMMMM0. oNMMMMO. .:'
.,lc .c0MMMMk .dNMMMNd.
NMMMO. ;WMMMX. .oXMMMNo.
0WMMMNxl;,',;oKMMMWd .:OWMMXd'
c0WMMMMMMMMMMMMMNo 'xWMXc
,o0WMMMMMMMWXd. ,c.
.';ccc:;.
Master branch:
git+ssh://<username>@repo.or.cz/srv/git/stereotypes.git
http://repo.or.cz/r/stereotypes.git
See summary at:
http://repo.or.cz/w/stereotypes.git
Synopsis
--------
Stereotypes is a content framework for Zope 3. Its target application
is a content management system.
An abstracted storage layer makes it possible to use the framework
with an ORM as well as the ZODB.
The content model is based on schemas and containment, allowing
flexible and powerful modelling. A dynamic adaptation pattern is
introduced to simplify access to the storage layer.
Parts
-----
stereotypes.annotation
Storage implementation that uses annotations
Content types
-------------
Content schemas are defined using ``zope.interface`` and
``zope.schema``, allowing complete separation of model and storage.
Content types are comprised of schema mixins and may act as local
content containers.
As an example, consider a document and an event type. The document
derives from a standard Dublin Core metadata schema and declares that
it's a container for media content and attachments.
>>> class IDocument(IContainer, IDCDescriptiveProperties):
... text = zope.schema.Text(title=u"Document text")
... contains(IMedia, IAttachment)
>>> class IEvent(IDocument):
... location = zope.schema.TextLine(title=u"Venue location")
... date = zope.schema.Date(title=u"Date")
Technically, we can query the containment contraints via the
precondition value:
>>> IDocument['__setitem__'].getTaggedValue('precondition').types
(<InterfaceClass ...IMedia>,
<InterfaceClass ...IAttachment>)
To contrast containment, consider another example.
>>> class IPhotograph(IDCDescriptiveProperties, IImage):
... location = zope.schema.TextLine(title=u"Shoot location")
Here we inherit directly from ``IImage``, instead of declaring
containment. This content type requires that an image is provided.
Adapting a context to content
-----------------------------
Let's consider a web application where we have a homogenous object
hierarchy based on a general object class ``Page``.
We use dynamic adaptation to adapt our page to the schema (this is
implemented by the storage layer).
>>> document = IDocument(page)
This will let us read and write the attributes of a document.
>>> document.title = u"How to be a gardener"
>>> document.description = u"A complete online guide gardening for beginners."
Inversely, we can examine the content on a page:
>>> content = IContent(page)
>>> list(content)
[<Content providing IDocument at ...>]
If we adapt to a content schema that is a subset of an already defined
schema, we retrieve an object that is per-attribute equivalent.
>>> descriptive = IDCDescriptiveProperties(page)
>>> descriptive.title = document.title
True
This holds even if we modify an attribute on the first object.
>>> document.title = u"How to be a farmer"
>>> descriptive.title == document.title
True
Similarly, if we first ask for ``IDCDescriptiveProperties``, then
``IDocument``, the same equivalency pertains.
>>> document = IDocument(page)
>>> descriptive.title = u"How to be an astronaut"
>>> descriptive.title == document.title
True
Depending on the storage layer, content may be kept as annotations, or
in some other implementation-specific way.
Adding contained content
------------------------
Content classes may act as containers, and we can use the standard
dictionary syntax to add items.
>>> document['my-image'] = Image("sunset.jpg")
>>> document.values()
[<Image("sunset.jpg") at ...>]
If we try to add an item that does not meet the constraints, an
exception is raised.
>>> document['my-string'] = "Sunset"
Traceback (most recent call first)
...
TypeError: Disallowed type 'str'