{ "info": { "author": "Zope Community", "author_email": "zope-dev@zope.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Zope3", "Intended Audience :: Developers", "License :: OSI Approved :: Zope Public License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Topic :: Internet :: WWW/HTTP" ], "description": "This package provides a configurator which is designed to extend a component \nafter its creation for Zope3.\n\n\n.. contents::\n\n================\nThe Configurator\n================\n\nThe configurator is designed to extend a component after its\ncreation. Traditionally this is done by listening to ``ObjectCreatedEvent``\nevents. However, this low-level method does not suffice, since configuration\noften depends on other configuration steps and additional data is often needed\nto complete the configuration. And this is where the configurator comes\nin. It uses a separate plugin mechanism to implement the mentioned high-level\nfunctionality.\n\nBefore we can demonstrate the configuration mechanism, we'll have to create an\ninterface and a component on which the configuration can act upon:\n\n >>> import zope.interface\n\n >>> class ISomething(zope.interface.Interface):\n ... \"\"\"Some interesting interface.\"\"\"\n\n >>> @zope.interface.implementer(ISomething)\n ... class Something(object):\n ... \"\"\"Implementation of something.\"\"\"\n\n >>> something = Something()\n\nNow we can have the configuration act on the component:\n\n >>> from z3c import configurator\n >>> configurator.configure(something, {})\n\nThe second argument is the data dictionary, which can be used to pass in\nadditional information that might be needed during the configuration. It is up\nto each plugin to interpret the data.\n\nOf course nothing happens, since no configuration plugins are\nregistered. Let's now create a new configuration plugin, which sets a new\nattribute on the component:\n\n >>> import zope.component\n >>> from z3c.configurator import interfaces\n\n >>> class AddFooAttribute(configurator.ConfigurationPluginBase):\n ... zope.component.adapts(ISomething)\n ...\n ... def __call__(self, data):\n ... setattr(self.context, 'foo', data.get('foo'))\n\n >>> zope.component.provideAdapter(AddFooAttribute, name='add foo')\n\nIf we execute the configuration again, the attribute will be added:\n\n >>> configurator.configure(something, {'foo': u'my value'})\n >>> something.foo\n u'my value'\n\n\nDependencies\n------------\n\nNow that we have simple configuration plugins, we can also develop plugins\nthat depend on another one. Let's create a configuration plugin that adds some\nadditional data to the foo attribute. Clearly, the foo attribute has to exist\nbefore this step can be taken. The ``dependencies`` attribute can be used to\nspecify all plugin dependencies by name:\n\n >>> class ExtendFooAttribute(configurator.ConfigurationPluginBase):\n ... zope.component.adapts(ISomething)\n ... dependencies = ('add foo',)\n ...\n ... def __call__(self, data):\n ... self.context.foo = u'Text: ' + self.context.foo\n\n >>> zope.component.provideAdapter(ExtendFooAttribute, name='extend foo')\n\nIf we now execute the configuration again, the extended result should be seen:\n\n >>> something = Something()\n >>> configurator.configure(something, {'foo': u'my value'})\n >>> something.foo\n u'Text: my value'\n\n\nData Schemas\n------------\n\nFor purely informational purposes, a ``schema`` attribute is used on the\nplugin to describe the fields that the plugin expects from the data\ndictionary. For adding another simple attribute, this could look as follows:\n\n >>> import zope.schema\n >>> class IAddBar(zope.interface.Interface):\n ... bar = zope.schema.Text(title=u'Bar')\n\n >>> class AddBarAttribute(configurator.SchemaConfigurationPluginBase):\n ... zope.component.adapts(ISomething)\n ... schema = IAddBar\n ...\n ... def __call__(self, data):\n ... self.verify(data)\n ... setattr(self.context, 'bar', data.get('bar'))\n\n >>> zope.component.provideAdapter(AddBarAttribute, name='add bar')\n\nThe advantage of using the base class for this case is that it provides a\n``verify()`` method that allows you to verify the data against the shema. We\ncan now run the configuration again:\n\n >>> something = Something()\n >>> configurator.configure(something, {'foo': u'my value', 'bar': u'value'})\n >>> something.bar\n u'value'\n\nThe value must exist and be valid:\n\n >>> something = Something()\n >>> configurator.configure(something, {'foo': u'my value'})\n Traceback (most recent call last):\n ...\n RequiredMissing: bar\n\n >>> something = Something()\n >>> configurator.configure(something, {'foo': u'my value', 'bar': 1})\n Traceback (most recent call last):\n ...\n WrongType: (1, , 'bar')\n\n\nData Namespaces\n---------------\n\nIn order to not confuse attribute names if two plugins share a common\nname it is possible to pass data as a dictionary of dictionaries. The\nkeys of the dictionary is the name under which the plugins are\nregistered.\n\n >>> something = Something()\n >>> data = {u'add foo': {'foo': u'foo value'},\n ... u'add bar': {'bar': u'bar value'}}\n >>> configurator.configure(something, data, useNameSpaces=True)\n >>> something.foo, something.bar\n (u'Text: foo value', u'bar value')\n\nNamed Configuration\n-------------------\n\nSometimes we do not want all registered configuration plugins to be\nexecuted. This can be achieved by providing the names argument to the\nconfigure function.\n\nLet us create a new something:\n\n >>> something = Something()\n\nIf we now configure it without names we get both attributes set.\n\n >>> configurator.configure(something, {'foo': u'my value', 'bar': u'asdf'})\n >>> sorted(something.__dict__.items())\n [('bar', 'asdf'), ('foo', 'Text: my value')]\n\nNow let us just configure the plugin 'add bar'.\n\n >>> something = Something()\n >>> configurator.configure(something, {'foo': u'my value', 'bar': u'asdf'},\n ... names=['add bar'])\n >>> something.__dict__\n {'bar': u'asdf'}\n\nDependencies of plugins are always executed - they don't have to be\nadded to the ```names``` argument.\n\n >>> something = Something()\n >>> configurator.configure(something, {'foo': u'my value'},\n ... names=['extend foo'])\n >>> something.foo\n u'Text: my value'\n\nNamed configurations are usefull when called manually through the web\n(see browser/README.txt). The configurator package does not look if a\nconfiguration is already applied if called twice. It is the\nresponsibility of the plugin to be aware that it doesn't do things\ntwice or delete things.\n\n\nWrong Implementations\n---------------------\n\nA configurator must provide a __call__ method.\n\n >>> class CallNotImplemented(configurator.ConfigurationPluginBase):\n ... zope.component.adapts(ISomething)\n >>> zope.component.provideAdapter(CallNotImplemented, name='no call')\n\n >>> configurator.configure(something, None, names=['no call'])\n Traceback (most recent call last):\n ...\n NotImplementedError\n\nThe same must happen for a schema base configurator.\n\n >>> class SchemaCallNotImplemented(configurator.SchemaConfigurationPluginBase):\n ... zope.component.adapts(ISomething)\n >>> zope.component.provideAdapter(SchemaCallNotImplemented, name='schema no call')\n\n >>> configurator.configure(something, None, names=['schema no call'])\n Traceback (most recent call last):\n ...\n NotImplementedError\n\n\nNo Recursion\n------------\n\nIt's possible to define recursive dependencies without to run into recursion \nerrors. Let's define a new plugin free object:\n\n >>> class IFoo(zope.interface.Interface):\n ... \"\"\"Just a foo interface.\"\"\"\n\n >>> @zope.interface.implementer(IFoo)\n ... class Foo(object):\n ... \"\"\"Implementation of foo.\"\"\"\n\nLet's define another plugin named `first` which depends on a plugin named \n`second`.\n\n >>> log = []\n >>> class FirstPlugin(configurator.ConfigurationPluginBase):\n ... zope.component.adapts(IFoo)\n ... dependencies = ('second',)\n ...\n ... def __call__(self, data):\n ... log.append('FirstPlugin called')\n\n >>> zope.component.provideAdapter(FirstPlugin, name='first')\n\nAnd define a plugin named `second` which depends on `first`:\n\n >>> class SecondPlugin(configurator.ConfigurationPluginBase):\n ... zope.component.adapts(IFoo)\n ... dependencies = ('first',)\n ...\n ... def __call__(self, data):\n ... log.append('SecondPlugin called')\n\n >>> zope.component.provideAdapter(SecondPlugin, name='second')\n\n >>> foo = Foo()\n >>> configurator.configure(foo, {})\n >>> for msg in sorted(log): print(msg)\n FirstPlugin called\n SecondPlugin called\n\n\n=========================\nCalling Configurators TTW\n=========================\n\nA configuration view is registered to apply named configuration on any\nobject. We defined two example configurators which we now gonna apply\nto the site object.\n\n >>> from zope.testbrowser.testing import Browser\n >>> browser = Browser()\n >>> browser.addHeader('Authorization','Basic mgr:mgrpw')\n >>> browser.handleErrors = False\n\n >>> browser.open('http://localhost/manage')\n >>> browser.url\n 'http://localhost/@@contents.html'\n\nThe view is registered in the zmi_views menu\n\n >>> browser.getLink(u'Configurators').click()\n >>> viewURL = browser.url\n >>> viewURL\n 'http://localhost/@@configurators.html'\n\n >>> sel = browser.getControl(name=\"form.pluginNames.to\")\n\nFirst we can choose from the registered named plugins.\n\n >>> plugs = browser.getControl(name=\"form.pluginNames.from\").options\n >>> sorted(plugs)\n ['z3c.configurator.testing.setdescription',\n 'z3c.configurator.testing.settitle']\n >>> browser.open(viewURL + '?form.pluginNames=z3c.configurator.testing.settitle')\n\nWe have choosen a plugin, so now we have a form for the arguments needed.\n\n >>> browser.getControl('Some Argument').value\n ''\n >>> browser.getControl('Some Argument').value = \"New Title\"\n >>> browser.getControl('Apply').click()\n\n\nXXX form.pluginNames have to be set, but we can't because the widget\nuses javascript.\n\n\n\n\n=======\nCHANGES\n=======\n\n\n2.0.0 (2015-11-09)\n------------------\n\n- Standardize namespace __init__\n\n\n2.0.0a1 (2013-03-04)\n--------------------\n\n- Added support for Python 3.3, dropped support for Python 2.4 and 2.5.\n\n\n1.3.0 (2010-12-12)\n------------------\n\n- Updated test set up to run with ZTK 1.0.\n\n\nVersion 1.2.1 (2009-12-27)\n--------------------------\n\n- Moved browser dependencies to 'zmi' extras\n\n\nVersion 1.2.0 (2009-12-19)\n--------------------------\n\n- Made registration of browser views conditional\n\n- Move packages required for testing to 'test' extras\n\n- Remove old zpkg-related SETUP.cfg file.\n\n- Copyright \"Zope Foundation and Contributors\"\n\n\nVersion 1.1.2 (2009-01-04)\n--------------------------\n\n- Added possibility to apply only specific named plugins in configure.\n\n- New option to configure allows to have namespaced data to resolve\n naming conflicts.\n\n- Added a page to call configurators TTW. This is the first step\n towards mergin z3c.configurator and z3c.sampledata into one package.\n\n- Added documentation to Pypi home page.\n\n- bugfix: Defining recursive dependent names in IConfigurationPlugin\n dependencies, ends in recursive plugin lookup.\n\n- bugfix: SchemaConfigurationPluginBase now implements\n ISchemaConfigurationPluginBase.\n\n\nVersion 1.1.1 (unknown)\n-----------------------\n\n- Initial Release", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://pypi.python.org/pypi/z3c.configurator", "keywords": "zope3 z3c configurator configuration", "license": "ZPL 2.1", "maintainer": null, "maintainer_email": null, "name": "z3c.configurator", "package_url": "https://pypi.org/project/z3c.configurator/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/z3c.configurator/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://pypi.python.org/pypi/z3c.configurator" }, "release_url": "https://pypi.org/project/z3c.configurator/2.0.0/", "requires_dist": null, "requires_python": null, "summary": "Dynamic configuration", "version": "2.0.0" }, "last_serial": 1808172, "releases": { "1.1.1": [ { "comment_text": "", "digests": { "md5": "4977e11ec9213ed31da98ee449e4daad", "sha256": "f3a16ac098f6dc9c581e41b3f78a0a62f4262979bb5beaf56cc27da0507cd435" }, "downloads": -1, "filename": "z3c.configurator-1.1.1.zip", "has_sig": false, "md5_digest": "4977e11ec9213ed31da98ee449e4daad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22239, "upload_time": "2008-05-07T14:38:22", "url": "https://files.pythonhosted.org/packages/0e/80/46a5c956654d907402900dbfb6a18f797a79a6052b2b5d7547204e7d8b93/z3c.configurator-1.1.1.zip" } ], "1.1.2": [ { "comment_text": "", "digests": { "md5": "07ad807c74173e888ddb55e1ae806692", "sha256": "cc0099820384bdab9b708675774c098b4e9f70a2135ac3429e561f8901a59373" }, "downloads": -1, "filename": "z3c.configurator-1.1.2.tar.gz", "has_sig": false, "md5_digest": "07ad807c74173e888ddb55e1ae806692", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19379, "upload_time": "2009-01-04T21:21:32", "url": "https://files.pythonhosted.org/packages/cd/ff/e726d86eb636315839cadabaced0a31c209d58f68569adfb0e6e8506b27e/z3c.configurator-1.1.2.tar.gz" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "9b88807b82f6cb464d6f286e6d67e00c", "sha256": "69aab356af6f83b9bb6af800189dd76a962592244aa732d4ce3719d682c15b50" }, "downloads": -1, "filename": "z3c.configurator-1.2.0.tar.gz", "has_sig": false, "md5_digest": "9b88807b82f6cb464d6f286e6d67e00c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17477, "upload_time": "2009-12-20T04:57:11", "url": "https://files.pythonhosted.org/packages/22/6b/d0e18e834c77558b76f216c87b0c4f7de1cd5fc3af72ec979b4824c20039/z3c.configurator-1.2.0.tar.gz" } ], "1.2.1": [ { "comment_text": "", "digests": { "md5": "46b362a6fad0be43d10e929a05df4bf1", "sha256": "ff56f04e37f0e6ff1620564bbb47f6fde32da49220c095e0f04e36111ddac65c" }, "downloads": -1, "filename": "z3c.configurator-1.2.1.tar.gz", "has_sig": false, "md5_digest": "46b362a6fad0be43d10e929a05df4bf1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14341, "upload_time": "2009-12-27T09:50:55", "url": "https://files.pythonhosted.org/packages/d1/27/4888f12f543e19279e9bc98d6476920ffd55fb05c2ef8a284c42bac441b8/z3c.configurator-1.2.1.tar.gz" } ], "1.3.0": [ { "comment_text": "", "digests": { "md5": "cd8ec7d15bfcfedcb3b841f40a611ad6", "sha256": "cd5be0ee453780a810bc02a50fbf74fb9fa8445f7331bc6c36e07d9566856555" }, "downloads": -1, "filename": "z3c.configurator-1.3.0.tar.gz", "has_sig": false, "md5_digest": "cd8ec7d15bfcfedcb3b841f40a611ad6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15404, "upload_time": "2010-12-12T16:54:33", "url": "https://files.pythonhosted.org/packages/3b/fe/c7ee05db7c82e686ba7e4d5b12cb2ca7d431e83321d3cea434f2ad30f4bc/z3c.configurator-1.3.0.tar.gz" } ], "2.0.0": [ { "comment_text": "", "digests": { "md5": "ec2351f4be5f0176f612432b3e9c0a2d", "sha256": "854d810cdfd92ae24207907313afb50f4ab9b5bf10e90aaa9f4cb1bffbeb6dac" }, "downloads": -1, "filename": "z3c.configurator-2.0.0.tar.gz", "has_sig": false, "md5_digest": "ec2351f4be5f0176f612432b3e9c0a2d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21083, "upload_time": "2015-11-09T16:36:37", "url": "https://files.pythonhosted.org/packages/5a/9a/ab7a8a842f92542c0d6cb8bac405ea28dee4b7bf378b38d8144e2d61448c/z3c.configurator-2.0.0.tar.gz" } ], "2.0.0a1": [ { "comment_text": "", "digests": { "md5": "db60cc365eef8089d242be025da99044", "sha256": "4c169527e13b4eab7eca2b970e7f72fcc3e6e0b5767737dcce9620f9d11c2aa8" }, "downloads": -1, "filename": "z3c.configurator-2.0.0a1.zip", "has_sig": false, "md5_digest": "db60cc365eef8089d242be025da99044", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29606, "upload_time": "2013-03-04T09:36:10", "url": "https://files.pythonhosted.org/packages/20/b9/bb8eb02d82ba40f5f9bcbd296e9dd77cd50282b58579cfed7842abae0e4f/z3c.configurator-2.0.0a1.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ec2351f4be5f0176f612432b3e9c0a2d", "sha256": "854d810cdfd92ae24207907313afb50f4ab9b5bf10e90aaa9f4cb1bffbeb6dac" }, "downloads": -1, "filename": "z3c.configurator-2.0.0.tar.gz", "has_sig": false, "md5_digest": "ec2351f4be5f0176f612432b3e9c0a2d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21083, "upload_time": "2015-11-09T16:36:37", "url": "https://files.pythonhosted.org/packages/5a/9a/ab7a8a842f92542c0d6cb8bac405ea28dee4b7bf378b38d8144e2d61448c/z3c.configurator-2.0.0.tar.gz" } ] }