From 7de404bb4af2744a64c13e31a780fc0229b8f9e5 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Mon, 7 Jul 2008 04:44:57 +0000 Subject: Look up a view after traversal; adapt it to IWSGIApplication. --- repoze/bfg/location.py | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 repoze/bfg/location.py (limited to 'repoze/bfg/location.py') diff --git a/repoze/bfg/location.py b/repoze/bfg/location.py new file mode 100644 index 000000000..37e5386b3 --- /dev/null +++ b/repoze/bfg/location.py @@ -0,0 +1,118 @@ +############################################################################## +# +# Copyright (c) 2003 Zope Corporation 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. +# +############################################################################## + +import zope.interface +from zope.proxy import ProxyBase +from zope.proxy import getProxiedObject +from zope.proxy import non_overridable +from zope.proxy.decorator import DecoratorSpecificationDescriptor +from repoze.bfg.interfaces import ILocation + +class Location(object): + """Stupid mix-in that defines `__parent__` and `__name__` attributes.""" + + zope.interface.implements(ILocation) + + __parent__ = __name__ = None + +def locate(object, parent, name=None): + """Locate an object in another + + This method should only be called from trusted code, because it + sets attributes that are normally unsettable. + """ + + object.__parent__ = parent + object.__name__ = name + + +def located(object, parent, name=None): + """Locate an object in another and return it. + + If the object does not provide ILocation a LocationProxy is returned. + + """ + if ILocation.providedBy(object): + if parent is not object.__parent__ or name != object.__name__: + locate(object, parent, name) + return object + return LocationProxy(object, parent, name) + + +def LocationIterator(object): + while object is not None: + yield object + object = getattr(object, '__parent__', None) + + +def inside(l1, l2): + """Is l1 inside l2 + + L1 is inside l2 if l2 is an ancestor of l1. + + """ + while l1 is not None: + if l1 is l2: + return True + l1 = l1.__parent__ + + return False + + +class ClassAndInstanceDescr(object): + + def __init__(self, *args): + self.funcs = args + + def __get__(self, inst, cls): + if inst is None: + return self.funcs[1](cls) + return self.funcs[0](inst) + + +class LocationProxy(ProxyBase): + """Location-object proxy + + This is a non-picklable proxy that can be put around objects that + don't implement `ILocation`. + + """ + + zope.interface.implements(ILocation) + + __slots__ = '__parent__', '__name__' + __safe_for_unpickling__ = True + + def __new__(self, ob, container=None, name=None): + return ProxyBase.__new__(self, ob) + + def __init__(self, ob, container=None, name=None): + ProxyBase.__init__(self, ob) + self.__parent__ = container + self.__name__ = name + + @non_overridable + def __reduce__(self, proto=None): + raise TypeError("Not picklable") + + + __doc__ = ClassAndInstanceDescr( + lambda inst: getProxiedObject(inst).__doc__, + lambda cls, __doc__ = __doc__: __doc__, + ) + + __reduce_ex__ = __reduce__ + + __providedBy__ = DecoratorSpecificationDescriptor() + -- cgit v1.2.3