diff options
| author | Chris McDonough <chrism@plope.com> | 2011-09-03 03:09:17 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-09-03 03:09:17 -0400 |
| commit | 79ef3d108e2aa1d630a6f06a8bed107e2ba6d43e (patch) | |
| tree | f7b2abb01e309f0cc13f40558c25c22054d4652b | |
| parent | a7d50d87b447384a30fc2c69eaaef1d974e7562a (diff) | |
| download | pyramid-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__.py | 308 | ||||
| -rw-r--r-- | pyramid/exceptions.py | 32 | ||||
| -rw-r--r-- | pyramid/registry.py | 4 | ||||
| -rw-r--r-- | pyramid/testing.py | 2 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_init.py | 155 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_security.py | 6 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_tweens.py | 3 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_views.py | 13 | ||||
| -rw-r--r-- | pyramid/tests/test_exceptions.py | 29 | ||||
| -rw-r--r-- | pyramid/tests/test_registry.py | 4 | ||||
| -rw-r--r-- | setup.py | 3 |
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) @@ -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', ] |
