{"id":10374,"library":"zope-traversing","title":"Zope Traversing","description":"Zope Traversing (current version 6.0) provides a robust and extensible mechanism for resolving paths within an object hierarchy, common in Zope-based applications and web frameworks. It allows developers to define how objects are looked up by name or through adapters, enabling flexible URL dispatching and content navigation. It has a steady release cadence, typically releasing new major versions every few years, with minor releases and bug fixes more frequently.","status":"active","version":"6.0","language":"en","source_language":"en","source_url":"https://github.com/zopefoundation/zope.traversing","tags":["zope","traversal","hierarchy","url-dispatch","path-resolution"],"install":[{"cmd":"pip install zope-traversing","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core Zope component for defining interfaces, central to Zope's object model and traversal contracts.","package":"zope.interface"},{"reason":"Provides __name__ and __parent__ attributes, which are fundamental for defining an object hierarchy that traversal operates on.","package":"zope.location"},{"reason":"Used for schema definitions, potentially for defining traversal-related configuration or data structures.","package":"zope.schema"}],"imports":[{"symbol":"traverse","correct":"from zope.traversing.api import traverse"},{"symbol":"ITraversable","correct":"from zope.traversing.interfaces import ITraversable"},{"symbol":"IPathAdapter","correct":"from zope.traversing.interfaces import IPathAdapter"},{"note":"The class AbsoluteURL was deprecated and removed in favor of the function absoluteURL in v4.0.","wrong":"from zope.traversing.browser import AbsoluteURL","symbol":"absoluteURL","correct":"from zope.traversing.browser import absoluteURL"}],"quickstart":{"code":"from zope.interface import implementer\nfrom zope.traversing.interfaces import ITraversable\nfrom zope.traversing.api import traverse\n\n# Define a simple traversable object (e.g., a Folder)\n@implementer(ITraversable)\nclass Folder:\n    def __init__(self, name, parent=None):\n        self.__name__ = name\n        self.__parent__ = parent\n        self.contents = {}\n\n    def __setitem__(self, name, item):\n        item.__name__ = name\n        item.__parent__ = self\n        self.contents[name] = item\n\n    def __getitem__(self, name):\n        if name in self.contents:\n            return self.contents[name]\n        raise KeyError(f\"No item named '{name}'\")\n\n    def traverse(self, name, furtherPath): # furtherPath is usually ignored for simple dict-like traversal\n        # Default traversal: look up in contents\n        return self.contents[name]\n\n    def __repr__(self):\n        return f\"<Folder '{self.__name__}'>\"\n\nclass Document:\n    def __init__(self, name, content=\"\", parent=None):\n        self.__name__ = name\n        self.__parent__ = parent\n        self.content = content\n\n    def __repr__(self):\n        return f\"<Document '{self.__name__}'>\"\n\n# Build a hierarchy\nroot = Folder('')\nproducts_folder = Folder('products')\nroot['products'] = products_folder\nproducts_folder['book1'] = Document('book1', \"The first book.\")\nproducts_folder['book2'] = Document('book2', \"The second book.\")\n\n# Traverse to an item\ntry:\n    item = traverse(root, 'products/book1')\n    print(f\"Found item at 'products/book1': {item}\")\n\n    # Attempt to traverse to a non-existent item\n    non_existent_item = traverse(root, 'products/nonexistent')\n    print(f\"Found non-existent item: {non_existent_item}\") # This line won't be reached\nexcept KeyError as e:\n    print(f\"Error traversing to 'products/nonexistent': {e} (expected behavior)\")\n\n# Traverse to a sub-path within an item if it also implements ITraversable\n# (not shown in this basic example for Document, but would work for nested Folders)\n","lang":"python","description":"This quickstart demonstrates how to define a simple object hierarchy using `ITraversable` and then navigate it using `zope.traversing.api.traverse`. It sets up a root folder containing sub-folders and documents, and shows how to retrieve an item by its path, as well as how `KeyError` (or `zope.traversing.interfaces.NotFound` in more complex setups) is raised for non-existent paths."},"warnings":[{"fix":"Upgrade your Python environment to 3.9 or newer, or pin your `zope-traversing` dependency to a version compatible with your Python (e.g., `<6.0` for Python 3.8).","message":"zope.traversing version 6.0 and higher require Python 3.9 or newer. Running on older Python versions will result in `ImportError` or `SyntaxError` depending on the exact Python features used by the package.","severity":"breaking","affected_versions":">=6.0"},{"fix":"Use the simpler utility function `zope.traversing.browser.absoluteURL` directly. This function now provides the same functionality without requiring interface implementation.","message":"The `zope.traversing.browser.AbsoluteURL` class and the `zope.traversing.browser.interfaces.IAbsoluteURL` interface were removed in version 4.0. Direct instantiation of `AbsoluteURL` or implementing `IAbsoluteURL` will no longer work.","severity":"deprecated","affected_versions":">=4.0"},{"fix":"Always explicitly handle cases where a name cannot be resolved in your `traverse` method by raising `KeyError` or a specific `NotFound` exception. For complex scenarios, consider using `zope.component.adapter` for `IPathAdapter` rather than implementing `ITraversable` directly on every object.","message":"When implementing custom traversal logic using `ITraversable` or `IPathAdapter`, incorrect handling of names or edge cases can lead to `KeyError`, `AttributeError`, or even infinite recursion if not carefully managed. Ensure your `traverse` method explicitly raises `KeyError` (or an appropriate `NotFound` exception) for unresolvable names.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Instead of `from zope.traversing.browser import AbsoluteURL`, use the utility function: `from zope.traversing.browser import absoluteURL`.","cause":"Attempting to import the `AbsoluteURL` class, which was deprecated and removed in `zope.traversing` version 4.0.","error":"ImportError: cannot import name 'AbsoluteURL' from 'zope.traversing.browser'"},{"fix":"Ensure you call `traverse` with both the root object and the path, e.g., `traverse(root_object, 'segment1/segment2')`.","cause":"The `zope.traversing.api.traverse` function requires at least two arguments: the object to start traversing from and the path string.","error":"TypeError: traverse() missing 1 required positional argument: 'path'"},{"fix":"This is often expected behavior. If it's not, verify the path string is correct, ensure the intermediate objects in the hierarchy are correctly set up and implement `ITraversable` (or have registered `IPathAdapter`s), and that the names exist within their respective containers.","cause":"The traversal mechanism (`ITraversable`'s `traverse` method or `IPathAdapter`) could not find an object matching the current path segment.","error":"KeyError: 'some_missing_name'"}]}