Zope 2 as WSGI application
I held a tutorial on PyCon DE in Leipzig how to run Zope 2 as a WSGI application. I post it here, too, so you can try the tutorial yourself.
ZopeEditManager for Mac OS X Lion
The current binary distribution of ZopeEditManager no longer works on Mac OS X Lion (10.7): It is PowerPC code which is no longer supported. (The package included in MacPorts, does not build either.)
To built ZopeEditManager from the sources I did the following:
- Installed the needed libraries using MacPorts:
sudo port install py27-py2app py27-pyobjc py27-pyobjc-cocoa
- Downloaded ZopeEditManager sources.
- Extracted them and patched them using the Lion-Patch:
patch -p1 < ZopeEditManager-Lion.patch
- Compiled the application:
/opt/local/bin/python2.7 setup.py py2app
- Ran ZopeEditManager from the dist-directory:
I built a ZopeEditManger-0.9.8.dmg containing the result, so you do not have to do it yourself :)
LaTeX: Same footnote number for more than one footnote
To reuse the current footnote number in LaTeX use:
\footnotemark[\value{footnote}]Example:
Lorem ipsum\footnote{See somewere.} dolor sit amet, consectetur, adipisci
velit\footnotemark[\value{footnote}]Result:
Get package version
To get the version of a currently installed package you can use:
import pkg_resources
pkg_resources.get_distribution('my.package').versionGetting rid of zope.app.testing
The zope.app.package has many dependencies but there are "lighter" packages which do the same.
zope.app.wsgi
To get rid of a zope.app.testing test dependency by using zope.app.wsgi (version 3.7 or newer) two things are necessary:
1) Use zope.app.wsgi.testlayer to set up the test layer
Instead of:
import os from zope.app.testing.functional import ZCMLLayer MyLayer = ZCMLLayer( os.path.join(os.path.split(__file__)[0], 'ftesting.zcml'), __name__, 'MyLayer', allow_teardown=True)
do:
import zope.app.wsgi.testlayer import my.package MyLayer = zope.app.wsgi.testlayer.BrowserLayer(my.package)
2) Use zope.app.wsgi.testlayer.Browser for browser tests
In browser tests use instead of:
>>> from zope.testbrowser.testing import Browser
the following one:
>>> from zope.app.wsgi.testlayer import Browser
unittest resp. doctest
1) Use unittest.TestCase instead of zope.app.testing.functional.FunctionalTestCase
No longer subclass zope.app.testing.functional.FunctionalTestCase but use:
class FunctionalTestCase(unittest.TestCase):
"""Base class for functional tests."""
layer = MyLayerMyLayer is the one defined in zope.app.wsgi 1).
Inside such functional unittests use
self.layer.getRootFolder()
instead of:
self.getRootFolder()
2) Use doctest.DocFileSuite instead of zope.app.testing.functional.FunctionalDocFileSuite
You need an extra step in test_suite() function now:
def test_suits():
suite = doctest.DocFileSuite('my_doctest.txt')
suite.layer = MyLayerMyLayer is the one defined in zope.app.wsgi 1).
3) getRootFolder is no longer per default in the globals
When you need getRootFolder in a doctest you have to put layer.getRootFolder into globs keyword argument of the DocFileSuite of the test.
zope.testing
To get rid of:
import zope.app.testing.setup def setUp(test): zope.app.testing.setup.setUpTestAsModule(test, 'my.package.README') def tearDown(test): zope.app.testing.setup.tearDownTestAsModule(test)
use:
import zope.testing.module def setUp(test): zope.testing.module.setUp(test, 'my.package.README') def tearDown(test): zope.testing.module.tearDown(test, 'my.package.README')
zope.component
To get rid of:
from zope.app.testing.placelesssetup import PlacelessSetup from zope.app.testing.placelesssetup import setUp, tearDown
it is enough to use (at least in the majority of cases):
from zope.component.testing import PlacelessSetup from zope.component.testing import setUp, tearDown
"unevolve" zope.app.generations
To set the zope.app.generations counter to a previous value generate an evolve step like this:
import transaction
MY_KEY = u'uc/dgb.internet'
BACK_TO = 38
def evolve(context):
context.connection.root()['zope.app.generations'][MY_KEY] = BACK_TO
transaction.commit()
transaction.doom()MY_KEY is the key used for your application. (I'm currently not sure how it is computed.) BACK_TO is the target generation. This generation fails because of the transaction.doom() but it saved the value of the key before.


