[Checkins] SVN: megrok.resourcelibrary/ Initial import.

Martijn Faassen faassen at infrae.com
Wed Aug 6 12:27:02 EDT 2008


Log message for revision 89450:
  Initial import.
  

Changed:
  A   megrok.resourcelibrary/
  A   megrok.resourcelibrary/trunk/
  A   megrok.resourcelibrary/trunk/README.txt
  A   megrok.resourcelibrary/trunk/bootstrap.py
  A   megrok.resourcelibrary/trunk/buildout.cfg
  A   megrok.resourcelibrary/trunk/setup.py
  A   megrok.resourcelibrary/trunk/src/
  A   megrok.resourcelibrary/trunk/src/megrok/
  A   megrok.resourcelibrary/trunk/src/megrok/__init__.py
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/README.txt
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/__init__.py
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/components.py
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/directive.py
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/meta.py
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/__init__.py
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/1.js
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/2.css
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/3.kss
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.css
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.js
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.kss
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/ftesting.zcml
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/resources1/
  A   megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/tests.py

-=-
Added: megrok.resourcelibrary/trunk/README.txt
===================================================================
--- megrok.resourcelibrary/trunk/README.txt	                        (rev 0)
+++ megrok.resourcelibrary/trunk/README.txt	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,4 @@
+Introduction
+============
+
+

Added: megrok.resourcelibrary/trunk/bootstrap.py
===================================================================
--- megrok.resourcelibrary/trunk/bootstrap.py	                        (rev 0)
+++ megrok.resourcelibrary/trunk/bootstrap.py	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,55 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 75593 2007-05-06 21:11:27Z jim $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+try:
+    import pkg_resources
+except ImportError:
+    ez = {}
+    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                         ).read() in ez
+    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Added: megrok.resourcelibrary/trunk/buildout.cfg
===================================================================
--- megrok.resourcelibrary/trunk/buildout.cfg	                        (rev 0)
+++ megrok.resourcelibrary/trunk/buildout.cfg	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,11 @@
+[buildout]
+develop = .
+parts = test
+newest = false
+extends = http://grok.zope.org/releaseinfo/grok-0.13.cfg
+versions = versions
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = megrok.resourcelibrary
+defaults = ['--tests-pattern', '^f?tests$', '-v']

