跳转到主要内容

ZAM(Zope应用管理)的API

项目描述

此软件包提供ZAM(Zope应用管理)的API。

CHANGES

0.7.0 (2011-01-13)

  • 更新测试设置和测试,以与ZTK 1.0和当前z3c.form版本一起运行。

  • 移除了对zope.app.twistedzc.configuration以及大部分zope.app.*软件包的依赖。

  • 使用Python的doctest模块代替已废弃的zope.testing.doctestunit

  • 修复了软件包元数据,在long_description中添加了doctests。

0.6.1 (2009-07-06)

  • 移除了弃用警告。

0.6.0 (2009-07-06)

  • 更新测试和依赖项以与软件包的最新版本一起工作。

0.5.3 (2008-06-07)

  • 测试依赖项(zope.app.session)缺失(仍在与KGS 3.4进行验证)

0.5.2 (2008-04-11)

  • 简化ftesting设置,删除了重复的配置。使其更具可重用性。现在我们可以在插件测试中同时包含app.zcml和mixin ftesting.zcml。

0.5.1 (2008-04-13)

  • 为zamplugin.contents插件添加了新的插件层

0.5.0 (2008-04-11)

  • 现在插件提供它自己的管理表单。默认情况下,可以使用PluginManagement页面,它是一个IContentProvider和IForm的混合体。这使得编写能够执行更多操作(而不仅仅是安装和卸载)的智能插件管理视图成为可能。

  • 初始发布

zam.api

本包包含Zope应用程序管理API。我们为此包提供测试皮肤,允许我们测试插件管理页面。还有一个可供此测试使用的ZAMTest站点。此测试站点也可以用于任何其他zam.*或zamplugin.*包。

首先以管理员的身份登录

>>> from zope.testbrowser.testing import Browser
>>> manager = Browser()
>>> manager.addHeader('Authorization', 'Basic mgr:mgrpw')

检查我们是否可以访问在ftesting.zcml文件中注册的page.html视图,并使用我们的皮肤

>>> manager = Browser()
>>> manager.handleErrors = False
>>> manager.addHeader('Authorization', 'Basic mgr:mgrpw')
>>> skinURL = 'https://127.0.0.1/++skin++ZAMTest/index.html'
>>> manager.open(skinURL)
>>> manager.url
'https://127.0.0.1/++skin++ZAMTest/index.html'

现在让我们创建一个名为first的测试站点并将其添加到根目录

>>> import zam.api.testing
>>> root = getRootFolder()
>>> firstSite = zam.api.testing.ZAMTestSite(u'first')
>>> root['first'] = firstSite

再创建一个名为second的站点

>>> secondSite = zam.api.testing.ZAMTestSite(u'second')
>>> root['second'] = secondSite

转到新的zam测试站点

>>> firstSiteURL = 'https://127.0.0.1/++skin++ZAMTest/first'
>>> manager.open(firstSiteURL + '/index.html')
>>> manager.url
'https://127.0.0.1/++skin++ZAMTest/first/index.html'

并转到second站点

>>> secondSiteURL = 'https://127.0.0.1/++skin++ZAMTest/second'
>>> manager.open(secondSiteURL + '/index.html')
>>> manager.url
'https://127.0.0.1/++skin++ZAMTest/second/index.html'

然后访问plugins.html页面

>>> manager.open(firstSiteURL + '/plugins.html')

现在我们看到了plugins.html页面

>>> print manager.contents
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
      lang="en">
<head>
<title>ZAM</title><meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="pragma" content="no-cache" />
</head>
<body>
<form action="./plugins.html" method="post" enctype="multipart/form-data" class="plugin-form">
  <h1>ZAM Plugin Management</h1>
  <fieldset id="pluginManagement">
    <strong class="notInstalledPlugin">ZAM test plugin</strong>
    <div class="description">ZAM test plugin.</div>
  <div class="viewspace">
    <div>
    </div>
  </div>
  <div>
    <div class="buttons">
      <input id="zam-api-testing-buttons-install"
             name="zam.api.testing.buttons.install"
             class="submit-widget button-field" value="Install"
             type="submit" />
    </div>
  </div>
  </fieldset>
</form>
</body>
</html>

在我们安装插件之前,我们尝试访问只有安装了zam测试插件才能访问的页面

>>> manager.open(firstSiteURL + '/test.html')
Traceback (most recent call last):
...
NotFound: Object: <ZAMTestSite u'first'>, name: u'test.html'

第二个站点也没有提供这样的测试页面

