summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2008-09-04 05:58:05 +0000
committerChris McDonough <chrism@agendaless.com>2008-09-04 05:58:05 +0000
commit23756f9943958e957270ad84912dc074ddc3b026 (patch)
tree936a47d40f5f5df1c1b9d89bc2c627e27148ccda
parent6f97fecf3b0a4fa9f3cb193b6efad3fc6fd67d44 (diff)
downloadpyramid-23756f9943958e957270ad84912dc074ddc3b026.tar.gz
pyramid-23756f9943958e957270ad84912dc074ddc3b026.tar.bz2
pyramid-23756f9943958e957270ad84912dc074ddc3b026.zip
- Allow configuration cache to be bypassed by actions which include
special "uncacheable" discriminators (for actions that have variable results).
-rw-r--r--CHANGES.txt4
-rw-r--r--repoze/bfg/registry.py13
-rw-r--r--repoze/bfg/tests/test_registry.py19
-rw-r--r--repoze/bfg/tests/test_zcml.py53
-rw-r--r--repoze/bfg/zcml.py28
5 files changed, 94 insertions, 23 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index c4ae68324..332b2b3b3 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,10 @@ Next Release
- Add startup process docs.
+ - Allow configuration cache to be bypassed by actions which include
+ special "uncacheable" discriminators (for actions that have
+ variable results).
+
Bug Fixes
- Move core repoze.bfg ZCML into a ``repoze.bfg.includes`` package so we can
diff --git a/repoze/bfg/registry.py b/repoze/bfg/registry.py
index 7d27a7126..6afd8de6c 100644
--- a/repoze/bfg/registry.py
+++ b/repoze/bfg/registry.py
@@ -50,13 +50,13 @@ def makeRegistry(filename, package, options=None, lock=threading.Lock()):
try:
registry = Components(package.__name__)
registry_manager.set(registry)
- original_getSiteManager.sethook(getSiteManager)
- zope.component.getGlobalSiteManager = registry_manager.get
- zcml_configure(filename, package=package)
if options is None:
options = {}
settings = Settings(options)
registry.registerUtility(settings, ISettings)
+ original_getSiteManager.sethook(getSiteManager)
+ zope.component.getGlobalSiteManager = registry_manager.get
+ zcml_configure(filename, package=package)
return registry
finally:
zope.component.getGlobalSiteManager = getGlobalSiteManager
@@ -66,7 +66,7 @@ def makeRegistry(filename, package, options=None, lock=threading.Lock()):
class Settings(object):
implements(ISettings)
def __init__(self, options):
- self.reload_templates = options.get('reload_templates', False)
+ self.__dict__.update(options)
def getSiteManager(context=None):
if context is None:
@@ -82,8 +82,9 @@ def asbool(s):
return s.lower() in ('t', 'true', 'y', 'yes', 'on', '1')
def get_options(kw):
- reload_templates = asbool(kw.get('reload_templates'))
- return {'reload_templates':reload_templates}
+ return {
+ 'reload_templates':asbool(kw.get('reload_templates')),
+ }
from zope.testing.cleanup import addCleanUp
try:
diff --git a/repoze/bfg/tests/test_registry.py b/repoze/bfg/tests/test_registry.py
index de8481fd8..efc99b41a 100644
--- a/repoze/bfg/tests/test_registry.py
+++ b/repoze/bfg/tests/test_registry.py
@@ -42,17 +42,16 @@ class TestGetOptions(unittest.TestCase):
from repoze.bfg.registry import get_options
return get_options
- def test_it(self):
+ def test_reload_templates(self):
get_options = self._getFUT()
- self.assertEqual(get_options({}),
- {'reload_templates':False})
- self.assertEqual(get_options({'reload_templates':'false'}),
- {'reload_templates':False})
- self.assertEqual(get_options({'reload_templates':'t'}),
- {'reload_templates':True})
- self.assertEqual(get_options({'reload_templates':'1'}),
- {'reload_templates':True})
-
+ result = get_options({})
+ self.assertEqual(result['reload_templates'], False)
+ result = get_options({'reload_templates':'false'})
+ self.assertEqual(result['reload_templates'], False)
+ result = get_options({'reload_templates':'t'})
+ self.assertEqual(result['reload_templates'], True)
+ result = get_options({'reload_templates':'1'})
+ self.assertEqual(result['reload_templates'], True)
class TestThreadLocalRegistryManager(unittest.TestCase, PlacelessSetup):
def setUp(self):
diff --git a/repoze/bfg/tests/test_zcml.py b/repoze/bfg/tests/test_zcml.py
index 28ea04ff6..158743c64 100644
--- a/repoze/bfg/tests/test_zcml.py
+++ b/repoze/bfg/tests/test_zcml.py
@@ -57,7 +57,7 @@ class TestViewDirective(unittest.TestCase, PlacelessSetup):
self.assertEqual(permission['args'][5], None)
regadapt = actions[2]
- regadapt_discriminator = ('view', IFoo, '', IRequest, IView)
+ regadapt_discriminator = ('view', IFoo, '', IRequest, IView, True)
self.assertEqual(regadapt['discriminator'], regadapt_discriminator)
self.assertEqual(regadapt['callable'], handler)
self.assertEqual(regadapt['args'][0], 'registerAdapter')
@@ -104,7 +104,34 @@ class TestViewDirective(unittest.TestCase, PlacelessSetup):
self.assertEqual(permission['args'][5], None)
regadapt = actions[2]
- regadapt_discriminator = ('view', IFoo, '', IDummy, IView)
+ regadapt_discriminator = ('view', IFoo, '', IDummy, IView, True)
+ self.assertEqual(regadapt['discriminator'], regadapt_discriminator)
+ self.assertEqual(regadapt['callable'], handler)
+ self.assertEqual(regadapt['args'][0], 'registerAdapter')
+ self.assertEqual(regadapt['args'][1], view)
+ self.assertEqual(regadapt['args'][2], (IFoo, IDummy))
+ self.assertEqual(regadapt['args'][3], IView)
+ self.assertEqual(regadapt['args'][4], '')
+ self.assertEqual(regadapt['args'][5], None)
+
+ def test_uncacheable(self):
+ f = self._getFUT()
+ context = DummyContext()
+ class IFoo:
+ pass
+ def view(context, request):
+ pass
+ f(context, 'repoze.view', IFoo, view=view, request_type=IDummy,
+ cacheable=False)
+ actions = context.actions
+ from repoze.bfg.interfaces import IView
+ from zope.component.zcml import handler
+ from repoze.bfg.zcml import Uncacheable
+
+ self.assertEqual(len(actions), 3)
+
+ regadapt = actions[2]
+ regadapt_discriminator = ('view', IFoo, '', IDummy, IView, Uncacheable)
self.assertEqual(regadapt['discriminator'], regadapt_discriminator)
self.assertEqual(regadapt['callable'], handler)
self.assertEqual(regadapt['args'][0], 'registerAdapter')
@@ -180,6 +207,28 @@ class TestZCMLPickling(unittest.TestCase, PlacelessSetup):
actions = cPickle.load(open(picklename, 'rb'))
self.failUnless(actions)
+ def test_file_configure_uncacheable_removes_cache(self):
+ import os
+ from repoze.bfg.zcml import file_configure
+ picklename = os.path.join(self.packagepath, 'configure.zcml.cache')
+ f = open(picklename, 'w')
+ f.write('imhere')
+ self.failUnless(os.path.exists(picklename))
+
+ import repoze.bfg.zcml
+ keep_view = repoze.bfg.zcml.view
+
+ def wrap_view(*arg, **kw):
+ kw['cacheable'] = False
+ return keep_view(*arg, **kw)
+
+ try:
+ repoze.bfg.zcml.view = wrap_view
+ file_configure('configure.zcml', self.module)
+ self.failIf(os.path.exists(picklename)) # should be deleted
+ finally:
+ repoze.bfg.zcml.view = keep_view
+
def test_file_configure_nonexistent_configure_dot_zcml(self):
import os
from repoze.bfg.zcml import file_configure
diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py
index 4a0094dc3..a2a063603 100644
--- a/repoze/bfg/zcml.py
+++ b/repoze/bfg/zcml.py
@@ -22,12 +22,17 @@ from repoze.bfg.path import package_path
from repoze.bfg.security import ViewPermissionFactory
+class Uncacheable(object):
+ """ Include in discriminators of actions which are not cacheable """
+ pass
+
def view(_context,
permission=None,
for_=None,
view=None,
name="",
request_type=IRequest,
+ cacheable=True,
):
if not view:
@@ -43,7 +48,7 @@ def view(_context,
if permission:
pfactory = ViewPermissionFactory(permission)
_context.action(
- discriminator = ('permission', for_,name, request_type,
+ discriminator = ('permission', for_, name, request_type,
IViewPermission),
callable = handler,
args = ('registerAdapter',
@@ -51,8 +56,10 @@ def view(_context,
_context.info),
)
+ cacheable = cacheable or Uncacheable
+
_context.action(
- discriminator = ('view', for_, name, request_type, IView),
+ discriminator = ('view', for_, name, request_type, IView, cacheable),
callable = handler,
args = ('registerAdapter',
view, (for_, request_type), IView, name,
@@ -93,7 +100,7 @@ class IViewDirective(Interface):
required=False
)
-PVERSION = 0
+PVERSION = 1
def pickle_name(name, package):
path = package_path(package)
@@ -127,9 +134,9 @@ def zcml_configure(name, package, load=cPickle.load):
files = set()
for action in actions:
- # files list used by pickled action is an element of the tuple
try:
- files.update(action[4])
+ fileset = action[4]
+ files.update(fileset)
except (TypeError, IndexError):
return file_configure(name, package)
@@ -145,6 +152,7 @@ def zcml_configure(name, package, load=cPickle.load):
context = zope.configuration.config.ConfigurationMachine()
xmlconfig.registerCommonDirectives(context)
context.actions = actions
+ context.cached_execution = True
context.execute_actions()
return True
@@ -159,6 +167,16 @@ def file_configure(name, package, dump=cPickle.dump):
actions = context.actions
pckname = pickle_name(name, package)
+ for action in actions:
+
+ discriminator = action[0]
+ if discriminator and Uncacheable in discriminator:
+ try:
+ os.remove(pckname)
+ except:
+ pass
+ return False
+
try:
data = (PVERSION, time.time(), actions)
dump(data, open(pckname, 'wb'), -1)