Added: megrok.resourcelibrary/trunk/setup.py
===================================================================
--- megrok.resourcelibrary/trunk/setup.py	                        (rev 0)
+++ megrok.resourcelibrary/trunk/setup.py	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,32 @@
+from setuptools import setup, find_packages
+import os
+
+version = '0.1'
+
+setup(name='megrok.resourcelibrary',
+      version=version,
+      description="static resource library support for Grok.",
+      # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[
+        "Programming Language :: Python",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+        ],
+      keywords='',
+      author='Grok Team',
+      author_email='grok-dev at zope.org',
+      url='',
+      license='ZPL',
+      packages=find_packages('src'),
+      package_dir = {'': 'src'},
+      namespace_packages=['megrok'],
+      include_package_data=True,
+      zip_safe=True,
+      install_requires=[
+          'setuptools',
+          'grok >= 0.13',
+          'zc.resourcelibrary',
+         ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: megrok.resourcelibrary/trunk/src/megrok/__init__.py
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/__init__.py	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/__init__.py	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/README.txt
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/README.txt	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/README.txt	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,210 @@
+megrok.resourcelibrary: Resources in Grok
+=========================================
+
+Introduction
+------------
+
+Grok already comes equipped with a simple way to expose static file
+resources, the ``static`` directory.
+
+``megrok.resourcelibrary`` allows the more flexible inclusion of
+static file resources in Grok. It uses the ``zc.resourcelibrary``
+package to do this.
+
+A resource library is essentially like a directory like the ``static``
+directory of a package, full of static resources, such as CSS files,
+javascript files and images. Resources are intended to be used from
+HTML pages, as additional resources to help display a particular
+layout or user interface.
+
+How is ``megrok.resourcelibrary`` more flexible than Grok's default
+``static`` directory?
+
+* A resource library can be in a layer.
+
+* A resource library can have a non-public permission.
+
+* A resource library can more easily be packaged for reuse by other
+  libraries. Resource libraries have unique names under the control of
+  the developer.
+
+* A resource library can automatically include some resources (such as
+  javascript or css) in the ``head`` section of a web page whenever a
+  particular widget needs it.
+
+* A resource library can also depend on other libraries.
+
+Basic example
+-------------
+
+Let's see how this all works. First we need to grok this package
+itself (this is normally done from ZCML)::
+
+  >>> from grok.testing import grok
+  >>> grok('megrok.resourcelibrary.meta')
+
+Now we can set up a simple resource library::
+  
+  >>> import grok
+  >>> import megrok.resourcelibrary
+  >>> class SomeLibrary(megrok.resourcelibrary.ResourceLibrary):
+  ...     megrok.resourcelibrary.directory('tests/example')
+
+We need to grok this to make it available (in normal use this is done
+automatically for you)::
+
+  >>> from grok.testing import grok_component
+  >>> grok_component('SomeLibrary', SomeLibrary)
+  True
+
+The resources in this directory are now published, by default under
+the class name of the library, lower cased (therefore
+``somelibrary``)::
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.open('http://localhost/@@/somelibrary/my-lib/included.js')
+  >>> print browser.contents
+      function be_annoying() {
+      alert('Hi there!');
+  }
+
+The default name can be overridden by using the ``grok.name``
+directive::
+
+  >>> class SomeLibrary2(megrok.resourcelibrary.ResourceLibrary):
+  ...     grok.name('some-library')
+  ...     megrok.resourcelibrary.directory('tests/example')
+  >>> grok_component('SomeLibrary2', SomeLibrary2)
+  True
+  >>> browser.open('http://localhost/@@/some-library/my-lib/included.js')
+  >>> print browser.contents
+      function be_annoying() {
+      alert('Hi there!');
+  }
+
+Automactic inclusion of resources
+---------------------------------
+
+We now set up a resource library that automatically includes two
+resources whenever it is used in a web page, namely ``included.js``
+and ``included.css``::
+
+  >>> class MyLib(megrok.resourcelibrary.ResourceLibrary):
+  ...    grok.name('my-lib')
+  ...    megrok.resourcelibrary.directory('tests/example/my-lib')
+  ...    megrok.resourcelibrary.include('included.js')
+  ...    megrok.resourcelibrary.include('included.css')
+  >>> grok_component('MyLib', MyLib)
+  True
+
+This is how you require the library to be loaded in a particular page
+template::
+
+  <tal:block replace="resource_library:my-lib"/>
+
+``test_template_2`` makes this requirement, so the included Javascript
+should be included::
+
+  >>> browser.open('http://localhost/zc.resourcelibrary.test_template_2')
+  >>> '/@@/my-lib/included.js' in browser.contents
+  True
+
+And the resource is also published::
+
+  >>> browser.open('/@@/my-lib/included.js')
+  >>> print browser.contents
+      function be_annoying() {
+      alert('Hi there!');
+  }
+
+A reference to the CSS is also inserted into the HTML::
+
+  >>> browser.open('http://localhost/zc.resourcelibrary.test_template_2')
+  >>> '/@@/my-lib/included.css' in browser.contents
+  True
+ 
+And the CSS is available from the URL referenced::
+
+    >>> browser.open('/@@/my-lib/included.css')
+    >>> print browser.contents
+    div .border {
+        border: 1px silid black;
+    }
+
+Programmatically signally resource requirements
+-----------------------------------------------
+
+Above we've demonstrated the use of the ``resource_library`` namespace
+in ZPT. Library usage can also be signalled programmatically, for
+instance in a view::
+
+  >>> import grok
+  >>> from zope.interface import Interface
+  >>> class View(grok.View):
+  ...   grok.context(Interface)
+  ...   def render(self):
+  ...      MyLib.need()
+  ...      return '<html><head></head><body>Example</body></html>'
+  >>> grok_component('View', View)
+  True
+
+  >>> browser.open('http://localhost/view')
+  >>> '/@@/my-lib/included.js' in browser.contents
+  True
+
+This also works for libraries which don't have an explicit ``grok.name``::
+
+  >>> class MyLib2(megrok.resourcelibrary.ResourceLibrary):
+  ...    megrok.resourcelibrary.directory('tests/example/my-lib')
+  ...    megrok.resourcelibrary.include('included.js')
+  ...    megrok.resourcelibrary.include('included.css')
+  >>> grok_component('MyLib2', MyLib2)
+  True
+
+  >>> class View2(grok.View):
+  ...   grok.context(Interface)
+  ...   def render(self):
+  ...      MyLib2.need()
+  ...      return '<html><head></head><body>Example</body></html>'
+  >>> grok_component('View2', View2)
+  True
+
+  >>> browser.open('http://localhost/view2')
+  >>> '/@@/mylib2/included.js' in browser.contents
+  True
+
+You can also signal inclusion by library name instead (like is done in page templates)::
+
+  >>> class View3(grok.View):
+  ...   grok.context(Interface)
+  ...   def render(self):
+  ...      megrok.resourcelibrary.need('my-lib')
+  ...      return '<html><head></head><body>Example</body></html>'
+
+  >>> grok_component('View3', View3)
+  True
+
+  >>> browser.open('http://localhost/view3')
+  >>> '/@@/my-lib/included.js' in browser.contents
+  True
+
+Protecting resources
+--------------------
+
+It's possible to give a resource a permission::
+
+  >>> class MyPermission(grok.Permission):
+  ...    grok.name("my.permission")
+  >>> grok_component('MyPermission', MyPermission)
+  True
+
+  >>> class MyLib3(megrok.resourcelibrary.ResourceLibrary):
+  ...    megrok.resourcelibrary.directory('tests/example/my-lib')
+  ...    grok.require(MyPermission)
+  >>> grok_component('MyLib3', MyLib3)
+  True
+
+XXX This doesn't work yet, as resources don't do their own security
+checks but rely on proxies, which Grok has removed... Need to introduce
+new resources/factories to do checks by hand.

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/__init__.py
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/__init__.py	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/__init__.py	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,3 @@
+from megrok.resourcelibrary.components import ResourceLibrary
+from megrok.resourcelibrary.directive import directory, use, include
+from zc.resourcelibrary import need

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/components.py
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/components.py	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/components.py	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,9 @@
+import grok
+import zc.resourcelibrary
+from megrok.resourcelibrary.directive import default_library_name
+
+class ResourceLibrary(object):
+    @classmethod
+    def need(cls):
+        name = grok.name.bind(get_default=default_library_name).get(cls)
+        zc.resourcelibrary.need(name)

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/directive.py
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/directive.py	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/directive.py	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,40 @@
+import os
+
+import martian
+from martian import util
+from martian.error import GrokImportError
+
+from zc.resourcelibrary.zcml import INCLUDABLE_EXTENTIONS
+
+def default_list(factory, module=None, **data):
+    return []
+
+def default_library_name(factory, module=None, **data):
+    return factory.__name__.lower()
+
+class directory(martian.Directive):
+    scope = martian.CLASS
+    store = martian.ONCE
+
+    validate = martian.validateText
+    
+class use(martian.Directive):
+    scope = martian.CLASS
+    store = martian.MULTIPLE
+    validate = martian.validateText
+    
+class include(martian.Directive):
+    scope = martian.CLASS
+    store = martian.MULTIPLE
+    
+    def validate(self, value):
+        if util.not_unicode_or_ascii(value):
+            raise GrokImportError(
+                "You can only pass unicode or ASCII to the '%s' directive." %
+                self.name)
+        ext = os.path.splitext(value)[1]
+        if ext not in INCLUDABLE_EXTENTIONS:
+            raise GrokImportError(
+                "The '%s' directive does not know how to include this file: %s" %
+                (value, self.name))
+

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/meta.py
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/meta.py	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/meta.py	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,60 @@
+import os
+
+import martian
+import grok
+from martian.error import GrokError
+
+from zope.publisher.interfaces.browser import (IDefaultBrowserLayer,
+                                               IBrowserRequest)
+from zope.app.publisher.browser import directoryresource
+from zope.app.publisher.browser.resourcemeta import allowed_names
+from zope.security.checker import CheckerPublic, NamesChecker
+from zc.resourcelibrary.zcml import handler
+from zc.resourcelibrary.resourcelibrary import LibraryInfo, library_info
+from zope.interface import Interface
+
+from megrok import resourcelibrary
+from megrok.resourcelibrary.directive import default_list, default_library_name
+
+class ResourceLibraryGrokker(martian.ClassGrokker):
+    martian.component(resourcelibrary.ResourceLibrary)
+    martian.directive(grok.name, get_default=default_library_name)
+    martian.directive(resourcelibrary.directory)
+    martian.directive(resourcelibrary.use, get_default=default_list)
+    martian.directive(resourcelibrary.include, get_default=default_list)
+    martian.directive(grok.layer, default=IDefaultBrowserLayer)
+    martian.directive(grok.require, name='permission')
+    
+    def grok(self, name, factory, module_info, **kw):
+        # need to tuck away module_info
+        factory.module_info = module_info
+        return super(ResourceLibraryGrokker, self).grok(
+            name, factory, module_info, **kw)
+    
+    def execute(self, class_, config, name, directory, use, include, layer,
+                permission,
+                **kw):
+        directory = class_.module_info.getResourcePath(directory)
+        if not os.path.isdir(directory):
+            raise GrokImportError(
+                "You can only pass a directory to the '%s' directive." %
+                self.name)
+
+        library_info[name] = LibraryInfo()
+        library_info[name].required.extend(use)
+        library_info[name].included.extend(include)
+
+        if permission == 'zope.Public' or permission is None:
+            permission = CheckerPublic
+        checker = NamesChecker(allowed_names, permission)
+
+        factory = directoryresource.DirectoryResourceFactory
+        factory = factory(directory, checker, name)
+        
+        config.action(
+            discriminator=('resource', name, IBrowserRequest, layer),
+            callable=handler,
+            args=(name, library_info[name].required, (layer,),
+                  Interface, name, factory, config.info),
+            )
+        return True

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/__init__.py
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/__init__.py	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/__init__.py	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1 @@
+#

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/1.js
===================================================================

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/2.css
===================================================================

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/3.kss
===================================================================

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.css
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.css	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.css	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,3 @@
+div .border {
+    border: 1px silid black;
+}

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.js
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.js	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.js	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,3 @@
+function be_annoying() {
+    alert('Hi there!');
+}

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.kss
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.kss	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/example/my-lib/included.kss	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,3 @@
+body:click {
+    action-client: alert;
+}
\ No newline at end of file

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/ftesting.zcml
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/ftesting.zcml	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/ftesting.zcml	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,34 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="zope"
+    package="megrok.resourcelibrary.tests"
+    >
+  <include package="zc.resourcelibrary.tests" file="ftesting.zcml" />
+  <include package="grok"/>
+
+  <!-- Typical functional testing security setup -->
+  <securityPolicy
+      component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy"
+      />
+
+  <unauthenticatedPrincipal
+      id="zope.anybody"
+      title="Unauthenticated User"
+      />
+  <grant
+      permission="zope.View"
+      principal="zope.anybody"
+      />
+  <principal
+      id="zope.mgr"
+      title="Manager"
+      login="mgr"
+      password="mgrpw"
+      />
+
+  <role id="zope.Manager" title="Site Manager" />
+  <grantAll role="zope.Manager" />
+  <grant role="zope.Manager" principal="zope.mgr" />
+  
+</configure>

Added: megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/tests.py
===================================================================
--- megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/tests.py	                        (rev 0)
+++ megrok.resourcelibrary/trunk/src/megrok/resourcelibrary/tests/tests.py	2008-08-06 16:27:01 UTC (rev 89450)
@@ -0,0 +1,27 @@
+import os
+import unittest, doctest
+from zope.app.testing import functional
+from zope.testing import module, cleanup
+
+ResourceLibraryFunctionalLayer = functional.ZCMLLayer(
+    os.path.join(os.path.split(__file__)[0], 'ftesting.zcml'),
+    __name__, 'ResourceLibraryFunctionalLayer')
+    
+def setUp(test):
+    module.setUp(test, 'megrok.resourcelibrary.tests')
+
+def tearDown(test):
+    module.tearDown(test)
+    cleanup.cleanUp()
+
+def test_suite():
+    suite = functional.FunctionalDocFileSuite(
+        '../README.txt',
+        optionflags=doctest.NORMALIZE_WHITESPACE + doctest.ELLIPSIS,
+        setUp=setUp,
+        tearDown=tearDown,
+        )
+    suite.layer = ResourceLibraryFunctionalLayer
+    return unittest.TestSuite([
+        suite,
+        ])



More information about the Checkins mailing list