def getParent(obj): """Returns the container the object was traversed via. Returns None if the object is a containment root. Raises TypeError if the object doesn't have enough context to get the parent. """ try: location_info = ILocationInfo(obj) except TypeError: pass else: return location_info.getParent() # XXX Keep the old implementation as the fallback behaviour in the case # that obj doesn't have a location parent. This seems advisable as the # 'parent' is sometimes taken to mean the traversal parent, and the # __parent__ attribute is used for both. if IRoot.providedBy(obj): return None parent = getattr(obj, '__parent__', None) if parent is not None: return parent raise TypeError("Not enough context information to get parent", obj)
def getParent(obj): """ Returns the container the object was traversed via. See `ITraversalAPI` for details. """ try: location_info = ILocationInfo(obj) except TypeError: pass else: return location_info.getParent() # XXX Keep the old implementation as the fallback behaviour in the case # that obj doesn't have a location parent. This seems advisable as the # 'parent' is sometimes taken to mean the traversal parent, and the # __parent__ attribute is used for both. if IRoot.providedBy(obj): return None parent = getattr(obj, '__parent__', None) if parent is not None: return parent raise TypeError("Not enough context information to get parent", obj)
def __call__(self, *args, **kwargs): conn = self.get_connection() try: with transaction.manager: if 'oid' in kwargs and not 'context' in kwargs: oid = kwargs.pop('oid') kwargs['context'] = conn.get(oid) if 'context' in kwargs: location_info = ILocationInfo(kwargs['context']) setSite(location_info.getNearestSite()) return self.run(*args, **kwargs) except Exception as e: self.retry(exc=e)
def getName(obj): """ Get the name an object was traversed via. See `ITraversalAPI` for details. """ return ILocationInfo(obj).getName()
def getRoot(obj): """ Returns the root of the traversal for the given object. See `ITraversalAPI` for details. """ return ILocationInfo(obj).getRoot()
def traverse(self, path, default=_marker, request=None): if not path: return self.context if isinstance(path, six.string_types): path = path.split('/') if len(path) > 1 and not path[-1]: # Remove trailing slash path.pop() else: path = list(path) path.reverse() pop = path.pop curr = self.context if not path[-1]: # Start at the root pop() curr = ILocationInfo(self.context).getRoot() try: while path: name = pop() curr = traversePathElement(curr, name, path, request=request) return curr except LocationError: if default == _marker: raise return default
def getPath(obj): """ Returns a string representing the physical path to the object. See `ITraversalAPI` for details. """ return ILocationInfo(obj).getPath()
def getParents(obj): """ Returns a list starting with the given object's parent followed by each of its parents. See `ITraversalAPI` for details. """ return ILocationInfo(obj).getParents()
def getParents(obj): """Returns a list starting with the given object's parent followed by each of its parents. Raises a TypeError if the context doesn't go all the way down to a containment root. """ return ILocationInfo(obj).getParents()
def find_interface(resource, interface, strict=True): # pylint:disable=inconsistent-return-statements """ Given an object, find the first object in its lineage providing the given interface. This is similar to :func:`nti.traversal.location.find_interface`, but, as with :func:`resource_path` requires the strict adherence to the resource tree, unless ``strict`` is set to ``False``. :keyword bool strict: Deprecated. Do not use. Non-strict lineage is broken lineage. """ if not strict: return _p_find_interface(resource, interface) # pylint: disable=too-many-function-args lineage = ILocationInfo(resource).getParents() lineage.insert(0, resource) for item in lineage: if interface.providedBy(item): return item
def resource_path(res): # This function is somewhat more flexible than Pyramid's, and # also more strict. It requires strings (not None, for example) # and bottoms out at an IRoot. This helps us get things right. # It is probably also a bit slower. # Could probably use a __traceback_supplement__ for this _known_parents = [] # Ask for the parents; we do this instead of getPath() and url_quote # to work properly with unicode paths through the magic of pyramid loc_info = ILocationInfo(res) try: # pylint: disable=too-many-function-args parents = loc_info.getParents() except TypeError: # "Not enough context information to get all parents" # This is a programming/design error: some object is not where it # should be _known_parents.extend(LocationIterator(res)) logger.exception("Failed to get all parents of %r; known parents: %s", res, _known_parents) raise if parents: # Take the root off, it's implicit and has a name of None parents.pop() # Put it in the order pyramid expects, root first # (root is added only to the names to avoid prepending) parents.reverse() parents.append(res) # And let pyramid construct the URL, doing proper escaping and # also caching. names = [''] # Bottom out at the root for p in parents: name = p.__name__ if name is None: __traceback_info__ = p raise TypeError("Element in the hierarchy is missing __name__") names.append(name) return join_path_tuple(tuple(names))
def _visitSublocations(self) : """Restricts the access to the objects that live within the nearest site if the catalog itself is locatable. """ uidutil = None locatable = ILocationInfo(self, None) if locatable is not None : site = locatable.getNearestSite() sm = site.getSiteManager() uidutil = sm.queryUtility(IIntIds) if uidutil not in [c.component for c in sm.registeredUtilities()]: # we do not have a local inits utility uidutil = component.getUtility(IIntIds, context=self) for uid in uidutil: obj = uidutil.getObject(uid) if location.inside(obj, site) : yield uid, obj return if uidutil is None: uidutil = component.getUtility(IIntIds) for uid in uidutil: yield uid, uidutil.getObject(uid)
def annotate(self, txn, request, ob): """Set some useful meta-information on the transaction. This information is used by the undo framework, for example. """ if request.principal is not None: txn.setUser(request.principal.id) # Work around methods that are usually used for views bare = removeSecurityProxy(ob) if isinstance(bare, instancemethod): ob = bare.im_self # set the location path path = None location = ILocationInfo(ob, None) if location is not None: # Views are made children of their contexts, but that # doesn't necessarily mean that we can fully resolve the # path. E.g. the family tree of a resource cannot be # resolved completely, as the site manager is a dead end. try: path = location.getPath() except (AttributeError, TypeError): pass if path is not None: txn.setExtendedInfo('location', path) # set the request type iface = IRequest for iface in providedBy(request): if iface.extends(IRequest): break iface_dotted = '%s.%s' % (iface.__module__, iface.getName()) txn.setExtendedInfo('request_type', iface_dotted) return txn
def find_nearest_site(context, root=None, ignore=None): """ Find the nearest :class:`ISite` in the lineage of *context*. :param context: The object whose lineage to search. If this object cannot be adapted to `ILocationInfo`, then we attempt to adapt ``context.target`` and get its site; failing that, we return the *root*. :param ignore: If the `ILocationInfo` of the *context* can be retrieved, but the :meth:`.ILocationInfo.getNearestSite` cannot, then, if *ignore* is given, and *context* provides that interface, return the *root*. This makes no sense and is deprecated. :return: The nearest site. Possibly the root site. .. deprecated:: 1.0 Relying on the fallback to ``context.target`` and *root* is deprecated; the *ignore* parameter is deprecated. All of these things signal a broken resource tree. """ try: loc_info = ILocationInfo(context) except TypeError: # Not adaptable (not located). What about the target? try: # pylint: disable=too-many-function-args loc_info = ILocationInfo(context.target) warnings.warn( "Relying on ``context.target`` is deprecated. " "Register an ILocationInfo adapter for ``context`` instead.", FutureWarning, stacklevel=2 ) nearest_site = loc_info.getNearestSite() except (TypeError, AttributeError): # Nothing. Assume the main site/root nearest_site = root else: # Located. Better be able to get a site, otherwise we have a # broken chain. try: # pylint: disable=too-many-function-args nearest_site = loc_info.getNearestSite() except TypeError: # Convertible, but not located correctly. if ignore is None or not ignore.providedBy(context): raise warnings.warn( "The ignore argument is deprecated. " "Register an appropriate ILocationInfo instead.", FutureWarning, stacklevel=2 ) nearest_site = root return nearest_site
def test(self): zope.traversing.testing.setUp() root = Root() f1 = contained(C(), root, name='f1') f2 = contained(SiteManagerContainer(), f1, name='f2') f3 = contained(C(), f2, name='f3') adapter = ILocationInfo(f3) self.assertEqual(adapter.getPath(), '/f1/f2/f3') self.assertEqual(adapter.getName(), 'f3') self.assertEqual(adapter.getRoot(), root) self.assertEqual(adapter.getNearestSite(), root) f2.setSiteManager(LocalSiteManager(f2)) self.assertEqual(adapter.getNearestSite(), f2)
def getName(obj): """Get the name an object was traversed via """ return ILocationInfo(obj).getName()
def getPath(obj): """Returns a string representing the physical path to the object. """ return ILocationInfo(obj).getPath()
def getRoot(obj): """Returns the root of the traversal for the given object. """ return ILocationInfo(obj).getRoot()
def name(self): # This method is filter try: return ILocationInfo(self.context).getName() except TypeError: return u''