[Zope3-Users] Container Constraints

Jeff Shell eucci.group at gmail.com
Sat Dec 31 17:53:57 EST 2005

First - you can use ``from zope.app.container.constraints import
contains``. It's a bit easier to write.

Anyways, in Python you can't reference the class you're in because
that name, 'ILinkContainer' does not exist **until the end of the
class statement** (after all of the things indented within the class).

A common thing to do in Zope 3 to deal with this is to separate the
container / containment constraints into separate interfaces. This
gets around the issue stated above. It's also nice to use 'IContained'
to say an object is contained (IContained defines the fields
__parent__ and __name__), but if you use that as a base interface for
something with a schema you're likely to see extra fields when using
edit forms. So the container / containment constraints are usually put
in a separate interface. It's a bit of a separate policy. For your
situation, you may want to separate that into a separate marker
interface that is then implemented by both Link and LinkContainer

from zope.app.container.interfaces import IContainer, IContained
from zope.app.container.constraints import contains

class ILinkContainerContainable(IContained):
    """ Declare support for this to be stored in an ILinkContainer """

class ILinkContainer(IContainer):
    A container that can contain LinkContainerContainable objects,
like links and other
    link containers.
    # this does the same as the __setitem__.precondition stuff.

And then in implementation:

from zope.app.container.contained import Contained
from interfaces import ILinkContainer, ILinkContainerContainable, ILink

class Link(Persistent, Contained):
    implements(ILink, ILinkContainerContainable)

class LinkContainer(WhateverYourContainerRootMightBe):
    implements(ILinkContainer, ILinkContainerContainable)

Having this one interface, 'ILinkContainerContainable' (or whatever
you choose) then allows you to add other objects in the future that
could be contained, or you can have a RootLinkContainer that's a
special class that is an ILinkContainer but not containable so you
can't add it below the root:

class RootLinkContainer(AgainWithTheRootClass):
    # Picks up the link container constraints, but since it doesn't add
    # ILinkContainerContainable, it can't be added to other link containers.

But just remember - without special tricks, you can't refer to a class
while you're inside of it.

class Foo:
    any statement
    at this level
    can't access Foo

but this level can.

On 12/31/05, Marcus J. Ertl <marcus.ertl at larp-welt.de> wrote:
> Hi!
> I want to have container, witch should contain links and others
> containers of his own type! What I did is this in my interface-definition:
> class ILinkContainer(IContainer):
>     """Basic folder, containing only links and other link folders."""
>     def __setitem__(name, object):
>         """ Add an ITodo object. """
>     __setitem__.precondition = ItemTypePrecondition(ILink, ILinkContainer)
> But zope tells me:
> NameError: name 'ILinkContainer' is not defined
> I'm shure, he is right! It's a little bit of recursion at this place.
> But what to do?
> Creating a marker interface? Something like:
> class IMarker(IContainer):
>     """ ... """
> class ILinkContainer(IMarker):
>     """Basic folder, containing only links and other link folders."""
>     def __setitem__(name, object):
>         """ Add an ITodo object. """
>     __setitem__.precondition = ItemTypePrecondition(ILink, IMarker)
> Should work, but why creating a Interface "for nothing"? Must be a
> better way!
> And last but not least: Happy new Year!
> Bye
>    Marcus Ertl
> _______________________________________________
> Zope3-users mailing list
> Zope3-users at zope.org
> http://mail.zope.org/mailman/listinfo/zope3-users

More information about the Zope3-users mailing list