def contained(obj, parent=None, name=None):
    """An implementation of zope.app.container.contained.contained
    that doesn't generate events, for internal use.

    copied from SQLOS / z3c.zalchemy
    """
    if (parent is None):
        raise TypeError('Must provide a parent')

    if not IContained.providedBy(obj):
        if ILocation.providedBy(obj):
            interface.directlyProvides(obj, IContained,
                                       interface.directlyProvidedBy(obj))
        else:
            obj = ContainedProxy(obj)

    oldparent = obj.__parent__
    oldname = obj.__name__

    if (oldparent is None) or not (oldparent is parent
                                   or sameProxiedObjects(oldparent, parent)):
        obj.__parent__ = parent

    if oldname != name and name is not None:
        obj.__name__ = name

    return obj
Exemple #2
0
def containedEvent(object, container, name=None):
    """Establish the containment of the object in the container

    The object and necessary event are returned. The object may be a
    `ContainedProxy` around the original object. The event is an added
    event, a moved event, or None.

    If the object implements `IContained`, simply set its `__parent__`
    and `__name__` attributes:

        >>> container = {}
        >>> item = Contained()
        >>> x, event = containedEvent(item, container, u'foo')
        >>> x is item
        True
        >>> item.__parent__ is container
        True
        >>> item.__name__
        u'foo'

    We have an added event:

        >>> event.__class__.__name__
        'ObjectAddedEvent'
        >>> event.object is item
        True
        >>> event.newParent is container
        True
        >>> event.newName
        u'foo'
        >>> event.oldParent
        >>> event.oldName

    Now if we call contained again:

        >>> x2, event = containedEvent(item, container, u'foo')
        >>> x2 is item
        True
        >>> item.__parent__ is container
        True
        >>> item.__name__
        u'foo'

    We don't get a new added event:

        >>> event

    If the object already had a parent but the parent or name was
    different, we get a moved event:

        >>> x, event = containedEvent(item, container, u'foo2')
        >>> event.__class__.__name__
        'ObjectMovedEvent'
        >>> event.object is item
        True
        >>> event.newParent is container
        True
        >>> event.newName
        u'foo2'
        >>> event.oldParent is container
        True
        >>> event.oldName
        u'foo'

    If the `object` implements `ILocation`, but not `IContained`, set it's
    `__parent__` and `__name__` attributes *and* declare that it
    implements `IContained`:

        >>> from zope.app.location import Location
        >>> item = Location()
        >>> IContained.providedBy(item)
        False
        >>> x, event = containedEvent(item, container, 'foo')
        >>> x is item
        True
        >>> item.__parent__ is container
        True
        >>> item.__name__
        'foo'
        >>> IContained.providedBy(item)
        True


    If the `object` doesn't even implement `ILocation`, put a
    `ContainedProxy` around it:

        >>> item = []
        >>> x, event = containedEvent(item, container, 'foo')
        >>> x is item
        False
        >>> x.__parent__ is container
        True
        >>> x.__name__
        'foo'

    Make sure we don't lose existing directly provided interfaces.

        >>> from zope.interface import Interface, directlyProvides
        >>> class IOther(Interface):
        ...     pass
        >>> from zope.app.location import Location
        >>> item = Location()
        >>> directlyProvides(item, IOther)
        >>> IOther.providedBy(item)
        True
        >>> x, event = containedEvent(item, container, 'foo')
        >>> IOther.providedBy(item)
        True
    """

    if not IContained.providedBy(object):
        if ILocation.providedBy(object):
            zope.interface.directlyProvides(
                object, IContained,
                zope.interface.directlyProvidedBy(object))
        else:
            object = ContainedProxy(object)

    oldparent = object.__parent__
    oldname = object.__name__

    if oldparent is container and oldname == name:
        # No events
        return object, None

    object.__parent__ = container
    object.__name__ = name

    if oldparent is None or oldname is None:
        event = ObjectAddedEvent(object, container, name)
    else:
        event = ObjectMovedEvent(object, oldparent, oldname, container, name)

    return object, event