Set custom configurations on a system level that your application can use ************************************************************************* :Author: Peter Bengtsson Certain properties are best stored persistently inside your application. Other properties are more appropriate to store on a "system" level. Purpose ======= You want to set a configuration variable that affects how your Grok application is running. Perhaps you have two instances running the same application on different servers. One which should log all emails sent through your application since you're doing some statistics or debugging and one where you want to leave it as is. One alternative is to set it as a persistent property inside the application itself as part of the ZODB but that would mean changes to the functionality or perhaps you feel that the configurations you want to set are a sys admins problem and not the application manager. Another alternative is to set environment variables in your system and then use ``os.environ`` to pick up the values but this is generally a bad idea since environment variables are difficult to "connect" to the application and it's really hard to tell if them have been set before your application starts. Step by step ============ First of all, the key is to use the file ``zope.conf`` in ``/parts/zopectl/`` **but** this file is autogenerated by buildout which means that if you make any changes to it (in fact, any changes inside ``parts/*``) you're likely to loose them the next time your run buildout. The ticket is to change the blueprint of your project: ``buildout.cfg``. By default it probably looks something like this:: [zopectl] recipe = zc.zope3recipes:instance application = app zope.conf = ${data:zconfig} This is your chance to add your own lines to go *into* ``zope.conf`` which goes on the next line like this:: [zopectl] recipe = zc.zope3recipes:instance application = app zope.conf = ${data:zconfig} debug-email-sending 1 dump-directory ${buildout:directory}/parts/dumps It might seem a little strange at first but is incredibly powerful and works well. Run buildout again and check for yourself that those extra lines were included by buildout by taking a look at ``parts/zopectl/zope.conf``. Now you can reach these inside your application and use as you please: .. code-block:: python from zope.app.appsetup.product import getProductConfiguration # see parts/zopectl/zope.conf config = getProductConfiguration('name_of_product_or_app') ... DEBUG_EMAIL_SENDING = config.get('debug-email-sending', False) DUMP_DIRECTORY = config.get('dump-directory', '/tmp/dumps') The function ``getProductConfiguration()`` will return ``None`` if there is no configuration under that name which means that you an ``AttributeError`` if you call ``.get()`` on it. So, if you envision that you might not set a configuration at all you should probably add these two lines so it looks like this: .. code-block:: python config = getProductConfiguration('name_of_product_or_app') if config is None: config = {} # config.get() below will return the default values Further information =================== At the time of writing this I can't find any documentation other than the `Zope 3 API doc `_ which is rather sparse. However, the syntax couldn't be easier to use. It's just a matter of remembering that this great tool is there. **EDIT** This how-to was rewritten after first publish by help of Philipp von Weitershausen. Thanks Philipp!