summaryrefslogtreecommitdiff
path: root/repoze/bfg/zcml.py
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2008-08-23 00:03:29 +0000
committerChris McDonough <chrism@agendaless.com>2008-08-23 00:03:29 +0000
commit434c0514dc7dd9c7881e1d30db4d988680220af2 (patch)
tree34cb5395ec0628ec216e54d863bc90fb8902ba5a /repoze/bfg/zcml.py
parentbe16f6b5c59043a164120171a5b0926d158959fd (diff)
downloadpyramid-434c0514dc7dd9c7881e1d30db4d988680220af2.tar.gz
pyramid-434c0514dc7dd9c7881e1d30db4d988680220af2.tar.bz2
pyramid-434c0514dc7dd9c7881e1d30db4d988680220af2.zip
- Read and write a pickled ZCML actions list, stored as
``configure.zcml.pck`` next to the applications's "normal" configuration file. A given bfg app will usually start faster if it's able to read the pickle data. It fails gracefully to reading the real ZCML file if it cannot read the pickle.
Diffstat (limited to 'repoze/bfg/zcml.py')
-rw-r--r--repoze/bfg/zcml.py85
1 files changed, 85 insertions, 0 deletions
diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py
index 343abc1d7..0bb049516 100644
--- a/repoze/bfg/zcml.py
+++ b/repoze/bfg/zcml.py
@@ -1,3 +1,11 @@
+import cPickle
+import os
+from os.path import realpath
+import time
+
+from zope.configuration import xmlconfig
+import zope.configuration.config
+
from zope.component.zcml import handler
from zope.component.interface import provideInterface
from zope.configuration.exceptions import ConfigurationError
@@ -10,6 +18,7 @@ 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.path import package_path
from repoze.bfg.security import ViewPermissionFactory
@@ -84,4 +93,80 @@ class IViewDirective(Interface):
required=False
)
+PVERSION = 0
+
+def pickle_name(name, package):
+ path = package_path(package)
+ basename = os.path.join(path, name)
+ return os.path.join(path, basename + '.pck')
+
+def zcml_configure(name, package, load=cPickle.load):
+ """ Execute pickled zcml actions or fall back to parsing from file
+ """
+ pckname = pickle_name(name, package)
+
+ if not (os.path.isfile(pckname) or os.path.islink(pckname)):
+ return file_configure(name, package)
+
+ try:
+ vers, ptime, actions = load(open(pckname, 'rb'))
+ except (IOError, cPickle.UnpicklingError, EOFError, TypeError, ValueError):
+ return file_configure(name, package)
+
+ if vers != PVERSION:
+ return file_configure(name, package)
+
+ try:
+ ptime = int(ptime)
+ except:
+ return file_configure(name, package)
+
+ if not hasattr(actions, '__iter__'):
+ return file_configure(name, package)
+
+ files = set()
+ for action in actions:
+ # files list used by pickled action is an element of the tuple
+ try:
+ files.update(action[4])
+ except (TypeError, IndexError):
+ return file_configure(name, package)
+
+ for file in files:
+ if not(os.path.isfile(file) or os.path.islink(file)):
+ return file_configure(name, package)
+
+ mtime = os.stat(realpath(file)).st_mtime
+
+ if mtime >= ptime:
+ return file_configure(name, package)
+
+ context = zope.configuration.config.ConfigurationMachine()
+ xmlconfig.registerCommonDirectives(context)
+ context.actions = actions
+ context.execute_actions()
+ return True
+
+def file_configure(name, package, dump=cPickle.dump):
+ context = zope.configuration.config.ConfigurationMachine()
+ xmlconfig.registerCommonDirectives(context)
+ context.package = package
+
+ xmlconfig.include(context, name, package)
+ context.execute_actions(clear=False)
+
+ actions = context.actions
+ pckname = pickle_name(name, package)
+
+ try:
+ data = (PVERSION, time.time(), actions)
+ dump(data, open(pckname, 'wb'), -1)
+ except (OSError, IOError, TypeError, cPickle.PickleError):
+ try:
+ os.remove(pckname)
+ except:
+ pass
+
+ return False
+