summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-09-03 03:09:17 -0400
committerChris McDonough <chrism@plope.com>2011-09-03 03:09:17 -0400
commit79ef3d108e2aa1d630a6f06a8bed107e2ba6d43e (patch)
treef7b2abb01e309f0cc13f40558c25c22054d4652b
parenta7d50d87b447384a30fc2c69eaaef1d974e7562a (diff)
downloadpyramid-79ef3d108e2aa1d630a6f06a8bed107e2ba6d43e.tar.gz
pyramid-79ef3d108e2aa1d630a6f06a8bed107e2ba6d43e.tar.bz2
pyramid-79ef3d108e2aa1d630a6f06a8bed107e2ba6d43e.zip
mechanical cut at removing zope.configuration dependencies (breaks pyramid_zcml right now)
-rw-r--r--pyramid/config/__init__.py308
-rw-r--r--pyramid/exceptions.py32
-rw-r--r--pyramid/registry.py4
-rw-r--r--pyramid/testing.py2
-rw-r--r--pyramid/tests/test_config/test_init.py155
-rw-r--r--pyramid/tests/test_config/test_security.py6
-rw-r--r--pyramid/tests/test_config/test_tweens.py3
-rw-r--r--pyramid/tests/test_config/test_views.py13
-rw-r--r--pyramid/tests/test_exceptions.py29
-rw-r--r--pyramid/tests/test_registry.py4
-rw-r--r--setup.py3
11 files changed, 506 insertions, 53 deletions
diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py
index 5e082828f..b7f5fc545 100644
--- a/pyramid/config/__init__.py
+++ b/pyramid/config/__init__.py
@@ -1,6 +1,7 @@
import inspect
import logging
import os
+import sys
import types
import warnings
@@ -9,17 +10,15 @@ import venusian
from webob.exc import WSGIHTTPException as WebobWSGIHTTPException
-from zope.configuration.config import GroupingContextDecorator
-from zope.configuration.config import ConfigurationMachine
-from zope.configuration.xmlconfig import registerCommonDirectives
-
from pyramid.interfaces import IExceptionResponse
from pyramid.interfaces import IDebugLogger
from pyramid.asset import resolve_asset_spec
from pyramid.authorization import ACLAuthorizationPolicy
from pyramid.events import ApplicationCreated
-from pyramid.exceptions import ConfigurationError # bw compat
+from pyramid.exceptions import ConfigurationError
+from pyramid.exceptions import ConfigurationConflictError
+from pyramid.exceptions import ConfigurationExecutionError
from pyramid.httpexceptions import default_exceptionresponse_view
from pyramid.path import caller_package
from pyramid.path import package_of
@@ -369,8 +368,7 @@ class Configurator(
self.include(inc)
def _make_spec(self, path_or_spec):
- package, filename = resolve_asset_spec(path_or_spec,
- self.package_name)
+ package, filename = resolve_asset_spec(path_or_spec, self.package_name)
if package is None:
return filename # absolute filename
return '%s:%s' % (package, filename)
@@ -412,8 +410,7 @@ class Configurator(
_registry.registerSelfAdapter = registerSelfAdapter
def _make_context(self, autocommit=False):
- context = PyramidConfigurationMachine()
- registerCommonDirectives(context)
+ context = ActionState()
context.registry = self.registry
context.autocommit = autocommit
context.route_prefix = self.route_prefix
@@ -463,7 +460,7 @@ class Configurator(
# wrapping the context in a decorator and attaching caller info
# to it, unless the context already has info (if it already has
# info, it's likely a context generated by a ZCML directive).
- context = GroupingContextDecorator(context)
+ context = ActionStateWrapper(context)
if self._ainfo:
info = self._ainfo[0]
else:
@@ -597,7 +594,7 @@ class Configurator(
spec = module.__name__ + ':' + c.__name__
sourcefile = inspect.getsourcefile(c)
if _context.processSpec(spec):
- context = GroupingContextDecorator(_context)
+ context = ActionStateWrapper(_context)
context.basepath = os.path.dirname(sourcefile)
context.includepath = _context.includepath + (spec,)
context.package = package_of(module)
@@ -669,7 +666,7 @@ class Configurator(
context = self._ctx
if context is None:
context = self._ctx = self._make_context(self.autocommit)
- context = GroupingContextDecorator(context)
+ context = ActionStateWrapper(context)
context.package = package
return self.__class__.with_context(context)
@@ -792,9 +789,9 @@ class Configurator(
return app
-class PyramidConfigurationMachine(ConfigurationMachine):
- autocommit = False
- route_prefix = None
+class ActionStateBase(object):
+ def __init__(self):
+ self._seen_files = set()
def processSpec(self, spec):
"""Check whether a callable needs to be processed. The ``spec``
@@ -810,5 +807,286 @@ class PyramidConfigurationMachine(ConfigurationMachine):
self._seen_files.add(spec)
return True
+ def action(self, discriminator, callable=None, args=(), kw={}, order=0,
+ includepath=None, info=None):
+ """Add an action with the given discriminator, callable and arguments
+
+ For testing purposes, the callable and arguments may be omitted.
+ In that case, a default noop callable is used.
+
+ The discriminator must be given, but it can be None, to indicate that
+ the action never conflicts.
+
+ Let's look at some examples:
+
+ >>> c = ConfigurationContext()
+
+ Normally, the context gets actions from subclasses. We'll provide
+ an actions attribute ourselves:
+
+ >>> c.actions = []
+
+ We'll use a test callable that has a convenient string representation
+
+ >>> from zope.configmachine.tests.directives import f
+
+ >>> c.action(1, f, (1, ), {'x': 1})
+ >>> c.actions
+ [(1, f, (1,), {'x': 1})]
+
+ >>> c.action(None)
+ >>> c.actions
+ [(1, f, (1,), {'x': 1}), (None, None)]
+
+ Now set the include path and info:
+
+ >>> c.includepath = ('foo.zcml',)
+ >>> c.info = "?"
+ >>> c.action(None)
+ >>> c.actions[-1]
+ (None, None, (), {}, ('foo.zcml',), '?')
+
+ We can add an order argument to crudely control the order
+ of execution:
+
+ >>> c.action(None, order=99999)
+ >>> c.actions[-1]
+ (None, None, (), {}, ('foo.zcml',), '?', 99999)
+
+ We can also pass an includepath argument, which will be used as the the
+ includepath for the action. (if includepath is None, self.includepath
+ will be used):
+
+ >>> c.action(None, includepath=('abc',))
+ >>> c.actions[-1]
+ (None, None, (), {}, ('abc',), '?')
+
+ We can also pass an info argument, which will be used as the the
+ source line info for the action. (if info is None, self.info will be
+ used):
+
+ >>> c.action(None, info='abc')
+ >>> c.actions[-1]
+ (None, None, (), {}, ('foo.zcml',), 'abc')
+
+ """
+ if info is None:
+ info = getattr(self, 'info', '')
+
+ if includepath is None:
+ includepath = getattr(self, 'includepath', ())
+
+ action = (discriminator, callable, args, kw, includepath, info, order)
+
+ # remove trailing false items
+ while (len(action) > 2) and not action[-1]:
+ action = action[:-1]
+
+ self.actions.append(action)
+
+
+class ActionStateWrapper(ActionStateBase):
+ """ Wrap an action state.
+ """
+ def __init__(self, state):
+ self.state = state
+
+ def __getattr__(self, name):
+ v = getattr(self.state, name)
+ # cache result in self
+ setattr(self, name, v)
+ return v
+
+class ActionState(ActionStateBase):
+ autocommit = False
+ route_prefix = None
+ package = None
+ basepath = None
+ includepath = ()
+ info = ''
+
+ def __init__(self):
+ super(ActionState, self).__init__()
+ self.actions = []
+
+ def execute_actions(self, clear=True):
+ """Execute the configuration actions
+
+ This calls the action callables after resolving conflicts
+
+ For example:
+
+ >>> output = []
+ >>> def f(*a, **k):
+ ... output.append(('f', a, k))
+ >>> context = ConfigurationMachine()
+ >>> context.actions = [
+ ... (1, f, (1,)),
+ ... (1, f, (11,), {}, ('x', )),
+ ... (2, f, (2,)),
+ ... ]
+ >>> context.execute_actions()
+ >>> output
+ [('f', (1,), {}), ('f', (2,), {})]
+
+ If the action raises an error, we convert it to a
+ ConfigurationExecutionError.
+
+ >>> output = []
+ >>> def bad():
+ ... bad.xxx
+ >>> context.actions = [
+ ... (1, f, (1,)),
+ ... (1, f, (11,), {}, ('x', )),
+ ... (2, f, (2,)),
+ ... (3, bad, (), {}, (), 'oops')
+ ... ]
+ >>> try:
+ ... v = context.execute_actions()
+ ... except ConfigurationExecutionError, v:
+ ... pass
+ >>> print v
+ exceptions.AttributeError: 'function' object has no attribute 'xxx'
+ in:
+ oops
+
+
+ Note that actions executed before the error still have an effect:
+
+ >>> output
+ [('f', (1,), {}), ('f', (2,), {})]
+
+
+ """
+ try:
+ for action in resolveConflicts(self.actions):
+ (discriminator, callable, args, kw, includepath, info, order
+ ) = expand_action(*action)
+ if callable is None:
+ continue
+ try:
+ callable(*args, **kw)
+ except (KeyboardInterrupt, SystemExit): # pragma: no cover
+ raise
+ except:
+ t, v, tb = sys.exc_info()
+ raise ConfigurationExecutionError(t, v, info), None, tb
+ finally:
+ if clear:
+ del self.actions[:]
+
+def resolveConflicts(actions):
+ """Resolve conflicting actions
+
+ Given an actions list, identify and try to resolve conflicting actions.
+ Actions conflict if they have the same non-null discriminator.
+ Conflicting actions can be resolved if the include path of one of
+ the actions is a prefix of the includepaths of the other
+ conflicting actions and is unequal to the include paths in the
+ other conflicting actions.
+
+ Here are some examples to illustrate how this works:
+
+ >>> from zope.configmachine.tests.directives import f
+ >>> from pprint import PrettyPrinter
+ >>> pprint=PrettyPrinter(width=60).pprint
+ >>> pprint(resolveConflicts([
+ ... (None, f),
+ ... (1, f, (1,), {}, (), 'first'),
+ ... (1, f, (2,), {}, ('x',), 'second'),
+ ... (1, f, (3,), {}, ('y',), 'third'),
+ ... (4, f, (4,), {}, ('y',), 'should be last', 99999),
+ ... (3, f, (3,), {}, ('y',)),
+ ... (None, f, (5,), {}, ('y',)),
+ ... ]))
+ [(None, f),
+ (1, f, (1,), {}, (), 'first'),
+ (3, f, (3,), {}, ('y',)),
+ (None, f, (5,), {}, ('y',)),
+ (4, f, (4,), {}, ('y',), 'should be last')]
+
+ >>> try:
+ ... v = resolveConflicts([
+ ... (None, f),
+ ... (1, f, (2,), {}, ('x',), 'eek'),
+ ... (1, f, (3,), {}, ('y',), 'ack'),
+ ... (4, f, (4,), {}, ('y',)),
+ ... (3, f, (3,), {}, ('y',)),
+ ... (None, f, (5,), {}, ('y',)),
+ ... ])
+ ... except ConfigurationConflictError, v:
+ ... pass
+ >>> print v
+ Conflicting configuration actions
+ For: 1
+ eek
+ ack
+
+ """
+
+ # organize actions by discriminators
+ unique = {}
+ output = []
+ for i in range(len(actions)):
+ (discriminator, callable, args, kw, includepath, info, order
+ ) = expand_action(*(actions[i]))
+
+ order = order or i
+ if discriminator is None:
+ # The discriminator is None, so this directive can
+ # never conflict. We can add it directly to the
+ # configuration actions.
+ output.append(
+ (order, discriminator, callable, args, kw, includepath, info)
+ )
+ continue
+
+
+ a = unique.setdefault(discriminator, [])
+ a.append(
+ (includepath, order, callable, args, kw, info)
+ )
+
+ # Check for conflicts
+ conflicts = {}
+ for discriminator, dups in unique.items():
+
+ # We need to sort the actions by the paths so that the shortest
+ # path with a given prefix comes first:
+ dups.sort()
+ (basepath, i, callable, args, kw, baseinfo) = dups[0]
+ output.append(
+ (i, discriminator, callable, args, kw, basepath, baseinfo)
+ )
+ for includepath, i, callable, args, kw, info in dups[1:]:
+ # Test whether path is a prefix of opath
+ if (includepath[:len(basepath)] != basepath # not a prefix
+ or
+ (includepath == basepath)
+ ):
+ if discriminator not in conflicts:
+ conflicts[discriminator] = [baseinfo]
+ conflicts[discriminator].append(info)
+
+
+ if conflicts:
+ raise ConfigurationConflictError(conflicts)
+
+ # Now put the output back in the original order, and return it:
+ output.sort()
+ r = []
+ for o in output:
+ action = o[1:]
+ while len(action) > 2 and not action[-1]:
+ action = action[:-1]
+ r.append(action)
+
+ return r
+
+def expand_action(discriminator, callable=None, args=(), kw={},
+ includepath=(), info='', order=0):
+ return (discriminator, callable, args, kw,
+ includepath, info, order)
+
global_registries = WeakOrderedSet()
diff --git a/pyramid/exceptions.py b/pyramid/exceptions.py
index 151fc241f..cafdb93f0 100644
--- a/pyramid/exceptions.py
+++ b/pyramid/exceptions.py
@@ -1,5 +1,3 @@
-from zope.configuration.exceptions import ConfigurationError as ZCE
-
from pyramid.httpexceptions import HTTPNotFound
from pyramid.httpexceptions import HTTPForbidden
@@ -26,8 +24,36 @@ class URLDecodeError(UnicodeDecodeError):
decoded.
"""
-class ConfigurationError(ZCE):
+class ConfigurationError(Exception):
""" Raised when inappropriate input values are supplied to an API
method of a :term:`Configurator`"""
+class ConfigurationConflictError(ConfigurationError):
+ """ Raised when a configuration conflict is detected during action
+ processing"""
+
+ def __init__(self, conflicts):
+ self._conflicts = conflicts
+
+ def __str__(self):
+ r = ["Conflicting configuration actions"]
+ items = self._conflicts.items()
+ items.sort()
+ for discriminator, infos in items:
+ r.append(" For: %s" % (discriminator, ))
+ for info in infos:
+ for line in unicode(info).rstrip().split(u'\n'):
+ r.append(u" "+line)
+
+ return "\n".join(r)
+
+
+class ConfigurationExecutionError(ConfigurationError):
+ """An error occurred during execution of a configuration action
+ """
+
+ def __init__(self, etype, evalue, info):
+ self.etype, self.evalue, self.info = etype, evalue, info
+ def __str__(self):
+ return "%s: %s\n in:\n %s" % (self.etype, self.evalue, self.info)
diff --git a/pyramid/registry.py b/pyramid/registry.py
index 6aaf44c2f..390ae8841 100644
--- a/pyramid/registry.py
+++ b/pyramid/registry.py
@@ -23,6 +23,10 @@ class Registry(Components, dict):
has_listeners = False
_settings = None
+ def __nonzero__(self):
+ # defeat bool determination via dict.__len__
+ return True
+
def registerSubscriptionAdapter(self, *arg, **kw):
result = Components.registerSubscriptionAdapter(self, *arg, **kw)
self.has_listeners = True
diff --git a/pyramid/testing.py b/pyramid/testing.py
index 86333b5fc..07f523868 100644
--- a/pyramid/testing.py
+++ b/pyramid/testing.py
@@ -1,7 +1,6 @@
import copy
import os
-from zope.configuration.xmlconfig import _clearContext
from zope.deprecation import deprecated
from zope.interface import implements
@@ -836,7 +835,6 @@ def tearDown(unhook_zca=True):
# however maybe somebody's using a registry we don't
# understand, let's not blow up
pass
- _clearContext() # XXX why?
def cleanUp(*arg, **kw):
""" :func:`pyramid.testing.cleanUp` is an alias for
diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py
index 3d2a0f38a..29be757d3 100644
--- a/pyramid/tests/test_config/test_init.py
+++ b/pyramid/tests/test_config/test_init.py
@@ -14,6 +14,10 @@ try:
except:
__pypy__ = None
+from pyramid.exceptions import ConfigurationExecutionError
+from pyramid.exceptions import ConfigurationConflictError
+from pyramid.exceptions import ConfigurationError
+
class ConfiguratorTests(unittest.TestCase):
def _makeOne(self, *arg, **kw):
from pyramid.config import Configurator
@@ -141,7 +145,6 @@ class ConfiguratorTests(unittest.TestCase):
self.assertEqual(policy, result)
def test_ctor_authorization_policy_only(self):
- from zope.configuration.config import ConfigurationExecutionError
policy = object()
config = self._makeOne(authorization_policy=policy)
self.assertRaises(ConfigurationExecutionError, config.commit)
@@ -266,8 +269,7 @@ class ConfiguratorTests(unittest.TestCase):
def test_maybe_dotted_string_fail(self):
config = self._makeOne()
- self.assertRaises(ImportError,
- config.maybe_dotted, 'cant.be.found')
+ self.assertRaises(ImportError, config.maybe_dotted, 'cant.be.found')
def test_maybe_dotted_notstring_success(self):
import pyramid.tests.test_config
@@ -463,7 +465,6 @@ class ConfiguratorTests(unittest.TestCase):
self.assertEqual(result, pyramid.tests.test_config)
def test_setup_registry_authorization_policy_only(self):
- from zope.configuration.config import ConfigurationExecutionError
from pyramid.registry import Registry
policy = object()
reg = Registry()
@@ -899,7 +900,6 @@ pyramid.tests.test_config.dummy_include2""",
sys.path.remove(path)
def test_scan_integration_conflict(self):
- from zope.configuration.config import ConfigurationConflictError
from pyramid.tests.test_config.pkgs import selfscan
from pyramid.config import Configurator
c = Configurator()
@@ -946,7 +946,6 @@ pyramid.tests.test_config.dummy_include2""",
getSiteManager.reset()
def test_commit_conflict_simple(self):
- from zope.configuration.config import ConfigurationConflictError
config = self._makeOne()
def view1(request): pass
def view2(request): pass
@@ -967,7 +966,6 @@ pyramid.tests.test_config.dummy_include2""",
self.assertEqual(registeredview.__name__, 'view1')
def test_commit_conflict_with_two_includes(self):
- from zope.configuration.config import ConfigurationConflictError
config = self._makeOne()
def view1(request): pass
def view2(request): pass
@@ -1016,7 +1014,6 @@ pyramid.tests.test_config.dummy_include2""",
self.assertEqual(registeredview.__name__, 'view3')
def test_conflict_set_notfound_view(self):
- from zope.configuration.config import ConfigurationConflictError
config = self._makeOne()
def view1(request): pass
def view2(request): pass
@@ -1032,7 +1029,6 @@ pyramid.tests.test_config.dummy_include2""",
raise AssertionError
def test_conflict_set_forbidden_view(self):
- from zope.configuration.config import ConfigurationConflictError
config = self._makeOne()
def view1(request): pass
def view2(request): pass
@@ -1273,7 +1269,6 @@ class TestConfiguratorDeprecatedFeatures(unittest.TestCase):
self.assertTrue(hasattr(wrapper, '__call_permissive__'))
def test_conflict_route_with_view(self):
- from zope.configuration.config import ConfigurationConflictError
config = self._makeOne()
def view1(request): pass
def view2(request): pass
@@ -1339,7 +1334,6 @@ class TestConfigurator_add_directive(unittest.TestCase):
)
def test_extend_action_method_successful(self):
- from zope.configuration.config import ConfigurationConflictError
config = self.config
config.add_directive(
'dummy_extend', dummy_extend)
@@ -1348,11 +1342,11 @@ class TestConfigurator_add_directive(unittest.TestCase):
self.assertRaises(ConfigurationConflictError, config.commit)
def test_directive_persists_across_configurator_creations(self):
- from zope.configuration.config import GroupingContextDecorator
+ from pyramid.config import ActionStateWrapper
config = self.config
config.add_directive('dummy_extend', dummy_extend)
context = config._make_context(autocommit=False)
- context = GroupingContextDecorator(context)
+ context = ActionStateWrapper(context)
config2 = config.with_context(context)
config2.dummy_extend('discrim')
context_after = config2._ctx
@@ -1363,12 +1357,137 @@ class TestConfigurator_add_directive(unittest.TestCase):
('discrim', None, config2.package),
)
-class TestPyramidConfigurationMachine(unittest.TestCase):
+class TestActionState(unittest.TestCase):
+ def _makeOne(self):
+ from pyramid.config import ActionState
+ return ActionState()
+
def test_it(self):
- from pyramid.config import PyramidConfigurationMachine
- m = PyramidConfigurationMachine()
- self.assertEqual(m.autocommit, False)
- self.assertEqual(m.route_prefix, None)
+ c = self._makeOne()
+ self.assertEqual(c.autocommit, False)
+ self.assertEqual(c.route_prefix, None)
+
+ def test_action_simple(self):
+ from pyramid.tests.test_config import dummyfactory as f
+ c = self._makeOne()
+ c.actions = []
+ c.action(1, f, (1,), {'x':1})
+ self.assertEqual(c.actions, [(1, f, (1,), {'x': 1})])
+ c.action(None)
+ self.assertEqual(c.actions, [(1, f, (1,), {'x': 1}), (None, None)])
+
+ def test_action_with_includepath_and_info(self):
+ c = self._makeOne()
+ c.actions = []
+ c.includepath = ('foo.zcml',)
+ c.info = '?'
+ c.action(None)
+ self.assertEqual(c.actions,
+ [(None, None, (), {}, ('foo.zcml',), '?')])
+
+ def test_action_with_order(self):
+ c = self._makeOne()
+ c.actions = []
+ c.action(None, order=99999)
+ self.assertEqual(c.actions, [(None, None, (), {}, (), '', 99999)])
+
+ def test_action_with_includepath_dynamic(self):
+ c = self._makeOne()
+ c.actions = []
+ c.action(None, includepath=('abc',))
+ self.assertEqual(c.actions, [(None, None, (), {}, ('abc',))])
+
+ def test_action_with_info_dynamic(self):
+ c = self._makeOne()
+ c.actions = []
+ c.action(None, info='abc')
+ self.assertEqual(c.actions, [(None, None, (), {}, (), 'abc')])
+
+ def test_processSpec(self):
+ c = self._makeOne()
+ self.assertTrue(c.processSpec('spec'))
+ self.assertFalse(c.processSpec('spec'))
+
+ def test_execute_actions_simple(self):
+ output = []
+ def f(*a, **k):
+ output.append(('f', a, k))
+ c = self._makeOne()
+ c.actions = [
+ (1, f, (1,)),
+ (1, f, (11,), {}, ('x', )),
+ (2, f, (2,)),
+ (None, None),
+ ]
+ c.execute_actions()
+ self.assertEqual(output, [('f', (1,), {}), ('f', (2,), {})])
+
+ def test_execute_actions_error(self):
+ output = []
+ def f(*a, **k):
+ output.append(('f', a, k))
+ def bad():
+ raise NotImplementedError
+ c = self._makeOne()
+ c.actions = [
+ (1, f, (1,)),
+ (1, f, (11,), {}, ('x', )),
+ (2, f, (2,)),
+ (3, bad, (), {}, (), 'oops')
+ ]
+ self.assertRaises(ConfigurationExecutionError, c.execute_actions)
+ self.assertEqual(output, [('f', (1,), {}), ('f', (2,), {})])
+
+class TestActionStateWrapper(unittest.TestCase):
+ def _makeOne(self, state):
+ from pyramid.config import ActionStateWrapper
+ return ActionStateWrapper(state)
+
+ def test___getattr__(self):
+ state = DummyContext()
+ state.foo = 1
+ state.bar = 2
+ wrapper = self._makeOne(state)
+ self.assertEqual(wrapper.foo, 1)
+ wrapper.bar = 2
+ self.assertEqual(state.bar, 2)
+
+class Test_resolveConflicts(unittest.TestCase):
+ def _callFUT(self, actions):
+ from pyramid.config import resolveConflicts
+ return resolveConflicts(actions)
+
+ def test_it_success(self):
+ from pyramid.tests.test_config import dummyfactory as f
+ result = self._callFUT([
+ (None, f),
+ (1, f, (1,), {}, (), 'first'),
+ (1, f, (2,), {}, ('x',), 'second'),
+ (1, f, (3,), {}, ('y',), 'third'),
+ (4, f, (4,), {}, ('y',), 'should be last', 99999),
+ (3, f, (3,), {}, ('y',)),
+ (None, f, (5,), {}, ('y',)),
+ ])
+ self.assertEqual(result,
+ [(None, f),
+ (1, f, (1,), {}, (), 'first'),
+ (3, f, (3,), {}, ('y',)),
+ (None, f, (5,), {}, ('y',)),
+ (4, f, (4,), {}, ('y',), 'should be last')])
+
+ def test_it_conflict(self):
+ from pyramid.tests.test_config import dummyfactory as f
+ self.assertRaises(
+ ConfigurationConflictError,
+ self._callFUT, [
+ (None, f),
+ (1, f, (2,), {}, ('x',), 'eek'),
+ (1, f, (3,), {}, ('y',), 'ack'),
+ (4, f, (4,), {}, ('y',)),
+ (3, f, (3,), {}, ('y',)),
+ (None, f, (5,), {}, ('y',)),
+ ]
+ )
class TestGlobalRegistriesIntegration(unittest.TestCase):
def setUp(self):
diff --git a/pyramid/tests/test_config/test_security.py b/pyramid/tests/test_config/test_security.py
index d5b8c339f..d05d1d471 100644
--- a/pyramid/tests/test_config/test_security.py
+++ b/pyramid/tests/test_config/test_security.py
@@ -1,5 +1,8 @@
import unittest
+from pyramid.exceptions import ConfigurationExecutionError
+from pyramid.exceptions import ConfigurationError
+
class ConfiguratorSecurityMethodsTests(unittest.TestCase):
def _makeOne(self, *arg, **kw):
from pyramid.config import Configurator
@@ -7,14 +10,12 @@ class ConfiguratorSecurityMethodsTests(unittest.TestCase):
return config
def test_set_authentication_policy_no_authz_policy(self):
- from zope.configuration.config import ConfigurationExecutionError
config = self._makeOne()
policy = object()
config.set_authentication_policy(policy)
self.assertRaises(ConfigurationExecutionError, config.commit)
def test_set_authentication_policy_no_authz_policy_autocommit(self):
- from pyramid.exceptions import ConfigurationError
config = self._makeOne(autocommit=True)
policy = object()
self.assertRaises(ConfigurationError,
@@ -45,7 +46,6 @@ class ConfiguratorSecurityMethodsTests(unittest.TestCase):
config.registry.getUtility(IAuthenticationPolicy), authn_policy)
def test_set_authorization_policy_no_authn_policy(self):
- from zope.configuration.config import ConfigurationExecutionError
config = self._makeOne()
policy = object()
config.set_authorization_policy(policy)
diff --git a/pyramid/tests/test_config/test_tweens.py b/pyramid/tests/test_config/test_tweens.py
index 335b745e2..0d96bf601 100644
--- a/pyramid/tests/test_config/test_tweens.py
+++ b/pyramid/tests/test_config/test_tweens.py
@@ -3,6 +3,8 @@ import unittest
from pyramid.tests.test_config import dummy_tween_factory
from pyramid.tests.test_config import dummy_tween_factory2
+from pyramid.exceptions import ConfigurationConflictError
+
class TestTweensConfiguratorMixin(unittest.TestCase):
def _makeOne(self, *arg, **kw):
from pyramid.config import Configurator
@@ -118,7 +120,6 @@ class TestTweensConfiguratorMixin(unittest.TestCase):
self.assertRaises(ConfigurationError, config.add_tween, MAIN)
def test_add_tweens_conflict(self):
- from zope.configuration.config import ConfigurationConflictError
config = self._makeOne()
config.add_tween('pyramid.tests.test_config.dummy_tween_factory')
config.add_tween('pyramid.tests.test_config.dummy_tween_factory')
diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py
index a4a53bd3a..872528c6c 100644
--- a/pyramid/tests/test_config/test_views.py
+++ b/pyramid/tests/test_config/test_views.py
@@ -5,6 +5,10 @@ from pyramid.tests.test_config import IDummy
from pyramid.tests.test_config import dummy_view
+from pyramid.exceptions import ConfigurationError
+from pyramid.exceptions import ConfigurationExecutionError
+from pyramid.exceptions import ConfigurationConflictError
+
class TestViewsConfigurationMixin(unittest.TestCase):
def _makeOne(self, *arg, **kw):
from pyramid.config import Configurator
@@ -69,12 +73,10 @@ class TestViewsConfigurationMixin(unittest.TestCase):
return route
def test_add_view_view_callable_None_no_renderer(self):
- from pyramid.exceptions import ConfigurationError
config = self._makeOne(autocommit=True)
self.assertRaises(ConfigurationError, config.add_view)
def test_add_view_with_request_type_and_route_name(self):
- from pyramid.exceptions import ConfigurationError
config = self._makeOne(autocommit=True)
view = lambda *arg: 'OK'
self.assertRaises(ConfigurationError, config.add_view, view, '', None,
@@ -952,7 +954,6 @@ class TestViewsConfigurationMixin(unittest.TestCase):
self.assertEqual(result, 'OK')
def test_add_view_with_request_type_as_noniface(self):
- from pyramid.exceptions import ConfigurationError
view = lambda *arg: 'OK'
config = self._makeOne()
self.assertRaises(ConfigurationError,
@@ -972,7 +973,6 @@ class TestViewsConfigurationMixin(unittest.TestCase):
def test_add_view_with_nonexistant_route_name(self):
from pyramid.renderers import null_renderer
- from zope.configuration.config import ConfigurationExecutionError
view = lambda *arg: 'OK'
config = self._makeOne()
config.add_view(view=view, route_name='foo', renderer=null_renderer)
@@ -1030,7 +1030,6 @@ class TestViewsConfigurationMixin(unittest.TestCase):
def test_add_view_with_request_method_sequence_conflict(self):
from pyramid.renderers import null_renderer
- from zope.configuration.config import ConfigurationConflictError
view = lambda *arg: 'OK'
config = self._makeOne()
config.add_view(view=view, request_method=('POST', 'GET'),
@@ -1107,7 +1106,6 @@ class TestViewsConfigurationMixin(unittest.TestCase):
self._assertNotFound(wrapper, None, request)
def test_add_view_with_header_badregex(self):
- from pyramid.exceptions import ConfigurationError
view = lambda *arg: 'OK'
config = self._makeOne()
self.assertRaises(ConfigurationError,
@@ -1214,7 +1212,6 @@ class TestViewsConfigurationMixin(unittest.TestCase):
self.assertEqual(wrapper(context, None), 'OK')
def test_add_view_with_path_info_badregex(self):
- from pyramid.exceptions import ConfigurationError
view = lambda *arg: 'OK'
config = self._makeOne()
self.assertRaises(ConfigurationError,
@@ -1299,7 +1296,6 @@ class TestViewsConfigurationMixin(unittest.TestCase):
self.assertEqual(wrapper(None, request), 'OK')
def test_add_view_same_predicates(self):
- from zope.configuration.config import ConfigurationConflictError
view2 = lambda *arg: 'second'
view1 = lambda *arg: 'first'
config = self._makeOne()
@@ -2992,7 +2988,6 @@ class TestViewDeriver(unittest.TestCase):
self.assertFalse('Cache-Control' in headers)
def test_http_cached_view_bad_tuple(self):
- from pyramid.exceptions import ConfigurationError
deriver = self._makeOne(http_cache=(None,))
def view(request): pass
self.assertRaises(ConfigurationError, deriver, view)
diff --git a/pyramid/tests/test_exceptions.py b/pyramid/tests/test_exceptions.py
index 50182ee5c..773767d89 100644
--- a/pyramid/tests/test_exceptions.py
+++ b/pyramid/tests/test_exceptions.py
@@ -45,3 +45,32 @@ class TestForbidden(unittest.TestCase):
from pyramid.httpexceptions import HTTPForbidden
self.assertTrue(Forbidden is HTTPForbidden)
+class TestConfigurationConflictError(unittest.TestCase):
+ def _makeOne(self, conflicts):
+ from pyramid.exceptions import ConfigurationConflictError
+ return ConfigurationConflictError(conflicts)
+
+ def test_str(self):
+ conflicts = {'a':('1', '2', '3'), 'b':('4', '5', '6')}
+ exc = self._makeOne(conflicts)
+ self.assertEqual(str(exc),
+"""\
+Conflicting configuration actions
+ For: a
+ 1
+ 2
+ 3
+ For: b
+ 4
+ 5
+ 6""")
+
+class TestConfigurationExecutionError(unittest.TestCase):
+ def _makeOne(self, etype, evalue, info):
+ from pyramid.exceptions import ConfigurationExecutionError
+ return ConfigurationExecutionError(etype, evalue, info)
+
+ def test_str(self):
+ exc = self._makeOne('etype', 'evalue', 'info')
+ self.assertEqual(str(exc), 'etype: evalue\n in:\n info')
+
diff --git a/pyramid/tests/test_registry.py b/pyramid/tests/test_registry.py
index 3d94cb645..6a20eaa5d 100644
--- a/pyramid/tests/test_registry.py
+++ b/pyramid/tests/test_registry.py
@@ -8,6 +8,10 @@ class TestRegistry(unittest.TestCase):
def _makeOne(self):
return self._getTargetClass()()
+ def test___nonzero__(self):
+ registry = self._makeOne()
+ self.assertEqual(registry.__nonzero__(), True)
+
def test_registerHandler_and_notify(self):
registry = self._makeOne()
self.assertEqual(registry.has_listeners, False)
diff --git a/setup.py b/setup.py
index 9a19b8a5b..18260b992 100644
--- a/setup.py
+++ b/setup.py
@@ -35,9 +35,8 @@ install_requires=[
'repoze.lru',
'setuptools',
'zope.component >= 3.6.0', # independent of zope.hookable
- 'zope.configuration',
- 'zope.deprecation',
'zope.interface >= 3.5.1', # 3.5.0 comment: "allow to bootstrap on jython"
+ 'zope.deprecation',
'venusian >= 1.0a1', # ``onerror``
'translationstring',
]