{"id":6951,"library":"zope-configuration","title":"Zope Configuration Markup Language (ZCML)","description":"zope.configuration provides the Zope Configuration Markup Language (ZCML), a declarative XML-based configuration system used extensively in the Zope and Plone ecosystems. It allows applications to register components, utilities, and services, defining application behavior and structure through XML directives. The current stable version is 7.1, with releases typically tied to Zope/Plone ecosystem needs and Python compatibility.","status":"active","version":"7.1","language":"en","source_language":"en","source_url":"https://github.com/zopefoundation/zope.configuration","tags":["zope","zcml","configuration","xml","component-architecture"],"install":[{"cmd":"pip install zope.configuration","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"note":"While technically correct, direct import is less common; 'from ... import ...' is preferred for specific symbols.","wrong":"import zope.configuration.xmlconfig","symbol":"xmlconfig","correct":"from zope.configuration import xmlconfig"},{"symbol":"ConfigurationContext","correct":"from zope.configuration.config import ConfigurationContext"},{"symbol":"ConfigurationError","correct":"from zope.configuration.exceptions import ConfigurationError"}],"quickstart":{"code":"import sys\nfrom zope.interface import Interface, implementer\nfrom zope.configuration import xmlconfig\nfrom zope.component import getUtility, ComponentLookupError\n\n# --- Step 1: Define an interface and an implementation ---\n# These would typically reside in a real Python module.\n# For this self-contained quickstart, we simulate a module.\nclass IMyService(Interface):\n    \"\"\"An interface for a dummy service.\"\"\"\n    def do_something():\n        \"\"\"Perform a dummy action.\"\"\"\n\n@implementer(IMyService)\nclass MyService:\n    \"\"\"A simple implementation of IMyService.\"\"\"\n    def do_something(self):\n        return \"Service action complete from ZCML!\"\n\n# Simulate a module for ZCML to find the classes\n# In a real application, 'quickstart_module' would be a package with your classes.\nclass DummyModule:\n    IMyService = IMyService\n    MyService = MyService\nsys.modules['quickstart_module'] = DummyModule\n\n# --- Step 2: Define a ZCML configuration string ---\nzcml_content = \"\"\"\n<configure\n    xmlns=\"http://namespaces.zope.org/zope\"\n    i18n_domain=\"my.package\">\n\n  <utility\n      factory=\"quickstart_module.MyService\"\n      provides=\"quickstart_module.IMyService\"\n      name=\"my.unique.service\"\n      />\n\n</configure>\n\"\"\"\n\n# --- Step 3: Load and process the ZCML configuration ---\ntry:\n    # xmlconfig.string processes the ZCML and registers components\n    context = xmlconfig.string(zcml_content)\n\n    # --- Step 4: Verify the utility was registered ---\n    service = getUtility(IMyService, name=\"my.unique.service\")\n    print(f\"Utility loaded successfully. Action: {service.do_something()}\")\nexcept ComponentLookupError:\n    print(\"Error: Utility not found after ZCML processing. Check ZCML registration.\")\nexcept Exception as e:\n    print(f\"An error occurred during ZCML loading: {e}\")\nfinally:\n    # Clean up the dummy module to avoid side effects in other tests/runs\n    if 'quickstart_module' in sys.modules:\n        del sys.modules['quickstart_module']\n","lang":"python","description":"Demonstrates how to load a ZCML string, register a utility (a common use case), and retrieve it using `zope.component`. This example simulates a Python module to allow ZCML to reference classes by dotted name, which is crucial for ZCML's operation. Note: `zope.interface` and `zope.component` are fundamental for ZCML's utility and component registration features."},"warnings":[{"fix":"Upgrade your Python environment to 3.10 or a newer compatible version.","message":"Python 3.10 or newer is now required. Older Python 3 versions (3.6-3.9) are no longer supported since version 7.0.","severity":"breaking","affected_versions":"7.0+"},{"fix":"Ensure the Python modules containing your classes/interfaces are correctly installed and on the `sys.path`, or for quickstarts/tests, temporarily add them to `sys.modules` as demonstrated in the quickstart.","message":"ZCML directives like `factory` and `provides` reference Python objects (classes, interfaces) by dotted names (e.g., `my.package.MyClass`). These objects must be discoverable and importable by Python's module system when ZCML is processed. If ZCML cannot find the referenced module or class, it will raise an `ImportError` or `ConfigurationError`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always include the default Zope namespace (`xmlns=\"http://namespaces.zope.org/zope\"`) and any specific namespaces for directives used from other packages (e.g., `xmlns:browser=\"http://namespaces.zope.org/browser\"`) in your `<configure>` tag or relevant directive tags.","message":"Missing or incorrect namespace declarations (`xmlns`, `xmlns:prefix`) in ZCML files can lead to directives not being recognized or parsing errors. Every ZCML file and every custom directive from another package needs its proper namespace declaration.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Be mindful of the order in which ZCML files are loaded (e.g., through `include` directives or programmatic loading) and how directives are declared. If you intend to override, ensure the overriding declaration comes after the original.","message":"The order of ZCML configuration matters. Later declarations can override earlier ones, particularly when registering utilities, adapters, or views with the same name/interface/for parameters. This can lead to unexpected behavior if not understood.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z","problems":[]}