[Checkins] SVN: z3c.reload/trunk/ Here is a renamed,
packaged and modernized version of the original
Stephan Richter
srichter at cosmos.phy.tufts.edu
Mon Aug 11 02:43:08 EDT 2008
Log message for revision 89636:
Here is a renamed, packaged and modernized version of the original
z3reload code.
Changed:
A z3c.reload/trunk/
A z3c.reload/trunk/CHANGES.txt
A z3c.reload/trunk/README.txt
A z3c.reload/trunk/bootstrap.py
A z3c.reload/trunk/buildout.cfg
A z3c.reload/trunk/setup.py
A z3c.reload/trunk/src/
A z3c.reload/trunk/src/z3c/
A z3c.reload/trunk/src/z3c/__init__.py
A z3c.reload/trunk/src/z3c/reload/
A z3c.reload/trunk/src/z3c/reload/README.txt
A z3c.reload/trunk/src/z3c/reload/__init__.py
A z3c.reload/trunk/src/z3c/reload/configure.zcml
A z3c.reload/trunk/src/z3c/reload/meta.zcml
A z3c.reload/trunk/src/z3c/reload/metaconfigure.py
A z3c.reload/trunk/src/z3c/reload/metadirectives.py
A z3c.reload/trunk/src/z3c/reload/reload.py
A z3c.reload/trunk/src/z3c/reload/subscriber.py
A z3c.reload/trunk/src/z3c/reload/tests/
A z3c.reload/trunk/src/z3c/reload/tests/__init__.py
A z3c.reload/trunk/src/z3c/reload/tests/application.zcml
A z3c.reload/trunk/src/z3c/reload/tests/dynamic.pt
A z3c.reload/trunk/src/z3c/reload/tests/dynamic.py
A z3c.reload/trunk/src/z3c/reload/tests/dynamic_orig.py
A z3c.reload/trunk/src/z3c/reload/tests/ftesting.zcml
A z3c.reload/trunk/src/z3c/reload/tests/reload.txt
A z3c.reload/trunk/src/z3c/reload/tests/tests.py
-=-
Added: z3c.reload/trunk/CHANGES.txt
===================================================================
--- z3c.reload/trunk/CHANGES.txt (rev 0)
+++ z3c.reload/trunk/CHANGES.txt 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,8 @@
+=======
+CHANGES
+=======
+
+Version 0.1.0 (2008-08-??)
+--------------------------
+
+- Initial Release
Property changes on: z3c.reload/trunk/CHANGES.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.reload/trunk/README.txt
===================================================================
--- z3c.reload/trunk/README.txt (rev 0)
+++ z3c.reload/trunk/README.txt 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,2 @@
+A package that automatically reloads view code on the fly eithout the need to
+restart a server.
Property changes on: z3c.reload/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.reload/trunk/bootstrap.py
===================================================================
--- z3c.reload/trunk/bootstrap.py (rev 0)
+++ z3c.reload/trunk/bootstrap.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2007 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$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+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)
Property changes on: z3c.reload/trunk/bootstrap.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/buildout.cfg
===================================================================
--- z3c.reload/trunk/buildout.cfg (rev 0)
+++ z3c.reload/trunk/buildout.cfg 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,24 @@
+[buildout]
+develop = .
+parts = test coverage-test coverage-report python
+index = http://download.zope.org/zope3.4
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.reload [test]
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = z3c.reload [test]
+defaults = ['--coverage', '../../coverage']
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')
+
+[python]
+recipe = zc.recipe.egg
+interpreter = python
+eggs = z3c.reload
Added: z3c.reload/trunk/setup.py
===================================================================
--- z3c.reload/trunk/setup.py (rev 0)
+++ z3c.reload/trunk/setup.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,75 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation 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.
+#
+##############################################################################
+"""Setup
+
+$Id$
+"""
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+ return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+setup (
+ name='z3c.reload',
+ version='0.1.0dev',
+ author = "Gintautas Miliauskas and the Zope Community",
+ author_email = "zope3-dev at zope.org",
+ description = "Automatic View Reload",
+ long_description=(
+ read('README.txt')
+ + '\n\n' +
+ 'Detailed Documentation\n'
+ '**********************'
+ + '\n\n' +
+ read('src', 'z3c', 'reload', 'README.txt')
+ + '\n\n' +
+ read('CHANGES.txt')
+ ),
+ license = "ZPL 2.1",
+ keywords = "zope3 view reload",
+ classifiers = [
+ 'Development Status :: 4 - Beta',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: Zope Public License',
+ 'Programming Language :: Python',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Framework :: Zope3'],
+ url = 'http://pypi.python.org/pypi/z3c.reload',
+ packages = find_packages('src'),
+ package_dir = {'':'src'},
+ namespace_packages = ['z3c'],
+ extras_require = dict(
+ test = ['zope.testing',
+ 'zope.securitypolicy',
+ 'zope.app.testing',
+ 'zope.app.twisted',
+ 'z3c.coverage',
+ 'zc.configuration'],
+ ),
+ install_requires = [
+ 'setuptools',
+ 'zope.component',
+ 'zope.configuration',
+ 'zope.interface',
+ 'zope.publisher',
+ 'zope.app.pagetemplate',
+ 'zope.app.publisher'
+ ],
+ include_package_data = True,
+ zip_safe = False,
+ )
Property changes on: z3c.reload/trunk/setup.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/src/z3c/__init__.py
===================================================================
--- z3c.reload/trunk/src/z3c/__init__.py (rev 0)
+++ z3c.reload/trunk/src/z3c/__init__.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,7 @@
+try:
+ # Declare this a namespace package if pkg_resources is available.
+ import pkg_resources
+ pkg_resources.declare_namespace('z3c')
+except ImportError:
+ pass
+
Property changes on: z3c.reload/trunk/src/z3c/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/src/z3c/reload/README.txt
===================================================================
--- z3c.reload/trunk/src/z3c/reload/README.txt (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/README.txt 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,108 @@
+===========
+View Reload
+===========
+
+z3reload is a Zope 3 product that enables automatic reloading of view code.
+
+Make sure to read the *pitfalls* section before you delve in.
+
+View instances are short-lived and references to them are stored very
+infrequently, which makes them a good candidate for dynamic reloading.
+In addition they are frequently the largest and most complex part of
+the code in a typical web application. Even within the restrictions of
+this implementation automatic code reloading is very handy to have as Zope 3
+can take a while to restart.
+
+Installation
+------------
+
+Copy the z3reload directory where Zope 3 can find it, copy all files in
+the package-includes/ subdirectory to package-includes/ in Zope 3.
+
+
+Configuration
+-------------
+
+In package-includes/z3reload-configure.zcml (the global one which you created,
+not the one inside the package), the namespace `reload` should be registered,
+like this:
+
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:z3c="http://namespaces.zope.org/z3c">
+
+In the same file you can specify individual classes, modules or packages which
+contain views that should be made reloadable using the ZCML directive
+`reload`. Here is an example:
+
+<z3c:reload
+ classes="somepackage.somemodule.SomeView
+ somepackage.anothermodule.AnotherView"
+ modules="anotherpackage.views"
+ packages="thirdpackage.browser"
+ />
+
+This configuration would make views SomeView and AnotherView reloadable.
+All views directly in anotherpackage.views, for example,
+anotherpackage.views.FooView (but not `anotherpackage.views.admin.BarView`),
+would be included too. Finally, all views in all modules that reside
+in thirdpackage.browser would be processed (`thirdpackage.browser.XView`,
+`thirdpackage.browser.admin.YView`, etc.).
+
+
+Usage
+-----
+
+Use the views as you normally would. The view code will be automatically
+reloaded before just before rendering the view each time.
+
+
+Pitfalls
+--------
+
+Only the module that the view code resides in will be reloaded. E.g., if
+you have a view `mypackage.browser.admin.AdminView` that inherits from
+`mypackage.browser.ViewBase`, the `mypackage.browser` module will not be
+reloaded, and therefore changes in ViewBase will not take effect.
+
+It is important to understand the implications of reloading a Python module.
+Basically, all objects -- classes, functions and others -- defined in the top
+level of the module "change". Old references (frequently in the form of
+imports) from other modules, however, will still point to the old objects.
+This way you can end up with two different references to distinct versions of
+the same class, which may cause unexpected behaviour with issubclass(). A
+similar problem can arise if the module defines interfaces which other modules
+use.
+
+`z3c.reload` can deal with updated views, but it will not notice changes in
+other components: adapters, utilities, subscribers. It will work with code
+outside the components (top-level functions and classes other than the
+registered one) though. This is because Zope 3 stores references to the
+components at startup time. It should be possible to reload these components
+automatically too, but that would probably require a different approach,
+because we would not be able not use the mixin hack.
+
+In general it is a good idea to only use automatic reloading for
+non-structural changes such as defining or modifying methods of views and do
+an old-fashioned server restart when you make a more significant change.
+
+
+Implementation details
+----------------------
+
+`z3c.reload` waits for the DatabaseOpened event, when all view registration
+has been completed, and then walks through the global adapter registry. For
+each view to be processed according to the `reload` directive it installs the
+mixin Reloader.
+
+Actually, Zope 3 ZCML directives that register views do not register the plain
+view class as a multi-adapter. Instead, they dynamically construct a new type
+which inherits from the given class and from a `simple view` class (that would
+be `zope.app.pagetemplate.simpleviewclass.simple` for views that have page
+templates defined in ZCML, and `zope.app.publisher.browser.viewmeta.simple`
+for views that don't). We use this fact and add Reloader as the first base
+class.
+
+Reloader overrides the ``__init__()`` method of the real view. In this method
+the module of the class is reloaded and the attribute ``__bases__`` of the
+class is updated with a new reference to the reloaded class. Then
+``__init__`` of the actual reloaded view is invoked.
Property changes on: z3c.reload/trunk/src/z3c/reload/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.reload/trunk/src/z3c/reload/__init__.py
===================================================================
--- z3c.reload/trunk/src/z3c/reload/__init__.py (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/__init__.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,2 @@
+# Set this to True to list processed view classes on stderr.
+BLATHER = False
Property changes on: z3c.reload/trunk/src/z3c/reload/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/src/z3c/reload/configure.zcml
===================================================================
--- z3c.reload/trunk/src/z3c/reload/configure.zcml (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/configure.zcml 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<configure xmlns="http://namespaces.zope.org/zope">
+
+ <subscriber
+ for="zope.app.appsetup.interfaces.IDatabaseOpenedEvent"
+ handler=".subscriber.database_opened"
+ />
+
+</configure>
Property changes on: z3c.reload/trunk/src/z3c/reload/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.reload/trunk/src/z3c/reload/meta.zcml
===================================================================
--- z3c.reload/trunk/src/z3c/reload/meta.zcml (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/meta.zcml 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,11 @@
+<configure xmlns="http://namespaces.zope.org/meta">
+
+ <directives namespace="http://namespaces.zope.org/z3c">
+ <directive
+ name="reload"
+ schema=".metadirectives.IReloadDirective"
+ handler=".metaconfigure.reload"
+ />
+ </directives>
+
+</configure>
Property changes on: z3c.reload/trunk/src/z3c/reload/meta.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.reload/trunk/src/z3c/reload/metaconfigure.py
===================================================================
--- z3c.reload/trunk/src/z3c/reload/metaconfigure.py (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/metaconfigure.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,23 @@
+import sys
+from zope.configuration.exceptions import ConfigurationError
+
+
+enabled_classes = [] # list of class objects
+enabled_modules = [] # list of module names
+enabled_packages = [] # list of package names
+
+
+def handle_reload(classes, modules, packages):
+ """Add provided objects to global registry of reloadable objects."""
+ enabled_classes.extend(classes)
+ enabled_modules.extend([mod.__name__ for mod in modules])
+ enabled_packages.extend([pkg.__name__ for pkg in packages])
+
+
+def reload(_context, classes=[], modules=[], packages=[]):
+ """Process the `reload` ZCML directive."""
+ if not (classes or modules or packages):
+ raise ConfigurationError("You must specify at least one of"
+ " `classes`, `modules` or `packages`.")
+ _context.action(discriminator=None, callable=handle_reload,
+ args=(classes, modules, packages))
Property changes on: z3c.reload/trunk/src/z3c/reload/metaconfigure.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/src/z3c/reload/metadirectives.py
===================================================================
--- z3c.reload/trunk/src/z3c/reload/metadirectives.py (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/metadirectives.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,37 @@
+from zope.interface import Interface
+from zope.configuration.fields import Tokens, GlobalObject
+
+
+class IReloadDirective(Interface):
+
+ classes = Tokens(
+ title=u"View classes",
+ required=False,
+ value_type=GlobalObject(
+ title=u"View class",
+ description=u"""
+ A view class for which automatic reload should be enabled.
+ """))
+
+ modules = Tokens(
+ title=u"Modules",
+ required=False,
+ value_type=GlobalObject(
+ title=u"Module",
+ description=u"""
+ A module containing views for which automatic reload should be
+ enabled.
+ """))
+
+ packages = Tokens(
+ title=u"Packages",
+ required=False,
+ value_type=GlobalObject(
+ title=u"Package",
+ description=u"""
+ A package containing views for which automatic reload should be
+ enabled.
+
+ `module` only works for a single module, whereas `package` also
+ applies for contained modules and packages.
+ """))
Property changes on: z3c.reload/trunk/src/z3c/reload/metadirectives.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/src/z3c/reload/reload.py
===================================================================
--- z3c.reload/trunk/src/z3c/reload/reload.py (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/reload.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,78 @@
+import sys
+from zope.app.pagetemplate.simpleviewclass import simple as SimplePTPage
+from zope.app.publisher.browser.viewmeta import simple as SimplePage
+
+from z3c.reload import BLATHER
+
+simple_view_classes = (SimplePTPage, SimplePage)
+
+
+class Reloader(object):
+ """A mixin to be used on SimpleViewClass instances.
+
+ These SimpleViewClass instances are in fact dynamically constructed types
+ with either zope.app.pagetemplate.simpleviewclass.simple or
+ zope.app.publisher,browser.viewmeta as one of the base classes.
+
+ This mixin must be the first superclass, because its __init__ must be
+ called on instantiation.
+ """
+
+ def __init__(self, *args, **kw):
+ bases = self.__class__.__bases__
+ assert len(bases) >= 2
+ reloader2, real_view = bases[:2]
+ assert reloader2 is Reloader
+
+ rest = bases[2:]
+
+ clsname = real_view.__name__
+ modname = real_view.__module__
+ module = sys.modules[modname]
+ if hasattr(module, clsname):
+ reload(module)
+ new_view = getattr(module, clsname)
+ self.__class__.__bases__ = (Reloader, new_view) + rest
+ else:
+ # If the module does not have such an attribute, chances are that
+ # the class was dynamically constructed. In this case reloading is
+ # likely to break so we don't do it.
+ new_view = real_view # just use the old view
+
+ self.__sanitize_bases(new_view)
+ new_view.__init__(self, *args, **kw)
+
+ def __sanitize_bases(self, cls):
+ """Make sure that the bases of a class are in the scope.
+
+ This works around the problem when a class bases do not correspond
+ to the same-named classes in the scope, which could happen after a
+ reload. This causes errors when invoking base clases
+ """
+ modname = cls.__module__
+ module = sys.modules[modname]
+
+ bases = cls.__bases__
+ new_bases = []
+ for b in bases:
+ bc = getattr(module, b.__name__, None)
+ if bc is not None and bc.__module__ != modname:
+ # Make sure that the base class comes from a different module.
+ new_base = getattr(module, b.__name__)
+ self.__sanitize_bases(new_base)
+ new_bases.append(new_base)
+ else:
+ # Couldn't find class in local scope, abort.
+ break
+ else:
+ # All bases checked successfully.
+ cls.__bases__ = tuple(new_bases)
+
+
+
+def install_reloader(view_class):
+ """Install the Reloader mixin on view_class."""
+ assert view_class.__bases__[-1] in simple_view_classes
+ if BLATHER:
+ print >> sys.stderr, 'Reloader installed for', view_class.__bases__[0]
+ view_class.__bases__ = (Reloader, ) + view_class.__bases__
Property changes on: z3c.reload/trunk/src/z3c/reload/reload.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/src/z3c/reload/subscriber.py
===================================================================
--- z3c.reload/trunk/src/z3c/reload/subscriber.py (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/subscriber.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,52 @@
+import sys
+
+from zope.component import getGlobalSiteManager
+from zope.publisher.interfaces import IRequest
+from zope.component.registry import AdapterRegistration
+
+from z3c.reload.reload import install_reloader, simple_view_classes
+from z3c.reload.metaconfigure import enabled_classes, enabled_modules
+from z3c.reload.metaconfigure import enabled_packages
+
+request_type = IRequest
+
+
+def is_simple_view(reg):
+ """Return True if reg is a registration for a `simple` view.
+
+ A `simple` view is one that subclasses one of simple_view_classes.
+ """
+ if not (isinstance(reg, AdapterRegistration) and
+ len(reg.required) > 0 and
+ reg.required[-1] is not None and
+ reg.required[-1].isOrExtends(IRequest)):
+ return False # this registration does not appear to be a view
+
+ return (type(reg.factory) == type and
+ issubclass(reg.factory, simple_view_classes))
+
+
+def reload_enabled_for(view_class):
+ """Return True if view_class should be made reloadable."""
+ assert view_class.__bases__[-1] in simple_view_classes
+ real_view = view_class.__bases__[0]
+ if real_view in enabled_classes:
+ return True
+ for module in enabled_modules:
+ if real_view.__module__ == module:
+ return True
+ for package in enabled_packages:
+ if real_view.__module__.startswith(package):
+ return True
+ return False
+
+
+def database_opened(event):
+ """Scan adapter registrations and make specified views reloadable.
+
+ Hooks on the DatabaseOpened event.
+ """
+ gsm = getGlobalSiteManager()
+ for reg in gsm.registeredAdapters():
+ if is_simple_view(reg) and reload_enabled_for(reg.factory):
+ install_reloader(reg.factory)
Property changes on: z3c.reload/trunk/src/z3c/reload/subscriber.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/src/z3c/reload/tests/__init__.py
===================================================================
Property changes on: z3c.reload/trunk/src/z3c/reload/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/src/z3c/reload/tests/application.zcml
===================================================================
--- z3c.reload/trunk/src/z3c/reload/tests/application.zcml (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/tests/application.zcml 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,47 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ i18n_domain="demo">
+
+ <include package="zope.app.component" file="meta.zcml" />
+ <include package="zope.app.component.browser" file="meta.zcml" />
+ <include package="zope.app.form.browser" file="meta.zcml" />
+ <include package="zope.app.pagetemplate" file="meta.zcml" />
+ <include package="zope.app.publication" file="meta.zcml" />
+ <include package="zope.app.publisher" file="meta.zcml" />
+ <include package="zope.app.security" file="meta.zcml" />
+ <include package="zope.securitypolicy" file="meta.zcml" />
+ <include package="z3c.reload" file="meta.zcml" />
+ <include package="zc.configuration" file="meta.zcml" />
+
+ <exclude package="zope.app.folder.browser" />
+
+ <browser:menu id="zmi_views" title="Views" />
+ <browser:menu id="zmi_actions" title="Actions" />
+
+ <include package="zope.app.appsetup" />
+ <include package="zope.app.component" />
+ <include package="zope.app.container" />
+ <include package="zope.app.error" />
+ <include package="zope.app.folder" />
+ <include package="zope.app.i18n" />
+ <include package="zope.app.publication" />
+ <include package="zope.app.security" />
+ <include package="zope.app.session" />
+ <include package="zope.app.twisted" />
+ <include package="zope.app.wsgi" />
+ <include package="zope.annotation" />
+ <include package="zope.component" />
+ <include package="zope.location" />
+ <include package="zope.publisher" />
+ <include package="zope.securitypolicy" />
+ <include package="zope.traversing" />
+ <include package="zope.traversing.browser" />
+ <include package="z3c.reload" />
+
+ <securityPolicy
+ component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+
+ <role id="zope.Anonymous" title="Everybody" />
+ <grantAll role="zope.Anonymous" />
+</configure>
Property changes on: z3c.reload/trunk/src/z3c/reload/tests/application.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.reload/trunk/src/z3c/reload/tests/dynamic.pt
===================================================================
--- z3c.reload/trunk/src/z3c/reload/tests/dynamic.pt (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/tests/dynamic.pt 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1 @@
+<p>The number is <span tal:replace="view/number" /></p>
Property changes on: z3c.reload/trunk/src/z3c/reload/tests/dynamic.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.reload/trunk/src/z3c/reload/tests/dynamic.py
===================================================================
--- z3c.reload/trunk/src/z3c/reload/tests/dynamic.py (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/tests/dynamic.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,19 @@
+from zope.publisher.browser import BrowserView
+
+
+class SomeNumberView(BrowserView):
+
+ def __init__(self, context, request):
+ BrowserView.__init__(self, context, request)
+ self.number = 1001
+
+
+class AnotherNumberView(BrowserView):
+
+ number = 2001
+
+
+class ThirdNumberView(BrowserView):
+
+ def __call__(self):
+ return '3001'
Property changes on: z3c.reload/trunk/src/z3c/reload/tests/dynamic.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/src/z3c/reload/tests/dynamic_orig.py
===================================================================
--- z3c.reload/trunk/src/z3c/reload/tests/dynamic_orig.py (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/tests/dynamic_orig.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,19 @@
+from zope.publisher.browser import BrowserView
+
+
+class SomeNumberView(BrowserView):
+
+ def __init__(self, context, request):
+ BrowserView.__init__(self, context, request)
+ self.number = 1001
+
+
+class AnotherNumberView(BrowserView):
+
+ number = 2001
+
+
+class ThirdNumberView(BrowserView):
+
+ def __call__(self):
+ return '3001'
Property changes on: z3c.reload/trunk/src/z3c/reload/tests/dynamic_orig.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.reload/trunk/src/z3c/reload/tests/ftesting.zcml
===================================================================
--- z3c.reload/trunk/src/z3c/reload/tests/ftesting.zcml (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/tests/ftesting.zcml 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,26 @@
+<configure xmlns="http://namespaces.zope.org/browser"
+ xmlns:z3c="http://namespaces.zope.org/z3c"
+ package="z3c.reload.tests">
+
+ <include file="application.zcml" />
+
+ <z3c:reload modules="z3c.reload.tests.dynamic" />
+
+ <page for="zope.traversing.interfaces.IContainmentRoot"
+ name="some.html"
+ class=".dynamic.SomeNumberView"
+ template="dynamic.pt"
+ permission="zope.Public" />
+
+ <page for="zope.traversing.interfaces.IContainmentRoot"
+ name="another.html"
+ class=".dynamic.AnotherNumberView"
+ template="dynamic.pt"
+ permission="zope.Public" />
+
+ <page for="zope.traversing.interfaces.IContainmentRoot"
+ name="third.txt"
+ class=".dynamic.ThirdNumberView"
+ permission="zope.Public" />
+
+</configure>
Property changes on: z3c.reload/trunk/src/z3c/reload/tests/ftesting.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.reload/trunk/src/z3c/reload/tests/reload.txt
===================================================================
--- z3c.reload/trunk/src/z3c/reload/tests/reload.txt (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/tests/reload.txt 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,68 @@
+===============
+Reloading Views
+===============
+
+
+Quick look
+----------
+
+First, let's simply try looking at the views, to make sure that
+the configuration is correct.
+
+ >>> print http("GET /some.html HTTP/1.1\n", handle_errors=False)
+ HTTP/1.1 200 Ok
+ ...
+ <p>The number is 1001</p>
+ <BLANKLINE>
+
+ >>> print http("GET /another.html HTTP/1.1\n", handle_errors=False)
+ HTTP/1.1 200 Ok
+ ...
+ <p>The number is 2001</p>
+ <BLANKLINE>
+
+ >>> print http("GET /third.txt HTTP/1.1\n", handle_errors=False)
+ HTTP/1.1 200 Ok
+ ...
+ Content-Type: text/plain
+ <BLANKLINE>
+ 3001
+
+
+Modification
+------------
+
+Now we will modify the view code:
+
+ >>> from z3c.reload.tests.tests import openfile
+ >>> import time
+ >>> def replace(old, new):
+ ... time.sleep(1.0) # longish, but shorter delays don't seem to work
+ ... orig = openfile('dynamic_orig.py').read()
+ ... f = openfile('dynamic.py', 'w')
+ ... f.write(orig.replace(old, new))
+ ... f.close()
+ ... time.sleep(1.0) # longish, but shorter delays don't seem to work
+
+ >>> replace('1001', '1123')
+ >>> print http("GET /some.html HTTP/1.1\n", handle_errors=False)
+ HTTP/1.1 200 Ok
+ ...
+ <p>The number is 1123</p>
+ <BLANKLINE>
+
+ >>> replace('2001', '2123')
+ >>> print http("GET /another.html HTTP/1.1\n", handle_errors=False)
+ HTTP/1.1 200 Ok
+ ...
+ <p>The number is 2123</p>
+ <BLANKLINE>
+
+ >>> replace('3001', '3123')
+
+ >>> print http("GET /third.txt HTTP/1.1\n", handle_errors=False)
+ HTTP/1.1 200 Ok
+ ...
+ Content-Type: text/plain
+ <BLANKLINE>
+ 3123
Property changes on: z3c.reload/trunk/src/z3c/reload/tests/reload.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: z3c.reload/trunk/src/z3c/reload/tests/tests.py
===================================================================
--- z3c.reload/trunk/src/z3c/reload/tests/tests.py (rev 0)
+++ z3c.reload/trunk/src/z3c/reload/tests/tests.py 2008-08-11 06:43:07 UTC (rev 89636)
@@ -0,0 +1,48 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation 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.
+#
+##############################################################################
+"""
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import os
+import unittest
+from zope.testing import doctest
+from zope.app.testing import functional
+
+ReloadLayer = functional.ZCMLLayer(
+ os.path.join(os.path.split(__file__)[0], 'ftesting.zcml'),
+ __name__, 'ReloadLayer', allow_teardown=True)
+
+current_dir = os.path.dirname(__file__)
+
+def openfile(filename, mode='r'):
+ return file(os.path.join(current_dir, filename), mode)
+
+def resetFile(test):
+ dynamic_orig = openfile('dynamic_orig.py').read()
+ openfile('dynamic.py', 'w').write(dynamic_orig)
+
+
+def test_suite():
+ optionflags = (doctest.ELLIPSIS | doctest.REPORT_NDIFF |
+ doctest.NORMALIZE_WHITESPACE |
+ doctest.REPORT_ONLY_FIRST_FAILURE)
+ suite = functional.FunctionalDocFileSuite(
+ 'reload.txt',
+ setUp=resetFile, tearDown=resetFile,
+ optionflags=optionflags)
+ suite.layer = ReloadLayer
+ return unittest.TestSuite((
+ suite,
+ ))
Property changes on: z3c.reload/trunk/src/z3c/reload/tests/tests.py
___________________________________________________________________
Name: svn:keywords
+ Id
More information about the Checkins
mailing list