>>> manager.open(secondSiteURL + '/test.html')
Traceback (most recent call last):
...
NotFound: Object: <ZAMTestSite u'second'>, name: u'test.html'

如您所见,没有这样的test.html页面。让我们安装我们的zam测试插件

>>> manager.open(firstSiteURL + '/plugins.html')
>>> manager.getControl(name='zam.api.testing.buttons.install').click()

现在我们可以看到插件已安装

>>> print manager.contents
<!DOCTYPE...
<h1>ZAM Plugin Management</h1>
<fieldset id="pluginManagement">
  <strong class="installedPlugin">ZAM test plugin</strong>
  <div class="description">ZAM test plugin.</div>
<div class="viewspace">
...
<div>
  <div class="buttons">
    <input id="zam-api-testing-buttons-uninstall"
           name="zam.api.testing.buttons.uninstall"
           class="submit-widget button-field" value="Uninstall"
           type="submit" />
  </div>
</div>
...

现在让测试覆盖满意,测试不同的事情。zam插件测试页面可在first站点找到

>>> manager.open(firstSiteURL + '/test.html')
>>> manager.url
'https://127.0.0.1/++skin++ZAMTest/first/test.html'

但在second站点不可用

>>> manager.open(secondSiteURL + '/test.html')
Traceback (most recent call last):
...
NotFound: Object: <ZAMTestSite u'second'>, name: u'test.html'

让我们卸载插件

>>> manager.open(firstSiteURL + '/plugins.html')
>>> manager.getControl(name='zam.api.testing.buttons.uninstall').click()

并检查站点是否不再可用

>>> manager.open(firstSiteURL + '/test.html')
Traceback (most recent call last):
...
NotFound: Object: <ZAMTestSite u'first'>, name: u'test.html'

ZAM插件框架

插件框架允许我们编写依赖于基础系统API的“第三方”软件,而基础系统不会以任何方式依赖于新软件。这使我们能够保持基础系统紧凑,并将可选功能分开到清晰分开的包中。

提供了两种不同类型的插件。简单插件在安装和卸载过程中完成它们需要完成的工作。支持基本注册的插件将安装自定义组件注册。

该包的基本概念是,可以为特定站点安装插件。在任何时候,您都可以询问插件,它是否为特定站点安装了。第三个API方法允许您从站点卸载插件。

所以让我们实现一个简单的插件,它存储一个属性

>>> from zam.api import plugin
>>> class SamplePlugin(plugin.Plugin):
...     title = u'Sample'
...     description = u'Sample Attribute Plugin'
...
...     def isInstalled(self, site):
...         """See interfaces.IPlugin"""
...         return hasattr(site, 'sample')
...
...     def install(self, site):
...         """See interfaces.IPlugin"""
...         if not self.isInstalled(site):
...             setattr(site, 'sample', 1)
...
...     def uninstall(self, site):
...         """See interfaces.IPlugin"""
...         if self.isInstalled(site):
...             delattr(site, 'sample')

插件标题和描述作为用户的信息片段,通常在UI中使用。

所以让我们使用示例插件

>>> from zam.api import testing
>>> site = testing.ZAMTestSite(u'ZAM Test Site')
>>> sm = site.getSiteManager()
>>> sample = SamplePlugin()

最初插件未安装,所以让我们处理这个问题。

>>> sample.isInstalled(site)
False
>>> sample.install(site)
>>> site.sample
1
>>> sample.isInstalled(site)
True

然而,一旦插件安装,就不能再次安装

>>> site.sample = 2
>>> sample.install(site)
>>> site.sample
2

这是API的要求。现在您也可以卸载插件

>>> sample.uninstall(site)
>>> sample.isInstalled(site)
False
>>> site.sample
Traceback (most recent call last):
...
AttributeError: 'ZAMTestSite' object has no attribute 'sample'

不能再次卸载插件

>>> sample.uninstall(site)

基本注册插件

一个重要的基本实现是安装新基本注册到站点的插件。

我们还需要为插件提供一个基本注册

>>> import zope.component
>>> from z3c.baseregistry import baseregistry
>>> sampleRegistry = baseregistry.BaseComponents(
...     zope.component.globalSiteManager, 'sampleRegistry')

现在我们可以创建插件,无论是通过实例化还是通过子类化

>>> class SampleRegistryPlugin(plugin.BaseRegistryPlugin):
...     title = u'Sample Registry'
...     description = u'Sample Registry Plugin'
...     registry = sampleRegistry
>>> regPlugin = SampleRegistryPlugin()

