{ "info": { "author": "Stephan Richter, Roger Ineichen and the Zope Community", "author_email": "zope-dev@zope.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Zope3", "Intended Audience :: Developers", "License :: OSI Approved :: Zope Public License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP" ], "description": "This package provides an API for ZAM (Zope Application Management).\n\n\n.. contents::\n\n=======\nCHANGES\n=======\n\n\n0.7.0 (2011-01-13)\n------------------\n\n- Updated test set up and tests to run with ZTK 1.0 and current z3c.form\n version.\n\n- Removed dependency on ``zope.app.twisted``, ``zc.configuration`` and most\n of the ``zope.app.*`` packages.\n\n- Using Python's ``doctest`` module instead of depreacted\n ``zope.testing.doctestunit``.\n\n- Fixed package metadata, added doctests top `long_description`.\n\n0.6.1 (2009-07-06)\n------------------\n\n- Removed deprecation warnings.\n\n0.6.0 (2009-07-06)\n------------------\n\n- Updating tests and dependencies to work with latest versions of packages.\n\n0.5.3 (2008-06-07)\n------------------\n\n- A test dependency (zope.app.session) was missing\n (still checking with KGS 3.4)\n\n0.5.2 (2008-04-11)\n------------------\n\n- Simplify ftesting setup, removed duplicated configuration. Make it better\n reusable. Now we can include app.zcml and mixin ftesting.zcml at the same\n time in plugin tests.\n\n0.5.1 (2008-04-13)\n------------------\n\n- Added new plugin layer for zamplugin.contents plugin\n\n0.5.0 (2008-04-11)\n------------------\n\n- Now plugin provides it's own management form. By default the PluginManagement\n page can be used which is a mixin of IContentProvider and IForm. This makes\n it possible to write intelligent plugin management views which can do more\n then just install and uninstall.\n\n- Initial Release\n\n\n=======\nzam.api\n=======\n\nThis package contains the Zope Application Management api. We support a test\nskin for this package which allows us to test the plugin management page.\nThere is also a ZAMTest site available whcih this test will use. This test site\ncan also be used in any other zam.* or zamplugin.* package.\n\nLogin as manager first:\n\n >>> from zope.testbrowser.testing import Browser\n >>> manager = Browser()\n >>> manager.addHeader('Authorization', 'Basic mgr:mgrpw')\n\nCheck if we can access the page.html view which is registred in the\nftesting.zcml file with our skin:\n\n >>> manager = Browser()\n >>> manager.handleErrors = False\n >>> manager.addHeader('Authorization', 'Basic mgr:mgrpw')\n >>> skinURL = 'http://localhost/++skin++ZAMTest/index.html'\n >>> manager.open(skinURL)\n >>> manager.url\n 'http://localhost/++skin++ZAMTest/index.html'\n\nNow let's create a test site called ``first`` and add them to the root:\n\n >>> import zam.api.testing\n >>> root = getRootFolder()\n >>> firstSite = zam.api.testing.ZAMTestSite(u'first')\n >>> root['first'] = firstSite\n\nAnd create another one called ``second``:\n\n >>> secondSite = zam.api.testing.ZAMTestSite(u'second')\n >>> root['second'] = secondSite\n\nGo the the new zam test site:\n\n >>> firstSiteURL = 'http://localhost/++skin++ZAMTest/first'\n >>> manager.open(firstSiteURL + '/index.html')\n >>> manager.url\n 'http://localhost/++skin++ZAMTest/first/index.html'\n\nand to the ``second`` site:\n\n >>> secondSiteURL = 'http://localhost/++skin++ZAMTest/second'\n >>> manager.open(secondSiteURL + '/index.html')\n >>> manager.url\n 'http://localhost/++skin++ZAMTest/second/index.html'\n\nand go to the ``plugins.html`` page:\n\n >>> manager.open(firstSiteURL + '/plugins.html')\n\nNow we see the plugins.html page:\n\n >>> print manager.contents\n \n \n \n ZAM\n \n \n \n
\n

ZAM Plugin Management

\n
\n ZAM test plugin\n
ZAM test plugin.
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n \n \n\nBefore we install the plugin, we try to access the page which only is available\nif the zam test plugin is installed:\n\n >>> manager.open(firstSiteURL + '/test.html')\n Traceback (most recent call last):\n ...\n NotFound: Object: , name: u'test.html'\n\nThe ``second`` site does also not provide such a test page:\n\n >>> manager.open(secondSiteURL + '/test.html')\n Traceback (most recent call last):\n ...\n NotFound: Object: , name: u'test.html'\n\nAs you can see there is no such ``test.html`` page. Let's install our zam test\nplugin:\n\n >>> manager.open(firstSiteURL + '/plugins.html')\n >>> manager.getControl(name='zam.api.testing.buttons.install').click()\n\nNow we can see that the plugin is installed:\n\n >>> print manager.contents\n ZAM Plugin Management\n
\n ZAM test plugin\n
ZAM test plugin.
\n
\n ...\n
\n
\n \n
\n
\n ...\n\nNow make test coverage happy and test different things. The zam plugin test\npage is available at the ``first`` site\n\n >>> manager.open(firstSiteURL + '/test.html')\n >>> manager.url\n 'http://localhost/++skin++ZAMTest/first/test.html'\n\nBut not at the ``second`` site:\n\n >>> manager.open(secondSiteURL + '/test.html')\n Traceback (most recent call last):\n ...\n NotFound: Object: , name: u'test.html'\n\nLet's unsinstall the plugin:\n\n >>> manager.open(firstSiteURL + '/plugins.html')\n >>> manager.getControl(name='zam.api.testing.buttons.uninstall').click()\n\nAnd check if the site is not available anymore:\n\n >>> manager.open(firstSiteURL + '/test.html')\n Traceback (most recent call last):\n ...\n NotFound: Object: , name: u'test.html'\n\n\n====================\nZAM Plugin Framework\n====================\n\nThe plugin framework allows us to write \"3rd party\" software that depends on\nthe base system's API, but the base system does not in any way depend on the\nnew software. This allows us to keep the base system compact, and separate\noptional features into clearly separated packages.\n\nThere are two different type of plugins offered. Simple plugin do what they\nneeds to do during the install and uninstall process. Base registry\nsupported plugins will install a custom component registry.\n\nThe fundamental concept of the package is that a plugin can be installed for a\nparticular site. At any time, you can ask the plugin, whether it has been\ninstalled for a particular site. The third API method allows you to uninstall\nthe plugin from a site.\n\nSo let's implement a trivial plugin that stores an attribute:\n\n >>> from zam.api import plugin\n\n >>> class SamplePlugin(plugin.Plugin):\n ... title = u'Sample'\n ... description = u'Sample Attribute Plugin'\n ...\n ... def isInstalled(self, site):\n ... \"\"\"See interfaces.IPlugin\"\"\"\n ... return hasattr(site, 'sample')\n ...\n ... def install(self, site):\n ... \"\"\"See interfaces.IPlugin\"\"\"\n ... if not self.isInstalled(site):\n ... setattr(site, 'sample', 1)\n ...\n ... def uninstall(self, site):\n ... \"\"\"See interfaces.IPlugin\"\"\"\n ... if self.isInstalled(site):\n ... delattr(site, 'sample')\n\nThe title and description of the plugin serve as pieces of information for the\nuser, and are commonly used in the UI.\n\nSo let's use the sample plugin:\n\n >>> from zam.api import testing\n >>> site = testing.ZAMTestSite(u'ZAM Test Site')\n >>> sm = site.getSiteManager()\n\n >>> sample = SamplePlugin()\n\nAt the beginning the plugin is not installed, so let's take care of that.\n\n >>> sample.isInstalled(site)\n False\n\n >>> sample.install(site)\n >>> site.sample\n 1\n\n >>> sample.isInstalled(site)\n True\n\nHowever, once the plugin is installed, it cannot be installed again:\n\n >>> site.sample = 2\n\n >>> sample.install(site)\n >>> site.sample\n 2\n\nThis is a requirement of the API. Now you can also uninstall the plugin:\n\n >>> sample.uninstall(site)\n >>> sample.isInstalled(site)\n False\n >>> site.sample\n Traceback (most recent call last):\n ...\n AttributeError: 'ZAMTestSite' object has no attribute 'sample'\n\nYou cannot uninstall the plugin again:\n\n >>> sample.uninstall(site)\n\n\nBase Registry Plugins\n---------------------\n\nAn important base implementation is a plugin that installs a new base registry\nto the to the site.\n\nWe also need a base registry for the plugin:\n\n >>> import zope.component\n >>> from z3c.baseregistry import baseregistry\n\n >>> sampleRegistry = baseregistry.BaseComponents(\n ... zope.component.globalSiteManager, 'sampleRegistry')\n\nNow we can create the plugin, either through instantiation or sub-classing:\n\n >>> class SampleRegistryPlugin(plugin.BaseRegistryPlugin):\n ... title = u'Sample Registry'\n ... description = u'Sample Registry Plugin'\n ... registry = sampleRegistry\n\n >>> regPlugin = SampleRegistryPlugin()\n\nWe use the same API methods as before. Initially the plugin is not installed:\n\n >>> sampleRegistry in sm.__bases__\n False\n >>> regPlugin.isInstalled(site)\n False\n\nNow we install the plugin:\n\n >>> regPlugin.install(site)\n\n >>> sampleRegistry in sm.__bases__\n True\n >>> regPlugin.isInstalled(site)\n True\n\nAs before, installing the plugin again does nothing:\n\n >>> len(sm.__bases__)\n 2\n\n >>> regPlugin.install(site)\n\n >>> len(sm.__bases__)\n 2\n\nAnd uninstalling the plugin is equally simple:\n\n >>> regPlugin.uninstall(site)\n\n >>> sampleRegistry in sm.__bases__\n False\n >>> regPlugin.isInstalled(site)\n False\n >>> len(sm.__bases__)\n 1\n\nUninstalling a second time does nothing:\n\n >>> regPlugin.uninstall(site)\n\n >>> sampleRegistry in sm.__bases__\n False\n >>> len(sm.__bases__)\n 1\n\n\nLayers\n------\n\nWe offer a fine grained layer concept which allows you to use the ZAM skin\nout of the box, or lets you define your own skins, offering what you need.\nEach ZAM plugin should configure it's component for the IZAMBrowserLayer and\nnot for the IZAMCoreLayer. This allows others to use the IZAMCoreLayer without\nany plugin configuration. See the different layer descriptions below for more\ninformation about the ZAM layer concept.\n\n\nBig note\n~~~~~~~~\n\nThis is only important if you'd like to define your own skin which uses\nselective zam plugins.\n\nThe layer concept has some limitations when it comes to adapter lookups. It's\nnot possible to define a custom layer and make an existing layer act like it\nwhould inherit this layer. ``Implements`` and ``provide`` concept only work on\nclasses but not on interfaces. Let's be more precise: they work but don't affect the\nrequest. Which means the request doesn't know about such applied layers. This\nmeans there is no[*] way to apply a later defined layer to an existing layer.\nThis is the reason why we offer all plugin layers in the zam.api.layer package.\nBut what does this mean if you'd like to define custom plugins and their layers?\nYou have to define your own skin and inherit your new layers in this skin.\nYou can skip the named skin configuration and configure your custom skin.\n\n[*] Ok, there is a way to apply layers to an existing layer or at least it will\nbe effectively the same thing. There are two ways: you can add a SkinChangedEvent which\nwill do an alsoProvide and inject your layer, or you can use a 'before traversal\nevent' subscriber which does the same. I decided not to use these patterns here\nas defaults, because such subscribers will affect every skin and will cost\nprocessing time on every request. The option we have with defining an explicit\nconfiguration for a custom skin is to small to pay that price.\n\n\nIZAMCoreLayer\n~~~~~~~~~~~~~\n\nThe core layer provides the ZAM core management views but no plugins and\nskin configuration. This allows us to write skins with a selective choice\nof plugins. Of course each plugin must be configured again for your\ncustom skin. Out of the box, there is no way to offer a working set without\nconfiguring a plugin twice using two different layers.\n\n\nIZAMPluginLayer\n~~~~~~~~~~~~~~~\n\nThe zam plugin layer should not be used in plugins. You need to define a\nplugin layer for your plugin in zam.api.layer and use this newly defined layer.\nThis layer then becomes a part of the IZAMPluginLayer. This makes it\npossible to use the IZAMPluginLayer and get all it's configuration.\n\nBut what happens if you don't develop in the zamplugin.* namespace? Then you\nonly have the option to configure your plugins for an additional layer and use\nanother skin which uses the IZAMPluginLayer and your custom layer. Using the\nIAZMPluginLayer for your configuration and sharing such packages ends in\nbad configuration and others needs to exclude your configuration if it\nis not needed in every skin they provide and is based on IZAMPluginLayer.\nOf course you can do this in your own private projects, but please do not\nuse it for public shared packages. Help us provide a clean IZAMPluginLayer!\n\nAny improvement which offers us a better layer usage concept is very welcome if\nit doesn't need to configure additional subscribers.\n\n\nIZAMBrowserLayer\n~~~~~~~~~~~~~~~~\n\nThis is the \"all in one\" layer which can be used for build skins which knows\nabout all plugin configurations. All plugins should use this layer.\n\n\nIZAMSkinLayer\n~~~~~~~~~~~~~\n\nThe IZAMSkinLayer offers the UI part for ZAM but is not registered as skin.\nYou can use this layer as base if you'd like to develop a custom skin. This\nlayer contains the nested div menu implementation.\n\n\nIZAMBrowserSkin\n~~~~~~~~~~~~~~~\n\nThe IZAMBrowserSkin uses the IZAMSkinLayer and IZAMBrowserLayer and offers the\nUI part for ZAM as named skin. This means the IZAMBrowserSkin is accessible\nas ++skin++ZAM.", "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/zam.api", "keywords": "zope3 z3c zam api", "license": "ZPL 2.1", "maintainer": null, "maintainer_email": null, "name": "zam.api", "package_url": "https://pypi.org/project/zam.api/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/zam.api/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://pypi.python.org/pypi/zam.api" }, "release_url": "https://pypi.org/project/zam.api/0.7.0/", "requires_dist": null, "requires_python": null, "summary": "API for ZAM (Zope Application Management", "version": "0.7.0" }, "last_serial": 802138, "releases": { "0.5.0": [ { "comment_text": "", "digests": { "md5": "ace9e602bb0e0e02ee24523add8e19bd", "sha256": "5a711a3d423443f974d434098aa7daaed5a892db5359ec93b820f93c95b5ece5" }, "downloads": -1, "filename": "zam.api-0.5.0.zip", "has_sig": false, "md5_digest": "ace9e602bb0e0e02ee24523add8e19bd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30714, "upload_time": "2008-04-11T13:42:22", "url": "https://files.pythonhosted.org/packages/49/22/54b31ce359f94c06556ae666d6dde8461be96c1849a988a73a82ee3e88e8/zam.api-0.5.0.zip" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "ce046756afbb1650323da9bd7737bc1e", "sha256": "4760567b06f69e37554043780be13bb2f31a422105e45a0a20d6e5872d54a270" }, "downloads": -1, "filename": "zam.api-0.5.1.zip", "has_sig": false, "md5_digest": "ce046756afbb1650323da9bd7737bc1e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30788, "upload_time": "2008-04-13T02:04:37", "url": "https://files.pythonhosted.org/packages/a0/bc/03680cb6a2d79413eab977350e21ea69383350f177fca1329239c17fa678/zam.api-0.5.1.zip" } ], "0.5.2": [ { "comment_text": "", "digests": { "md5": "af6189171fcb521dc735bc9f6bc31375", "sha256": "91065a02c7bda6108e0f6d0ad0f02ac4f8f829c4b0ea80002fe708d9018b4b0a" }, "downloads": -1, "filename": "zam.api-0.5.2.zip", "has_sig": false, "md5_digest": "af6189171fcb521dc735bc9f6bc31375", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 30911, "upload_time": "2008-04-13T15:13:57", "url": "https://files.pythonhosted.org/packages/6f/9f/ad919b1f2ff1af1173cb8062c2f08b508a00f51117a979d2ebc20e17975f/zam.api-0.5.2.zip" } ], "0.5.3": [ { "comment_text": "", "digests": { "md5": "aaaeee4026e24801dc1c6810cd580d35", "sha256": "7d6eaaae933a7112c1fbe1abdde6d2bf374eee32f6efc015e6d81f5ec6e10d1a" }, "downloads": -1, "filename": "zam.api-0.5.3.zip", "has_sig": false, "md5_digest": "aaaeee4026e24801dc1c6810cd580d35", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31089, "upload_time": "2009-06-07T11:42:25", "url": "https://files.pythonhosted.org/packages/e1/ae/9bffa5389b427cdd0e9afc145a73f1d5499c63c22f1e0d0f8dccc7e8d7e6/zam.api-0.5.3.zip" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "56edae948f32ff860b4d881c4d0baf0c", "sha256": "c182792b3777d7b7e93d87f68ffea55c1177ef9488f2039a8a99b887bc238ee3" }, "downloads": -1, "filename": "zam.api-0.6.0.tar.gz", "has_sig": false, "md5_digest": "56edae948f32ff860b4d881c4d0baf0c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15918, "upload_time": "2009-07-06T20:42:16", "url": "https://files.pythonhosted.org/packages/b2/ed/bbf684d6ff0c723d1606121cfde82ab38e7dde6240cd4afe702bdefe693a/zam.api-0.6.0.tar.gz" } ], "0.6.1": [ { "comment_text": "", "digests": { "md5": "d4eba180e64f6d3a23a9868a29434b84", "sha256": "8effa5c5601efb484d3f9ee582e547646e596910970b045d78696df82d8cae4b" }, "downloads": -1, "filename": "zam.api-0.6.1.tar.gz", "has_sig": false, "md5_digest": "d4eba180e64f6d3a23a9868a29434b84", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15959, "upload_time": "2009-07-06T21:04:55", "url": "https://files.pythonhosted.org/packages/c4/4a/fe098c06549207c84811a06e88a4049a0e1eb73186a9925a739f943d4831/zam.api-0.6.1.tar.gz" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "0b2979a87b73861e7664b6a8e7ebf609", "sha256": "4c58cd17674fde4d22037177831fd9d947d280319edaf7eb5bc2966cbaf28994" }, "downloads": -1, "filename": "zam.api-0.7.0.tar.gz", "has_sig": false, "md5_digest": "0b2979a87b73861e7664b6a8e7ebf609", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20002, "upload_time": "2011-01-13T11:06:33", "url": "https://files.pythonhosted.org/packages/5c/bf/f0aada9955b3176f72c03a96cd2ab9e36cb324bc2bd81cd650b01d209840/zam.api-0.7.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0b2979a87b73861e7664b6a8e7ebf609", "sha256": "4c58cd17674fde4d22037177831fd9d947d280319edaf7eb5bc2966cbaf28994" }, "downloads": -1, "filename": "zam.api-0.7.0.tar.gz", "has_sig": false, "md5_digest": "0b2979a87b73861e7664b6a8e7ebf609", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20002, "upload_time": "2011-01-13T11:06:33", "url": "https://files.pythonhosted.org/packages/5c/bf/f0aada9955b3176f72c03a96cd2ab9e36cb324bc2bd81cd650b01d209840/zam.api-0.7.0.tar.gz" } ] }