diff options
| author | Chris McDonough <chrism@agendaless.com> | 2008-08-23 00:03:29 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2008-08-23 00:03:29 +0000 |
| commit | 434c0514dc7dd9c7881e1d30db4d988680220af2 (patch) | |
| tree | 34cb5395ec0628ec216e54d863bc90fb8902ba5a /repoze/bfg/zcml.py | |
| parent | be16f6b5c59043a164120171a5b0926d158959fd (diff) | |
| download | pyramid-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.py | 85 |
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 + |
