{"id":10371,"library":"zope-site","title":"Zope Site","description":"zope.site is a foundational Python library that provides local registries for the Zope Component Architecture (ZCA). It enables the creation and retrieval of localized component managers (site managers) for specific object contexts, allowing components to be registered and looked up dynamically based on their position in an object hierarchy. The current version is 6.0, and its release cadence is tied to the broader Zope ecosystem.","status":"active","version":"6.0","language":"en","source_language":"en","source_url":"https://github.com/zopefoundation/zope.site","tags":["zope","component-architecture","zca","registry","dependency-injection"],"install":[{"cmd":"pip install zope.site","lang":"bash","label":"Install zope.site"}],"dependencies":[{"reason":"Provides the core component architecture for registration and lookup.","package":"zope.component"},{"reason":"Required for defining interfaces and implementing them for ZCA objects.","package":"zope.interface"},{"reason":"Provides the Located base class, useful for context objects that host local sites.","package":"zope.location"}],"imports":[{"note":"`provideSite` resides within the `site` submodule, not directly under `zope.site`.","wrong":"from zope.site import provideSite","symbol":"provideSite","correct":"from zope.site.site import provideSite"},{"note":"`getSiteManager` is also in the `site` submodule.","wrong":"from zope.site import getSiteManager","symbol":"getSiteManager","correct":"from zope.site.site import getSiteManager"},{"note":"Used if you need to directly interact with the local site manager class, less common for basic usage.","symbol":"LocalSiteManager","correct":"from zope.site.site import LocalSiteManager"}],"quickstart":{"code":"import zope.component\nimport zope.interface\nimport zope.site.site\nfrom zope.location import Located\n\n# 1. Define an interface for your context and services\nclass IMyContext(zope.interface.Interface):\n    \"\"\"An interface for objects that can serve as local site contexts.\"\"\"\n\nclass IMyService(zope.interface.Interface):\n    \"\"\"An interface for a service.\"\"\"\n\n# 2. Implement the context and service\n@zope.interface.implementer(IMyContext)\nclass MyContext(Located): # Inherit from Located for Zope site integration\n    \"\"\"A sample context object that can host a local site.\"\"\"\n    def __init__(self, name=\"Default\"):\n        self.name = name\n\n@zope.interface.implementer(IMyService)\nclass MyService:\n    \"\"\"A sample service implementation.\"\"\"\n    def __init__(self, name):\n        self.name = name\n    def __repr__(self):\n        return f\"<MyService: {self.name}>\"\n\n# 3. Register a global service\nprint(\"--- Global Scope ---\")\nzope.component.provideUtility(IMyService, MyService(\"Global Service\"), name=\"shared_service\")\nprint(f\"Globally available: {zope.component.getUtility(IMyService, name='shared_service')}\")\n\n# 4. Create a context instance and establish a local site\ncontext_a = MyContext(\"Context A\")\nprint(f\"\\n--- Inside Local Site for {context_a.name} ---\")\nwith zope.site.site.provideSite(context_a):\n    # Register a service locally for Context A\n    zope.component.provideUtility(IMyService, MyService(\"Local Service A\"), name=\"my_local_service\")\n    print(f\"Local to {context_a.name}: {zope.component.getUtility(IMyService, name='my_local_service')}\")\n    # Global service is still accessible\n    print(f\"Global from {context_a.name}: {zope.component.getUtility(IMyService, name='shared_service')}\")\n\n# 5. Create another context and establish a different local site\ncontext_b = MyContext(\"Context B\")\nprint(f\"\\n--- Inside Local Site for {context_b.name} ---\")\nwith zope.site.site.provideSite(context_b):\n    # Register a service locally for Context B (different from Context A's local service)\n    zope.component.provideUtility(IMyService, MyService(\"Local Service B\"), name=\"my_local_service\")\n    print(f\"Local to {context_b.name}: {zope.component.getUtility(IMyService, name='my_local_service')}\")\n    # Global service is still accessible\n    print(f\"Global from {context_b.name}: {zope.component.getUtility(IMyService, name='shared_service')}\")\n\n# 6. Outside any local site\nprint(\"\\n--- Outside any Local Site ---\")\ntry:\n    # Attempting to access a local service will fail\n    zope.component.getUtility(IMyService, name=\"my_local_service\")\nexcept zope.component.ComponentLookupError as e:\n    print(f\"Error: {e} (local service not available globally)\")\n\nprint(f\"Globally available: {zope.component.getUtility(IMyService, name='shared_service')}\")","lang":"python","description":"This quickstart demonstrates how to use `zope.site.site.provideSite` to establish local component registries for different contexts. It shows how local registrations are isolated to their respective sites, while global registrations remain accessible from within local sites. Note the use of `zope.location.Located` for context objects, which is common in Zope applications."},"warnings":[{"fix":"Ensure your project runs on Python 3.9 or newer. Upgrade your Python environment if necessary.","message":"`zope.site` dropped support for Python 3.7 and 3.8 in version 6.0.","severity":"breaking","affected_versions":"6.0+"},{"fix":"Always remember that `provideSite` creates a temporary, localized scope for ZCA registrations. If a component needs to be accessible globally, register it before entering any local site context.","message":"Registrations made within a `provideSite` context manager block are local to that site and do not persist globally or outside that specific context.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Be mindful of component naming and interface usage across global and local scopes. Ensure that local components either provide unique interfaces/names or are intended to override global ones within their specific context.","message":"When looking up components using `zope.component.getUtility` (or similar) within a local site, the lookup order is local registry first, then the global registry. This can lead to unexpected behavior if a component is registered globally and then also locally with the same name/interface.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use `from zope.site.site import provideSite` instead of `from zope.site import provideSite` to avoid `ImportError`.","message":"The `provideSite` function (and other core site-related utilities) is located in the `zope.site.site` submodule, not directly in `zope.site`.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Ensure that operations requiring a local site manager are performed within a `with provideSite(context):` block. Local registrations are temporary for the duration of this block.","cause":"Attempting to register or look up a component locally without an active site manager context, or trying to access a local component outside the `provideSite` block.","error":"zope.component.ComponentLookupError: The object has no component site.\n    I tried to look up a local component site for\n    <__main__.MyContext object at 0x...>"},{"fix":"Correct the import statement to `from zope.site.site import provideSite`.","cause":"`provideSite` is not directly exposed by the `zope.site` package's `__init__.py`.","error":"ImportError: cannot import name 'provideSite' from 'zope.site' (path_to_zope_site/__init__.py)"},{"fix":"Ensure a site is active. For local sites, use `with provideSite(context):` which implicitly sets the site manager for the context. For global site managers, ensure `zope.component.setSite()` has been called if not using `provideSite`.","cause":"This error often occurs when `zope.component.getSiteManager()` is called when no site has been set (globally or locally), or when attempting to get the local site manager from a context that hasn't been properly provided with one.","error":"TypeError: 'NoneType' object has no attribute 'getSiteManager'"}]}