我们使用之前相同的API方法。最初插件未安装

>>> sampleRegistry in sm.__bases__
False
>>> regPlugin.isInstalled(site)
False

现在我们安装插件

>>> regPlugin.install(site)
>>> sampleRegistry in sm.__bases__
True
>>> regPlugin.isInstalled(site)
True

就像以前一样,再次安装插件没有任何作用

>>> len(sm.__bases__)
2
>>> regPlugin.install(site)
>>> len(sm.__bases__)
2

卸载插件同样简单

>>> regPlugin.uninstall(site)
>>> sampleRegistry in sm.__bases__
False
>>> regPlugin.isInstalled(site)
False
>>> len(sm.__bases__)
1

第二次卸载没有任何作用

>>> regPlugin.uninstall(site)
>>> sampleRegistry in sm.__bases__
False
>>> len(sm.__bases__)
1

我们提供了一个细粒度的层概念,允许您使用开箱即用的ZAM皮肤,或者让您定义自己的皮肤,提供您所需的功能。每个ZAM插件应为其组件配置IZAMBrowserLayer,而不是IZAMCoreLayer。这允许其他人使用IZAMCoreLayer而无需任何插件配置。有关ZAM层概念的更多信息,请参阅下面的不同层描述。

重要提示

这仅在你想要定义自己的皮肤,该皮肤使用选定的zam插件时才重要。

在适配器查找方面,层概念有一些局限性。无法定义一个自定义层,并使现有层表现得像它继承了该层。只有类上的实现提供概念起作用,但不是接口。让我们更精确地说:它们起作用,但不会影响请求。这意味着请求不知道有这些应用层。这意味着没有[*]方法可以将后来定义的层应用于现有层。这就是为什么我们在zam.api.layer包中提供所有插件层的原因。但如果你想定义自定义插件及其层呢?你必须定义自己的皮肤,并在该皮肤中继承你的新层。你可以跳过命名的皮肤配置,并配置你的自定义皮肤。

[*] 好吧,有一种方法可以将层应用于现有层,或者至少它将产生相同的效果。有两种方法:你可以添加一个SkinChangedEvent,这将执行alsoProvide并注入你的层,或者你可以使用一个“遍历前事件”订阅者来完成同样的工作。我决定不在这里使用这些模式作为默认设置,因为这样的订阅者将影响每个皮肤,并且将在每个请求上消耗处理时间。我们定义一个自定义皮肤显式配置的选项太小,不足以付出这个代价。

IZAMCoreLayer

核心层提供了ZAM核心管理视图,但没有插件和皮肤配置。这允许我们编写具有选择性插件选择的皮肤。当然,每个插件都必须为你的自定义皮肤重新配置。默认情况下,没有方法在不使用两个不同层的情况下配置插件集以使其工作。

IZAMPluginLayer

zam插件层不应在插件中使用。您需要在zam.api.layer中为您的插件定义一个插件层,并使用这个新定义的层。这个层然后成为IZAMPluginLayer的一部分。这使得使用IZAMPluginLayer并获得所有配置成为可能。

但如果你不在zamplugin.*命名空间下开发会发生什么?那么你只能选择为额外的层配置你的插件,并使用另一个使用IZAMPluginLayer和你的自定义层的皮肤。使用IAZMPluginLayer进行配置并共享这样的包会导致配置不良,其他人如果他们的皮肤不依赖于IZAMPluginLayer且不需要使用你的配置,则需要排除你的配置。当然,你可以在自己的私有项目中这样做,但请不要将其用于公共共享的包。帮助我们提供一个干净的IZAMPluginLayer!

如果它不需要配置额外的订阅者,任何提供更好层使用概念的改进都受到欢迎。

IZAMBrowserLayer

这是一个“一应俱全”的层,可用于构建了解所有插件配置的皮肤。所有插件都应该使用这个层。

IZAMSkinLayer

IZAMSkinLayer提供了ZAM的UI部分,但未注册为皮肤。如果你想要开发一个自定义皮肤,可以使用这个层作为基础。这个层包含嵌套的div菜单实现。

IZAMBrowserSkin

IZAMBrowserSkin使用IZAMSkinLayer和IZAMBrowserLayer,作为命名皮肤的UI部分。这意味着IZAMBrowserSkin可以通过++skin++ZAM访问。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分布

zam.api-0.7.0.tar.gz (20.0 kB 查看散列)

上传于 源代码

由以下支持