summaryrefslogtreecommitdiff
path: root/repoze
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-11-22 03:33:45 +0000
committerChris McDonough <chrism@agendaless.com>2009-11-22 03:33:45 +0000
commitff0eb79c0137976f69d261f5e6ad7471c1c53dc9 (patch)
tree4d1f872e573e3509223c942948c9beb71c1e576c /repoze
parentc947545b2a86b5fd07fe5ad6a33556a5ce1f2f7b (diff)
downloadpyramid-ff0eb79c0137976f69d261f5e6ad7471c1c53dc9.tar.gz
pyramid-ff0eb79c0137976f69d261f5e6ad7471c1c53dc9.tar.bz2
pyramid-ff0eb79c0137976f69d261f5e6ad7471c1c53dc9.zip
Test load_zcml.
Diffstat (limited to 'repoze')
-rw-r--r--repoze/bfg/configuration.py89
-rw-r--r--repoze/bfg/tests/test_configuration.py45
2 files changed, 111 insertions, 23 deletions
diff --git a/repoze/bfg/configuration.py b/repoze/bfg/configuration.py
index 9a48fa2d7..bf3284d00 100644
--- a/repoze/bfg/configuration.py
+++ b/repoze/bfg/configuration.py
@@ -64,9 +64,21 @@ from repoze.bfg.view import static
import martian
class Configurator(object):
- """ A wrapper around the registry that performs configuration tasks """
- def __init__(self, registry=None):
- self.package = caller_package()
+ """
+ A wrapper around the registry that performs configuration tasks.
+ A Configurator is used to configure a :mod:`repoze.bfg`
+ :term:`application registry`. The Configurator accepts a single
+ argument: ``registry``. If the ``registry`` argument is passed as
+ a non-``None`` value, it must be an instance of the
+ :mod:`repoze.bfg.registry.Registry` class representing the
+ registry to configure. If ``registry`` is ``None``, the
+ configurator will create a Registry instance itself and perform
+ some default configuration on the registry it creates. After
+ construction, the configurator may be used to add configuration to
+ the registry. The overall state of a registry is called the
+ 'configuration state'."""
+ def __init__(self, registry=None, package=None):
+ self.package = package or caller_package()
self.reg = registry
if registry is None:
registry = Registry(self.package.__name__)
@@ -78,11 +90,13 @@ class Configurator(object):
self.renderer(chameleon_text.renderer_factory, '.txt')
self.renderer(renderers.json_renderer_factory, 'json')
self.renderer(renderers.string_renderer_factory, 'string')
- self.settings(Settings({}))
+ self.settings({})
self.root_factory(DefaultRootFactory)
self.debug_logger(None)
def make_wsgi_app(self, manager=manager, getSiteManager=getSiteManager):
+ """ Returns a :mod:`repoze.bfg` WSGI application representing
+ the current configuration state."""
# manager and getSiteManager in arglist for testing dep injection only
from repoze.bfg.router import Router # avoid circdep
app = Router(self.reg)
@@ -102,7 +116,6 @@ class Configurator(object):
def declarative(self, root_factory, spec='configure.zcml',
settings=None, debug_logger=None, os=os,
lock=threading.Lock()):
-
self._default_configuration()
# debug_logger, os and lock *only* for unittests
@@ -130,23 +143,30 @@ class Configurator(object):
def split_spec(self, path_or_spec):
return resolve_resource_spec(path_or_spec, self.package.__name__)
- def load_zcml(self, spec, lock=threading.Lock()):
+ def load_zcml(self, spec='configure.zcml', lock=threading.Lock()):
+ """ Load configuration from a :term:`ZCML` file into the
+ current configuration state. The ``spec`` argument is an
+ absolute filename, a relative filename, or a :term:`resource
+ specification`, defaulting to ``configure.zcml``."""
+
# We push our ZCML-defined configuration into an app-local
- # component registry in order to allow more than one bfg app to live
- # in the same process space without one unnecessarily stomping on
- # the other's component registrations (although I suspect directives
- # that have side effects are going to fail). The only way to do
- # that currently is to override zope.component.getGlobalSiteManager
- # for the duration of the ZCML includes. We acquire a lock in case
- # another make_app runs in a different thread simultaneously, in a
- # vain attempt to prevent mixing of registrations. There's not much
- # we can do about non-makeRegistry code that tries to use the global
- # site manager API directly in a different thread while we hold the
- # lock. Those registrations will end up in our application's
- # registry.
+ # component registry in order to allow more than one bfg app
+ # to live in the same process space without one unnecessarily
+ # stomping on the other's component registrations (although I
+ # suspect directives that have side effects are going to
+ # fail). The only way to do that currently is to override
+ # zope.component.getGlobalSiteManager for the duration of the
+ # ZCML includes. We acquire a lock in case another load_zcml
+ # runs in a different thread simultaneously, in a vain attempt
+ # to prevent mixing of registrations. There's not much we can
+ # do about non-load_zcml code that tries to use the global
+ # site manager API directly in a different thread while we
+ # hold the lock. Those registrations will end up in our
+ # application's registry.
+
package_name, filename = self.split_spec(spec)
if package_name is None: # absolute filename
- package = None
+ package = self.package
else:
__import__(package_name)
package = sys.modules[package_name]
@@ -162,12 +182,15 @@ class Configurator(object):
lock.release()
manager.pop()
getSiteManager.reset()
+ return self.reg
def view(self, view=None, name="", for_=None, permission=None,
request_type=None, route_name=None, request_method=None,
request_param=None, containment=None, attr=None,
renderer=None, wrapper=None, xhr=False, accept=None,
header=None, path_info=None, _info=u''):
+ """ Add a :term:`view configuration` to the current
+ configuration state."""
if not view:
if renderer:
@@ -285,8 +308,8 @@ class Configurator(object):
renderer=None, view_renderer=None, view_header=None,
view_accept=None, view_xhr=False,
view_path_info=None, _info=u''):
- # the strange ordering of the request kw args above is for b/w
- # compatibility purposes.
+ """ Add a :term:`route configuration` to the current
+ configuration state."""
# these are route predicates; if they do not match, the next route
# in the routelist will be tried
_, predicates = _make_predicates(xhr=xhr,
@@ -330,6 +353,9 @@ class Configurator(object):
mapper.connect(path, name, factory, predicates=predicates)
def scan(self, package, _info=u'', martian=martian):
+ """ Scan a Python package and any of its subpackages for
+ configuration decorators such as ``@bfg_view``. Any decorator
+ found will influence the current configuration state."""
# martian overrideable only for unit tests
multi_grokker = BFGMultiGrokker()
multi_grokker.register(BFGViewGrokker())
@@ -340,18 +366,27 @@ class Configurator(object):
exclude_filter=lambda name: name.startswith('.'))
def authentication_policy(self, policy, _info=u''):
+ """ Add a :mod:`repoze.bfg` :term:`authentication policy` to
+ the current configuration."""
self.reg.registerUtility(policy, IAuthenticationPolicy, info=_info)
def authorization_policy(self, policy, _info=u''):
+ """ Add a :mod:`repoze.bfg` :term:`authorization policy` to
+ the current configuration state."""
self.reg.registerUtility(policy, IAuthorizationPolicy, info=_info)
def renderer(self, factory, name, _info=u''):
+ """ Add a :mod:`repoze.bfg` :term:`renderer` to the current
+ configuration state."""
iface = IRendererFactory
if name.startswith('.'):
iface = ITemplateRendererFactory
self.reg.registerUtility(factory, iface, name=name, info=_info)
def resource(self, to_override, override_with, _info=u'', _override=None,):
+ """ Add a :mod:`repoze.bfg` resource override to the current
+ configuration state. See :ref:`resources_chapter` for more
+ information about resource overrides."""
if to_override == override_with:
raise ConfigurationError('You cannot override a resource with '
'itself')
@@ -399,9 +434,14 @@ class Configurator(object):
override.insert(path, override_pkg_name, override_prefix)
def forbidden(self, *arg, **kw):
+ """ Add a default forbidden view to the current configuration
+ state."""
+
return self.system_view(IForbiddenView, *arg, **kw)
def notfound(self, *arg, **kw):
+ """ Add a default not found view to the current configuration
+ state."""
return self.system_view(INotFoundView, *arg, **kw)
def system_view(self, iface, view=None, attr=None, renderer=None,
@@ -421,6 +461,7 @@ class Configurator(object):
self.reg.registerUtility(derived_view, iface, '', info=_info)
def static(self, name, path, cache_max_age=3600, _info=u''):
+ """ Add a static view to the current configuration state."""
spec = self.make_spec(path)
view = static(spec, cache_max_age=cache_max_age)
self.route(name, "%s*subpath" % name, view=view,
@@ -428,6 +469,10 @@ class Configurator(object):
_info=_info)
def settings(self, settings):
+ """ Register the value passed in as ``settings`` as the basis
+ of the value returned by the
+ ``repoze.bfg.settings.get_settings`` API."""
+ settings = Settings(settings)
self.reg.registerUtility(settings, ISettings)
def debug_logger(self, logger):
@@ -436,6 +481,8 @@ class Configurator(object):
self.reg.registerUtility(logger, ILogger, 'repoze.bfg.debug')
def root_factory(self, factory):
+ """ Add a :term:`root factory` to the current configuration
+ state."""
self.reg.registerUtility(factory, IRootFactory)
self.reg.registerUtility(factory, IDefaultRootFactory) # b/c
diff --git a/repoze/bfg/tests/test_configuration.py b/repoze/bfg/tests/test_configuration.py
index 8053256c4..477525431 100644
--- a/repoze/bfg/tests/test_configuration.py
+++ b/repoze/bfg/tests/test_configuration.py
@@ -3,12 +3,12 @@ import unittest
from repoze.bfg.testing import cleanUp
class ConfiguratorTests(unittest.TestCase):
- def _makeOne(self, registry=None):
+ def _makeOne(self, registry=None, package=None):
from repoze.bfg.registry import Registry
from repoze.bfg.configuration import Configurator
if registry is None:
registry = Registry()
- return Configurator(registry)
+ return Configurator(registry, package)
def _registerRenderer(self, config, name='.txt'):
from repoze.bfg.interfaces import IRendererFactory
@@ -91,10 +91,20 @@ class ConfiguratorTests(unittest.TestCase):
config.reg.registerUtility(settings, ISettings)
def test_ctor_no_registry(self):
+ import sys
from repoze.bfg.interfaces import ISettings
from repoze.bfg.configuration import Configurator
config = Configurator()
+ this_pkg = sys.modules['repoze.bfg.tests']
self.failUnless(config.reg.getUtility(ISettings))
+ self.assertEqual(config.package, this_pkg)
+
+ def test_ctor_with_package_registry(self):
+ import sys
+ from repoze.bfg.configuration import Configurator
+ bfg_pkg = sys.modules['repoze.bfg']
+ config = Configurator(package=bfg_pkg)
+ self.assertEqual(config.package, bfg_pkg)
def test__default_configuration(self):
from repoze.bfg.interfaces import ISettings
@@ -130,6 +140,37 @@ class ConfiguratorTests(unittest.TestCase):
self.failUnless(manager.popped)
self.assertEqual(len(subscriber), 1)
+ def test_load_zcml_default(self):
+ import repoze.bfg.tests.fixtureapp
+ config = self._makeOne(package=repoze.bfg.tests.fixtureapp)
+ registry = config.load_zcml()
+ from repoze.bfg.tests.fixtureapp.models import IFixture
+ self.failUnless(registry.queryUtility(IFixture)) # only in c.zcml
+
+ def test_load_zcml_as_resource_spec(self):
+ config = self._makeOne()
+ registry = config.load_zcml(
+ 'repoze.bfg.tests.fixtureapp:configure.zcml')
+ from repoze.bfg.tests.fixtureapp.models import IFixture
+ self.failUnless(registry.queryUtility(IFixture)) # only in c.zcml
+
+ def test_load_zcml_as_relative_filename(self):
+ import repoze.bfg.tests.fixtureapp
+ config = self._makeOne(package=repoze.bfg.tests.fixtureapp)
+ registry = config.load_zcml('configure.zcml')
+ from repoze.bfg.tests.fixtureapp.models import IFixture
+ self.failUnless(registry.queryUtility(IFixture)) # only in c.zcml
+
+ def test_load_zcml_as_absolute_filename(self):
+ import os
+ import repoze.bfg.tests.fixtureapp
+ config = self._makeOne(package=repoze.bfg.tests.fixtureapp)
+ dn = os.path.dirname(repoze.bfg.tests.fixtureapp.__file__)
+ c_z = os.path.join(dn, 'configure.zcml')
+ registry = config.load_zcml(c_z)
+ from repoze.bfg.tests.fixtureapp.models import IFixture
+ self.failUnless(registry.queryUtility(IFixture)) # only in c.zcml
+
def test_declarative_fixtureapp_default_filename_withpackage(self):
rootfactory = DummyRootFactory(None)
registry = self._callDeclarative(