summaryrefslogtreecommitdiff
path: root/repoze
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2008-08-17 17:32:54 +0000
committerChris McDonough <chrism@agendaless.com>2008-08-17 17:32:54 +0000
commit0e21c22166f5160a2a64fad714d69d81897ef7d3 (patch)
tree6a576d0edfafe0e204a1770c094f13ff8aa74487 /repoze
parent157721dda97f5aea95f40e307d9d5dceb1014f83 (diff)
downloadpyramid-0e21c22166f5160a2a64fad714d69d81897ef7d3.tar.gz
pyramid-0e21c22166f5160a2a64fad714d69d81897ef7d3.tar.bz2
pyramid-0e21c22166f5160a2a64fad714d69d81897ef7d3.zip
- Add ``<bfg:settings>`` directive. This directive currently allows
only one attribute: ``reload_templates``. If e.g.:: <bfg:settings reload_templates="true"/> is in your application's ZCML, you will not need to restart the appserver in order for ``z3c.pt`` or XSLT template changes to be detected and displayed.
Diffstat (limited to 'repoze')
-rw-r--r--repoze/bfg/interfaces.py7
-rw-r--r--repoze/bfg/meta.zcml6
-rw-r--r--repoze/bfg/sampleapp/configure.zcml3
-rw-r--r--repoze/bfg/template.py33
-rw-r--r--repoze/bfg/tests/test_zcml.py31
-rw-r--r--repoze/bfg/zcml.py27
6 files changed, 94 insertions, 13 deletions
diff --git a/repoze/bfg/interfaces.py b/repoze/bfg/interfaces.py
index 4f1a203df..3a4c45373 100644
--- a/repoze/bfg/interfaces.py
+++ b/repoze/bfg/interfaces.py
@@ -27,7 +27,7 @@ class ITraverserFactory(Interface):
""" Return an object that implements IPublishTraverser """
class ITemplateFactory(Interface):
- def __call__(path):
+ def __call__(path, auto_reload=False):
""" Return an an ITemplate given a filesystem path """
class ITemplate(Interface):
@@ -79,3 +79,8 @@ class INewResponse(Interface):
""" An event type that is emitted whenever any repoze.bfg view
returns a response."""
response = Attribute('The response object')
+
+class ISettings(Interface):
+ """ Runtime settings for repoze.bfg """
+ reload_templates = Attribute('Reload templates when they change')
+
diff --git a/repoze/bfg/meta.zcml b/repoze/bfg/meta.zcml
index 72e963ae6..91b4f40e8 100644
--- a/repoze/bfg/meta.zcml
+++ b/repoze/bfg/meta.zcml
@@ -10,6 +10,12 @@
handler=".zcml.view"
/>
+ <meta:directive
+ name="settings"
+ schema=".zcml.ISettingsDirective"
+ handler=".zcml.settings"
+ />
+
</meta:directives>
</configure>
diff --git a/repoze/bfg/sampleapp/configure.zcml b/repoze/bfg/sampleapp/configure.zcml
index a5f27595e..d20d7d8f9 100644
--- a/repoze/bfg/sampleapp/configure.zcml
+++ b/repoze/bfg/sampleapp/configure.zcml
@@ -4,6 +4,9 @@
<include package="repoze.bfg" />
+ <bfg:settings
+ reload_templates="true"/>
+
<utility
provides="repoze.bfg.interfaces.ISecurityPolicy"
factory="repoze.bfg.security.RemoteUserACLSecurityPolicy"
diff --git a/repoze/bfg/template.py b/repoze/bfg/template.py
index 3c60dd19e..de049f5fa 100644
--- a/repoze/bfg/template.py
+++ b/repoze/bfg/template.py
@@ -13,14 +13,19 @@ from zope.interface import implements
from repoze.bfg.interfaces import ITemplateFactory
from repoze.bfg.interfaces import ITemplate
from repoze.bfg.interfaces import INodeTemplate
+from repoze.bfg.interfaces import ISettings
class Z3CPTTemplateFactory(object):
classProvides(ITemplateFactory)
implements(ITemplate)
- def __init__(self, path):
+ def __init__(self, path, auto_reload=False):
from z3c.pt import PageTemplateFile
- self.template = PageTemplateFile(path)
+ try:
+ self.template = PageTemplateFile(path, auto_reload=auto_reload)
+ except TypeError:
+ # z3c.pt before 1.0
+ self.template = PageTemplateFile(path)
def __call__(self, **kw):
result = self.template.render(**kw)
@@ -30,11 +35,12 @@ class XSLTemplateFactory(object):
classProvides(ITemplateFactory)
implements(INodeTemplate)
- def __init__(self, path):
+ def __init__(self, path, auto_reload=False):
self.path = path
+ self.auto_reload = auto_reload
def __call__(self, node, **kw):
- processor = get_processor(self.path)
+ processor = get_processor(self.path, self.auto_reload)
result = str(processor(node, **kw))
return result
@@ -42,13 +48,14 @@ class XSLTemplateFactory(object):
import threading
from lxml import etree
xslt_pool = threading.local()
-def get_processor(xslt_fn):
- try:
- return xslt_pool.processors[xslt_fn]
- except AttributeError:
- xslt_pool.processors = {}
- except KeyError:
- pass
+def get_processor(xslt_fn, auto_reload=False):
+ if not auto_reload:
+ try:
+ return xslt_pool.processors[xslt_fn]
+ except AttributeError:
+ xslt_pool.processors = {}
+ except KeyError:
+ pass
# Make a processor and add it to the pool
source = etree.ElementTree(file=xslt_fn)
@@ -74,7 +81,9 @@ def _get_template(path, **kw):
if template is None:
if not os.path.exists(path):
raise ValueError('Missing template file: %s' % path)
- template = Z3CPTTemplateFactory(path)
+ settings = queryUtility(ISettings)
+ auto_reload = settings and settings.reload_templates
+ template = Z3CPTTemplateFactory(path, auto_reload)
registerTemplate(ITemplate, template, path)
return template
diff --git a/repoze/bfg/tests/test_zcml.py b/repoze/bfg/tests/test_zcml.py
index 663022796..407eaf24e 100644
--- a/repoze/bfg/tests/test_zcml.py
+++ b/repoze/bfg/tests/test_zcml.py
@@ -114,6 +114,37 @@ class TestViewDirective(unittest.TestCase, PlacelessSetup):
self.assertEqual(regadapt['args'][4], '')
self.assertEqual(regadapt['args'][5], None)
+class TestSettingsDirective(unittest.TestCase, PlacelessSetup):
+ def setUp(self):
+ PlacelessSetup.setUp(self)
+
+ def tearDown(self):
+ PlacelessSetup.tearDown(self)
+
+ def _getFUT(self):
+ from repoze.bfg.zcml import settings
+ return settings
+
+ def test_defaults(self):
+ context = DummyContext()
+ settings = self._getFUT()
+ settings(context)
+ actions = context.actions
+ from repoze.bfg.interfaces import ISettings
+ from zope.component.zcml import handler
+ self.assertEqual(len(actions), 1)
+ action = actions[0]
+ self.assertEqual(action['discriminator'], ('settings', ISettings))
+ self.assertEqual(action['callable'], handler)
+ self.assertEqual(len(action['args']), 5)
+ self.assertEqual(action['args'][0], 'registerUtility')
+ settings = action['args'][1]
+ self.assertEqual(settings.reload_templates, False)
+ self.failUnless(ISettings.providedBy(settings), settings)
+ self.assertEqual(action['args'][2], ISettings)
+ self.assertEqual(action['args'][3], '')
+ self.assertEqual(action['args'][4], context.info)
+
class TestSampleApp(unittest.TestCase, PlacelessSetup):
def setUp(self):
PlacelessSetup.setUp(self)
diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py
index 343abc1d7..bb37c6581 100644
--- a/repoze/bfg/zcml.py
+++ b/repoze/bfg/zcml.py
@@ -2,17 +2,44 @@ from zope.component.zcml import handler
from zope.component.interface import provideInterface
from zope.configuration.exceptions import ConfigurationError
from zope.configuration.fields import GlobalObject
+from zope.configuration.fields import Bool
from zope.interface import Interface
+from zope.interface import implements
from zope.schema import TextLine
from repoze.bfg.interfaces import IRequest
from repoze.bfg.interfaces import IViewPermission
from repoze.bfg.interfaces import IView
+from repoze.bfg.interfaces import ISettings
from repoze.bfg.security import ViewPermissionFactory
+def _handler(*arg, **kw):
+ import pdb; pdb.set_trace()
+ return handler(*arg, **kw)
+
+class Settings(object):
+ implements(ISettings)
+ def __init__(self, reload_templates=False):
+ self.reload_templates = reload_templates
+
+def settings(_context, reload_templates=False):
+ settings = Settings(reload_templates=reload_templates)
+ _context.action(
+ discriminator = ('settings', ISettings),
+ callable = handler,
+ args = ('registerUtility', settings, ISettings, '', _context.info),
+ )
+
+class ISettingsDirective(Interface):
+ reload_templates = Bool(
+ title=u"Reload templates when they change",
+ description=(u"Specifies whether templates should be reloaded when"
+ "a change is made"),
+ default=False)
+
def view(_context,
permission=None,
for_=None,