summaryrefslogtreecommitdiff
path: root/tests/test_config
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_config')
-rw-r--r--tests/test_config/__init__.py70
-rw-r--r--tests/test_config/files/assets/dummy.txt1
-rw-r--r--tests/test_config/files/minimal.txt1
-rw-r--r--tests/test_config/path/scanerror/__init__.py1
-rw-r--r--tests/test_config/path/scanerror/will_raise_error.py1
-rw-r--r--tests/test_config/pkgs/__init__.py1
-rw-r--r--tests/test_config/pkgs/asset/__init__.py1
-rw-r--r--tests/test_config/pkgs/asset/subpackage/__init__.py1
-rw-r--r--tests/test_config/pkgs/asset/subpackage/templates/bar.pt0
-rw-r--r--tests/test_config/pkgs/scanextrakw/__init__.py17
-rw-r--r--tests/test_config/pkgs/scannable/__init__.py117
-rw-r--r--tests/test_config/pkgs/scannable/another.py83
-rw-r--r--tests/test_config/pkgs/scannable/pod/notinit.py7
-rw-r--r--tests/test_config/pkgs/scannable/subpackage/__init__.py7
-rw-r--r--tests/test_config/pkgs/scannable/subpackage/notinit.py7
-rw-r--r--tests/test_config/pkgs/scannable/subpackage/subsubpackage/__init__.py7
-rw-r--r--tests/test_config/pkgs/selfscan/__init__.py14
-rw-r--r--tests/test_config/pkgs/selfscan/another.py6
-rw-r--r--tests/test_config/test_actions.py1090
-rw-r--r--tests/test_config/test_adapters.py431
-rw-r--r--tests/test_config/test_assets.py1081
-rw-r--r--tests/test_config/test_factories.py203
-rw-r--r--tests/test_config/test_i18n.py171
-rw-r--r--tests/test_config/test_init.py1455
-rw-r--r--tests/test_config/test_predicates.py480
-rw-r--r--tests/test_config/test_rendering.py43
-rw-r--r--tests/test_config/test_routes.py322
-rw-r--r--tests/test_config/test_security.py151
-rw-r--r--tests/test_config/test_settings.py635
-rw-r--r--tests/test_config/test_testing.py235
-rw-r--r--tests/test_config/test_tweens.py484
-rw-r--r--tests/test_config/test_views.py4360
32 files changed, 11483 insertions, 0 deletions
diff --git a/tests/test_config/__init__.py b/tests/test_config/__init__.py
new file mode 100644
index 000000000..ac1f19667
--- /dev/null
+++ b/tests/test_config/__init__.py
@@ -0,0 +1,70 @@
+# package
+from functools import partial
+from zope.interface import implementer
+from zope.interface import Interface
+
+
+class IFactory(Interface):
+ pass
+
+
+def dummy_tween_factory(handler, registry): # pragma: no cover
+ pass
+
+
+def dummy_tween_factory2(handler, registry): # pragma: no cover
+ pass
+
+
+def dummy_include(config):
+ config.registry.included = True
+ config.action('discrim', None, config.package)
+
+
+def dummy_include2(config):
+ config.registry.also_included = True
+ config.action('discrim', None, config.package)
+
+
+includeme = dummy_include
+
+
+class DummyContext:
+ pass
+
+
+@implementer(IFactory)
+class DummyFactory(object):
+ def __call__(self):
+ """ """
+
+
+def dummyfactory(request):
+ """ """
+
+
+class IDummy(Interface):
+ pass
+
+
+def dummy_view(request):
+ return 'OK'
+
+
+def dummy_extend(config, discrim):
+ config.action(discrim, None, config.package)
+
+
+def dummy_extend2(config, discrim):
+ config.action(discrim, None, config.registry)
+
+
+dummy_partial = partial(dummy_extend, discrim='partial')
+
+
+class DummyCallable(object):
+ def __call__(self, config, discrim):
+ config.action(discrim, None, config.package)
+
+
+dummy_callable = DummyCallable()
diff --git a/tests/test_config/files/assets/dummy.txt b/tests/test_config/files/assets/dummy.txt
new file mode 100644
index 000000000..18832d351
--- /dev/null
+++ b/tests/test_config/files/assets/dummy.txt
@@ -0,0 +1 @@
+Hello.
diff --git a/tests/test_config/files/minimal.txt b/tests/test_config/files/minimal.txt
new file mode 100644
index 000000000..19fe66dfa
--- /dev/null
+++ b/tests/test_config/files/minimal.txt
@@ -0,0 +1 @@
+<div clas="header"></div>
diff --git a/tests/test_config/path/scanerror/__init__.py b/tests/test_config/path/scanerror/__init__.py
new file mode 100644
index 000000000..934d6d3ad
--- /dev/null
+++ b/tests/test_config/path/scanerror/__init__.py
@@ -0,0 +1 @@
+# scan error package
diff --git a/tests/test_config/path/scanerror/will_raise_error.py b/tests/test_config/path/scanerror/will_raise_error.py
new file mode 100644
index 000000000..9098ff1fe
--- /dev/null
+++ b/tests/test_config/path/scanerror/will_raise_error.py
@@ -0,0 +1 @@
+import wont.exist
diff --git a/tests/test_config/pkgs/__init__.py b/tests/test_config/pkgs/__init__.py
new file mode 100644
index 000000000..5bb534f79
--- /dev/null
+++ b/tests/test_config/pkgs/__init__.py
@@ -0,0 +1 @@
+# package
diff --git a/tests/test_config/pkgs/asset/__init__.py b/tests/test_config/pkgs/asset/__init__.py
new file mode 100644
index 000000000..5bb534f79
--- /dev/null
+++ b/tests/test_config/pkgs/asset/__init__.py
@@ -0,0 +1 @@
+# package
diff --git a/tests/test_config/pkgs/asset/subpackage/__init__.py b/tests/test_config/pkgs/asset/subpackage/__init__.py
new file mode 100644
index 000000000..5bb534f79
--- /dev/null
+++ b/tests/test_config/pkgs/asset/subpackage/__init__.py
@@ -0,0 +1 @@
+# package
diff --git a/tests/test_config/pkgs/asset/subpackage/templates/bar.pt b/tests/test_config/pkgs/asset/subpackage/templates/bar.pt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/test_config/pkgs/asset/subpackage/templates/bar.pt
diff --git a/tests/test_config/pkgs/scanextrakw/__init__.py b/tests/test_config/pkgs/scanextrakw/__init__.py
new file mode 100644
index 000000000..ddda504e1
--- /dev/null
+++ b/tests/test_config/pkgs/scanextrakw/__init__.py
@@ -0,0 +1,17 @@
+import venusian
+
+
+def foo(wrapped):
+ def bar(scanner, name, wrapped):
+ scanner.config.a = scanner.a
+
+ venusian.attach(wrapped, bar)
+ return wrapped
+
+
+@foo
+def hello():
+ pass
+
+
+hello() # appease coverage
diff --git a/tests/test_config/pkgs/scannable/__init__.py b/tests/test_config/pkgs/scannable/__init__.py
new file mode 100644
index 000000000..585f4357b
--- /dev/null
+++ b/tests/test_config/pkgs/scannable/__init__.py
@@ -0,0 +1,117 @@
+from pyramid.view import view_config
+from pyramid.renderers import null_renderer
+
+
+@view_config(renderer=null_renderer)
+def grokked(context, request):
+ return 'grokked'
+
+
+@view_config(request_method='POST', renderer=null_renderer)
+def grokked_post(context, request):
+ return 'grokked_post'
+
+
+@view_config(name='stacked2', renderer=null_renderer)
+@view_config(name='stacked1', renderer=null_renderer)
+def stacked(context, request):
+ return 'stacked'
+
+
+class stacked_class(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ def __call__(self):
+ return 'stacked_class'
+
+
+stacked_class = view_config(name='stacked_class1', renderer=null_renderer)(
+ stacked_class
+)
+stacked_class = view_config(name='stacked_class2', renderer=null_renderer)(
+ stacked_class
+)
+
+
+class oldstyle_grokked_class:
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ def __call__(self):
+ return 'oldstyle_grokked_class'
+
+
+oldstyle_grokked_class = view_config(
+ name='oldstyle_grokked_class', renderer=null_renderer
+)(oldstyle_grokked_class)
+
+
+class grokked_class(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ def __call__(self):
+ return 'grokked_class'
+
+
+grokked_class = view_config(name='grokked_class', renderer=null_renderer)(
+ grokked_class
+)
+
+
+class Foo(object):
+ def __call__(self, context, request):
+ return 'grokked_instance'
+
+
+grokked_instance = Foo()
+grokked_instance = view_config(
+ name='grokked_instance', renderer=null_renderer
+)(grokked_instance)
+
+
+class Base(object):
+ @view_config(name='basemethod', renderer=null_renderer)
+ def basemethod(self):
+ """ """
+
+
+class MethodViews(Base):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ @view_config(name='method1', renderer=null_renderer)
+ def method1(self):
+ return 'method1'
+
+ @view_config(name='method2', renderer=null_renderer)
+ def method2(self):
+ return 'method2'
+
+ @view_config(name='stacked_method2', renderer=null_renderer)
+ @view_config(name='stacked_method1', renderer=null_renderer)
+ def stacked(self):
+ return 'stacked_method'
+
+
+# ungrokkable
+
+A = 1
+B = {}
+
+
+def stuff():
+ """ """
+
+
+class Whatever(object):
+ pass
+
+
+class Whatever2:
+ pass
diff --git a/tests/test_config/pkgs/scannable/another.py b/tests/test_config/pkgs/scannable/another.py
new file mode 100644
index 000000000..e8b71e5e3
--- /dev/null
+++ b/tests/test_config/pkgs/scannable/another.py
@@ -0,0 +1,83 @@
+from pyramid.view import view_config
+from pyramid.renderers import null_renderer
+
+
+@view_config(name='another', renderer=null_renderer)
+def grokked(context, request):
+ return 'another_grokked'
+
+
+@view_config(request_method='POST', name='another', renderer=null_renderer)
+def grokked_post(context, request):
+ return 'another_grokked_post'
+
+
+@view_config(name='another_stacked2', renderer=null_renderer)
+@view_config(name='another_stacked1', renderer=null_renderer)
+def stacked(context, request):
+ return 'another_stacked'
+
+
+class stacked_class(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ def __call__(self):
+ return 'another_stacked_class'
+
+
+stacked_class = view_config(
+ name='another_stacked_class1', renderer=null_renderer
+)(stacked_class)
+stacked_class = view_config(
+ name='another_stacked_class2', renderer=null_renderer
+)(stacked_class)
+
+
+class oldstyle_grokked_class:
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ def __call__(self):
+ return 'another_oldstyle_grokked_class'
+
+
+oldstyle_grokked_class = view_config(
+ name='another_oldstyle_grokked_class', renderer=null_renderer
+)(oldstyle_grokked_class)
+
+
+class grokked_class(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ def __call__(self):
+ return 'another_grokked_class'
+
+
+grokked_class = view_config(
+ name='another_grokked_class', renderer=null_renderer
+)(grokked_class)
+
+
+class Foo(object):
+ def __call__(self, context, request):
+ return 'another_grokked_instance'
+
+
+grokked_instance = Foo()
+grokked_instance = view_config(
+ name='another_grokked_instance', renderer=null_renderer
+)(grokked_instance)
+
+# ungrokkable
+
+A = 1
+B = {}
+
+
+def stuff():
+ """ """
diff --git a/tests/test_config/pkgs/scannable/pod/notinit.py b/tests/test_config/pkgs/scannable/pod/notinit.py
new file mode 100644
index 000000000..03c93857f
--- /dev/null
+++ b/tests/test_config/pkgs/scannable/pod/notinit.py
@@ -0,0 +1,7 @@
+from pyramid.view import view_config
+from pyramid.renderers import null_renderer
+
+
+@view_config(name='pod_notinit', renderer=null_renderer)
+def subpackage_notinit(context, request):
+ return 'pod_notinit'
diff --git a/tests/test_config/pkgs/scannable/subpackage/__init__.py b/tests/test_config/pkgs/scannable/subpackage/__init__.py
new file mode 100644
index 000000000..f89ca33f7
--- /dev/null
+++ b/tests/test_config/pkgs/scannable/subpackage/__init__.py
@@ -0,0 +1,7 @@
+from pyramid.view import view_config
+from pyramid.renderers import null_renderer
+
+
+@view_config(name='subpackage_init', renderer=null_renderer)
+def subpackage_init(context, request):
+ return 'subpackage_init'
diff --git a/tests/test_config/pkgs/scannable/subpackage/notinit.py b/tests/test_config/pkgs/scannable/subpackage/notinit.py
new file mode 100644
index 000000000..65c2a4929
--- /dev/null
+++ b/tests/test_config/pkgs/scannable/subpackage/notinit.py
@@ -0,0 +1,7 @@
+from pyramid.view import view_config
+from pyramid.renderers import null_renderer
+
+
+@view_config(name='subpackage_notinit', renderer=null_renderer)
+def subpackage_notinit(context, request):
+ return 'subpackage_notinit'
diff --git a/tests/test_config/pkgs/scannable/subpackage/subsubpackage/__init__.py b/tests/test_config/pkgs/scannable/subpackage/subsubpackage/__init__.py
new file mode 100644
index 000000000..ec4bab818
--- /dev/null
+++ b/tests/test_config/pkgs/scannable/subpackage/subsubpackage/__init__.py
@@ -0,0 +1,7 @@
+from pyramid.view import view_config
+from pyramid.renderers import null_renderer
+
+
+@view_config(name='subsubpackage_init', renderer=null_renderer)
+def subpackage_init(context, request):
+ return 'subsubpackage_init'
diff --git a/tests/test_config/pkgs/selfscan/__init__.py b/tests/test_config/pkgs/selfscan/__init__.py
new file mode 100644
index 000000000..8bc8761ca
--- /dev/null
+++ b/tests/test_config/pkgs/selfscan/__init__.py
@@ -0,0 +1,14 @@
+from pyramid.view import view_config
+
+
+@view_config(renderer='string')
+def abc(request):
+ return 'root'
+
+
+def main():
+ from pyramid.config import Configurator
+
+ c = Configurator()
+ c.scan()
+ return c
diff --git a/tests/test_config/pkgs/selfscan/another.py b/tests/test_config/pkgs/selfscan/another.py
new file mode 100644
index 000000000..79e0b08de
--- /dev/null
+++ b/tests/test_config/pkgs/selfscan/another.py
@@ -0,0 +1,6 @@
+from pyramid.view import view_config
+
+
+@view_config(name='two', renderer='string')
+def two(request):
+ return 'two'
diff --git a/tests/test_config/test_actions.py b/tests/test_config/test_actions.py
new file mode 100644
index 000000000..a72d0d7b1
--- /dev/null
+++ b/tests/test_config/test_actions.py
@@ -0,0 +1,1090 @@
+import unittest
+
+from pyramid.exceptions import ConfigurationConflictError
+from pyramid.exceptions import ConfigurationExecutionError
+
+from pyramid.interfaces import IRequest
+
+
+class ActionConfiguratorMixinTests(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def _getViewCallable(
+ self,
+ config,
+ ctx_iface=None,
+ request_iface=None,
+ name='',
+ exception_view=False,
+ ):
+ from zope.interface import Interface
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IExceptionViewClassifier
+
+ if exception_view: # pragma: no cover
+ classifier = IExceptionViewClassifier
+ else:
+ classifier = IViewClassifier
+ if ctx_iface is None:
+ ctx_iface = Interface
+ if request_iface is None:
+ request_iface = IRequest
+ return config.registry.adapters.lookup(
+ (classifier, request_iface, ctx_iface),
+ IView,
+ name=name,
+ default=None,
+ )
+
+ def test_action_branching_kw_is_None(self):
+ config = self._makeOne(autocommit=True)
+ self.assertEqual(config.action('discrim'), None)
+
+ def test_action_branching_kw_is_not_None(self):
+ config = self._makeOne(autocommit=True)
+ self.assertEqual(config.action('discrim', kw={'a': 1}), None)
+
+ def test_action_autocommit_with_introspectables(self):
+ from pyramid.config.actions import ActionInfo
+
+ config = self._makeOne(autocommit=True)
+ intr = DummyIntrospectable()
+ config.action('discrim', introspectables=(intr,))
+ self.assertEqual(len(intr.registered), 1)
+ self.assertEqual(intr.registered[0][0], config.introspector)
+ self.assertEqual(intr.registered[0][1].__class__, ActionInfo)
+
+ def test_action_autocommit_with_introspectables_introspection_off(self):
+ config = self._makeOne(autocommit=True)
+ config.introspection = False
+ intr = DummyIntrospectable()
+ config.action('discrim', introspectables=(intr,))
+ self.assertEqual(len(intr.registered), 0)
+
+ def test_action_branching_nonautocommit_with_config_info(self):
+ config = self._makeOne(autocommit=False)
+ config.info = 'abc'
+ state = DummyActionState()
+ state.autocommit = False
+ config.action_state = state
+ config.action('discrim', kw={'a': 1})
+ self.assertEqual(
+ state.actions,
+ [
+ (
+ (),
+ {
+ 'args': (),
+ 'callable': None,
+ 'discriminator': 'discrim',
+ 'includepath': (),
+ 'info': 'abc',
+ 'introspectables': (),
+ 'kw': {'a': 1},
+ 'order': 0,
+ },
+ )
+ ],
+ )
+
+ def test_action_branching_nonautocommit_without_config_info(self):
+ config = self._makeOne(autocommit=False)
+ config.info = ''
+ config._ainfo = ['z']
+ state = DummyActionState()
+ config.action_state = state
+ state.autocommit = False
+ config.action('discrim', kw={'a': 1})
+ self.assertEqual(
+ state.actions,
+ [
+ (
+ (),
+ {
+ 'args': (),
+ 'callable': None,
+ 'discriminator': 'discrim',
+ 'includepath': (),
+ 'info': 'z',
+ 'introspectables': (),
+ 'kw': {'a': 1},
+ 'order': 0,
+ },
+ )
+ ],
+ )
+
+ def test_action_branching_nonautocommit_with_introspectables(self):
+ config = self._makeOne(autocommit=False)
+ config.info = ''
+ config._ainfo = []
+ state = DummyActionState()
+ config.action_state = state
+ state.autocommit = False
+ intr = DummyIntrospectable()
+ config.action('discrim', introspectables=(intr,))
+ self.assertEqual(state.actions[0][1]['introspectables'], (intr,))
+
+ def test_action_nonautocommit_with_introspectables_introspection_off(self):
+ config = self._makeOne(autocommit=False)
+ config.info = ''
+ config._ainfo = []
+ config.introspection = False
+ state = DummyActionState()
+ config.action_state = state
+ state.autocommit = False
+ intr = DummyIntrospectable()
+ config.action('discrim', introspectables=(intr,))
+ self.assertEqual(state.actions[0][1]['introspectables'], ())
+
+ def test_commit_conflict_simple(self):
+ config = self._makeOne()
+
+ def view1(request): # pragma: no cover
+ pass
+
+ def view2(request): # pragma: no cover
+ pass
+
+ config.add_view(view1)
+ config.add_view(view2)
+ self.assertRaises(ConfigurationConflictError, config.commit)
+
+ def test_commit_conflict_resolved_with_include(self):
+ config = self._makeOne()
+
+ def view1(request): # pragma: no cover
+ pass
+
+ def view2(request): # pragma: no cover
+ pass
+
+ def includeme(config):
+ config.add_view(view2)
+
+ config.add_view(view1)
+ config.include(includeme)
+ config.commit()
+ registeredview = self._getViewCallable(config)
+ self.assertEqual(registeredview.__name__, 'view1')
+
+ def test_commit_conflict_with_two_includes(self):
+ config = self._makeOne()
+
+ def view1(request): # pragma: no cover
+ pass
+
+ def view2(request): # pragma: no cover
+ pass
+
+ def includeme1(config):
+ config.add_view(view1)
+
+ def includeme2(config):
+ config.add_view(view2)
+
+ config.include(includeme1)
+ config.include(includeme2)
+ try:
+ config.commit()
+ except ConfigurationConflictError as why:
+ c1, c2 = _conflictFunctions(why)
+ self.assertEqual(c1, 'includeme1')
+ self.assertEqual(c2, 'includeme2')
+ else: # pragma: no cover
+ raise AssertionError
+
+ def test_commit_conflict_resolved_with_two_includes_and_local(self):
+ config = self._makeOne()
+
+ def view1(request): # pragma: no cover
+ pass
+
+ def view2(request): # pragma: no cover
+ pass
+
+ def view3(request): # pragma: no cover
+ pass
+
+ def includeme1(config):
+ config.add_view(view1)
+
+ def includeme2(config):
+ config.add_view(view2)
+
+ config.include(includeme1)
+ config.include(includeme2)
+ config.add_view(view3)
+ config.commit()
+ registeredview = self._getViewCallable(config)
+ self.assertEqual(registeredview.__name__, 'view3')
+
+ def test_autocommit_no_conflicts(self):
+ from pyramid.renderers import null_renderer
+
+ config = self._makeOne(autocommit=True)
+
+ def view1(request): # pragma: no cover
+ pass
+
+ def view2(request): # pragma: no cover
+ pass
+
+ def view3(request): # pragma: no cover
+ pass
+
+ config.add_view(view1, renderer=null_renderer)
+ config.add_view(view2, renderer=null_renderer)
+ config.add_view(view3, renderer=null_renderer)
+ config.commit()
+ registeredview = self._getViewCallable(config)
+ self.assertEqual(registeredview.__name__, 'view3')
+
+ def test_conflict_set_notfound_view(self):
+ config = self._makeOne()
+
+ def view1(request): # pragma: no cover
+ pass
+
+ def view2(request): # pragma: no cover
+ pass
+
+ config.set_notfound_view(view1)
+ config.set_notfound_view(view2)
+ try:
+ config.commit()
+ except ConfigurationConflictError as why:
+ c1, c2 = _conflictFunctions(why)
+ self.assertEqual(c1, 'test_conflict_set_notfound_view')
+ self.assertEqual(c2, 'test_conflict_set_notfound_view')
+ else: # pragma: no cover
+ raise AssertionError
+
+ def test_conflict_set_forbidden_view(self):
+ config = self._makeOne()
+
+ def view1(request): # pragma: no cover
+ pass
+
+ def view2(request): # pragma: no cover
+ pass
+
+ config.set_forbidden_view(view1)
+ config.set_forbidden_view(view2)
+ try:
+ config.commit()
+ except ConfigurationConflictError as why:
+ c1, c2 = _conflictFunctions(why)
+ self.assertEqual(c1, 'test_conflict_set_forbidden_view')
+ self.assertEqual(c2, 'test_conflict_set_forbidden_view')
+ else: # pragma: no cover
+ raise AssertionError
+
+
+class TestActionState(unittest.TestCase):
+ def _makeOne(self):
+ from pyramid.config.actions import ActionState
+
+ return ActionState()
+
+ def test_it(self):
+ c = self._makeOne()
+ self.assertEqual(c.actions, [])
+
+ def test_action_simple(self):
+ from . import dummyfactory as f
+
+ c = self._makeOne()
+ c.actions = []
+ c.action(1, f, (1,), {'x': 1})
+ self.assertEqual(
+ c.actions,
+ [
+ {
+ 'args': (1,),
+ 'callable': f,
+ 'discriminator': 1,
+ 'includepath': (),
+ 'info': None,
+ 'introspectables': (),
+ 'kw': {'x': 1},
+ 'order': 0,
+ }
+ ],
+ )
+ c.action(None)
+ self.assertEqual(
+ c.actions,
+ [
+ {
+ 'args': (1,),
+ 'callable': f,
+ 'discriminator': 1,
+ 'includepath': (),
+ 'info': None,
+ 'introspectables': (),
+ 'kw': {'x': 1},
+ 'order': 0,
+ },
+ {
+ 'args': (),
+ 'callable': None,
+ 'discriminator': None,
+ 'includepath': (),
+ 'info': None,
+ 'introspectables': (),
+ 'kw': {},
+ 'order': 0,
+ },
+ ],
+ )
+
+ def test_action_with_includepath(self):
+ c = self._makeOne()
+ c.actions = []
+ c.action(None, includepath=('abc',))
+ self.assertEqual(
+ c.actions,
+ [
+ {
+ 'args': (),
+ 'callable': None,
+ 'discriminator': None,
+ 'includepath': ('abc',),
+ 'info': None,
+ 'introspectables': (),
+ 'kw': {},
+ 'order': 0,
+ }
+ ],
+ )
+
+ def test_action_with_info(self):
+ c = self._makeOne()
+ c.action(None, info='abc')
+ self.assertEqual(
+ c.actions,
+ [
+ {
+ 'args': (),
+ 'callable': None,
+ 'discriminator': None,
+ 'includepath': (),
+ 'info': 'abc',
+ 'introspectables': (),
+ 'kw': {},
+ 'order': 0,
+ }
+ ],
+ )
+
+ def test_action_with_includepath_and_info(self):
+ c = self._makeOne()
+ c.action(None, includepath=('spec',), info='bleh')
+ self.assertEqual(
+ c.actions,
+ [
+ {
+ 'args': (),
+ 'callable': None,
+ 'discriminator': None,
+ 'includepath': ('spec',),
+ 'info': 'bleh',
+ 'introspectables': (),
+ 'kw': {},
+ 'order': 0,
+ }
+ ],
+ )
+
+ def test_action_with_order(self):
+ c = self._makeOne()
+ c.actions = []
+ c.action(None, order=99999)
+ self.assertEqual(
+ c.actions,
+ [
+ {
+ 'args': (),
+ 'callable': None,
+ 'discriminator': None,
+ 'includepath': (),
+ 'info': None,
+ 'introspectables': (),
+ 'kw': {},
+ 'order': 99999,
+ }
+ ],
+ )
+
+ def test_action_with_introspectables(self):
+ c = self._makeOne()
+ c.actions = []
+ intr = DummyIntrospectable()
+ c.action(None, introspectables=(intr,))
+ self.assertEqual(
+ c.actions,
+ [
+ {
+ 'args': (),
+ 'callable': None,
+ 'discriminator': None,
+ 'includepath': (),
+ 'info': None,
+ 'introspectables': (intr,),
+ 'kw': {},
+ 'order': 0,
+ }
+ ],
+ )
+
+ def test_processSpec(self):
+ c = self._makeOne()
+ self.assertTrue(c.processSpec('spec'))
+ self.assertFalse(c.processSpec('spec'))
+
+ def test_execute_actions_tuples(self):
+ output = []
+
+ def f(*a, **k):
+ output.append((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, [((1,), {}), ((2,), {})])
+
+ def test_execute_actions_dicts(self):
+ output = []
+
+ def f(*a, **k):
+ output.append((a, k))
+
+ c = self._makeOne()
+ c.actions = [
+ {
+ 'discriminator': 1,
+ 'callable': f,
+ 'args': (1,),
+ 'kw': {},
+ 'order': 0,
+ 'includepath': (),
+ 'info': None,
+ 'introspectables': (),
+ },
+ {
+ 'discriminator': 1,
+ 'callable': f,
+ 'args': (11,),
+ 'kw': {},
+ 'includepath': ('x',),
+ 'order': 0,
+ 'info': None,
+ 'introspectables': (),
+ },
+ {
+ 'discriminator': 2,
+ 'callable': f,
+ 'args': (2,),
+ 'kw': {},
+ 'order': 0,
+ 'includepath': (),
+ 'info': None,
+ 'introspectables': (),
+ },
+ {
+ 'discriminator': None,
+ 'callable': None,
+ 'args': (),
+ 'kw': {},
+ 'order': 0,
+ 'includepath': (),
+ 'info': None,
+ 'introspectables': (),
+ },
+ ]
+ c.execute_actions()
+ self.assertEqual(output, [((1,), {}), ((2,), {})])
+
+ def test_execute_actions_with_introspectables(self):
+ output = []
+
+ def f(*a, **k):
+ output.append((a, k))
+
+ c = self._makeOne()
+ intr = DummyIntrospectable()
+ c.actions = [
+ {
+ 'discriminator': 1,
+ 'callable': f,
+ 'args': (1,),
+ 'kw': {},
+ 'order': 0,
+ 'includepath': (),
+ 'info': None,
+ 'introspectables': (intr,),
+ }
+ ]
+ introspector = object()
+ c.execute_actions(introspector=introspector)
+ self.assertEqual(output, [((1,), {})])
+ self.assertEqual(intr.registered, [(introspector, None)])
+
+ def test_execute_actions_with_introspectable_no_callable(self):
+ c = self._makeOne()
+ intr = DummyIntrospectable()
+ c.actions = [
+ {
+ 'discriminator': 1,
+ 'callable': None,
+ 'args': (1,),
+ 'kw': {},
+ 'order': 0,
+ 'includepath': (),
+ 'info': None,
+ 'introspectables': (intr,),
+ }
+ ]
+ introspector = object()
+ c.execute_actions(introspector=introspector)
+ self.assertEqual(intr.registered, [(introspector, None)])
+
+ 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,), {})])
+
+ def test_reentrant_action(self):
+ output = []
+ c = self._makeOne()
+
+ def f(*a, **k):
+ output.append(('f', a, k))
+ c.actions.append((3, g, (8,), {}))
+
+ def g(*a, **k):
+ output.append(('g', a, k))
+
+ c.actions = [(1, f, (1,))]
+ c.execute_actions()
+ self.assertEqual(output, [('f', (1,), {}), ('g', (8,), {})])
+
+ def test_reentrant_action_with_deferred_discriminator(self):
+ # see https://github.com/Pylons/pyramid/issues/2697
+ from pyramid.registry import Deferred
+
+ output = []
+ c = self._makeOne()
+
+ def f(*a, **k):
+ output.append(('f', a, k))
+ c.actions.append((4, g, (4,), {}, (), None, 2))
+
+ def g(*a, **k):
+ output.append(('g', a, k))
+
+ def h(*a, **k):
+ output.append(('h', a, k))
+
+ def discrim():
+ self.assertEqual(output, [('f', (1,), {}), ('g', (2,), {})])
+ return 3
+
+ d = Deferred(discrim)
+ c.actions = [
+ (d, h, (3,), {}, (), None, 1), # order 1
+ (1, f, (1,)), # order 0
+ (2, g, (2,)), # order 0
+ ]
+ c.execute_actions()
+ self.assertEqual(
+ output,
+ [
+ ('f', (1,), {}),
+ ('g', (2,), {}),
+ ('h', (3,), {}),
+ ('g', (4,), {}),
+ ],
+ )
+
+ def test_reentrant_action_error(self):
+ from pyramid.exceptions import ConfigurationError
+
+ c = self._makeOne()
+
+ def f(*a, **k):
+ c.actions.append((3, g, (8,), {}, (), None, -1))
+
+ def g(*a, **k): # pragma: no cover
+ pass
+
+ c.actions = [(1, f, (1,))]
+ self.assertRaises(ConfigurationError, c.execute_actions)
+
+ def test_reentrant_action_without_clear(self):
+ c = self._makeOne()
+
+ def f(*a, **k):
+ c.actions.append((3, g, (8,)))
+
+ def g(*a, **k):
+ pass
+
+ c.actions = [(1, f, (1,))]
+ c.execute_actions(clear=False)
+ self.assertEqual(c.actions, [(1, f, (1,)), (3, g, (8,))])
+
+ def test_executing_conflicting_action_across_orders(self):
+ from pyramid.exceptions import ConfigurationConflictError
+
+ c = self._makeOne()
+
+ def f(*a, **k):
+ pass
+
+ def g(*a, **k): # pragma: no cover
+ pass
+
+ c.actions = [(1, f, (1,), {}, (), None, -1), (1, g, (2,))]
+ self.assertRaises(ConfigurationConflictError, c.execute_actions)
+
+ def test_executing_conflicting_action_across_reentrant_orders(self):
+ from pyramid.exceptions import ConfigurationConflictError
+
+ c = self._makeOne()
+
+ def f(*a, **k):
+ c.actions.append((1, g, (8,)))
+
+ def g(*a, **k): # pragma: no cover
+ pass
+
+ c.actions = [(1, f, (1,), {}, (), None, -1)]
+ self.assertRaises(ConfigurationConflictError, c.execute_actions)
+
+
+class Test_reentrant_action_functional(unittest.TestCase):
+ def _makeConfigurator(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_functional(self):
+ def add_auto_route(config, name, view):
+ def register():
+ config.add_view(route_name=name, view=view)
+ config.add_route(name, '/' + name)
+
+ config.action(('auto route', name), register, order=-30)
+
+ config = self._makeConfigurator()
+ config.add_directive('add_auto_route', add_auto_route)
+
+ def my_view(request): # pragma: no cover
+ return request.response
+
+ config.add_auto_route('foo', my_view)
+ config.commit()
+ from pyramid.interfaces import IRoutesMapper
+
+ mapper = config.registry.getUtility(IRoutesMapper)
+ routes = mapper.get_routes()
+ route = routes[0]
+ self.assertEqual(len(routes), 1)
+ self.assertEqual(route.name, 'foo')
+ self.assertEqual(route.path, '/foo')
+
+ def test_deferred_discriminator(self):
+ # see https://github.com/Pylons/pyramid/issues/2697
+ from pyramid.config import PHASE0_CONFIG
+
+ config = self._makeConfigurator()
+
+ def deriver(view, info):
+ return view
+
+ deriver.options = ('foo',)
+ config.add_view_deriver(deriver, 'foo_view')
+ # add_view uses a deferred discriminator and will fail if executed
+ # prior to add_view_deriver executing its action
+ config.add_view(lambda r: r.response, name='', foo=1)
+
+ def dummy_action():
+ # trigger a re-entrant action
+ config.action(None, lambda: None)
+
+ config.action(None, dummy_action, order=PHASE0_CONFIG)
+ config.commit()
+
+
+class Test_resolveConflicts(unittest.TestCase):
+ def _callFUT(self, actions):
+ from pyramid.config.actions import resolveConflicts
+
+ return resolveConflicts(actions)
+
+ def test_it_success_tuples(self):
+ from . 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',)),
+ ]
+ )
+ result = list(result)
+ self.assertEqual(
+ result,
+ [
+ {
+ 'info': None,
+ 'args': (),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': None,
+ 'includepath': (),
+ 'order': 0,
+ },
+ {
+ 'info': 'first',
+ 'args': (1,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 1,
+ 'includepath': (),
+ 'order': 0,
+ },
+ {
+ 'info': None,
+ 'args': (3,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 3,
+ 'includepath': ('y',),
+ 'order': 0,
+ },
+ {
+ 'info': None,
+ 'args': (5,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': None,
+ 'includepath': ('y',),
+ 'order': 0,
+ },
+ {
+ 'info': 'should be last',
+ 'args': (4,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 4,
+ 'includepath': ('y',),
+ 'order': 99999,
+ },
+ ],
+ )
+
+ def test_it_success_dicts(self):
+ from . 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',)),
+ ]
+ )
+ result = list(result)
+ self.assertEqual(
+ result,
+ [
+ {
+ 'info': None,
+ 'args': (),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': None,
+ 'includepath': (),
+ 'order': 0,
+ },
+ {
+ 'info': 'first',
+ 'args': (1,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 1,
+ 'includepath': (),
+ 'order': 0,
+ },
+ {
+ 'info': None,
+ 'args': (3,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 3,
+ 'includepath': ('y',),
+ 'order': 0,
+ },
+ {
+ 'info': None,
+ 'args': (5,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': None,
+ 'includepath': ('y',),
+ 'order': 0,
+ },
+ {
+ 'info': 'should be last',
+ 'args': (4,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 4,
+ 'includepath': ('y',),
+ 'order': 99999,
+ },
+ ],
+ )
+
+ def test_it_conflict(self):
+ from . import dummyfactory as f
+
+ result = self._callFUT(
+ [
+ (None, f),
+ (1, f, (2,), {}, ('x',), 'eek'), # will conflict
+ (1, f, (3,), {}, ('y',), 'ack'), # will conflict
+ (4, f, (4,), {}, ('y',)),
+ (3, f, (3,), {}, ('y',)),
+ (None, f, (5,), {}, ('y',)),
+ ]
+ )
+ self.assertRaises(ConfigurationConflictError, list, result)
+
+ def test_it_with_actions_grouped_by_order(self):
+ from . import dummyfactory as f
+
+ result = self._callFUT(
+ [
+ (None, f), # X
+ (1, f, (1,), {}, (), 'third', 10), # X
+ (1, f, (2,), {}, ('x',), 'fourth', 10),
+ (1, f, (3,), {}, ('y',), 'fifth', 10),
+ (2, f, (1,), {}, (), 'sixth', 10), # X
+ (3, f, (1,), {}, (), 'seventh', 10), # X
+ (5, f, (4,), {}, ('y',), 'eighth', 99999), # X
+ (4, f, (3,), {}, (), 'first', 5), # X
+ (4, f, (5,), {}, ('y',), 'second', 5),
+ ]
+ )
+ result = list(result)
+ self.assertEqual(len(result), 6)
+ # resolved actions should be grouped by (order, i)
+ self.assertEqual(
+ result,
+ [
+ {
+ 'info': None,
+ 'args': (),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': None,
+ 'includepath': (),
+ 'order': 0,
+ },
+ {
+ 'info': 'first',
+ 'args': (3,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 4,
+ 'includepath': (),
+ 'order': 5,
+ },
+ {
+ 'info': 'third',
+ 'args': (1,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 1,
+ 'includepath': (),
+ 'order': 10,
+ },
+ {
+ 'info': 'sixth',
+ 'args': (1,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 2,
+ 'includepath': (),
+ 'order': 10,
+ },
+ {
+ 'info': 'seventh',
+ 'args': (1,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 3,
+ 'includepath': (),
+ 'order': 10,
+ },
+ {
+ 'info': 'eighth',
+ 'args': (4,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 5,
+ 'includepath': ('y',),
+ 'order': 99999,
+ },
+ ],
+ )
+
+ def test_override_success_across_orders(self):
+ from . import dummyfactory as f
+
+ result = self._callFUT(
+ [
+ (1, f, (2,), {}, ('x',), 'eek', 0),
+ (1, f, (3,), {}, ('x', 'y'), 'ack', 10),
+ ]
+ )
+ result = list(result)
+ self.assertEqual(
+ result,
+ [
+ {
+ 'info': 'eek',
+ 'args': (2,),
+ 'callable': f,
+ 'introspectables': (),
+ 'kw': {},
+ 'discriminator': 1,
+ 'includepath': ('x',),
+ 'order': 0,
+ }
+ ],
+ )
+
+ def test_conflicts_across_orders(self):
+ from . import dummyfactory as f
+
+ result = self._callFUT(
+ [
+ (1, f, (2,), {}, ('x', 'y'), 'eek', 0),
+ (1, f, (3,), {}, ('x'), 'ack', 10),
+ ]
+ )
+ self.assertRaises(ConfigurationConflictError, list, result)
+
+
+class TestActionInfo(unittest.TestCase):
+ def _getTargetClass(self):
+ from pyramid.config.actions import ActionInfo
+
+ return ActionInfo
+
+ def _makeOne(self, filename, lineno, function, linerepr):
+ return self._getTargetClass()(filename, lineno, function, linerepr)
+
+ def test_class_conforms(self):
+ from zope.interface.verify import verifyClass
+ from pyramid.interfaces import IActionInfo
+
+ verifyClass(IActionInfo, self._getTargetClass())
+
+ def test_instance_conforms(self):
+ from zope.interface.verify import verifyObject
+ from pyramid.interfaces import IActionInfo
+
+ verifyObject(IActionInfo, self._makeOne('f', 0, 'f', 'f'))
+
+ def test_ctor(self):
+ inst = self._makeOne('filename', 10, 'function', 'src')
+ self.assertEqual(inst.file, 'filename')
+ self.assertEqual(inst.line, 10)
+ self.assertEqual(inst.function, 'function')
+ self.assertEqual(inst.src, 'src')
+
+ def test___str__(self):
+ inst = self._makeOne('filename', 0, 'function', ' linerepr ')
+ self.assertEqual(
+ str(inst), "Line 0 of file filename:\n linerepr "
+ )
+
+
+def _conflictFunctions(e):
+ conflicts = e._conflicts.values()
+ for conflict in conflicts:
+ for confinst in conflict:
+ yield confinst.function
+
+
+class DummyActionState(object):
+ autocommit = False
+ info = ''
+
+ def __init__(self):
+ self.actions = []
+
+ def action(self, *arg, **kw):
+ self.actions.append((arg, kw))
+
+
+class DummyIntrospectable(object):
+ def __init__(self):
+ self.registered = []
+
+ def register(self, introspector, action_info):
+ self.registered.append((introspector, action_info))
diff --git a/tests/test_config/test_adapters.py b/tests/test_config/test_adapters.py
new file mode 100644
index 000000000..d871e8825
--- /dev/null
+++ b/tests/test_config/test_adapters.py
@@ -0,0 +1,431 @@
+import unittest
+
+from pyramid.compat import PY2
+from . import IDummy
+
+
+class AdaptersConfiguratorMixinTests(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_add_subscriber_defaults(self):
+ from zope.interface import implementer
+ from zope.interface import Interface
+
+ class IEvent(Interface):
+ pass
+
+ @implementer(IEvent)
+ class Event:
+ pass
+
+ L = []
+
+ def subscriber(event):
+ L.append(event)
+
+ config = self._makeOne(autocommit=True)
+ config.add_subscriber(subscriber)
+ event = Event()
+ config.registry.notify(event)
+ self.assertEqual(len(L), 1)
+ self.assertEqual(L[0], event)
+ config.registry.notify(object())
+ self.assertEqual(len(L), 2)
+
+ def test_add_subscriber_iface_specified(self):
+ from zope.interface import implementer
+ from zope.interface import Interface
+
+ class IEvent(Interface):
+ pass
+
+ @implementer(IEvent)
+ class Event:
+ pass
+
+ L = []
+
+ def subscriber(event):
+ L.append(event)
+
+ config = self._makeOne(autocommit=True)
+ config.add_subscriber(subscriber, IEvent)
+ event = Event()
+ config.registry.notify(event)
+ self.assertEqual(len(L), 1)
+ self.assertEqual(L[0], event)
+ config.registry.notify(object())
+ self.assertEqual(len(L), 1)
+
+ def test_add_subscriber_dottednames(self):
+ import tests.test_config
+ from pyramid.interfaces import INewRequest
+
+ config = self._makeOne(autocommit=True)
+ config.add_subscriber(
+ 'tests.test_config', 'pyramid.interfaces.INewRequest'
+ )
+ handlers = list(config.registry.registeredHandlers())
+ self.assertEqual(len(handlers), 1)
+ handler = handlers[0]
+ self.assertEqual(handler.handler, tests.test_config)
+ self.assertEqual(handler.required, (INewRequest,))
+
+ def test_add_object_event_subscriber(self):
+ from zope.interface import implementer
+ from zope.interface import Interface
+
+ class IEvent(Interface):
+ pass
+
+ @implementer(IEvent)
+ class Event:
+ object = 'foo'
+
+ event = Event()
+ L = []
+
+ def subscriber(object, event):
+ L.append(event)
+
+ config = self._makeOne(autocommit=True)
+ config.add_subscriber(subscriber, (Interface, IEvent))
+ config.registry.subscribers((event.object, event), None)
+ self.assertEqual(len(L), 1)
+ self.assertEqual(L[0], event)
+ config.registry.subscribers((event.object, IDummy), None)
+ self.assertEqual(len(L), 1)
+
+ def test_add_subscriber_with_specific_type_and_predicates_True(self):
+ from zope.interface import implementer
+ from zope.interface import Interface
+
+ class IEvent(Interface):
+ pass
+
+ @implementer(IEvent)
+ class Event:
+ pass
+
+ L = []
+
+ def subscriber(event):
+ L.append(event)
+
+ config = self._makeOne(autocommit=True)
+ predlist = config.get_predlist('subscriber')
+ jam_predicate = predicate_maker('jam')
+ jim_predicate = predicate_maker('jim')
+ predlist.add('jam', jam_predicate)
+ predlist.add('jim', jim_predicate)
+ config.add_subscriber(subscriber, IEvent, jam=True, jim=True)
+ event = Event()
+ event.jam = True
+ event.jim = True
+ config.registry.notify(event)
+ self.assertEqual(len(L), 1)
+ self.assertEqual(L[0], event)
+ config.registry.notify(object())
+ self.assertEqual(len(L), 1)
+
+ def test_add_subscriber_with_default_type_predicates_True(self):
+ from zope.interface import implementer
+ from zope.interface import Interface
+
+ class IEvent(Interface):
+ pass
+
+ @implementer(IEvent)
+ class Event:
+ pass
+
+ L = []
+
+ def subscriber(event):
+ L.append(event)
+
+ config = self._makeOne(autocommit=True)
+ predlist = config.get_predlist('subscriber')
+ jam_predicate = predicate_maker('jam')
+ jim_predicate = predicate_maker('jim')
+ predlist.add('jam', jam_predicate)
+ predlist.add('jim', jim_predicate)
+ config.add_subscriber(subscriber, jam=True, jim=True)
+ event = Event()
+ event.jam = True
+ event.jim = True
+ config.registry.notify(event)
+ self.assertEqual(len(L), 1)
+ self.assertEqual(L[0], event)
+ config.registry.notify(object())
+ self.assertEqual(len(L), 1)
+
+ def test_add_subscriber_with_specific_type_and_predicates_False(self):
+ from zope.interface import implementer
+ from zope.interface import Interface
+
+ class IEvent(Interface):
+ pass
+
+ @implementer(IEvent)
+ class Event:
+ pass
+
+ L = []
+
+ def subscriber(event): # pragma: no cover
+ L.append(event)
+
+ config = self._makeOne(autocommit=True)
+ predlist = config.get_predlist('subscriber')
+ jam_predicate = predicate_maker('jam')
+ jim_predicate = predicate_maker('jim')
+ predlist.add('jam', jam_predicate)
+ predlist.add('jim', jim_predicate)
+ config.add_subscriber(subscriber, IEvent, jam=True, jim=True)
+ event = Event()
+ event.jam = True
+ event.jim = False
+ config.registry.notify(event)
+ self.assertEqual(len(L), 0)
+
+ def test_add_subscriber_with_default_type_predicates_False(self):
+ from zope.interface import implementer
+ from zope.interface import Interface
+
+ class IEvent(Interface):
+ pass
+
+ @implementer(IEvent)
+ class Event:
+ pass
+
+ L = []
+
+ def subscriber(event): # pragma: no cover
+ L.append(event)
+
+ config = self._makeOne(autocommit=True)
+ predlist = config.get_predlist('subscriber')
+ jam_predicate = predicate_maker('jam')
+ jim_predicate = predicate_maker('jim')
+ predlist.add('jam', jam_predicate)
+ predlist.add('jim', jim_predicate)
+ config.add_subscriber(subscriber, jam=True, jim=True)
+ event = Event()
+ event.jam = False
+ event.jim = True
+ config.registry.notify(event)
+ self.assertEqual(len(L), 0)
+
+ def test_add_subscriber_predicate(self):
+ config = self._makeOne()
+ L = []
+
+ def add_predicate(
+ type, name, factory, weighs_less_than=None, weighs_more_than=None
+ ):
+ self.assertEqual(type, 'subscriber')
+ self.assertEqual(name, 'name')
+ self.assertEqual(factory, 'factory')
+ self.assertEqual(weighs_more_than, 1)
+ self.assertEqual(weighs_less_than, 2)
+ L.append(1)
+
+ config._add_predicate = add_predicate
+ config.add_subscriber_predicate('name', 'factory', 1, 2)
+ self.assertTrue(L)
+
+ def test_add_response_adapter(self):
+ from pyramid.interfaces import IResponse
+
+ config = self._makeOne(autocommit=True)
+
+ class Adapter(object):
+ def __init__(self, other):
+ self.other = other
+
+ config.add_response_adapter(Adapter, str)
+ result = config.registry.queryAdapter('foo', IResponse)
+ self.assertTrue(result.other, 'foo')
+
+ def test_add_response_adapter_self(self):
+ from pyramid.interfaces import IResponse
+
+ config = self._makeOne(autocommit=True)
+
+ class Adapter(object):
+ pass
+
+ config.add_response_adapter(None, Adapter)
+ adapter = Adapter()
+ result = config.registry.queryAdapter(adapter, IResponse)
+ self.assertTrue(result is adapter)
+
+ def test_add_response_adapter_dottednames(self):
+ from pyramid.interfaces import IResponse
+
+ config = self._makeOne(autocommit=True)
+ if PY2:
+ str_name = '__builtin__.str'
+ else:
+ str_name = 'builtins.str'
+ config.add_response_adapter('pyramid.response.Response', str_name)
+ result = config.registry.queryAdapter('foo', IResponse)
+ self.assertTrue(result.body, b'foo')
+
+ def test_add_traverser_dotted_names(self):
+ from pyramid.interfaces import ITraverser
+
+ config = self._makeOne(autocommit=True)
+ config.add_traverser(
+ 'tests.test_config.test_adapters.DummyTraverser',
+ 'tests.test_config.test_adapters.DummyIface',
+ )
+ iface = DummyIface()
+ traverser = config.registry.getAdapter(iface, ITraverser)
+ self.assertEqual(traverser.__class__, DummyTraverser)
+ self.assertEqual(traverser.root, iface)
+
+ def test_add_traverser_default_iface_means_Interface(self):
+ from pyramid.interfaces import ITraverser
+
+ config = self._makeOne(autocommit=True)
+ config.add_traverser(DummyTraverser)
+ traverser = config.registry.getAdapter(None, ITraverser)
+ self.assertEqual(traverser.__class__, DummyTraverser)
+
+ def test_add_traverser_nondefault_iface(self):
+ from pyramid.interfaces import ITraverser
+
+ config = self._makeOne(autocommit=True)
+ config.add_traverser(DummyTraverser, DummyIface)
+ iface = DummyIface()
+ traverser = config.registry.getAdapter(iface, ITraverser)
+ self.assertEqual(traverser.__class__, DummyTraverser)
+ self.assertEqual(traverser.root, iface)
+
+ def test_add_traverser_introspectables(self):
+ config = self._makeOne()
+ config.add_traverser(DummyTraverser, DummyIface)
+ actions = config.action_state.actions
+ self.assertEqual(len(actions), 1)
+ intrs = actions[0]['introspectables']
+ self.assertEqual(len(intrs), 1)
+ intr = intrs[0]
+ self.assertEqual(intr.type_name, 'traverser')
+ self.assertEqual(intr.discriminator, ('traverser', DummyIface))
+ self.assertEqual(intr.category_name, 'traversers')
+ self.assertEqual(intr.title, 'traverser for %r' % DummyIface)
+ self.assertEqual(intr['adapter'], DummyTraverser)
+ self.assertEqual(intr['iface'], DummyIface)
+
+ def test_add_resource_url_adapter_dotted_names(self):
+ from pyramid.interfaces import IResourceURL
+
+ config = self._makeOne(autocommit=True)
+ config.add_resource_url_adapter(
+ 'tests.test_config.test_adapters.DummyResourceURL',
+ 'tests.test_config.test_adapters.DummyIface',
+ )
+ iface = DummyIface()
+ adapter = config.registry.getMultiAdapter((iface, iface), IResourceURL)
+ self.assertEqual(adapter.__class__, DummyResourceURL)
+ self.assertEqual(adapter.resource, iface)
+ self.assertEqual(adapter.request, iface)
+
+ def test_add_resource_url_default_resource_iface_means_Interface(self):
+ from pyramid.interfaces import IResourceURL
+
+ config = self._makeOne(autocommit=True)
+ config.add_resource_url_adapter(DummyResourceURL)
+ iface = DummyIface()
+ adapter = config.registry.getMultiAdapter((iface, iface), IResourceURL)
+ self.assertEqual(adapter.__class__, DummyResourceURL)
+ self.assertEqual(adapter.resource, iface)
+ self.assertEqual(adapter.request, iface)
+
+ def test_add_resource_url_nodefault_resource_iface(self):
+ from zope.interface import Interface
+ from pyramid.interfaces import IResourceURL
+
+ config = self._makeOne(autocommit=True)
+ config.add_resource_url_adapter(DummyResourceURL, DummyIface)
+ iface = DummyIface()
+ adapter = config.registry.getMultiAdapter((iface, iface), IResourceURL)
+ self.assertEqual(adapter.__class__, DummyResourceURL)
+ self.assertEqual(adapter.resource, iface)
+ self.assertEqual(adapter.request, iface)
+ bad_result = config.registry.queryMultiAdapter(
+ (Interface, Interface), IResourceURL
+ )
+ self.assertEqual(bad_result, None)
+
+ def test_add_resource_url_adapter_introspectables(self):
+ config = self._makeOne()
+ config.add_resource_url_adapter(DummyResourceURL, DummyIface)
+ actions = config.action_state.actions
+ self.assertEqual(len(actions), 1)
+ intrs = actions[0]['introspectables']
+ self.assertEqual(len(intrs), 1)
+ intr = intrs[0]
+ self.assertEqual(intr.type_name, 'resource url adapter')
+ self.assertEqual(
+ intr.discriminator, ('resource url adapter', DummyIface)
+ )
+ self.assertEqual(intr.category_name, 'resource url adapters')
+ self.assertEqual(
+ intr.title,
+ "resource url adapter for resource iface "
+ "<class 'tests.test_config.test_adapters.DummyIface'>",
+ )
+ self.assertEqual(intr['adapter'], DummyResourceURL)
+ self.assertEqual(intr['resource_iface'], DummyIface)
+
+
+class Test_eventonly(unittest.TestCase):
+ def _callFUT(self, callee):
+ from pyramid.config.adapters import eventonly
+
+ return eventonly(callee)
+
+ def test_defaults(self):
+ def acallable(event, a=1, b=2): # pragma: no cover
+ pass
+
+ self.assertTrue(self._callFUT(acallable))
+
+
+class DummyTraverser(object):
+ def __init__(self, root):
+ self.root = root
+
+
+class DummyIface(object):
+ pass
+
+
+class DummyResourceURL(object):
+ def __init__(self, resource, request):
+ self.resource = resource
+ self.request = request
+
+
+def predicate_maker(name):
+ class Predicate(object):
+ def __init__(self, val, config):
+ self.val = val
+
+ def phash(self):
+ return 'phash'
+
+ text = phash
+
+ def __call__(self, event):
+ return getattr(event, name, None) == self.val
+
+ return Predicate
diff --git a/tests/test_config/test_assets.py b/tests/test_config/test_assets.py
new file mode 100644
index 000000000..875846dbd
--- /dev/null
+++ b/tests/test_config/test_assets.py
@@ -0,0 +1,1081 @@
+import os.path
+import unittest
+from pyramid.testing import cleanUp
+
+# we use this folder
+here = os.path.dirname(os.path.abspath(__file__))
+
+
+class TestAssetsConfiguratorMixin(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_override_asset_samename(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ self.assertRaises(ConfigurationError, config.override_asset, 'a', 'a')
+
+ def test_override_asset_directory_with_file(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.override_asset,
+ 'a:foo/',
+ 'tests.test_config.pkgs.asset:foo.pt',
+ )
+
+ def test_override_asset_file_with_directory(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.override_asset,
+ 'a:foo.pt',
+ 'tests.test_config.pkgs.asset:templates/',
+ )
+
+ def test_override_asset_file_with_package(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.override_asset,
+ 'a:foo.pt',
+ 'tests.test_config.pkgs.asset',
+ )
+
+ def test_override_asset_file_with_file(self):
+ from pyramid.config.assets import PackageAssetSource
+
+ config = self._makeOne(autocommit=True)
+ override = DummyUnderOverride()
+ config.override_asset(
+ 'tests.test_config.pkgs.asset:templates/foo.pt',
+ 'tests.test_config.pkgs.asset.subpackage:templates/bar.pt',
+ _override=override,
+ )
+ from tests.test_config.pkgs import asset
+ from tests.test_config.pkgs.asset import subpackage
+
+ self.assertEqual(override.package, asset)
+ self.assertEqual(override.path, 'templates/foo.pt')
+ source = override.source
+ self.assertTrue(isinstance(source, PackageAssetSource))
+ self.assertEqual(source.package, subpackage)
+ self.assertEqual(source.prefix, 'templates/bar.pt')
+
+ resource_name = ''
+ expected = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt'
+ )
+ self.assertEqual(override.source.get_filename(resource_name), expected)
+
+ def test_override_asset_package_with_package(self):
+ from pyramid.config.assets import PackageAssetSource
+
+ config = self._makeOne(autocommit=True)
+ override = DummyUnderOverride()
+ config.override_asset(
+ 'tests.test_config.pkgs.asset',
+ 'tests.test_config.pkgs.asset.subpackage',
+ _override=override,
+ )
+ from tests.test_config.pkgs import asset
+ from tests.test_config.pkgs.asset import subpackage
+
+ self.assertEqual(override.package, asset)
+ self.assertEqual(override.path, '')
+ source = override.source
+ self.assertTrue(isinstance(source, PackageAssetSource))
+ self.assertEqual(source.package, subpackage)
+ self.assertEqual(source.prefix, '')
+
+ resource_name = 'templates/bar.pt'
+ expected = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt'
+ )
+ self.assertEqual(override.source.get_filename(resource_name), expected)
+
+ def test_override_asset_directory_with_directory(self):
+ from pyramid.config.assets import PackageAssetSource
+
+ config = self._makeOne(autocommit=True)
+ override = DummyUnderOverride()
+ config.override_asset(
+ 'tests.test_config.pkgs.asset:templates/',
+ 'tests.test_config.pkgs.asset.subpackage:templates/',
+ _override=override,
+ )
+ from tests.test_config.pkgs import asset
+ from tests.test_config.pkgs.asset import subpackage
+
+ self.assertEqual(override.package, asset)
+ self.assertEqual(override.path, 'templates/')
+ source = override.source
+ self.assertTrue(isinstance(source, PackageAssetSource))
+ self.assertEqual(source.package, subpackage)
+ self.assertEqual(source.prefix, 'templates/')
+
+ resource_name = 'bar.pt'
+ expected = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt'
+ )
+ self.assertEqual(override.source.get_filename(resource_name), expected)
+
+ def test_override_asset_directory_with_package(self):
+ from pyramid.config.assets import PackageAssetSource
+
+ config = self._makeOne(autocommit=True)
+ override = DummyUnderOverride()
+ config.override_asset(
+ 'tests.test_config.pkgs.asset:templates/',
+ 'tests.test_config.pkgs.asset.subpackage',
+ _override=override,
+ )
+ from tests.test_config.pkgs import asset
+ from tests.test_config.pkgs.asset import subpackage
+
+ self.assertEqual(override.package, asset)
+ self.assertEqual(override.path, 'templates/')
+ source = override.source
+ self.assertTrue(isinstance(source, PackageAssetSource))
+ self.assertEqual(source.package, subpackage)
+ self.assertEqual(source.prefix, '')
+
+ resource_name = 'templates/bar.pt'
+ expected = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt'
+ )
+ self.assertEqual(override.source.get_filename(resource_name), expected)
+
+ def test_override_asset_package_with_directory(self):
+ from pyramid.config.assets import PackageAssetSource
+
+ config = self._makeOne(autocommit=True)
+ override = DummyUnderOverride()
+ config.override_asset(
+ 'tests.test_config.pkgs.asset',
+ 'tests.test_config.pkgs.asset.subpackage:templates/',
+ _override=override,
+ )
+ from tests.test_config.pkgs import asset
+ from tests.test_config.pkgs.asset import subpackage
+
+ self.assertEqual(override.package, asset)
+ self.assertEqual(override.path, '')
+ source = override.source
+ self.assertTrue(isinstance(source, PackageAssetSource))
+ self.assertEqual(source.package, subpackage)
+ self.assertEqual(source.prefix, 'templates/')
+
+ resource_name = 'bar.pt'
+ expected = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt'
+ )
+ self.assertEqual(override.source.get_filename(resource_name), expected)
+
+ def test_override_asset_directory_with_absfile(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.override_asset,
+ 'a:foo/',
+ os.path.join(here, 'pkgs', 'asset', 'foo.pt'),
+ )
+
+ def test_override_asset_file_with_absdirectory(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ abspath = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates'
+ )
+ self.assertRaises(
+ ConfigurationError, config.override_asset, 'a:foo.pt', abspath
+ )
+
+ def test_override_asset_file_with_missing_abspath(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.override_asset,
+ 'a:foo.pt',
+ os.path.join(here, 'wont_exist'),
+ )
+
+ def test_override_asset_file_with_absfile(self):
+ from pyramid.config.assets import FSAssetSource
+
+ config = self._makeOne(autocommit=True)
+ override = DummyUnderOverride()
+ abspath = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt'
+ )
+ config.override_asset(
+ 'tests.test_config.pkgs.asset:templates/foo.pt',
+ abspath,
+ _override=override,
+ )
+ from tests.test_config.pkgs import asset
+
+ self.assertEqual(override.package, asset)
+ self.assertEqual(override.path, 'templates/foo.pt')
+ source = override.source
+ self.assertTrue(isinstance(source, FSAssetSource))
+ self.assertEqual(source.prefix, abspath)
+
+ resource_name = ''
+ expected = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt'
+ )
+ self.assertEqual(override.source.get_filename(resource_name), expected)
+
+ def test_override_asset_directory_with_absdirectory(self):
+ from pyramid.config.assets import FSAssetSource
+
+ config = self._makeOne(autocommit=True)
+ override = DummyUnderOverride()
+ abspath = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates'
+ )
+ config.override_asset(
+ 'tests.test_config.pkgs.asset:templates/',
+ abspath,
+ _override=override,
+ )
+ from tests.test_config.pkgs import asset
+
+ self.assertEqual(override.package, asset)
+ self.assertEqual(override.path, 'templates/')
+ source = override.source
+ self.assertTrue(isinstance(source, FSAssetSource))
+ self.assertEqual(source.prefix, abspath)
+
+ resource_name = 'bar.pt'
+ expected = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt'
+ )
+ self.assertEqual(override.source.get_filename(resource_name), expected)
+
+ def test_override_asset_package_with_absdirectory(self):
+ from pyramid.config.assets import FSAssetSource
+
+ config = self._makeOne(autocommit=True)
+ override = DummyUnderOverride()
+ abspath = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates'
+ )
+ config.override_asset(
+ 'tests.test_config.pkgs.asset', abspath, _override=override
+ )
+ from tests.test_config.pkgs import asset
+
+ self.assertEqual(override.package, asset)
+ self.assertEqual(override.path, '')
+ source = override.source
+ self.assertTrue(isinstance(source, FSAssetSource))
+ self.assertEqual(source.prefix, abspath)
+
+ resource_name = 'bar.pt'
+ expected = os.path.join(
+ here, 'pkgs', 'asset', 'subpackage', 'templates', 'bar.pt'
+ )
+ self.assertEqual(override.source.get_filename(resource_name), expected)
+
+ def test__override_not_yet_registered(self):
+ from pyramid.interfaces import IPackageOverrides
+
+ package = DummyPackage('package')
+ source = DummyAssetSource()
+ config = self._makeOne()
+ config._override(
+ package, 'path', source, PackageOverrides=DummyPackageOverrides
+ )
+ overrides = config.registry.queryUtility(
+ IPackageOverrides, name='package'
+ )
+ self.assertEqual(overrides.inserted, [('path', source)])
+ self.assertEqual(overrides.package, package)
+
+ def test__override_already_registered(self):
+ from pyramid.interfaces import IPackageOverrides
+
+ package = DummyPackage('package')
+ source = DummyAssetSource()
+ overrides = DummyPackageOverrides(package)
+ config = self._makeOne()
+ config.registry.registerUtility(
+ overrides, IPackageOverrides, name='package'
+ )
+ config._override(
+ package, 'path', source, PackageOverrides=DummyPackageOverrides
+ )
+ self.assertEqual(overrides.inserted, [('path', source)])
+ self.assertEqual(overrides.package, package)
+
+
+class TestOverrideProvider(unittest.TestCase):
+ def setUp(self):
+ cleanUp()
+
+ def tearDown(self):
+ cleanUp()
+
+ def _getTargetClass(self):
+ from pyramid.config.assets import OverrideProvider
+
+ return OverrideProvider
+
+ def _makeOne(self, module):
+ klass = self._getTargetClass()
+ return klass(module)
+
+ def _registerOverrides(self, overrides, name='tests.test_config'):
+ from pyramid.interfaces import IPackageOverrides
+ from pyramid.threadlocal import get_current_registry
+
+ reg = get_current_registry()
+ reg.registerUtility(overrides, IPackageOverrides, name=name)
+
+ def test_get_resource_filename_no_overrides(self):
+ resource_name = 'test_assets.py'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ expected = os.path.join(here, resource_name)
+ result = provider.get_resource_filename(None, resource_name)
+ self.assertEqual(result, expected)
+
+ def test_get_resource_stream_no_overrides(self):
+ resource_name = 'test_assets.py'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ with provider.get_resource_stream(None, resource_name) as result:
+ _assertBody(result.read(), os.path.join(here, resource_name))
+
+ def test_get_resource_string_no_overrides(self):
+ resource_name = 'test_assets.py'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ result = provider.get_resource_string(None, resource_name)
+ _assertBody(result, os.path.join(here, resource_name))
+
+ def test_has_resource_no_overrides(self):
+ resource_name = 'test_assets.py'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ result = provider.has_resource(resource_name)
+ self.assertEqual(result, True)
+
+ def test_resource_isdir_no_overrides(self):
+ file_resource_name = 'test_assets.py'
+ directory_resource_name = 'files'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ result = provider.resource_isdir(file_resource_name)
+ self.assertEqual(result, False)
+ result = provider.resource_isdir(directory_resource_name)
+ self.assertEqual(result, True)
+
+ def test_resource_listdir_no_overrides(self):
+ resource_name = 'files'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ result = provider.resource_listdir(resource_name)
+ self.assertTrue(result)
+
+ def test_get_resource_filename_override_returns_None(self):
+ overrides = DummyOverrides(None)
+ self._registerOverrides(overrides)
+ resource_name = 'test_assets.py'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ expected = os.path.join(here, resource_name)
+ result = provider.get_resource_filename(None, resource_name)
+ self.assertEqual(result, expected)
+
+ def test_get_resource_stream_override_returns_None(self):
+ overrides = DummyOverrides(None)
+ self._registerOverrides(overrides)
+ resource_name = 'test_assets.py'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ with provider.get_resource_stream(None, resource_name) as result:
+ _assertBody(result.read(), os.path.join(here, resource_name))
+
+ def test_get_resource_string_override_returns_None(self):
+ overrides = DummyOverrides(None)
+ self._registerOverrides(overrides)
+ resource_name = 'test_assets.py'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ result = provider.get_resource_string(None, resource_name)
+ _assertBody(result, os.path.join(here, resource_name))
+
+ def test_has_resource_override_returns_None(self):
+ overrides = DummyOverrides(None)
+ self._registerOverrides(overrides)
+ resource_name = 'test_assets.py'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ result = provider.has_resource(resource_name)
+ self.assertEqual(result, True)
+
+ def test_resource_isdir_override_returns_None(self):
+ overrides = DummyOverrides(None)
+ self._registerOverrides(overrides)
+ resource_name = 'files'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ result = provider.resource_isdir(resource_name)
+ self.assertEqual(result, True)
+
+ def test_resource_listdir_override_returns_None(self):
+ overrides = DummyOverrides(None)
+ self._registerOverrides(overrides)
+ resource_name = 'files'
+ import tests.test_config
+
+ provider = self._makeOne(tests.test_config)
+ result = provider.resource_listdir(resource_name)
+ self.assertTrue(result)
+
+ def test_get_resource_filename_override_returns_value(self):
+ overrides = DummyOverrides('value')
+ import tests.test_config
+
+ self._registerOverrides(overrides)
+ provider = self._makeOne(tests.test_config)
+ result = provider.get_resource_filename(None, 'test_assets.py')
+ self.assertEqual(result, 'value')
+
+ def test_get_resource_stream_override_returns_value(self):
+ from io import BytesIO
+
+ overrides = DummyOverrides(BytesIO(b'value'))
+ import tests.test_config
+
+ self._registerOverrides(overrides)
+ provider = self._makeOne(tests.test_config)
+ with provider.get_resource_stream(None, 'test_assets.py') as stream:
+ self.assertEqual(stream.getvalue(), b'value')
+
+ def test_get_resource_string_override_returns_value(self):
+ overrides = DummyOverrides('value')
+ import tests.test_config
+
+ self._registerOverrides(overrides)
+ provider = self._makeOne(tests.test_config)
+ result = provider.get_resource_string(None, 'test_assets.py')
+ self.assertEqual(result, 'value')
+
+ def test_has_resource_override_returns_True(self):
+ overrides = DummyOverrides(True)
+ import tests.test_config
+
+ self._registerOverrides(overrides)
+ provider = self._makeOne(tests.test_config)
+ result = provider.has_resource('test_assets.py')
+ self.assertEqual(result, True)
+
+ def test_resource_isdir_override_returns_False(self):
+ overrides = DummyOverrides(False)
+ import tests.test_config
+
+ self._registerOverrides(overrides)
+ provider = self._makeOne(tests.test_config)
+ result = provider.resource_isdir('files')
+ self.assertEqual(result, False)
+
+ def test_resource_listdir_override_returns_values(self):
+ overrides = DummyOverrides(['a'])
+ import tests.test_config
+
+ self._registerOverrides(overrides)
+ provider = self._makeOne(tests.test_config)
+ result = provider.resource_listdir('files')
+ self.assertEqual(result, ['a'])
+
+
+class TestPackageOverrides(unittest.TestCase):
+ def _getTargetClass(self):
+ from pyramid.config.assets import PackageOverrides
+
+ return PackageOverrides
+
+ def _makeOne(self, package=None, pkg_resources=None):
+ if package is None:
+ package = DummyPackage('package')
+ klass = self._getTargetClass()
+ if pkg_resources is None:
+ pkg_resources = DummyPkgResources()
+ return klass(package, pkg_resources=pkg_resources)
+
+ def test_class_conforms_to_IPackageOverrides(self):
+ from zope.interface.verify import verifyClass
+ from pyramid.interfaces import IPackageOverrides
+
+ verifyClass(IPackageOverrides, self._getTargetClass())
+
+ def test_instance_conforms_to_IPackageOverrides(self):
+ from zope.interface.verify import verifyObject
+ from pyramid.interfaces import IPackageOverrides
+
+ verifyObject(IPackageOverrides, self._makeOne())
+
+ def test_class_conforms_to_IPEP302Loader(self):
+ from zope.interface.verify import verifyClass
+ from pyramid.interfaces import IPEP302Loader
+
+ verifyClass(IPEP302Loader, self._getTargetClass())
+
+ def test_instance_conforms_to_IPEP302Loader(self):
+ from zope.interface.verify import verifyObject
+ from pyramid.interfaces import IPEP302Loader
+
+ verifyObject(IPEP302Loader, self._makeOne())
+
+ def test_ctor_package_already_has_loader_of_different_type(self):
+ package = DummyPackage('package')
+ loader = package.__loader__ = DummyLoader()
+ po = self._makeOne(package)
+ self.assertTrue(package.__loader__ is po)
+ self.assertTrue(po.real_loader is loader)
+
+ def test_ctor_package_already_has_loader_of_same_type(self):
+ package = DummyPackage('package')
+ package.__loader__ = self._makeOne(package)
+ po = self._makeOne(package)
+ self.assertEqual(package.__loader__, po)
+
+ def test_ctor_sets_loader(self):
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ self.assertEqual(package.__loader__, po)
+
+ def test_ctor_registers_loader_type(self):
+ from pyramid.config.assets import OverrideProvider
+
+ dummy_pkg_resources = DummyPkgResources()
+ package = DummyPackage('package')
+ po = self._makeOne(package, dummy_pkg_resources)
+ self.assertEqual(
+ dummy_pkg_resources.registered, [(po.__class__, OverrideProvider)]
+ )
+
+ def test_ctor_sets_local_state(self):
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ self.assertEqual(po.overrides, [])
+ self.assertEqual(po.overridden_package_name, 'package')
+
+ def test_insert_directory(self):
+ from pyramid.config.assets import DirectoryOverride
+
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = [None]
+ po.insert('foo/', DummyAssetSource())
+ self.assertEqual(len(po.overrides), 2)
+ override = po.overrides[0]
+ self.assertEqual(override.__class__, DirectoryOverride)
+
+ def test_insert_file(self):
+ from pyramid.config.assets import FileOverride
+
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = [None]
+ po.insert('foo.pt', DummyAssetSource())
+ self.assertEqual(len(po.overrides), 2)
+ override = po.overrides[0]
+ self.assertEqual(override.__class__, FileOverride)
+
+ def test_insert_emptystring(self):
+ # XXX is this a valid case for a directory?
+ from pyramid.config.assets import DirectoryOverride
+
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = [None]
+ source = DummyAssetSource()
+ po.insert('', source)
+ self.assertEqual(len(po.overrides), 2)
+ override = po.overrides[0]
+ self.assertEqual(override.__class__, DirectoryOverride)
+
+ def test_filtered_sources(self):
+ overrides = [DummyOverride(None), DummyOverride('foo')]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(list(po.filtered_sources('whatever')), ['foo'])
+
+ def test_get_filename(self):
+ source = DummyAssetSource(filename='foo.pt')
+ overrides = [DummyOverride(None), DummyOverride((source, ''))]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ result = po.get_filename('whatever')
+ self.assertEqual(result, 'foo.pt')
+ self.assertEqual(source.resource_name, '')
+
+ def test_get_filename_file_doesnt_exist(self):
+ source = DummyAssetSource(filename=None)
+ overrides = [
+ DummyOverride(None),
+ DummyOverride((source, 'wont_exist')),
+ ]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.get_filename('whatever'), None)
+ self.assertEqual(source.resource_name, 'wont_exist')
+
+ def test_get_stream(self):
+ source = DummyAssetSource(stream='a stream?')
+ overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.get_stream('whatever'), 'a stream?')
+ self.assertEqual(source.resource_name, 'foo.pt')
+
+ def test_get_stream_file_doesnt_exist(self):
+ source = DummyAssetSource(stream=None)
+ overrides = [
+ DummyOverride(None),
+ DummyOverride((source, 'wont_exist')),
+ ]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.get_stream('whatever'), None)
+ self.assertEqual(source.resource_name, 'wont_exist')
+
+ def test_get_string(self):
+ source = DummyAssetSource(string='a string')
+ overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.get_string('whatever'), 'a string')
+ self.assertEqual(source.resource_name, 'foo.pt')
+
+ def test_get_string_file_doesnt_exist(self):
+ source = DummyAssetSource(string=None)
+ overrides = [
+ DummyOverride(None),
+ DummyOverride((source, 'wont_exist')),
+ ]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.get_string('whatever'), None)
+ self.assertEqual(source.resource_name, 'wont_exist')
+
+ def test_has_resource(self):
+ source = DummyAssetSource(exists=True)
+ overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.has_resource('whatever'), True)
+ self.assertEqual(source.resource_name, 'foo.pt')
+
+ def test_has_resource_file_doesnt_exist(self):
+ source = DummyAssetSource(exists=None)
+ overrides = [
+ DummyOverride(None),
+ DummyOverride((source, 'wont_exist')),
+ ]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.has_resource('whatever'), None)
+ self.assertEqual(source.resource_name, 'wont_exist')
+
+ def test_isdir_false(self):
+ source = DummyAssetSource(isdir=False)
+ overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.isdir('whatever'), False)
+ self.assertEqual(source.resource_name, 'foo.pt')
+
+ def test_isdir_true(self):
+ source = DummyAssetSource(isdir=True)
+ overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.isdir('whatever'), True)
+ self.assertEqual(source.resource_name, 'foo.pt')
+
+ def test_isdir_doesnt_exist(self):
+ source = DummyAssetSource(isdir=None)
+ overrides = [
+ DummyOverride(None),
+ DummyOverride((source, 'wont_exist')),
+ ]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.isdir('whatever'), None)
+ self.assertEqual(source.resource_name, 'wont_exist')
+
+ def test_listdir(self):
+ source = DummyAssetSource(listdir=True)
+ overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.listdir('whatever'), True)
+ self.assertEqual(source.resource_name, 'foo.pt')
+
+ def test_listdir_doesnt_exist(self):
+ source = DummyAssetSource(listdir=None)
+ overrides = [
+ DummyOverride(None),
+ DummyOverride((source, 'wont_exist')),
+ ]
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ po.overrides = overrides
+ self.assertEqual(po.listdir('whatever'), None)
+ self.assertEqual(source.resource_name, 'wont_exist')
+
+ # PEP 302 __loader__ extensions: use the "real" __loader__, if present.
+ def test_get_data_pkg_has_no___loader__(self):
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ self.assertRaises(NotImplementedError, po.get_data, 'whatever')
+
+ def test_get_data_pkg_has___loader__(self):
+ package = DummyPackage('package')
+ loader = package.__loader__ = DummyLoader()
+ po = self._makeOne(package)
+ self.assertEqual(po.get_data('whatever'), b'DEADBEEF')
+ self.assertEqual(loader._got_data, 'whatever')
+
+ def test_is_package_pkg_has_no___loader__(self):
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ self.assertRaises(NotImplementedError, po.is_package, 'whatever')
+
+ def test_is_package_pkg_has___loader__(self):
+ package = DummyPackage('package')
+ loader = package.__loader__ = DummyLoader()
+ po = self._makeOne(package)
+ self.assertTrue(po.is_package('whatever'))
+ self.assertEqual(loader._is_package, 'whatever')
+
+ def test_get_code_pkg_has_no___loader__(self):
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ self.assertRaises(NotImplementedError, po.get_code, 'whatever')
+
+ def test_get_code_pkg_has___loader__(self):
+ package = DummyPackage('package')
+ loader = package.__loader__ = DummyLoader()
+ po = self._makeOne(package)
+ self.assertEqual(po.get_code('whatever'), b'DEADBEEF')
+ self.assertEqual(loader._got_code, 'whatever')
+
+ def test_get_source_pkg_has_no___loader__(self):
+ package = DummyPackage('package')
+ po = self._makeOne(package)
+ self.assertRaises(NotImplementedError, po.get_source, 'whatever')
+
+ def test_get_source_pkg_has___loader__(self):
+ package = DummyPackage('package')
+ loader = package.__loader__ = DummyLoader()
+ po = self._makeOne(package)
+ self.assertEqual(po.get_source('whatever'), 'def foo():\n pass')
+ self.assertEqual(loader._got_source, 'whatever')
+
+
+class AssetSourceIntegrationTests(object):
+ def test_get_filename(self):
+ source = self._makeOne('')
+ self.assertEqual(
+ source.get_filename('test_assets.py'),
+ os.path.join(here, 'test_assets.py'),
+ )
+
+ def test_get_filename_with_prefix(self):
+ source = self._makeOne('test_assets.py')
+ self.assertEqual(
+ source.get_filename(''), os.path.join(here, 'test_assets.py')
+ )
+
+ def test_get_filename_file_doesnt_exist(self):
+ source = self._makeOne('')
+ self.assertEqual(source.get_filename('wont_exist'), None)
+
+ def test_get_stream(self):
+ source = self._makeOne('')
+ with source.get_stream('test_assets.py') as stream:
+ _assertBody(stream.read(), os.path.join(here, 'test_assets.py'))
+
+ def test_get_stream_with_prefix(self):
+ source = self._makeOne('test_assets.py')
+ with source.get_stream('') as stream:
+ _assertBody(stream.read(), os.path.join(here, 'test_assets.py'))
+
+ def test_get_stream_file_doesnt_exist(self):
+ source = self._makeOne('')
+ self.assertEqual(source.get_stream('wont_exist'), None)
+
+ def test_get_string(self):
+ source = self._makeOne('')
+ _assertBody(
+ source.get_string('test_assets.py'),
+ os.path.join(here, 'test_assets.py'),
+ )
+
+ def test_get_string_with_prefix(self):
+ source = self._makeOne('test_assets.py')
+ _assertBody(
+ source.get_string(''), os.path.join(here, 'test_assets.py')
+ )
+
+ def test_get_string_file_doesnt_exist(self):
+ source = self._makeOne('')
+ self.assertEqual(source.get_string('wont_exist'), None)
+
+ def test_exists(self):
+ source = self._makeOne('')
+ self.assertEqual(source.exists('test_assets.py'), True)
+
+ def test_exists_with_prefix(self):
+ source = self._makeOne('test_assets.py')
+ self.assertEqual(source.exists(''), True)
+
+ def test_exists_file_doesnt_exist(self):
+ source = self._makeOne('')
+ self.assertEqual(source.exists('wont_exist'), None)
+
+ def test_isdir_false(self):
+ source = self._makeOne('')
+ self.assertEqual(source.isdir('test_assets.py'), False)
+
+ def test_isdir_true(self):
+ source = self._makeOne('')
+ self.assertEqual(source.isdir('files'), True)
+
+ def test_isdir_doesnt_exist(self):
+ source = self._makeOne('')
+ self.assertEqual(source.isdir('wont_exist'), None)
+
+ def test_listdir(self):
+ source = self._makeOne('')
+ self.assertTrue(source.listdir('files'))
+
+ def test_listdir_doesnt_exist(self):
+ source = self._makeOne('')
+ self.assertEqual(source.listdir('wont_exist'), None)
+
+
+class TestPackageAssetSource(AssetSourceIntegrationTests, unittest.TestCase):
+ def _getTargetClass(self):
+ from pyramid.config.assets import PackageAssetSource
+
+ return PackageAssetSource
+
+ def _makeOne(self, prefix, package='tests.test_config'):
+ klass = self._getTargetClass()
+ return klass(package, prefix)
+
+
+class TestFSAssetSource(AssetSourceIntegrationTests, unittest.TestCase):
+ def _getTargetClass(self):
+ from pyramid.config.assets import FSAssetSource
+
+ return FSAssetSource
+
+ def _makeOne(self, prefix, base_prefix=here):
+ klass = self._getTargetClass()
+ return klass(os.path.join(base_prefix, prefix))
+
+
+class TestDirectoryOverride(unittest.TestCase):
+ def _getTargetClass(self):
+ from pyramid.config.assets import DirectoryOverride
+
+ return DirectoryOverride
+
+ def _makeOne(self, path, source):
+ klass = self._getTargetClass()
+ return klass(path, source)
+
+ def test_it_match(self):
+ source = DummyAssetSource()
+ o = self._makeOne('foo/', source)
+ result = o('foo/something.pt')
+ self.assertEqual(result, (source, 'something.pt'))
+
+ def test_it_no_match(self):
+ source = DummyAssetSource()
+ o = self._makeOne('foo/', source)
+ result = o('baz/notfound.pt')
+ self.assertEqual(result, None)
+
+
+class TestFileOverride(unittest.TestCase):
+ def _getTargetClass(self):
+ from pyramid.config.assets import FileOverride
+
+ return FileOverride
+
+ def _makeOne(self, path, source):
+ klass = self._getTargetClass()
+ return klass(path, source)
+
+ def test_it_match(self):
+ source = DummyAssetSource()
+ o = self._makeOne('foo.pt', source)
+ result = o('foo.pt')
+ self.assertEqual(result, (source, ''))
+
+ def test_it_no_match(self):
+ source = DummyAssetSource()
+ o = self._makeOne('foo.pt', source)
+ result = o('notfound.pt')
+ self.assertEqual(result, None)
+
+
+class DummyOverride:
+ def __init__(self, result):
+ self.result = result
+
+ def __call__(self, resource_name):
+ return self.result
+
+
+class DummyOverrides:
+ def __init__(self, result):
+ self.result = result
+
+ def get_filename(self, resource_name):
+ return self.result
+
+ listdir = isdir = has_resource = get_stream = get_string = get_filename
+
+
+class DummyPackageOverrides:
+ def __init__(self, package):
+ self.package = package
+ self.inserted = []
+
+ def insert(self, path, source):
+ self.inserted.append((path, source))
+
+
+class DummyPkgResources:
+ def __init__(self):
+ self.registered = []
+
+ def register_loader_type(self, typ, inst):
+ self.registered.append((typ, inst))
+
+
+class DummyPackage:
+ def __init__(self, name):
+ self.__name__ = name
+
+
+class DummyAssetSource:
+ def __init__(self, **kw):
+ self.kw = kw
+
+ def get_filename(self, resource_name):
+ self.resource_name = resource_name
+ return self.kw['filename']
+
+ def get_stream(self, resource_name):
+ self.resource_name = resource_name
+ return self.kw['stream']
+
+ def get_string(self, resource_name):
+ self.resource_name = resource_name
+ return self.kw['string']
+
+ def exists(self, resource_name):
+ self.resource_name = resource_name
+ return self.kw['exists']
+
+ def isdir(self, resource_name):
+ self.resource_name = resource_name
+ return self.kw['isdir']
+
+ def listdir(self, resource_name):
+ self.resource_name = resource_name
+ return self.kw['listdir']
+
+
+class DummyLoader:
+ _got_data = _is_package = None
+
+ def get_data(self, path):
+ self._got_data = path
+ return b'DEADBEEF'
+
+ def is_package(self, fullname):
+ self._is_package = fullname
+ return True
+
+ def get_code(self, fullname):
+ self._got_code = fullname
+ return b'DEADBEEF'
+
+ def get_source(self, fullname):
+ self._got_source = fullname
+ return 'def foo():\n pass'
+
+
+class DummyUnderOverride:
+ def __call__(self, package, path, source, _info=''):
+ self.package = package
+ self.path = path
+ self.source = source
+
+
+def read_(src):
+ with open(src, 'rb') as f:
+ contents = f.read()
+ return contents
+
+
+def _assertBody(body, filename):
+ # strip both \n and \r for windows
+ body = body.replace(b'\r', b'')
+ body = body.replace(b'\n', b'')
+ data = read_(filename)
+ data = data.replace(b'\r', b'')
+ data = data.replace(b'\n', b'')
+ assert body == data
diff --git a/tests/test_config/test_factories.py b/tests/test_config/test_factories.py
new file mode 100644
index 000000000..c03d3f68b
--- /dev/null
+++ b/tests/test_config/test_factories.py
@@ -0,0 +1,203 @@
+import unittest
+
+from . import dummyfactory
+
+
+class TestFactoriesMixin(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_set_request_factory(self):
+ from pyramid.interfaces import IRequestFactory
+
+ config = self._makeOne(autocommit=True)
+ factory = object()
+ config.set_request_factory(factory)
+ self.assertEqual(config.registry.getUtility(IRequestFactory), factory)
+
+ def test_set_request_factory_dottedname(self):
+ from pyramid.interfaces import IRequestFactory
+
+ config = self._makeOne(autocommit=True)
+ config.set_request_factory('tests.test_config.dummyfactory')
+ self.assertEqual(
+ config.registry.getUtility(IRequestFactory), dummyfactory
+ )
+
+ def test_set_response_factory(self):
+ from pyramid.interfaces import IResponseFactory
+
+ config = self._makeOne(autocommit=True)
+ factory = lambda r: object()
+ config.set_response_factory(factory)
+ self.assertEqual(config.registry.getUtility(IResponseFactory), factory)
+
+ def test_set_response_factory_dottedname(self):
+ from pyramid.interfaces import IResponseFactory
+
+ config = self._makeOne(autocommit=True)
+ config.set_response_factory('tests.test_config.dummyfactory')
+ self.assertEqual(
+ config.registry.getUtility(IResponseFactory), dummyfactory
+ )
+
+ def test_set_root_factory(self):
+ from pyramid.interfaces import IRootFactory
+
+ config = self._makeOne()
+ config.set_root_factory(dummyfactory)
+ self.assertEqual(config.registry.queryUtility(IRootFactory), None)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IRootFactory), dummyfactory
+ )
+
+ def test_set_root_factory_as_None(self):
+ from pyramid.interfaces import IRootFactory
+ from pyramid.traversal import DefaultRootFactory
+
+ config = self._makeOne()
+ config.set_root_factory(None)
+ self.assertEqual(config.registry.queryUtility(IRootFactory), None)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IRootFactory), DefaultRootFactory
+ )
+
+ def test_set_root_factory_dottedname(self):
+ from pyramid.interfaces import IRootFactory
+
+ config = self._makeOne()
+ config.set_root_factory('tests.test_config.dummyfactory')
+ self.assertEqual(config.registry.queryUtility(IRootFactory), None)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IRootFactory), dummyfactory
+ )
+
+ def test_set_session_factory(self):
+ from pyramid.interfaces import ISessionFactory
+
+ config = self._makeOne()
+ config.set_session_factory(dummyfactory)
+ self.assertEqual(config.registry.queryUtility(ISessionFactory), None)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(ISessionFactory), dummyfactory
+ )
+
+ def test_set_session_factory_dottedname(self):
+ from pyramid.interfaces import ISessionFactory
+
+ config = self._makeOne()
+ config.set_session_factory('tests.test_config.dummyfactory')
+ self.assertEqual(config.registry.queryUtility(ISessionFactory), None)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(ISessionFactory), dummyfactory
+ )
+
+ def test_add_request_method_with_callable(self):
+ from pyramid.interfaces import IRequestExtensions
+
+ config = self._makeOne(autocommit=True)
+ callable = lambda x: None
+ config.add_request_method(callable, name='foo')
+ exts = config.registry.getUtility(IRequestExtensions)
+ self.assertTrue('foo' in exts.methods)
+
+ def test_add_request_method_with_unnamed_callable(self):
+ from pyramid.interfaces import IRequestExtensions
+
+ config = self._makeOne(autocommit=True)
+
+ def foo(self): # pragma: no cover
+ pass
+
+ config.add_request_method(foo)
+ exts = config.registry.getUtility(IRequestExtensions)
+ self.assertTrue('foo' in exts.methods)
+
+ def test_set_multiple_request_methods_conflict(self):
+ from pyramid.exceptions import ConfigurationConflictError
+
+ config = self._makeOne()
+
+ def foo(self): # pragma: no cover
+ pass
+
+ def bar(self): # pragma: no cover
+ pass
+
+ config.add_request_method(foo, name='bar')
+ config.add_request_method(bar, name='bar')
+ self.assertRaises(ConfigurationConflictError, config.commit)
+
+ def test_add_request_method_with_None_callable(self):
+ from pyramid.interfaces import IRequestExtensions
+
+ config = self._makeOne(autocommit=True)
+ config.add_request_method(name='foo')
+ exts = config.registry.queryUtility(IRequestExtensions)
+ self.assertTrue(exts is None)
+
+ def test_add_request_method_with_None_callable_conflict(self):
+ from pyramid.exceptions import ConfigurationConflictError
+
+ config = self._makeOne()
+
+ def bar(self): # pragma: no cover
+ pass
+
+ config.add_request_method(name='foo')
+ config.add_request_method(bar, name='foo')
+ self.assertRaises(ConfigurationConflictError, config.commit)
+
+ def test_add_request_method_with_None_callable_and_no_name(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(AttributeError, config.add_request_method)
+
+ def test_add_request_method_with_text_type_name(self):
+ from pyramid.compat import text_, PY2
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne(autocommit=True)
+
+ def boomshaka(r): # pragma: no cover
+ pass
+
+ def get_bad_name():
+ if PY2:
+ name = text_(b'La Pe\xc3\xb1a', 'utf-8')
+ else:
+ name = b'La Pe\xc3\xb1a'
+
+ config.add_request_method(boomshaka, name=name)
+
+ self.assertRaises(ConfigurationError, get_bad_name)
+
+ def test_set_execution_policy(self):
+ from pyramid.interfaces import IExecutionPolicy
+
+ config = self._makeOne(autocommit=True)
+
+ def dummy_policy(environ, router): # pragma: no cover
+ pass
+
+ config.set_execution_policy(dummy_policy)
+ registry = config.registry
+ result = registry.queryUtility(IExecutionPolicy)
+ self.assertEqual(result, dummy_policy)
+
+ def test_set_execution_policy_to_None(self):
+ from pyramid.interfaces import IExecutionPolicy
+ from pyramid.router import default_execution_policy
+
+ config = self._makeOne(autocommit=True)
+ config.set_execution_policy(None)
+ registry = config.registry
+ result = registry.queryUtility(IExecutionPolicy)
+ self.assertEqual(result, default_execution_policy)
diff --git a/tests/test_config/test_i18n.py b/tests/test_config/test_i18n.py
new file mode 100644
index 000000000..b840c1976
--- /dev/null
+++ b/tests/test_config/test_i18n.py
@@ -0,0 +1,171 @@
+import os
+import unittest
+
+from . import dummyfactory
+
+here = os.path.dirname(__file__)
+locale = os.path.abspath(
+ os.path.join(here, '..', 'pkgs', 'localeapp', 'locale')
+)
+locale2 = os.path.abspath(
+ os.path.join(here, '..', 'pkgs', 'localeapp', 'locale2')
+)
+locale3 = os.path.abspath(
+ os.path.join(here, '..', 'pkgs', 'localeapp', 'locale3')
+)
+
+
+class TestI18NConfiguratorMixin(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_set_locale_negotiator(self):
+ from pyramid.interfaces import ILocaleNegotiator
+
+ config = self._makeOne(autocommit=True)
+
+ def negotiator(request): # pragma: no cover
+ pass
+
+ config.set_locale_negotiator(negotiator)
+ self.assertEqual(
+ config.registry.getUtility(ILocaleNegotiator), negotiator
+ )
+
+ def test_set_locale_negotiator_dottedname(self):
+ from pyramid.interfaces import ILocaleNegotiator
+
+ config = self._makeOne(autocommit=True)
+ config.set_locale_negotiator('tests.test_config.dummyfactory')
+ self.assertEqual(
+ config.registry.getUtility(ILocaleNegotiator), dummyfactory
+ )
+
+ def test_add_translation_dirs_missing_dir(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ config.add_translation_dirs('/wont/exist/on/my/system')
+ self.assertRaises(ConfigurationError, config.commit)
+
+ def test_add_translation_dirs_no_specs(self):
+ from pyramid.interfaces import ITranslationDirectories
+
+ config = self._makeOne()
+ config.add_translation_dirs()
+ self.assertEqual(
+ config.registry.queryUtility(ITranslationDirectories), None
+ )
+
+ def test_add_translation_dirs_asset_spec(self):
+ from pyramid.interfaces import ITranslationDirectories
+
+ config = self._makeOne(autocommit=True)
+ config.add_translation_dirs('tests.pkgs.localeapp:locale')
+ self.assertEqual(
+ config.registry.getUtility(ITranslationDirectories), [locale]
+ )
+
+ def test_add_translation_dirs_asset_spec_existing_translation_dirs(self):
+ from pyramid.interfaces import ITranslationDirectories
+
+ config = self._makeOne(autocommit=True)
+ directories = ['abc']
+ config.registry.registerUtility(directories, ITranslationDirectories)
+ config.add_translation_dirs('tests.pkgs.localeapp:locale')
+ result = config.registry.getUtility(ITranslationDirectories)
+ self.assertEqual(result, [locale, 'abc'])
+
+ def test_add_translation_dirs_multiple_specs(self):
+ from pyramid.interfaces import ITranslationDirectories
+
+ config = self._makeOne(autocommit=True)
+ config.add_translation_dirs(
+ 'tests.pkgs.localeapp:locale', 'tests.pkgs.localeapp:locale2'
+ )
+ self.assertEqual(
+ config.registry.getUtility(ITranslationDirectories),
+ [locale, locale2],
+ )
+
+ def test_add_translation_dirs_multiple_specs_multiple_calls(self):
+ from pyramid.interfaces import ITranslationDirectories
+
+ config = self._makeOne(autocommit=True)
+ config.add_translation_dirs(
+ 'tests.pkgs.localeapp:locale', 'tests.pkgs.localeapp:locale2'
+ )
+ config.add_translation_dirs('tests.pkgs.localeapp:locale3')
+ self.assertEqual(
+ config.registry.getUtility(ITranslationDirectories),
+ [locale3, locale, locale2],
+ )
+
+ def test_add_translation_dirs_override_multiple_specs_multiple_calls(self):
+ from pyramid.interfaces import ITranslationDirectories
+
+ config = self._makeOne(autocommit=True)
+ config.add_translation_dirs(
+ 'tests.pkgs.localeapp:locale', 'tests.pkgs.localeapp:locale2'
+ )
+ config.add_translation_dirs(
+ 'tests.pkgs.localeapp:locale3', override=True
+ )
+ self.assertEqual(
+ config.registry.getUtility(ITranslationDirectories),
+ [locale, locale2, locale3],
+ )
+
+ def test_add_translation_dirs_invalid_kwargs(self):
+ config = self._makeOne(autocommit=True)
+ with self.assertRaises(TypeError):
+ config.add_translation_dirs('tests.pkgs.localeapp:locale', foo=1)
+
+ def test_add_translation_dirs_abspath(self):
+ from pyramid.interfaces import ITranslationDirectories
+
+ config = self._makeOne(autocommit=True)
+ config.add_translation_dirs(locale)
+ self.assertEqual(
+ config.registry.getUtility(ITranslationDirectories), [locale]
+ )
+
+ def test_add_translation_dirs_uses_override_out_of_order(self):
+ from pyramid.interfaces import ITranslationDirectories
+
+ config = self._makeOne()
+ config.add_translation_dirs('tests.pkgs.localeapp:locale')
+ config.override_asset(
+ 'tests.pkgs.localeapp:locale/', 'tests.pkgs.localeapp:locale2/'
+ )
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(ITranslationDirectories), [locale2]
+ )
+
+ def test_add_translation_dirs_doesnt_use_override_w_autocommit(self):
+ from pyramid.interfaces import ITranslationDirectories
+
+ config = self._makeOne(autocommit=True)
+ config.add_translation_dirs('tests.pkgs.localeapp:locale')
+ config.override_asset(
+ 'tests.pkgs.localeapp:locale/', 'tests.pkgs.localeapp:locale2/'
+ )
+ self.assertEqual(
+ config.registry.getUtility(ITranslationDirectories), [locale]
+ )
+
+ def test_add_translation_dirs_uses_override_w_autocommit(self):
+ from pyramid.interfaces import ITranslationDirectories
+
+ config = self._makeOne(autocommit=True)
+ config.override_asset(
+ 'tests.pkgs.localeapp:locale/', 'tests.pkgs.localeapp:locale2/'
+ )
+ config.add_translation_dirs('tests.pkgs.localeapp:locale')
+ self.assertEqual(
+ config.registry.getUtility(ITranslationDirectories), [locale2]
+ )
diff --git a/tests/test_config/test_init.py b/tests/test_config/test_init.py
new file mode 100644
index 000000000..811672fb3
--- /dev/null
+++ b/tests/test_config/test_init.py
@@ -0,0 +1,1455 @@
+import os
+import unittest
+
+from pyramid.compat import im_func
+from pyramid.testing import skip_on
+
+from . import dummy_tween_factory
+from . import dummy_include
+from . import dummy_extend
+from . import dummy_extend2
+from . import DummyContext
+
+from pyramid.exceptions import ConfigurationExecutionError
+from pyramid.exceptions import ConfigurationConflictError
+
+from pyramid.interfaces import IRequest
+
+
+class ConfiguratorTests(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def _getViewCallable(
+ self,
+ config,
+ ctx_iface=None,
+ request_iface=None,
+ name='',
+ exception_view=False,
+ ):
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IExceptionViewClassifier
+
+ if exception_view: # pragma: no cover
+ classifier = IExceptionViewClassifier
+ else:
+ classifier = IViewClassifier
+ return config.registry.adapters.lookup(
+ (classifier, request_iface, ctx_iface),
+ IView,
+ name=name,
+ default=None,
+ )
+
+ def _registerEventListener(self, config, event_iface=None):
+ if event_iface is None: # pragma: no cover
+ from zope.interface import Interface
+
+ event_iface = Interface
+ L = []
+
+ def subscriber(*event):
+ L.extend(event)
+
+ config.registry.registerHandler(subscriber, (event_iface,))
+ return L
+
+ def _makeRequest(self, config):
+ request = DummyRequest()
+ request.registry = config.registry
+ return request
+
+ def test_ctor_no_registry(self):
+ import sys
+ from pyramid.interfaces import ISettings
+ from pyramid.config import Configurator
+ from pyramid.interfaces import IRendererFactory
+
+ config = Configurator()
+ this_pkg = sys.modules['tests.test_config']
+ self.assertTrue(config.registry.getUtility(ISettings))
+ self.assertEqual(config.package, this_pkg)
+ config.commit()
+ self.assertTrue(config.registry.getUtility(IRendererFactory, 'json'))
+ self.assertTrue(config.registry.getUtility(IRendererFactory, 'string'))
+
+ def test_begin(self):
+ from pyramid.config import Configurator
+
+ config = Configurator()
+ manager = DummyThreadLocalManager()
+ config.manager = manager
+ config.begin()
+ self.assertEqual(
+ manager.pushed, {'registry': config.registry, 'request': None}
+ )
+ self.assertEqual(manager.popped, False)
+
+ def test_begin_with_request(self):
+ from pyramid.config import Configurator
+
+ config = Configurator()
+ request = object()
+ manager = DummyThreadLocalManager()
+ config.manager = manager
+ config.begin(request=request)
+ self.assertEqual(
+ manager.pushed, {'registry': config.registry, 'request': request}
+ )
+ self.assertEqual(manager.popped, False)
+
+ def test_begin_overrides_request(self):
+ from pyramid.config import Configurator
+
+ config = Configurator()
+ manager = DummyThreadLocalManager()
+ req = object()
+ # set it up for auto-propagation
+ pushed = {'registry': config.registry, 'request': None}
+ manager.pushed = pushed
+ config.manager = manager
+ config.begin(req)
+ self.assertTrue(manager.pushed is not pushed)
+ self.assertEqual(manager.pushed['request'], req)
+ self.assertEqual(manager.pushed['registry'], config.registry)
+
+ def test_begin_propagates_request_for_same_registry(self):
+ from pyramid.config import Configurator
+
+ config = Configurator()
+ manager = DummyThreadLocalManager()
+ req = object()
+ pushed = {'registry': config.registry, 'request': req}
+ manager.pushed = pushed
+ config.manager = manager
+ config.begin()
+ self.assertTrue(manager.pushed is not pushed)
+ self.assertEqual(manager.pushed['request'], req)
+ self.assertEqual(manager.pushed['registry'], config.registry)
+
+ def test_begin_does_not_propagate_request_for_diff_registry(self):
+ from pyramid.config import Configurator
+
+ config = Configurator()
+ manager = DummyThreadLocalManager()
+ req = object()
+ pushed = {'registry': object(), 'request': req}
+ manager.pushed = pushed
+ config.manager = manager
+ config.begin()
+ self.assertTrue(manager.pushed is not pushed)
+ self.assertEqual(manager.pushed['request'], None)
+ self.assertEqual(manager.pushed['registry'], config.registry)
+
+ def test_end(self):
+ from pyramid.config import Configurator
+
+ config = Configurator()
+ manager = DummyThreadLocalManager()
+ pushed = manager.pushed
+ config.manager = manager
+ config.end()
+ self.assertEqual(manager.pushed, pushed)
+ self.assertEqual(manager.popped, True)
+
+ def test_context_manager(self):
+ from pyramid.config import Configurator
+
+ config = Configurator()
+ manager = DummyThreadLocalManager()
+ config.manager = manager
+ view = lambda r: None
+ with config as ctx:
+ self.assertTrue(config is ctx)
+ self.assertEqual(
+ manager.pushed, {'registry': config.registry, 'request': None}
+ )
+ self.assertFalse(manager.popped)
+ config.add_view(view)
+ self.assertTrue(manager.popped)
+ config.add_view(view) # did not raise a conflict because of commit
+ config.commit()
+
+ def test_ctor_with_package_registry(self):
+ import sys
+ from pyramid.config import Configurator
+
+ pkg = sys.modules['pyramid']
+ config = Configurator(package=pkg)
+ self.assertEqual(config.package, pkg)
+
+ def test_ctor_noreg_custom_settings(self):
+ from pyramid.interfaces import ISettings
+
+ settings = {'reload_templates': True, 'mysetting': True}
+ config = self._makeOne(settings=settings)
+ settings = config.registry.getUtility(ISettings)
+ self.assertEqual(settings['reload_templates'], True)
+ self.assertEqual(settings['debug_authorization'], False)
+ self.assertEqual(settings['mysetting'], True)
+
+ def test_ctor_noreg_debug_logger_None_default(self):
+ from pyramid.interfaces import IDebugLogger
+
+ config = self._makeOne()
+ logger = config.registry.getUtility(IDebugLogger)
+ self.assertEqual(logger.name, 'tests.test_config')
+
+ def test_ctor_noreg_debug_logger_non_None(self):
+ from pyramid.interfaces import IDebugLogger
+
+ logger = object()
+ config = self._makeOne(debug_logger=logger)
+ result = config.registry.getUtility(IDebugLogger)
+ self.assertEqual(logger, result)
+
+ def test_ctor_authentication_policy(self):
+ from pyramid.interfaces import IAuthenticationPolicy
+
+ policy = object()
+ config = self._makeOne(authentication_policy=policy)
+ config.commit()
+ result = config.registry.getUtility(IAuthenticationPolicy)
+ self.assertEqual(policy, result)
+
+ def test_ctor_authorization_policy_only(self):
+ policy = object()
+ config = self._makeOne(authorization_policy=policy)
+ self.assertRaises(ConfigurationExecutionError, config.commit)
+
+ def test_ctor_no_root_factory(self):
+ from pyramid.interfaces import IRootFactory
+
+ config = self._makeOne()
+ self.assertEqual(config.registry.queryUtility(IRootFactory), None)
+ config.commit()
+ self.assertEqual(config.registry.queryUtility(IRootFactory), None)
+
+ def test_ctor_with_root_factory(self):
+ from pyramid.interfaces import IRootFactory
+
+ factory = object()
+ config = self._makeOne(root_factory=factory)
+ self.assertEqual(config.registry.queryUtility(IRootFactory), None)
+ config.commit()
+ self.assertEqual(config.registry.queryUtility(IRootFactory), factory)
+
+ def test_ctor_alternate_renderers(self):
+ from pyramid.interfaces import IRendererFactory
+
+ renderer = object()
+ config = self._makeOne(renderers=[('yeah', renderer)])
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IRendererFactory, 'yeah'), renderer
+ )
+
+ def test_ctor_default_renderers(self):
+ from pyramid.interfaces import IRendererFactory
+ from pyramid.renderers import json_renderer_factory
+
+ config = self._makeOne()
+ self.assertEqual(
+ config.registry.getUtility(IRendererFactory, 'json'),
+ json_renderer_factory,
+ )
+
+ def test_ctor_default_permission(self):
+ from pyramid.interfaces import IDefaultPermission
+
+ config = self._makeOne(default_permission='view')
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IDefaultPermission), 'view'
+ )
+
+ def test_ctor_session_factory(self):
+ from pyramid.interfaces import ISessionFactory
+
+ factory = object()
+ config = self._makeOne(session_factory=factory)
+ self.assertEqual(config.registry.queryUtility(ISessionFactory), None)
+ config.commit()
+ self.assertEqual(config.registry.getUtility(ISessionFactory), factory)
+
+ def test_ctor_default_view_mapper(self):
+ from pyramid.interfaces import IViewMapperFactory
+
+ mapper = object()
+ config = self._makeOne(default_view_mapper=mapper)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IViewMapperFactory), mapper
+ )
+
+ def test_ctor_httpexception_view_default(self):
+ from pyramid.interfaces import IExceptionResponse
+ from pyramid.httpexceptions import default_exceptionresponse_view
+
+ config = self._makeOne()
+ view = self._getViewCallable(
+ config, ctx_iface=IExceptionResponse, request_iface=IRequest
+ )
+ self.assertTrue(view.__wraps__ is default_exceptionresponse_view)
+
+ def test_ctor_exceptionresponse_view_None(self):
+ from pyramid.interfaces import IExceptionResponse
+
+ config = self._makeOne(exceptionresponse_view=None)
+ view = self._getViewCallable(
+ config, ctx_iface=IExceptionResponse, request_iface=IRequest
+ )
+ self.assertTrue(view is None)
+
+ def test_ctor_exceptionresponse_view_custom(self):
+ from pyramid.interfaces import IExceptionResponse
+
+ def exceptionresponse_view(context, request): # pragma: no cover
+ pass
+
+ config = self._makeOne(exceptionresponse_view=exceptionresponse_view)
+ view = self._getViewCallable(
+ config, ctx_iface=IExceptionResponse, request_iface=IRequest
+ )
+ self.assertTrue(view.__wraps__ is exceptionresponse_view)
+
+ def test_ctor_with_introspection(self):
+ config = self._makeOne(introspection=False)
+ self.assertEqual(config.introspection, False)
+
+ def test_ctor_default_webob_response_adapter_registered(self):
+ from webob import Response as WebobResponse
+
+ response = WebobResponse()
+ from pyramid.interfaces import IResponse
+
+ config = self._makeOne(autocommit=True)
+ result = config.registry.queryAdapter(response, IResponse)
+ self.assertEqual(result, response)
+
+ def test_with_package_module(self):
+ from . import test_init
+
+ config = self._makeOne()
+ newconfig = config.with_package(test_init)
+ import tests.test_config
+
+ self.assertEqual(newconfig.package, tests.test_config)
+
+ def test_with_package_package(self):
+ from tests import test_config
+
+ config = self._makeOne()
+ newconfig = config.with_package(test_config)
+ self.assertEqual(newconfig.package, test_config)
+
+ def test_with_package(self):
+ import tests
+
+ config = self._makeOne()
+ config.basepath = 'basepath'
+ config.info = 'info'
+ config.includepath = ('spec',)
+ config.autocommit = True
+ config.route_prefix = 'prefix'
+ newconfig = config.with_package(tests)
+ self.assertEqual(newconfig.package, tests)
+ self.assertEqual(newconfig.registry, config.registry)
+ self.assertEqual(newconfig.autocommit, True)
+ self.assertEqual(newconfig.route_prefix, 'prefix')
+ self.assertEqual(newconfig.info, 'info')
+ self.assertEqual(newconfig.basepath, 'basepath')
+ self.assertEqual(newconfig.includepath, ('spec',))
+
+ def test_maybe_dotted_string_success(self):
+ import tests.test_config
+
+ config = self._makeOne()
+ result = config.maybe_dotted('tests.test_config')
+ self.assertEqual(result, tests.test_config)
+
+ def test_maybe_dotted_string_fail(self):
+ config = self._makeOne()
+ self.assertRaises(ImportError, config.maybe_dotted, 'cant.be.found')
+
+ def test_maybe_dotted_notstring_success(self):
+ import tests.test_config
+
+ config = self._makeOne()
+ result = config.maybe_dotted(tests.test_config)
+ self.assertEqual(result, tests.test_config)
+
+ def test_absolute_asset_spec_already_absolute(self):
+ import tests.test_config
+
+ config = self._makeOne(package=tests.test_config)
+ result = config.absolute_asset_spec('already:absolute')
+ self.assertEqual(result, 'already:absolute')
+
+ def test_absolute_asset_spec_notastring(self):
+ import tests.test_config
+
+ config = self._makeOne(package=tests.test_config)
+ result = config.absolute_asset_spec(None)
+ self.assertEqual(result, None)
+
+ def test_absolute_asset_spec_relative(self):
+ import tests.test_config
+
+ config = self._makeOne(package=tests.test_config)
+ result = config.absolute_asset_spec('files')
+ self.assertEqual(result, 'tests.test_config:files')
+
+ def test__fix_registry_has_listeners(self):
+ reg = DummyRegistry()
+ config = self._makeOne(reg)
+ config._fix_registry()
+ self.assertEqual(reg.has_listeners, True)
+
+ def test__fix_registry_notify(self):
+ reg = DummyRegistry()
+ config = self._makeOne(reg)
+ config._fix_registry()
+ self.assertEqual(reg.notify(1), None)
+ self.assertEqual(reg.events, (1,))
+
+ def test__fix_registry_queryAdapterOrSelf(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class IFoo(Interface):
+ pass
+
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+
+ class Bar(object):
+ pass
+
+ adaptation = ()
+ foo = Foo()
+ bar = Bar()
+ reg = DummyRegistry(adaptation)
+ config = self._makeOne(reg)
+ config._fix_registry()
+ self.assertTrue(reg.queryAdapterOrSelf(foo, IFoo) is foo)
+ self.assertTrue(reg.queryAdapterOrSelf(bar, IFoo) is adaptation)
+
+ def test__fix_registry_registerSelfAdapter(self):
+ reg = DummyRegistry()
+ config = self._makeOne(reg)
+ config._fix_registry()
+ reg.registerSelfAdapter('required', 'provided', name='abc')
+ self.assertEqual(len(reg.adapters), 1)
+ args, kw = reg.adapters[0]
+ self.assertEqual(args[0]('abc'), 'abc')
+ self.assertEqual(
+ kw,
+ {
+ 'info': '',
+ 'provided': 'provided',
+ 'required': 'required',
+ 'name': 'abc',
+ 'event': True,
+ },
+ )
+
+ def test__fix_registry_adds__lock(self):
+ reg = DummyRegistry()
+ config = self._makeOne(reg)
+ config._fix_registry()
+ self.assertTrue(hasattr(reg, '_lock'))
+
+ def test__fix_registry_adds_clear_view_lookup_cache(self):
+ reg = DummyRegistry()
+ config = self._makeOne(reg)
+ self.assertFalse(hasattr(reg, '_clear_view_lookup_cache'))
+ config._fix_registry()
+ self.assertFalse(hasattr(reg, '_view_lookup_cache'))
+ reg._clear_view_lookup_cache()
+ self.assertEqual(reg._view_lookup_cache, {})
+
+ def test_setup_registry_calls_fix_registry(self):
+ reg = DummyRegistry()
+ config = self._makeOne(reg)
+ config.add_view = lambda *arg, **kw: False
+ config._add_tween = lambda *arg, **kw: False
+ config.setup_registry()
+ self.assertEqual(reg.has_listeners, True)
+
+ def test_setup_registry_registers_default_exceptionresponse_views(self):
+ from webob.exc import WSGIHTTPException
+ from pyramid.interfaces import IExceptionResponse
+ from pyramid.view import default_exceptionresponse_view
+
+ reg = DummyRegistry()
+ config = self._makeOne(reg)
+ views = []
+ config.add_view = lambda *arg, **kw: views.append((arg, kw))
+ config.add_default_view_predicates = lambda *arg: None
+ config._add_tween = lambda *arg, **kw: False
+ config.setup_registry()
+ self.assertEqual(
+ views[0],
+ (
+ (default_exceptionresponse_view,),
+ {'context': IExceptionResponse},
+ ),
+ )
+ self.assertEqual(
+ views[1],
+ (
+ (default_exceptionresponse_view,),
+ {'context': WSGIHTTPException},
+ ),
+ )
+
+ def test_setup_registry_registers_default_view_predicates(self):
+ reg = DummyRegistry()
+ config = self._makeOne(reg)
+ vp_called = []
+ config.add_view = lambda *arg, **kw: None
+ config.add_default_view_predicates = lambda *arg: vp_called.append(
+ True
+ )
+ config._add_tween = lambda *arg, **kw: False
+ config.setup_registry()
+ self.assertTrue(vp_called)
+
+ def test_setup_registry_registers_default_webob_iresponse_adapter(self):
+ from webob import Response
+ from pyramid.interfaces import IResponse
+
+ config = self._makeOne()
+ config.setup_registry()
+ response = Response()
+ self.assertTrue(
+ config.registry.queryAdapter(response, IResponse) is response
+ )
+
+ def test_setup_registry_explicit_notfound_trumps_iexceptionresponse(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.httpexceptions import HTTPNotFound
+ from pyramid.registry import Registry
+
+ reg = Registry()
+ config = self._makeOne(reg, autocommit=True)
+ config.setup_registry() # registers IExceptionResponse default view
+
+ def myview(context, request):
+ return 'OK'
+
+ config.add_view(myview, context=HTTPNotFound, renderer=null_renderer)
+ request = self._makeRequest(config)
+ view = self._getViewCallable(
+ config,
+ ctx_iface=implementedBy(HTTPNotFound),
+ request_iface=IRequest,
+ )
+ result = view(None, request)
+ self.assertEqual(result, 'OK')
+
+ def test_setup_registry_custom_settings(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import ISettings
+
+ settings = {'reload_templates': True, 'mysetting': True}
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.setup_registry(settings=settings)
+ settings = reg.getUtility(ISettings)
+ self.assertEqual(settings['reload_templates'], True)
+ self.assertEqual(settings['debug_authorization'], False)
+ self.assertEqual(settings['mysetting'], True)
+
+ def test_setup_registry_debug_logger_None_default(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IDebugLogger
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.setup_registry()
+ logger = reg.getUtility(IDebugLogger)
+ self.assertEqual(logger.name, 'tests.test_config')
+
+ def test_setup_registry_debug_logger_non_None(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IDebugLogger
+
+ logger = object()
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.setup_registry(debug_logger=logger)
+ result = reg.getUtility(IDebugLogger)
+ self.assertEqual(logger, result)
+
+ def test_setup_registry_debug_logger_name(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IDebugLogger
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.setup_registry(debug_logger='foo')
+ result = reg.getUtility(IDebugLogger)
+ self.assertEqual(result.name, 'foo')
+
+ def test_setup_registry_authentication_policy(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IAuthenticationPolicy
+
+ policy = object()
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.setup_registry(authentication_policy=policy)
+ config.commit()
+ result = reg.getUtility(IAuthenticationPolicy)
+ self.assertEqual(policy, result)
+
+ def test_setup_registry_authentication_policy_dottedname(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IAuthenticationPolicy
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.setup_registry(authentication_policy='tests.test_config')
+ config.commit()
+ result = reg.getUtility(IAuthenticationPolicy)
+ import tests.test_config
+
+ self.assertEqual(result, tests.test_config)
+
+ def test_setup_registry_authorization_policy_dottedname(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IAuthorizationPolicy
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ dummy = object()
+ config.setup_registry(
+ authentication_policy=dummy,
+ authorization_policy='tests.test_config',
+ )
+ config.commit()
+ result = reg.getUtility(IAuthorizationPolicy)
+ import tests.test_config
+
+ self.assertEqual(result, tests.test_config)
+
+ def test_setup_registry_authorization_policy_only(self):
+ from pyramid.registry import Registry
+
+ policy = object()
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.setup_registry(authorization_policy=policy)
+ config = self.assertRaises(ConfigurationExecutionError, config.commit)
+
+ def test_setup_registry_no_default_root_factory(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IRootFactory
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.setup_registry()
+ config.commit()
+ self.assertEqual(reg.queryUtility(IRootFactory), None)
+
+ def test_setup_registry_dottedname_root_factory(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IRootFactory
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ import tests.test_config
+
+ config.setup_registry(root_factory='tests.test_config')
+ self.assertEqual(reg.queryUtility(IRootFactory), None)
+ config.commit()
+ self.assertEqual(reg.getUtility(IRootFactory), tests.test_config)
+
+ def test_setup_registry_locale_negotiator_dottedname(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import ILocaleNegotiator
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ import tests.test_config
+
+ config.setup_registry(locale_negotiator='tests.test_config')
+ self.assertEqual(reg.queryUtility(ILocaleNegotiator), None)
+ config.commit()
+ utility = reg.getUtility(ILocaleNegotiator)
+ self.assertEqual(utility, tests.test_config)
+
+ def test_setup_registry_locale_negotiator(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import ILocaleNegotiator
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ negotiator = object()
+ config.setup_registry(locale_negotiator=negotiator)
+ self.assertEqual(reg.queryUtility(ILocaleNegotiator), None)
+ config.commit()
+ utility = reg.getUtility(ILocaleNegotiator)
+ self.assertEqual(utility, negotiator)
+
+ def test_setup_registry_request_factory(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IRequestFactory
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ factory = object()
+ config.setup_registry(request_factory=factory)
+ self.assertEqual(reg.queryUtility(IRequestFactory), None)
+ config.commit()
+ utility = reg.getUtility(IRequestFactory)
+ self.assertEqual(utility, factory)
+
+ def test_setup_registry_response_factory(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IResponseFactory
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ factory = lambda r: object()
+ config.setup_registry(response_factory=factory)
+ self.assertEqual(reg.queryUtility(IResponseFactory), None)
+ config.commit()
+ utility = reg.getUtility(IResponseFactory)
+ self.assertEqual(utility, factory)
+
+ def test_setup_registry_request_factory_dottedname(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IRequestFactory
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ import tests.test_config
+
+ config.setup_registry(request_factory='tests.test_config')
+ self.assertEqual(reg.queryUtility(IRequestFactory), None)
+ config.commit()
+ utility = reg.getUtility(IRequestFactory)
+ self.assertEqual(utility, tests.test_config)
+
+ def test_setup_registry_alternate_renderers(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IRendererFactory
+
+ renderer = object()
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.setup_registry(renderers=[('yeah', renderer)])
+ config.commit()
+ self.assertEqual(reg.getUtility(IRendererFactory, 'yeah'), renderer)
+
+ def test_setup_registry_default_permission(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import IDefaultPermission
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.setup_registry(default_permission='view')
+ config.commit()
+ self.assertEqual(reg.getUtility(IDefaultPermission), 'view')
+
+ def test_setup_registry_includes(self):
+ from pyramid.registry import Registry
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ settings = {
+ 'pyramid.includes': """tests.test_config.dummy_include
+tests.test_config.dummy_include2"""
+ }
+ config.setup_registry(settings=settings)
+ self.assertTrue(reg.included)
+ self.assertTrue(reg.also_included)
+
+ def test_setup_registry_includes_spaces(self):
+ from pyramid.registry import Registry
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ settings = {
+ 'pyramid.includes': """tests.test_config.dummy_include tests.\
+test_config.dummy_include2"""
+ }
+ config.setup_registry(settings=settings)
+ self.assertTrue(reg.included)
+ self.assertTrue(reg.also_included)
+
+ def test_setup_registry_tweens(self):
+ from pyramid.interfaces import ITweens
+ from pyramid.registry import Registry
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ settings = {'pyramid.tweens': 'tests.test_config.dummy_tween_factory'}
+ config.setup_registry(settings=settings)
+ config.commit()
+ tweens = config.registry.getUtility(ITweens)
+ self.assertEqual(
+ tweens.explicit,
+ [('tests.test_config.dummy_tween_factory', dummy_tween_factory)],
+ )
+
+ def test_introspector_decorator(self):
+ inst = self._makeOne()
+ default = inst.introspector
+ self.assertTrue(hasattr(default, 'add'))
+ self.assertEqual(inst.introspector, inst.registry.introspector)
+ introspector = object()
+ inst.introspector = introspector
+ new = inst.introspector
+ self.assertTrue(new is introspector)
+ self.assertEqual(inst.introspector, inst.registry.introspector)
+ del inst.introspector
+ default = inst.introspector
+ self.assertFalse(default is new)
+ self.assertTrue(hasattr(default, 'add'))
+
+ def test_make_wsgi_app(self):
+ import pyramid.config
+ from pyramid.router import Router
+ from pyramid.interfaces import IApplicationCreated
+
+ manager = DummyThreadLocalManager()
+ config = self._makeOne()
+ subscriber = self._registerEventListener(config, IApplicationCreated)
+ config.manager = manager
+ app = config.make_wsgi_app()
+ self.assertEqual(app.__class__, Router)
+ self.assertEqual(manager.pushed['registry'], config.registry)
+ self.assertEqual(manager.pushed['request'], None)
+ self.assertTrue(manager.popped)
+ self.assertEqual(pyramid.config.global_registries.last, app.registry)
+ self.assertEqual(len(subscriber), 1)
+ self.assertTrue(IApplicationCreated.providedBy(subscriber[0]))
+ pyramid.config.global_registries.empty()
+
+ def test_include_with_dotted_name(self):
+ from tests import test_config
+
+ config = self._makeOne()
+ config.include('tests.test_config.dummy_include')
+ after = config.action_state
+ actions = after.actions
+ self.assertEqual(len(actions), 1)
+ action = after.actions[0]
+ self.assertEqual(action['discriminator'], 'discrim')
+ self.assertEqual(action['callable'], None)
+ self.assertEqual(action['args'], test_config)
+
+ def test_include_with_python_callable(self):
+ from tests import test_config
+
+ config = self._makeOne()
+ config.include(dummy_include)
+ after = config.action_state
+ actions = after.actions
+ self.assertEqual(len(actions), 1)
+ action = actions[0]
+ self.assertEqual(action['discriminator'], 'discrim')
+ self.assertEqual(action['callable'], None)
+ self.assertEqual(action['args'], test_config)
+
+ def test_include_with_module_defaults_to_includeme(self):
+ from tests import test_config
+
+ config = self._makeOne()
+ config.include('tests.test_config')
+ after = config.action_state
+ actions = after.actions
+ self.assertEqual(len(actions), 1)
+ action = actions[0]
+ self.assertEqual(action['discriminator'], 'discrim')
+ self.assertEqual(action['callable'], None)
+ self.assertEqual(action['args'], test_config)
+
+ def test_include_with_module_defaults_to_includeme_missing(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ self.assertRaises(ConfigurationError, config.include, 'tests')
+
+ def test_include_with_route_prefix(self):
+ root_config = self._makeOne(autocommit=True)
+
+ def dummy_subapp(config):
+ self.assertEqual(config.route_prefix, 'root')
+
+ root_config.include(dummy_subapp, route_prefix='root')
+
+ def test_include_with_nested_route_prefix(self):
+ root_config = self._makeOne(autocommit=True, route_prefix='root')
+
+ def dummy_subapp2(config):
+ self.assertEqual(config.route_prefix, 'root/nested')
+
+ def dummy_subapp3(config):
+ self.assertEqual(config.route_prefix, 'root/nested/nested2')
+ config.include(dummy_subapp4)
+
+ def dummy_subapp4(config):
+ self.assertEqual(config.route_prefix, 'root/nested/nested2')
+
+ def dummy_subapp(config):
+ self.assertEqual(config.route_prefix, 'root/nested')
+ config.include(dummy_subapp2)
+ config.include(dummy_subapp3, route_prefix='nested2')
+
+ root_config.include(dummy_subapp, route_prefix='nested')
+
+ def test_include_with_missing_source_file(self):
+ from pyramid.exceptions import ConfigurationError
+ import inspect
+
+ config = self._makeOne()
+
+ class DummyInspect(object):
+ def getmodule(self, c):
+ return inspect.getmodule(c)
+
+ def getsourcefile(self, c):
+ return None
+
+ config.inspect = DummyInspect()
+ try:
+ config.include('tests.test_config.dummy_include')
+ except ConfigurationError as e:
+ self.assertEqual(
+ e.args[0],
+ "No source file for module 'tests.test_config' (.py "
+ "file must exist, refusing to use orphan .pyc or .pyo file).",
+ )
+ else: # pragma: no cover
+ raise AssertionError
+
+ def test_include_constant_root_package(self):
+ import tests
+ from tests import test_config
+
+ config = self._makeOne(root_package=tests)
+ results = {}
+
+ def include(config):
+ results['package'] = config.package
+ results['root_package'] = config.root_package
+
+ config.include(include)
+ self.assertEqual(results['root_package'], tests)
+ self.assertEqual(results['package'], test_config)
+
+ def test_include_threadlocals_active(self):
+ from pyramid.threadlocal import get_current_registry
+
+ stack = []
+
+ def include(config):
+ stack.append(get_current_registry())
+
+ config = self._makeOne()
+ config.include(include)
+ self.assertTrue(stack[0] is config.registry)
+
+ def test_scan_integration(self):
+ from zope.interface import alsoProvides
+ from pyramid.view import render_view_to_response
+ import tests.test_config.pkgs.scannable as package
+
+ config = self._makeOne(autocommit=True)
+ config.scan(package)
+
+ ctx = DummyContext()
+ req = DummyRequest()
+ alsoProvides(req, IRequest)
+ req.registry = config.registry
+
+ req.method = 'GET'
+ result = render_view_to_response(ctx, req, '')
+ self.assertEqual(result, 'grokked')
+
+ req.method = 'POST'
+ result = render_view_to_response(ctx, req, '')
+ self.assertEqual(result, 'grokked_post')
+
+ result = render_view_to_response(ctx, req, 'grokked_class')
+ self.assertEqual(result, 'grokked_class')
+
+ result = render_view_to_response(ctx, req, 'grokked_instance')
+ self.assertEqual(result, 'grokked_instance')
+
+ result = render_view_to_response(ctx, req, 'oldstyle_grokked_class')
+ self.assertEqual(result, 'oldstyle_grokked_class')
+
+ req.method = 'GET'
+ result = render_view_to_response(ctx, req, 'another')
+ self.assertEqual(result, 'another_grokked')
+
+ req.method = 'POST'
+ result = render_view_to_response(ctx, req, 'another')
+ self.assertEqual(result, 'another_grokked_post')
+
+ result = render_view_to_response(ctx, req, 'another_grokked_class')
+ self.assertEqual(result, 'another_grokked_class')
+
+ result = render_view_to_response(ctx, req, 'another_grokked_instance')
+ self.assertEqual(result, 'another_grokked_instance')
+
+ result = render_view_to_response(
+ ctx, req, 'another_oldstyle_grokked_class'
+ )
+ self.assertEqual(result, 'another_oldstyle_grokked_class')
+
+ result = render_view_to_response(ctx, req, 'stacked1')
+ self.assertEqual(result, 'stacked')
+
+ result = render_view_to_response(ctx, req, 'stacked2')
+ self.assertEqual(result, 'stacked')
+
+ result = render_view_to_response(ctx, req, 'another_stacked1')
+ self.assertEqual(result, 'another_stacked')
+
+ result = render_view_to_response(ctx, req, 'another_stacked2')
+ self.assertEqual(result, 'another_stacked')
+
+ result = render_view_to_response(ctx, req, 'stacked_class1')
+ self.assertEqual(result, 'stacked_class')
+
+ result = render_view_to_response(ctx, req, 'stacked_class2')
+ self.assertEqual(result, 'stacked_class')
+
+ result = render_view_to_response(ctx, req, 'another_stacked_class1')
+ self.assertEqual(result, 'another_stacked_class')
+
+ result = render_view_to_response(ctx, req, 'another_stacked_class2')
+ self.assertEqual(result, 'another_stacked_class')
+
+ # NB: on Jython, a class without an __init__ apparently accepts
+ # any number of arguments without raising a TypeError, so the next
+ # assertion may fail there. We don't support Jython at the moment,
+ # this is just a note to a future self.
+
+ self.assertRaises(
+ TypeError, render_view_to_response, ctx, req, 'basemethod'
+ )
+
+ result = render_view_to_response(ctx, req, 'method1')
+ self.assertEqual(result, 'method1')
+
+ result = render_view_to_response(ctx, req, 'method2')
+ self.assertEqual(result, 'method2')
+
+ result = render_view_to_response(ctx, req, 'stacked_method1')
+ self.assertEqual(result, 'stacked_method')
+
+ result = render_view_to_response(ctx, req, 'stacked_method2')
+ self.assertEqual(result, 'stacked_method')
+
+ result = render_view_to_response(ctx, req, 'subpackage_init')
+ self.assertEqual(result, 'subpackage_init')
+
+ result = render_view_to_response(ctx, req, 'subpackage_notinit')
+ self.assertEqual(result, 'subpackage_notinit')
+
+ result = render_view_to_response(ctx, req, 'subsubpackage_init')
+ self.assertEqual(result, 'subsubpackage_init')
+
+ result = render_view_to_response(ctx, req, 'pod_notinit')
+ self.assertEqual(result, None)
+
+ def test_scan_integration_with_ignore(self):
+ from zope.interface import alsoProvides
+ from pyramid.view import render_view_to_response
+ import tests.test_config.pkgs.scannable as package
+
+ config = self._makeOne(autocommit=True)
+ config.scan(package, ignore='tests.test_config.pkgs.scannable.another')
+
+ ctx = DummyContext()
+ req = DummyRequest()
+ alsoProvides(req, IRequest)
+ req.registry = config.registry
+
+ req.method = 'GET'
+ result = render_view_to_response(ctx, req, '')
+ self.assertEqual(result, 'grokked')
+
+ # ignored
+ v = render_view_to_response(ctx, req, 'another_stacked_class2')
+ self.assertEqual(v, None)
+
+ def test_scan_integration_dottedname_package(self):
+ from zope.interface import alsoProvides
+ from pyramid.view import render_view_to_response
+
+ config = self._makeOne(autocommit=True)
+ config.scan('tests.test_config.pkgs.scannable')
+
+ ctx = DummyContext()
+ req = DummyRequest()
+ alsoProvides(req, IRequest)
+ req.registry = config.registry
+
+ req.method = 'GET'
+ result = render_view_to_response(ctx, req, '')
+ self.assertEqual(result, 'grokked')
+
+ def test_scan_integration_with_extra_kw(self):
+ config = self._makeOne(autocommit=True)
+ config.scan('tests.test_config.pkgs.scanextrakw', a=1)
+ self.assertEqual(config.a, 1)
+
+ def test_scan_integration_with_onerror(self):
+ # fancy sys.path manipulation here to appease "setup.py test" which
+ # fails miserably when it can't import something in the package
+ import sys
+
+ try:
+ here = os.path.dirname(__file__)
+ path = os.path.join(here, 'path')
+ sys.path.append(path)
+ config = self._makeOne(autocommit=True)
+
+ class FooException(Exception):
+ pass
+
+ def onerror(name):
+ raise FooException
+
+ self.assertRaises(
+ FooException, config.scan, 'scanerror', onerror=onerror
+ )
+ finally:
+ sys.path.remove(path)
+
+ def test_scan_integration_conflict(self):
+ from tests.test_config.pkgs import selfscan
+ from pyramid.config import Configurator
+
+ c = Configurator()
+ c.scan(selfscan)
+ c.scan(selfscan)
+ try:
+ c.commit()
+ except ConfigurationConflictError as why:
+
+ def scanconflicts(e):
+ conflicts = e._conflicts.values()
+ for conflict in conflicts:
+ for confinst in conflict:
+ yield confinst.src
+
+ which = list(scanconflicts(why))
+ self.assertEqual(len(which), 4)
+ self.assertTrue("@view_config(renderer='string')" in which)
+ self.assertTrue(
+ "@view_config(name='two', renderer='string')" in which
+ )
+
+ @skip_on('py3')
+ def test_hook_zca(self):
+ from zope.component import getSiteManager
+
+ def foo():
+ '123'
+
+ try:
+ config = self._makeOne()
+ config.hook_zca()
+ config.begin()
+ sm = getSiteManager()
+ self.assertEqual(sm, config.registry)
+ finally:
+ getSiteManager.reset()
+
+ @skip_on('py3')
+ def test_unhook_zca(self):
+ from zope.component import getSiteManager
+
+ def foo():
+ '123'
+
+ try:
+ getSiteManager.sethook(foo)
+ config = self._makeOne()
+ config.unhook_zca()
+ sm = getSiteManager()
+ self.assertNotEqual(sm, '123')
+ finally:
+ getSiteManager.reset()
+
+ def test___getattr__missing_when_directives_exist(self):
+ config = self._makeOne()
+ directives = {}
+ config.registry._directives = directives
+ self.assertRaises(AttributeError, config.__getattr__, 'wontexist')
+
+ def test___getattr__missing_when_directives_dont_exist(self):
+ config = self._makeOne()
+ self.assertRaises(AttributeError, config.__getattr__, 'wontexist')
+
+ def test___getattr__matches(self):
+ config = self._makeOne()
+
+ def foo(config): # pragma: no cover
+ pass
+
+ directives = {'foo': (foo, True)}
+ config.registry._directives = directives
+ foo_meth = config.foo
+ self.assertTrue(getattr(foo_meth, im_func).__docobj__ is foo)
+
+ def test___getattr__matches_no_action_wrap(self):
+ config = self._makeOne()
+
+ def foo(config): # pragma: no cover
+ pass
+
+ directives = {'foo': (foo, False)}
+ config.registry._directives = directives
+ foo_meth = config.foo
+ self.assertTrue(getattr(foo_meth, im_func) is foo)
+
+
+class TestConfigurator_add_directive(unittest.TestCase):
+ def setUp(self):
+ from pyramid.config import Configurator
+
+ self.config = Configurator()
+
+ def test_extend_with_dotted_name(self):
+ from tests import test_config
+
+ config = self.config
+ config.add_directive('dummy_extend', 'tests.test_config.dummy_extend')
+ self.assertTrue(hasattr(config, 'dummy_extend'))
+ config.dummy_extend('discrim')
+ after = config.action_state
+ action = after.actions[-1]
+ self.assertEqual(action['discriminator'], 'discrim')
+ self.assertEqual(action['callable'], None)
+ self.assertEqual(action['args'], test_config)
+
+ def test_add_directive_with_partial(self):
+ from tests import test_config
+
+ config = self.config
+ config.add_directive(
+ 'dummy_partial', 'tests.test_config.dummy_partial'
+ )
+ self.assertTrue(hasattr(config, 'dummy_partial'))
+ config.dummy_partial()
+ after = config.action_state
+ action = after.actions[-1]
+ self.assertEqual(action['discriminator'], 'partial')
+ self.assertEqual(action['callable'], None)
+ self.assertEqual(action['args'], test_config)
+
+ def test_add_directive_with_custom_callable(self):
+ from tests import test_config
+
+ config = self.config
+ config.add_directive(
+ 'dummy_callable', 'tests.test_config.dummy_callable'
+ )
+ self.assertTrue(hasattr(config, 'dummy_callable'))
+ config.dummy_callable('discrim')
+ after = config.action_state
+ action = after.actions[-1]
+ self.assertEqual(action['discriminator'], 'discrim')
+ self.assertEqual(action['callable'], None)
+ self.assertEqual(action['args'], test_config)
+
+ def test_extend_with_python_callable(self):
+ from tests import test_config
+
+ config = self.config
+ config.add_directive('dummy_extend', dummy_extend)
+ self.assertTrue(hasattr(config, 'dummy_extend'))
+ config.dummy_extend('discrim')
+ after = config.action_state
+ action = after.actions[-1]
+ self.assertEqual(action['discriminator'], 'discrim')
+ self.assertEqual(action['callable'], None)
+ self.assertEqual(action['args'], test_config)
+
+ def test_extend_same_name_doesnt_conflict(self):
+ config = self.config
+ config.add_directive('dummy_extend', dummy_extend)
+ config.add_directive('dummy_extend', dummy_extend2)
+ self.assertTrue(hasattr(config, 'dummy_extend'))
+ config.dummy_extend('discrim')
+ after = config.action_state
+ action = after.actions[-1]
+ self.assertEqual(action['discriminator'], 'discrim')
+ self.assertEqual(action['callable'], None)
+ self.assertEqual(action['args'], config.registry)
+
+ def test_extend_action_method_successful(self):
+ config = self.config
+ config.add_directive('dummy_extend', dummy_extend)
+ config.dummy_extend('discrim')
+ config.dummy_extend('discrim')
+ self.assertRaises(ConfigurationConflictError, config.commit)
+
+ def test_directive_persists_across_configurator_creations(self):
+ config = self.config
+ config.add_directive('dummy_extend', dummy_extend)
+ config2 = config.with_package('tests')
+ config2.dummy_extend('discrim')
+ after = config2.action_state
+ actions = after.actions
+ self.assertEqual(len(actions), 1)
+ action = actions[0]
+ self.assertEqual(action['discriminator'], 'discrim')
+ self.assertEqual(action['callable'], None)
+ self.assertEqual(action['args'], config2.package)
+
+
+class TestConfigurator__add_predicate(unittest.TestCase):
+ def _makeOne(self):
+ from pyramid.config import Configurator
+
+ return Configurator()
+
+ def test_factory_as_object(self):
+ config = self._makeOne()
+
+ def _fakeAction(
+ discriminator,
+ callable=None,
+ args=(),
+ kw=None,
+ order=0,
+ introspectables=(),
+ **extra
+ ):
+ self.assertEqual(len(introspectables), 1)
+ self.assertEqual(introspectables[0]['name'], 'testing')
+ self.assertEqual(introspectables[0]['factory'], DummyPredicate)
+
+ config.action = _fakeAction
+ config._add_predicate('route', 'testing', DummyPredicate)
+
+ def test_factory_as_dotted_name(self):
+ config = self._makeOne()
+
+ def _fakeAction(
+ discriminator,
+ callable=None,
+ args=(),
+ kw=None,
+ order=0,
+ introspectables=(),
+ **extra
+ ):
+ self.assertEqual(len(introspectables), 1)
+ self.assertEqual(introspectables[0]['name'], 'testing')
+ self.assertEqual(introspectables[0]['factory'], DummyPredicate)
+
+ config.action = _fakeAction
+ config._add_predicate(
+ 'route', 'testing', 'tests.test_config.test_init.DummyPredicate'
+ )
+
+
+class TestGlobalRegistriesIntegration(unittest.TestCase):
+ def setUp(self):
+ from pyramid.config import global_registries
+
+ global_registries.empty()
+
+ tearDown = setUp
+
+ def _makeConfigurator(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_global_registries_empty(self):
+ from pyramid.config import global_registries
+
+ self.assertEqual(global_registries.last, None)
+
+ def test_global_registries(self):
+ from pyramid.config import global_registries
+
+ config1 = self._makeConfigurator()
+ config1.make_wsgi_app()
+ self.assertEqual(global_registries.last, config1.registry)
+ config2 = self._makeConfigurator()
+ config2.make_wsgi_app()
+ self.assertEqual(global_registries.last, config2.registry)
+ self.assertEqual(
+ list(global_registries), [config1.registry, config2.registry]
+ )
+ global_registries.remove(config2.registry)
+ self.assertEqual(global_registries.last, config1.registry)
+
+
+class DummyRequest:
+ subpath = ()
+ matchdict = None
+ request_iface = IRequest
+
+ def __init__(self, environ=None):
+ if environ is None:
+ environ = {}
+ self.environ = environ
+ self.params = {}
+ self.cookies = {}
+
+
+class DummyThreadLocalManager(object):
+ def __init__(self):
+ self.pushed = {'registry': None, 'request': None}
+ self.popped = False
+
+ def push(self, d):
+ self.pushed = d
+
+ def get(self):
+ return self.pushed
+
+ def pop(self):
+ self.popped = True
+
+
+class DummyRegistry(object):
+ def __init__(self, adaptation=None, util=None):
+ self.utilities = []
+ self.adapters = []
+ self.adaptation = adaptation
+ self.util = util
+
+ def subscribers(self, events, name):
+ self.events = events
+ return events
+
+ def registerUtility(self, *arg, **kw):
+ self.utilities.append((arg, kw))
+
+ def registerAdapter(self, *arg, **kw):
+ self.adapters.append((arg, kw))
+
+ def queryAdapter(self, *arg, **kw):
+ return self.adaptation
+
+ def queryUtility(self, *arg, **kw):
+ return self.util
+
+
+class DummyPredicate(object):
+ pass
diff --git a/tests/test_config/test_predicates.py b/tests/test_config/test_predicates.py
new file mode 100644
index 000000000..079652b39
--- /dev/null
+++ b/tests/test_config/test_predicates.py
@@ -0,0 +1,480 @@
+import unittest
+
+from pyramid.compat import text_
+
+
+class TestPredicateList(unittest.TestCase):
+ def _makeOne(self):
+ from pyramid.config.predicates import PredicateList
+ from pyramid import predicates
+
+ inst = PredicateList()
+ for name, factory in (
+ ('xhr', predicates.XHRPredicate),
+ ('request_method', predicates.RequestMethodPredicate),
+ ('path_info', predicates.PathInfoPredicate),
+ ('request_param', predicates.RequestParamPredicate),
+ ('header', predicates.HeaderPredicate),
+ ('accept', predicates.AcceptPredicate),
+ ('containment', predicates.ContainmentPredicate),
+ ('request_type', predicates.RequestTypePredicate),
+ ('match_param', predicates.MatchParamPredicate),
+ ('custom', predicates.CustomPredicate),
+ ('traverse', predicates.TraversePredicate),
+ ):
+ inst.add(name, factory)
+ return inst
+
+ def _callFUT(self, **kw):
+ inst = self._makeOne()
+ config = DummyConfigurator()
+ return inst.make(config, **kw)
+
+ def test_ordering_xhr_and_request_method_trump_only_containment(self):
+ order1, _, _ = self._callFUT(xhr=True, request_method='GET')
+ order2, _, _ = self._callFUT(containment=True)
+ self.assertTrue(order1 < order2)
+
+ def test_ordering_number_of_predicates(self):
+ from pyramid.config.predicates import predvalseq
+
+ order1, _, _ = self._callFUT(
+ xhr='xhr',
+ request_method='request_method',
+ path_info='path_info',
+ request_param='param',
+ match_param='foo=bar',
+ header='header',
+ accept='accept',
+ containment='containment',
+ request_type='request_type',
+ custom=predvalseq([DummyCustomPredicate()]),
+ )
+ order2, _, _ = self._callFUT(
+ xhr='xhr',
+ request_method='request_method',
+ path_info='path_info',
+ request_param='param',
+ match_param='foo=bar',
+ header='header',
+ accept='accept',
+ containment='containment',
+ request_type='request_type',
+ custom=predvalseq([DummyCustomPredicate()]),
+ )
+ order3, _, _ = self._callFUT(
+ xhr='xhr',
+ request_method='request_method',
+ path_info='path_info',
+ request_param='param',
+ match_param='foo=bar',
+ header='header',
+ accept='accept',
+ containment='containment',
+ request_type='request_type',
+ )
+ order4, _, _ = self._callFUT(
+ xhr='xhr',
+ request_method='request_method',
+ path_info='path_info',
+ request_param='param',
+ match_param='foo=bar',
+ header='header',
+ accept='accept',
+ containment='containment',
+ )
+ order5, _, _ = self._callFUT(
+ xhr='xhr',
+ request_method='request_method',
+ path_info='path_info',
+ request_param='param',
+ match_param='foo=bar',
+ header='header',
+ accept='accept',
+ )
+ order6, _, _ = self._callFUT(
+ xhr='xhr',
+ request_method='request_method',
+ path_info='path_info',
+ request_param='param',
+ match_param='foo=bar',
+ header='header',
+ )
+ order7, _, _ = self._callFUT(
+ xhr='xhr',
+ request_method='request_method',
+ path_info='path_info',
+ request_param='param',
+ match_param='foo=bar',
+ )
+ order8, _, _ = self._callFUT(
+ xhr='xhr',
+ request_method='request_method',
+ path_info='path_info',
+ request_param='param',
+ )
+ order9, _, _ = self._callFUT(
+ xhr='xhr', request_method='request_method', path_info='path_info'
+ )
+ order10, _, _ = self._callFUT(
+ xhr='xhr', request_method='request_method'
+ )
+ order11, _, _ = self._callFUT(xhr='xhr')
+ order12, _, _ = self._callFUT()
+ self.assertEqual(order1, order2)
+ self.assertTrue(order3 > order2)
+ self.assertTrue(order4 > order3)
+ self.assertTrue(order5 > order4)
+ self.assertTrue(order6 > order5)
+ self.assertTrue(order7 > order6)
+ self.assertTrue(order8 > order7)
+ self.assertTrue(order9 > order8)
+ self.assertTrue(order10 > order9)
+ self.assertTrue(order11 > order10)
+ self.assertTrue(order12 > order10)
+
+ def test_ordering_importance_of_predicates(self):
+ from pyramid.config.predicates import predvalseq
+
+ order1, _, _ = self._callFUT(xhr='xhr')
+ order2, _, _ = self._callFUT(request_method='request_method')
+ order3, _, _ = self._callFUT(path_info='path_info')
+ order4, _, _ = self._callFUT(request_param='param')
+ order5, _, _ = self._callFUT(header='header')
+ order6, _, _ = self._callFUT(accept='accept')
+ order7, _, _ = self._callFUT(containment='containment')
+ order8, _, _ = self._callFUT(request_type='request_type')
+ order9, _, _ = self._callFUT(match_param='foo=bar')
+ order10, _, _ = self._callFUT(
+ custom=predvalseq([DummyCustomPredicate()])
+ )
+ self.assertTrue(order1 > order2)
+ self.assertTrue(order2 > order3)
+ self.assertTrue(order3 > order4)
+ self.assertTrue(order4 > order5)
+ self.assertTrue(order5 > order6)
+ self.assertTrue(order6 > order7)
+ self.assertTrue(order7 > order8)
+ self.assertTrue(order8 > order9)
+ self.assertTrue(order9 > order10)
+
+ def test_ordering_importance_and_number(self):
+ from pyramid.config.predicates import predvalseq
+
+ order1, _, _ = self._callFUT(
+ xhr='xhr', request_method='request_method'
+ )
+ order2, _, _ = self._callFUT(
+ custom=predvalseq([DummyCustomPredicate()])
+ )
+ self.assertTrue(order1 < order2)
+
+ order1, _, _ = self._callFUT(
+ xhr='xhr', request_method='request_method'
+ )
+ order2, _, _ = self._callFUT(
+ request_method='request_method',
+ custom=predvalseq([DummyCustomPredicate()]),
+ )
+ self.assertTrue(order1 > order2)
+
+ order1, _, _ = self._callFUT(
+ xhr='xhr', request_method='request_method', path_info='path_info'
+ )
+ order2, _, _ = self._callFUT(
+ request_method='request_method',
+ custom=predvalseq([DummyCustomPredicate()]),
+ )
+ self.assertTrue(order1 < order2)
+
+ order1, _, _ = self._callFUT(
+ xhr='xhr', request_method='request_method', path_info='path_info'
+ )
+ order2, _, _ = self._callFUT(
+ xhr='xhr',
+ request_method='request_method',
+ custom=predvalseq([DummyCustomPredicate()]),
+ )
+ self.assertTrue(order1 > order2)
+
+ def test_different_custom_predicates_with_same_hash(self):
+ from pyramid.config.predicates import predvalseq
+
+ class PredicateWithHash(object):
+ def __hash__(self):
+ return 1
+
+ a = PredicateWithHash()
+ b = PredicateWithHash()
+ _, _, a_phash = self._callFUT(custom=predvalseq([a]))
+ _, _, b_phash = self._callFUT(custom=predvalseq([b]))
+ self.assertEqual(a_phash, b_phash)
+
+ def test_traverse_has_remainder_already(self):
+ order, predicates, phash = self._callFUT(traverse='/1/:a/:b')
+ self.assertEqual(len(predicates), 1)
+ pred = predicates[0]
+ info = {'traverse': 'abc'}
+ request = DummyRequest()
+ result = pred(info, request)
+ self.assertEqual(result, True)
+ self.assertEqual(info, {'traverse': 'abc'})
+
+ def test_traverse_matches(self):
+ order, predicates, phash = self._callFUT(traverse='/1/:a/:b')
+ self.assertEqual(len(predicates), 1)
+ pred = predicates[0]
+ info = {'match': {'a': 'a', 'b': 'b'}}
+ request = DummyRequest()
+ result = pred(info, request)
+ self.assertEqual(result, True)
+ self.assertEqual(
+ info, {'match': {'a': 'a', 'b': 'b', 'traverse': ('1', 'a', 'b')}}
+ )
+
+ def test_traverse_matches_with_highorder_chars(self):
+ order, predicates, phash = self._callFUT(
+ traverse=text_(b'/La Pe\xc3\xb1a/{x}', 'utf-8')
+ )
+ self.assertEqual(len(predicates), 1)
+ pred = predicates[0]
+ info = {'match': {'x': text_(b'Qu\xc3\xa9bec', 'utf-8')}}
+ request = DummyRequest()
+ result = pred(info, request)
+ self.assertEqual(result, True)
+ self.assertEqual(
+ info['match']['traverse'],
+ (
+ text_(b'La Pe\xc3\xb1a', 'utf-8'),
+ text_(b'Qu\xc3\xa9bec', 'utf-8'),
+ ),
+ )
+
+ def test_custom_predicates_can_affect_traversal(self):
+ from pyramid.config.predicates import predvalseq
+
+ def custom(info, request):
+ m = info['match']
+ m['dummy'] = 'foo'
+ return True
+
+ _, predicates, _ = self._callFUT(
+ custom=predvalseq([custom]), traverse='/1/:dummy/:a'
+ )
+ self.assertEqual(len(predicates), 2)
+ info = {'match': {'a': 'a'}}
+ request = DummyRequest()
+ self.assertTrue(all([p(info, request) for p in predicates]))
+ self.assertEqual(
+ info,
+ {
+ 'match': {
+ 'a': 'a',
+ 'dummy': 'foo',
+ 'traverse': ('1', 'foo', 'a'),
+ }
+ },
+ )
+
+ def test_predicate_text_is_correct(self):
+ from pyramid.config.predicates import predvalseq
+
+ _, predicates, _ = self._callFUT(
+ xhr='xhr',
+ request_method='request_method',
+ path_info='path_info',
+ request_param='param',
+ header='header',
+ accept='accept',
+ containment='containment',
+ request_type='request_type',
+ custom=predvalseq(
+ [
+ DummyCustomPredicate(),
+ DummyCustomPredicate.classmethod_predicate,
+ DummyCustomPredicate.classmethod_predicate_no_text,
+ ]
+ ),
+ match_param='foo=bar',
+ )
+ self.assertEqual(predicates[0].text(), 'xhr = True')
+ self.assertEqual(
+ predicates[1].text(), "request_method = request_method"
+ )
+ self.assertEqual(predicates[2].text(), 'path_info = path_info')
+ self.assertEqual(predicates[3].text(), 'request_param param')
+ self.assertEqual(predicates[4].text(), 'header header')
+ self.assertEqual(predicates[5].text(), 'accept = accept')
+ self.assertEqual(predicates[6].text(), 'containment = containment')
+ self.assertEqual(predicates[7].text(), 'request_type = request_type')
+ self.assertEqual(predicates[8].text(), "match_param foo=bar")
+ self.assertEqual(predicates[9].text(), 'custom predicate')
+ self.assertEqual(predicates[10].text(), 'classmethod predicate')
+ self.assertTrue(predicates[11].text().startswith('custom predicate'))
+
+ def test_match_param_from_string(self):
+ _, predicates, _ = self._callFUT(match_param='foo=bar')
+ request = DummyRequest()
+ request.matchdict = {'foo': 'bar', 'baz': 'bum'}
+ self.assertTrue(predicates[0](Dummy(), request))
+
+ def test_match_param_from_string_fails(self):
+ _, predicates, _ = self._callFUT(match_param='foo=bar')
+ request = DummyRequest()
+ request.matchdict = {'foo': 'bum', 'baz': 'bum'}
+ self.assertFalse(predicates[0](Dummy(), request))
+
+ def test_match_param_from_dict(self):
+ _, predicates, _ = self._callFUT(match_param=('foo=bar', 'baz=bum'))
+ request = DummyRequest()
+ request.matchdict = {'foo': 'bar', 'baz': 'bum'}
+ self.assertTrue(predicates[0](Dummy(), request))
+
+ def test_match_param_from_dict_fails(self):
+ _, predicates, _ = self._callFUT(match_param=('foo=bar', 'baz=bum'))
+ request = DummyRequest()
+ request.matchdict = {'foo': 'bar', 'baz': 'foo'}
+ self.assertFalse(predicates[0](Dummy(), request))
+
+ def test_request_method_sequence(self):
+ _, predicates, _ = self._callFUT(request_method=('GET', 'HEAD'))
+ request = DummyRequest()
+ request.method = 'HEAD'
+ self.assertTrue(predicates[0](Dummy(), request))
+ request.method = 'GET'
+ self.assertTrue(predicates[0](Dummy(), request))
+ request.method = 'POST'
+ self.assertFalse(predicates[0](Dummy(), request))
+
+ def test_request_method_ordering_hashes_same(self):
+ hash1, _, __ = self._callFUT(request_method=('GET', 'HEAD'))
+ hash2, _, __ = self._callFUT(request_method=('HEAD', 'GET'))
+ self.assertEqual(hash1, hash2)
+ hash1, _, __ = self._callFUT(request_method=('GET',))
+ hash2, _, __ = self._callFUT(request_method='GET')
+ self.assertEqual(hash1, hash2)
+
+ def test_unknown_predicate(self):
+ from pyramid.exceptions import ConfigurationError
+
+ self.assertRaises(ConfigurationError, self._callFUT, unknown=1)
+
+ def test_predicate_close_matches(self):
+ from pyramid.exceptions import ConfigurationError
+
+ with self.assertRaises(ConfigurationError) as context:
+ self._callFUT(method='GET')
+ expected_msg = (
+ "Unknown predicate values: {'method': 'GET'} "
+ "(did you mean request_method)"
+ )
+ self.assertEqual(context.exception.args[0], expected_msg)
+
+ def test_notted(self):
+ from pyramid.config import not_
+ from pyramid.testing import DummyRequest
+
+ request = DummyRequest()
+ _, predicates, _ = self._callFUT(
+ xhr='xhr', request_method=not_('POST'), header=not_('header')
+ )
+ self.assertEqual(predicates[0].text(), 'xhr = True')
+ self.assertEqual(predicates[1].text(), "!request_method = POST")
+ self.assertEqual(predicates[2].text(), '!header header')
+ self.assertEqual(predicates[1](None, request), True)
+ self.assertEqual(predicates[2](None, request), True)
+
+
+class Test_sort_accept_offers(unittest.TestCase):
+ def _callFUT(self, offers, order=None):
+ from pyramid.config.predicates import sort_accept_offers
+
+ return sort_accept_offers(offers, order)
+
+ def test_default_specificities(self):
+ result = self._callFUT(['text/html', 'text/html;charset=utf8'])
+ self.assertEqual(result, ['text/html;charset=utf8', 'text/html'])
+
+ def test_specific_type_order(self):
+ result = self._callFUT(
+ [
+ 'text/html',
+ 'application/json',
+ 'text/html;charset=utf8',
+ 'text/plain',
+ ],
+ ['application/json', 'text/html'],
+ )
+ self.assertEqual(
+ result,
+ [
+ 'application/json',
+ 'text/html;charset=utf8',
+ 'text/html',
+ 'text/plain',
+ ],
+ )
+
+ def test_params_order(self):
+ result = self._callFUT(
+ [
+ 'text/html;charset=utf8',
+ 'text/html;charset=latin1',
+ 'text/html;foo=bar',
+ ],
+ ['text/html;charset=latin1', 'text/html;charset=utf8'],
+ )
+ self.assertEqual(
+ result,
+ [
+ 'text/html;charset=latin1',
+ 'text/html;charset=utf8',
+ 'text/html;foo=bar',
+ ],
+ )
+
+ def test_params_inherit_type_prefs(self):
+ result = self._callFUT(
+ ['text/html;charset=utf8', 'text/plain;charset=latin1'],
+ ['text/plain', 'text/html'],
+ )
+ self.assertEqual(
+ result, ['text/plain;charset=latin1', 'text/html;charset=utf8']
+ )
+
+
+class DummyCustomPredicate(object):
+ def __init__(self):
+ self.__text__ = 'custom predicate'
+
+ def classmethod_predicate(*args): # pragma: no cover
+ pass
+
+ classmethod_predicate.__text__ = 'classmethod predicate'
+ classmethod_predicate = classmethod(classmethod_predicate)
+
+ @classmethod
+ def classmethod_predicate_no_text(*args):
+ pass # pragma: no cover
+
+
+class Dummy(object):
+ def __init__(self, **kw):
+ self.__dict__.update(**kw)
+
+
+class DummyRequest:
+ subpath = ()
+ matchdict = None
+
+ def __init__(self, environ=None):
+ if environ is None:
+ environ = {}
+ self.environ = environ
+ self.params = {}
+ self.cookies = {}
+
+
+class DummyConfigurator(object):
+ def maybe_dotted(self, thing):
+ return thing
diff --git a/tests/test_config/test_rendering.py b/tests/test_config/test_rendering.py
new file mode 100644
index 000000000..a33977c28
--- /dev/null
+++ b/tests/test_config/test_rendering.py
@@ -0,0 +1,43 @@
+import unittest
+
+
+class TestRenderingConfiguratorMixin(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_add_default_renderers(self):
+ from pyramid.config.rendering import DEFAULT_RENDERERS
+ from pyramid.interfaces import IRendererFactory
+
+ config = self._makeOne(autocommit=True)
+ config.add_default_renderers()
+ for name, impl in DEFAULT_RENDERERS:
+ self.assertTrue(
+ config.registry.queryUtility(IRendererFactory, name)
+ is not None
+ )
+
+ def test_add_renderer(self):
+ from pyramid.interfaces import IRendererFactory
+
+ config = self._makeOne(autocommit=True)
+ renderer = object()
+ config.add_renderer('name', renderer)
+ self.assertEqual(
+ config.registry.getUtility(IRendererFactory, 'name'), renderer
+ )
+
+ def test_add_renderer_dottedname_factory(self):
+ from pyramid.interfaces import IRendererFactory
+
+ config = self._makeOne(autocommit=True)
+ import tests.test_config
+
+ config.add_renderer('name', 'tests.test_config')
+ self.assertEqual(
+ config.registry.getUtility(IRendererFactory, 'name'),
+ tests.test_config,
+ )
diff --git a/tests/test_config/test_routes.py b/tests/test_config/test_routes.py
new file mode 100644
index 000000000..1c1ed6700
--- /dev/null
+++ b/tests/test_config/test_routes.py
@@ -0,0 +1,322 @@
+import unittest
+
+from . import dummyfactory
+from . import DummyContext
+from pyramid.compat import text_
+
+
+class RoutesConfiguratorMixinTests(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def _assertRoute(self, config, name, path, num_predicates=0):
+ from pyramid.interfaces import IRoutesMapper
+
+ mapper = config.registry.getUtility(IRoutesMapper)
+ routes = mapper.get_routes()
+ route = routes[0]
+ self.assertEqual(len(routes), 1)
+ self.assertEqual(route.name, name)
+ self.assertEqual(route.path, path)
+ self.assertEqual(len(routes[0].predicates), num_predicates)
+ return route
+
+ def _makeRequest(self, config):
+ request = DummyRequest()
+ request.registry = config.registry
+ return request
+
+ def test_get_routes_mapper_not_yet_registered(self):
+ config = self._makeOne()
+ mapper = config.get_routes_mapper()
+ self.assertEqual(mapper.routelist, [])
+
+ def test_get_routes_mapper_already_registered(self):
+ from pyramid.interfaces import IRoutesMapper
+
+ config = self._makeOne()
+ mapper = object()
+ config.registry.registerUtility(mapper, IRoutesMapper)
+ result = config.get_routes_mapper()
+ self.assertEqual(result, mapper)
+
+ def test_add_route_defaults(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', 'path')
+ self._assertRoute(config, 'name', 'path')
+
+ def test_add_route_with_route_prefix(self):
+ config = self._makeOne(autocommit=True)
+ config.route_prefix = 'root'
+ config.add_route('name', 'path')
+ self._assertRoute(config, 'name', 'root/path')
+
+ def test_add_route_with_empty_string_with_route_prefix(self):
+ config = self._makeOne(autocommit=True)
+ config.route_prefix = 'root'
+ config.add_route('name', '')
+ self._assertRoute(config, 'name', 'root')
+
+ def test_add_route_with_root_slash_with_route_prefix(self):
+ config = self._makeOne(autocommit=True)
+ config.route_prefix = 'root'
+ config.add_route('name', '/')
+ self._assertRoute(config, 'name', 'root/')
+
+ def test_add_route_discriminator(self):
+ config = self._makeOne()
+ config.add_route('name', 'path')
+ self.assertEqual(
+ config.action_state.actions[-1]['discriminator'], ('route', 'name')
+ )
+
+ def test_add_route_with_factory(self):
+ config = self._makeOne(autocommit=True)
+ factory = object()
+ config.add_route('name', 'path', factory=factory)
+ route = self._assertRoute(config, 'name', 'path')
+ self.assertEqual(route.factory, factory)
+
+ def test_add_route_with_static(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', 'path/{foo}', static=True)
+ mapper = config.get_routes_mapper()
+ self.assertEqual(len(mapper.get_routes()), 0)
+ self.assertEqual(mapper.generate('name', {"foo": "a"}), '/path/a')
+
+ def test_add_route_with_factory_dottedname(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route(
+ 'name', 'path', factory='tests.test_config.dummyfactory'
+ )
+ route = self._assertRoute(config, 'name', 'path')
+ self.assertEqual(route.factory, dummyfactory)
+
+ def test_add_route_with_xhr(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', 'path', xhr=True)
+ route = self._assertRoute(config, 'name', 'path', 1)
+ predicate = route.predicates[0]
+ request = self._makeRequest(config)
+ request.is_xhr = True
+ self.assertEqual(predicate(None, request), True)
+ request = self._makeRequest(config)
+ request.is_xhr = False
+ self.assertEqual(predicate(None, request), False)
+
+ def test_add_route_with_request_method(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', 'path', request_method='GET')
+ route = self._assertRoute(config, 'name', 'path', 1)
+ predicate = route.predicates[0]
+ request = self._makeRequest(config)
+ request.method = 'GET'
+ self.assertEqual(predicate(None, request), True)
+ request = self._makeRequest(config)
+ request.method = 'POST'
+ self.assertEqual(predicate(None, request), False)
+
+ def test_add_route_with_path_info(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', 'path', path_info='/foo')
+ route = self._assertRoute(config, 'name', 'path', 1)
+ predicate = route.predicates[0]
+ request = self._makeRequest(config)
+ request.upath_info = '/foo'
+ self.assertEqual(predicate(None, request), True)
+ request = self._makeRequest(config)
+ request.upath_info = '/'
+ self.assertEqual(predicate(None, request), False)
+
+ def test_add_route_with_path_info_highorder(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route(
+ 'name', 'path', path_info=text_(b'/La Pe\xc3\xb1a', 'utf-8')
+ )
+ route = self._assertRoute(config, 'name', 'path', 1)
+ predicate = route.predicates[0]
+ request = self._makeRequest(config)
+ request.upath_info = text_(b'/La Pe\xc3\xb1a', 'utf-8')
+ self.assertEqual(predicate(None, request), True)
+ request = self._makeRequest(config)
+ request.upath_info = text_('/')
+ self.assertEqual(predicate(None, request), False)
+
+ def test_add_route_with_path_info_regex(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route(
+ 'name', 'path', path_info=text_(br'/La Pe\w*', 'utf-8')
+ )
+ route = self._assertRoute(config, 'name', 'path', 1)
+ predicate = route.predicates[0]
+ request = self._makeRequest(config)
+ request.upath_info = text_(b'/La Pe\xc3\xb1a', 'utf-8')
+ self.assertEqual(predicate(None, request), True)
+ request = self._makeRequest(config)
+ request.upath_info = text_('/')
+ self.assertEqual(predicate(None, request), False)
+
+ def test_add_route_with_request_param(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', 'path', request_param='abc')
+ route = self._assertRoute(config, 'name', 'path', 1)
+ predicate = route.predicates[0]
+ request = self._makeRequest(config)
+ request.params = {'abc': '123'}
+ self.assertEqual(predicate(None, request), True)
+ request = self._makeRequest(config)
+ request.params = {}
+ self.assertEqual(predicate(None, request), False)
+
+ def test_add_route_with_custom_predicates(self):
+ import warnings
+
+ config = self._makeOne(autocommit=True)
+
+ def pred1(context, request): # pragma: no cover
+ pass
+
+ def pred2(context, request): # pragma: no cover
+ pass
+
+ with warnings.catch_warnings(record=True) as w:
+ warnings.filterwarnings('always')
+ config.add_route('name', 'path', custom_predicates=(pred1, pred2))
+ self.assertEqual(len(w), 1)
+ route = self._assertRoute(config, 'name', 'path', 2)
+ self.assertEqual(len(route.predicates), 2)
+
+ def test_add_route_with_header(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', 'path', header='Host')
+ route = self._assertRoute(config, 'name', 'path', 1)
+ predicate = route.predicates[0]
+ request = self._makeRequest(config)
+ request.headers = {'Host': 'example.com'}
+ self.assertEqual(predicate(None, request), True)
+ request = self._makeRequest(config)
+ request.headers = {}
+ self.assertEqual(predicate(None, request), False)
+
+ def test_add_route_with_accept(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', 'path', accept='text/xml')
+ route = self._assertRoute(config, 'name', 'path', 1)
+ predicate = route.predicates[0]
+ request = self._makeRequest(config)
+ request.accept = DummyAccept('text/xml')
+ self.assertEqual(predicate(None, request), True)
+ request = self._makeRequest(config)
+ request.accept = DummyAccept('text/html')
+ self.assertEqual(predicate(None, request), False)
+
+ def test_add_route_with_accept_list(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', 'path', accept=['text/xml', 'text/plain'])
+ route = self._assertRoute(config, 'name', 'path', 1)
+ predicate = route.predicates[0]
+ request = self._makeRequest(config)
+ request.accept = DummyAccept('text/xml')
+ self.assertEqual(predicate(None, request), True)
+ request = self._makeRequest(config)
+ request.accept = DummyAccept('text/plain')
+ self.assertEqual(predicate(None, request), True)
+ request = self._makeRequest(config)
+ request.accept = DummyAccept('text/html')
+ self.assertEqual(predicate(None, request), False)
+
+ def test_add_route_with_wildcard_accept_raises(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ValueError,
+ lambda: config.add_route('name', 'path', accept='text/*'),
+ )
+
+ def test_add_route_no_pattern_with_path(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', path='path')
+ self._assertRoute(config, 'name', 'path')
+
+ def test_add_route_no_path_no_pattern(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ self.assertRaises(ConfigurationError, config.add_route, 'name')
+
+ def test_add_route_with_pregenerator(self):
+ config = self._makeOne(autocommit=True)
+ config.add_route('name', 'pattern', pregenerator='123')
+ route = self._assertRoute(config, 'name', 'pattern')
+ self.assertEqual(route.pregenerator, '123')
+
+ def test_add_route_no_view_with_view_attr(self):
+ config = self._makeOne(autocommit=True)
+ from pyramid.exceptions import ConfigurationError
+
+ try:
+ config.add_route('name', '/pattern', view_attr='abc')
+ except ConfigurationError:
+ pass
+ else: # pragma: no cover
+ raise AssertionError
+
+ def test_add_route_no_view_with_view_context(self):
+ config = self._makeOne(autocommit=True)
+ from pyramid.exceptions import ConfigurationError
+
+ try:
+ config.add_route('name', '/pattern', view_context=DummyContext)
+ except ConfigurationError:
+ pass
+ else: # pragma: no cover
+ raise AssertionError
+
+ def test_add_route_no_view_with_view_permission(self):
+ config = self._makeOne(autocommit=True)
+ from pyramid.exceptions import ConfigurationError
+
+ try:
+ config.add_route('name', '/pattern', view_permission='edit')
+ except ConfigurationError:
+ pass
+ else: # pragma: no cover
+ raise AssertionError
+
+ def test_add_route_no_view_with_view_renderer(self):
+ config = self._makeOne(autocommit=True)
+ from pyramid.exceptions import ConfigurationError
+
+ try:
+ config.add_route('name', '/pattern', view_renderer='json')
+ except ConfigurationError:
+ pass
+ else: # pragma: no cover
+ raise AssertionError
+
+
+class DummyRequest:
+ subpath = ()
+ matchdict = None
+
+ def __init__(self, environ=None):
+ if environ is None:
+ environ = {}
+ self.environ = environ
+ self.params = {}
+ self.cookies = {}
+
+
+class DummyAccept(object):
+ def __init__(self, *matches, **kw):
+ self.matches = list(matches)
+ self.contains = kw.pop('contains', False)
+
+ def acceptable_offers(self, offers):
+ results = []
+ for match in self.matches:
+ if match in offers:
+ results.append((match, 1.0))
+ return results
diff --git a/tests/test_config/test_security.py b/tests/test_config/test_security.py
new file mode 100644
index 000000000..5ebd78f8d
--- /dev/null
+++ b/tests/test_config/test_security.py
@@ -0,0 +1,151 @@
+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
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_set_authentication_policy_no_authz_policy(self):
+ 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):
+ config = self._makeOne(autocommit=True)
+ policy = object()
+ self.assertRaises(
+ ConfigurationError, config.set_authentication_policy, policy
+ )
+
+ def test_set_authentication_policy_with_authz_policy(self):
+ from pyramid.interfaces import IAuthenticationPolicy
+ from pyramid.interfaces import IAuthorizationPolicy
+
+ config = self._makeOne()
+ authn_policy = object()
+ authz_policy = object()
+ config.registry.registerUtility(authz_policy, IAuthorizationPolicy)
+ config.set_authentication_policy(authn_policy)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IAuthenticationPolicy), authn_policy
+ )
+
+ def test_set_authentication_policy_with_authz_policy_autocommit(self):
+ from pyramid.interfaces import IAuthenticationPolicy
+ from pyramid.interfaces import IAuthorizationPolicy
+
+ config = self._makeOne(autocommit=True)
+ authn_policy = object()
+ authz_policy = object()
+ config.registry.registerUtility(authz_policy, IAuthorizationPolicy)
+ config.set_authentication_policy(authn_policy)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IAuthenticationPolicy), authn_policy
+ )
+
+ def test_set_authorization_policy_no_authn_policy(self):
+ config = self._makeOne()
+ policy = object()
+ config.set_authorization_policy(policy)
+ self.assertRaises(ConfigurationExecutionError, config.commit)
+
+ def test_set_authorization_policy_no_authn_policy_autocommit(self):
+ from pyramid.interfaces import IAuthorizationPolicy
+
+ config = self._makeOne(autocommit=True)
+ policy = object()
+ config.set_authorization_policy(policy)
+ self.assertEqual(
+ config.registry.getUtility(IAuthorizationPolicy), policy
+ )
+
+ def test_set_authorization_policy_with_authn_policy(self):
+ from pyramid.interfaces import IAuthorizationPolicy
+ from pyramid.interfaces import IAuthenticationPolicy
+
+ config = self._makeOne()
+ authn_policy = object()
+ authz_policy = object()
+ config.registry.registerUtility(authn_policy, IAuthenticationPolicy)
+ config.set_authorization_policy(authz_policy)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IAuthorizationPolicy), authz_policy
+ )
+
+ def test_set_authorization_policy_with_authn_policy_autocommit(self):
+ from pyramid.interfaces import IAuthorizationPolicy
+ from pyramid.interfaces import IAuthenticationPolicy
+
+ config = self._makeOne(autocommit=True)
+ authn_policy = object()
+ authz_policy = object()
+ config.registry.registerUtility(authn_policy, IAuthenticationPolicy)
+ config.set_authorization_policy(authz_policy)
+ self.assertEqual(
+ config.registry.getUtility(IAuthorizationPolicy), authz_policy
+ )
+
+ def test_set_default_permission(self):
+ from pyramid.interfaces import IDefaultPermission
+
+ config = self._makeOne(autocommit=True)
+ config.set_default_permission('view')
+ self.assertEqual(
+ config.registry.getUtility(IDefaultPermission), 'view'
+ )
+
+ def test_add_permission(self):
+ config = self._makeOne(autocommit=True)
+ config.add_permission('perm')
+ cat = config.registry.introspector.get_category('permissions')
+ self.assertEqual(len(cat), 1)
+ D = cat[0]
+ intr = D['introspectable']
+ self.assertEqual(intr['value'], 'perm')
+
+ def test_set_default_csrf_options(self):
+ from pyramid.interfaces import IDefaultCSRFOptions
+
+ config = self._makeOne(autocommit=True)
+ config.set_default_csrf_options()
+ result = config.registry.getUtility(IDefaultCSRFOptions)
+ self.assertEqual(result.require_csrf, True)
+ self.assertEqual(result.token, 'csrf_token')
+ self.assertEqual(result.header, 'X-CSRF-Token')
+ self.assertEqual(
+ list(sorted(result.safe_methods)),
+ ['GET', 'HEAD', 'OPTIONS', 'TRACE'],
+ )
+ self.assertTrue(result.callback is None)
+
+ def test_changing_set_default_csrf_options(self):
+ from pyramid.interfaces import IDefaultCSRFOptions
+
+ config = self._makeOne(autocommit=True)
+
+ def callback(request): # pragma: no cover
+ return True
+
+ config.set_default_csrf_options(
+ require_csrf=False,
+ token='DUMMY',
+ header=None,
+ safe_methods=('PUT',),
+ callback=callback,
+ )
+ result = config.registry.getUtility(IDefaultCSRFOptions)
+ self.assertEqual(result.require_csrf, False)
+ self.assertEqual(result.token, 'DUMMY')
+ self.assertEqual(result.header, None)
+ self.assertEqual(list(sorted(result.safe_methods)), ['PUT'])
+ self.assertTrue(result.callback is callback)
diff --git a/tests/test_config/test_settings.py b/tests/test_config/test_settings.py
new file mode 100644
index 000000000..2fe769add
--- /dev/null
+++ b/tests/test_config/test_settings.py
@@ -0,0 +1,635 @@
+import unittest
+
+
+class TestSettingsConfiguratorMixin(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test__set_settings_as_None(self):
+ config = self._makeOne()
+ settings = config._set_settings(None)
+ self.assertTrue(settings)
+
+ def test__set_settings_does_not_uses_original_dict(self):
+ config = self._makeOne()
+ dummy = {}
+ result = config._set_settings(dummy)
+ self.assertTrue(dummy is not result)
+ self.assertNotIn('pyramid.debug_all', dummy)
+
+ def test__set_settings_as_dictwithvalues(self):
+ config = self._makeOne()
+ settings = config._set_settings({'a': '1'})
+ self.assertEqual(settings['a'], '1')
+
+ def test_get_settings_nosettings(self):
+ from pyramid.registry import Registry
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ self.assertEqual(config.get_settings(), None)
+
+ def test_get_settings_withsettings(self):
+ settings = {'a': 1}
+ config = self._makeOne()
+ config.registry.settings = settings
+ self.assertEqual(config.get_settings(), settings)
+
+ def test_add_settings_settings_already_registered(self):
+ from pyramid.registry import Registry
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ config._set_settings({'a': 1})
+ config.add_settings({'b': 2})
+ settings = reg.settings
+ self.assertEqual(settings['a'], 1)
+ self.assertEqual(settings['b'], 2)
+
+ def test_add_settings_settings_not_yet_registered(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import ISettings
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.add_settings({'a': 1})
+ settings = reg.getUtility(ISettings)
+ self.assertEqual(settings['a'], 1)
+
+ def test_add_settings_settings_None(self):
+ from pyramid.registry import Registry
+ from pyramid.interfaces import ISettings
+
+ reg = Registry()
+ config = self._makeOne(reg)
+ config.add_settings(None, a=1)
+ settings = reg.getUtility(ISettings)
+ self.assertEqual(settings['a'], 1)
+
+ def test_settings_parameter_dict_is_never_updated(self):
+ class ReadOnlyDict(dict):
+ def __readonly__(self, *args, **kwargs): # pragma: no cover
+ raise RuntimeError("Cannot modify ReadOnlyDict")
+
+ __setitem__ = __readonly__
+ __delitem__ = __readonly__
+ pop = __readonly__
+ popitem = __readonly__
+ clear = __readonly__
+ update = __readonly__
+ setdefault = __readonly__
+ del __readonly__
+
+ initial = ReadOnlyDict()
+ config = self._makeOne(settings=initial)
+ config._set_settings({'a': '1'})
+
+
+class TestSettings(unittest.TestCase):
+ def _getTargetClass(self):
+ from pyramid.config.settings import Settings
+
+ return Settings
+
+ def _makeOne(self, d=None, environ=None):
+ if environ is None:
+ environ = {}
+ klass = self._getTargetClass()
+ return klass(d, _environ_=environ)
+
+ def test_noargs(self):
+ settings = self._makeOne()
+ self.assertEqual(settings['debug_authorization'], False)
+ self.assertEqual(settings['debug_notfound'], False)
+ self.assertEqual(settings['debug_routematch'], False)
+ self.assertEqual(settings['reload_templates'], False)
+ self.assertEqual(settings['reload_resources'], False)
+
+ self.assertEqual(settings['pyramid.debug_authorization'], False)
+ self.assertEqual(settings['pyramid.debug_notfound'], False)
+ self.assertEqual(settings['pyramid.debug_routematch'], False)
+ self.assertEqual(settings['pyramid.reload_templates'], False)
+ self.assertEqual(settings['pyramid.reload_resources'], False)
+
+ def test_prevent_http_cache(self):
+ settings = self._makeOne({})
+ self.assertEqual(settings['prevent_http_cache'], False)
+ self.assertEqual(settings['pyramid.prevent_http_cache'], False)
+ result = self._makeOne({'prevent_http_cache': 'false'})
+ self.assertEqual(result['prevent_http_cache'], False)
+ self.assertEqual(result['pyramid.prevent_http_cache'], False)
+ result = self._makeOne({'prevent_http_cache': 't'})
+ self.assertEqual(result['prevent_http_cache'], True)
+ self.assertEqual(result['pyramid.prevent_http_cache'], True)
+ result = self._makeOne({'prevent_http_cache': '1'})
+ self.assertEqual(result['prevent_http_cache'], True)
+ self.assertEqual(result['pyramid.prevent_http_cache'], True)
+ result = self._makeOne({'pyramid.prevent_http_cache': 't'})
+ self.assertEqual(result['prevent_http_cache'], True)
+ self.assertEqual(result['pyramid.prevent_http_cache'], True)
+ result = self._makeOne({}, {'PYRAMID_PREVENT_HTTP_CACHE': '1'})
+ self.assertEqual(result['prevent_http_cache'], True)
+ self.assertEqual(result['pyramid.prevent_http_cache'], True)
+ result = self._makeOne(
+ {'prevent_http_cache': 'false', 'pyramid.prevent_http_cache': '1'}
+ )
+ self.assertEqual(result['prevent_http_cache'], True)
+ self.assertEqual(result['pyramid.prevent_http_cache'], True)
+ result = self._makeOne(
+ {'prevent_http_cache': 'false', 'pyramid.prevent_http_cache': 'f'},
+ {'PYRAMID_PREVENT_HTTP_CACHE': '1'},
+ )
+ self.assertEqual(result['prevent_http_cache'], True)
+ self.assertEqual(result['pyramid.prevent_http_cache'], True)
+
+ def test_prevent_cachebust(self):
+ settings = self._makeOne({})
+ self.assertEqual(settings['prevent_cachebust'], False)
+ self.assertEqual(settings['pyramid.prevent_cachebust'], False)
+ result = self._makeOne({'prevent_cachebust': 'false'})
+ self.assertEqual(result['prevent_cachebust'], False)
+ self.assertEqual(result['pyramid.prevent_cachebust'], False)
+ result = self._makeOne({'prevent_cachebust': 't'})
+ self.assertEqual(result['prevent_cachebust'], True)
+ self.assertEqual(result['pyramid.prevent_cachebust'], True)
+ result = self._makeOne({'prevent_cachebust': '1'})
+ self.assertEqual(result['prevent_cachebust'], True)
+ self.assertEqual(result['pyramid.prevent_cachebust'], True)
+ result = self._makeOne({'pyramid.prevent_cachebust': 't'})
+ self.assertEqual(result['prevent_cachebust'], True)
+ self.assertEqual(result['pyramid.prevent_cachebust'], True)
+ result = self._makeOne({}, {'PYRAMID_PREVENT_CACHEBUST': '1'})
+ self.assertEqual(result['prevent_cachebust'], True)
+ self.assertEqual(result['pyramid.prevent_cachebust'], True)
+ result = self._makeOne(
+ {'prevent_cachebust': 'false', 'pyramid.prevent_cachebust': '1'}
+ )
+ self.assertEqual(result['prevent_cachebust'], True)
+ self.assertEqual(result['pyramid.prevent_cachebust'], True)
+ result = self._makeOne(
+ {'prevent_cachebust': 'false', 'pyramid.prevent_cachebust': 'f'},
+ {'PYRAMID_PREVENT_CACHEBUST': '1'},
+ )
+ self.assertEqual(result['prevent_cachebust'], True)
+ self.assertEqual(result['pyramid.prevent_cachebust'], True)
+
+ def test_reload_templates(self):
+ settings = self._makeOne({})
+ self.assertEqual(settings['reload_templates'], False)
+ self.assertEqual(settings['pyramid.reload_templates'], False)
+ result = self._makeOne({'reload_templates': 'false'})
+ self.assertEqual(result['reload_templates'], False)
+ self.assertEqual(result['pyramid.reload_templates'], False)
+ result = self._makeOne({'reload_templates': 't'})
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ result = self._makeOne({'reload_templates': '1'})
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ result = self._makeOne({'pyramid.reload_templates': '1'})
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ result = self._makeOne({}, {'PYRAMID_RELOAD_TEMPLATES': '1'})
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ result = self._makeOne(
+ {'reload_templates': 'false', 'pyramid.reload_templates': '1'}
+ )
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ result = self._makeOne(
+ {'reload_templates': 'false'}, {'PYRAMID_RELOAD_TEMPLATES': '1'}
+ )
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+
+ def test_reload_resources(self):
+ # alias for reload_assets
+ result = self._makeOne({})
+ self.assertEqual(result['reload_resources'], False)
+ self.assertEqual(result['reload_assets'], False)
+ self.assertEqual(result['pyramid.reload_resources'], False)
+ self.assertEqual(result['pyramid.reload_assets'], False)
+ result = self._makeOne({'reload_resources': 'false'})
+ self.assertEqual(result['reload_resources'], False)
+ self.assertEqual(result['reload_assets'], False)
+ self.assertEqual(result['pyramid.reload_resources'], False)
+ self.assertEqual(result['pyramid.reload_assets'], False)
+ result = self._makeOne({'reload_resources': 't'})
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ result = self._makeOne({'reload_resources': '1'})
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ result = self._makeOne({'pyramid.reload_resources': '1'})
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ result = self._makeOne({}, {'PYRAMID_RELOAD_RESOURCES': '1'})
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ result = self._makeOne(
+ {'reload_resources': 'false', 'pyramid.reload_resources': '1'}
+ )
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ result = self._makeOne(
+ {'reload_resources': 'false', 'pyramid.reload_resources': 'false'},
+ {'PYRAMID_RELOAD_RESOURCES': '1'},
+ )
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+
+ def test_reload_assets(self):
+ # alias for reload_resources
+ result = self._makeOne({})
+ self.assertEqual(result['reload_assets'], False)
+ self.assertEqual(result['reload_resources'], False)
+ self.assertEqual(result['pyramid.reload_assets'], False)
+ self.assertEqual(result['pyramid.reload_resources'], False)
+ result = self._makeOne({'reload_assets': 'false'})
+ self.assertEqual(result['reload_resources'], False)
+ self.assertEqual(result['reload_assets'], False)
+ self.assertEqual(result['pyramid.reload_assets'], False)
+ self.assertEqual(result['pyramid.reload_resources'], False)
+ result = self._makeOne({'reload_assets': 't'})
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ result = self._makeOne({'reload_assets': '1'})
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ result = self._makeOne({'pyramid.reload_assets': '1'})
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ result = self._makeOne({}, {'PYRAMID_RELOAD_ASSETS': '1'})
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ result = self._makeOne(
+ {'reload_assets': 'false', 'pyramid.reload_assets': '1'}
+ )
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ result = self._makeOne(
+ {'reload_assets': 'false', 'pyramid.reload_assets': 'false'},
+ {'PYRAMID_RELOAD_ASSETS': '1'},
+ )
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+
+ def test_reload_all(self):
+ result = self._makeOne({})
+ self.assertEqual(result['reload_templates'], False)
+ self.assertEqual(result['reload_resources'], False)
+ self.assertEqual(result['reload_assets'], False)
+ self.assertEqual(result['pyramid.reload_templates'], False)
+ self.assertEqual(result['pyramid.reload_resources'], False)
+ self.assertEqual(result['pyramid.reload_assets'], False)
+ result = self._makeOne({'reload_all': 'false'})
+ self.assertEqual(result['reload_templates'], False)
+ self.assertEqual(result['reload_resources'], False)
+ self.assertEqual(result['reload_assets'], False)
+ self.assertEqual(result['pyramid.reload_templates'], False)
+ self.assertEqual(result['pyramid.reload_resources'], False)
+ self.assertEqual(result['pyramid.reload_assets'], False)
+ result = self._makeOne({'reload_all': 't'})
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ result = self._makeOne({'reload_all': '1'})
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ result = self._makeOne({'pyramid.reload_all': '1'})
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ result = self._makeOne({}, {'PYRAMID_RELOAD_ALL': '1'})
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ result = self._makeOne(
+ {'reload_all': 'false', 'pyramid.reload_all': '1'}
+ )
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+ result = self._makeOne(
+ {'reload_all': 'false', 'pyramid.reload_all': 'false'},
+ {'PYRAMID_RELOAD_ALL': '1'},
+ )
+ self.assertEqual(result['reload_templates'], True)
+ self.assertEqual(result['reload_resources'], True)
+ self.assertEqual(result['reload_assets'], True)
+ self.assertEqual(result['pyramid.reload_templates'], True)
+ self.assertEqual(result['pyramid.reload_resources'], True)
+ self.assertEqual(result['pyramid.reload_assets'], True)
+
+ def test_debug_authorization(self):
+ result = self._makeOne({})
+ self.assertEqual(result['debug_authorization'], False)
+ self.assertEqual(result['pyramid.debug_authorization'], False)
+ result = self._makeOne({'debug_authorization': 'false'})
+ self.assertEqual(result['debug_authorization'], False)
+ self.assertEqual(result['pyramid.debug_authorization'], False)
+ result = self._makeOne({'debug_authorization': 't'})
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ result = self._makeOne({'debug_authorization': '1'})
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ result = self._makeOne({'pyramid.debug_authorization': '1'})
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ result = self._makeOne({}, {'PYRAMID_DEBUG_AUTHORIZATION': '1'})
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ result = self._makeOne(
+ {
+ 'debug_authorization': 'false',
+ 'pyramid.debug_authorization': '1',
+ }
+ )
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ result = self._makeOne(
+ {
+ 'debug_authorization': 'false',
+ 'pyramid.debug_authorization': 'false',
+ },
+ {'PYRAMID_DEBUG_AUTHORIZATION': '1'},
+ )
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+
+ def test_debug_notfound(self):
+ result = self._makeOne({})
+ self.assertEqual(result['debug_notfound'], False)
+ self.assertEqual(result['pyramid.debug_notfound'], False)
+ result = self._makeOne({'debug_notfound': 'false'})
+ self.assertEqual(result['debug_notfound'], False)
+ self.assertEqual(result['pyramid.debug_notfound'], False)
+ result = self._makeOne({'debug_notfound': 't'})
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ result = self._makeOne({'debug_notfound': '1'})
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ result = self._makeOne({'pyramid.debug_notfound': '1'})
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ result = self._makeOne({}, {'PYRAMID_DEBUG_NOTFOUND': '1'})
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ result = self._makeOne(
+ {'debug_notfound': 'false', 'pyramid.debug_notfound': '1'}
+ )
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ result = self._makeOne(
+ {'debug_notfound': 'false', 'pyramid.debug_notfound': 'false'},
+ {'PYRAMID_DEBUG_NOTFOUND': '1'},
+ )
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+
+ def test_debug_routematch(self):
+ result = self._makeOne({})
+ self.assertEqual(result['debug_routematch'], False)
+ self.assertEqual(result['pyramid.debug_routematch'], False)
+ result = self._makeOne({'debug_routematch': 'false'})
+ self.assertEqual(result['debug_routematch'], False)
+ self.assertEqual(result['pyramid.debug_routematch'], False)
+ result = self._makeOne({'debug_routematch': 't'})
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ result = self._makeOne({'debug_routematch': '1'})
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ result = self._makeOne({'pyramid.debug_routematch': '1'})
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ result = self._makeOne({}, {'PYRAMID_DEBUG_ROUTEMATCH': '1'})
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ result = self._makeOne(
+ {'debug_routematch': 'false', 'pyramid.debug_routematch': '1'}
+ )
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ result = self._makeOne(
+ {'debug_routematch': 'false', 'pyramid.debug_routematch': 'false'},
+ {'PYRAMID_DEBUG_ROUTEMATCH': '1'},
+ )
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+
+ def test_debug_templates(self):
+ result = self._makeOne({})
+ self.assertEqual(result['debug_templates'], False)
+ self.assertEqual(result['pyramid.debug_templates'], False)
+ result = self._makeOne({'debug_templates': 'false'})
+ self.assertEqual(result['debug_templates'], False)
+ self.assertEqual(result['pyramid.debug_templates'], False)
+ result = self._makeOne({'debug_templates': 't'})
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+ result = self._makeOne({'debug_templates': '1'})
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+ result = self._makeOne({'pyramid.debug_templates': '1'})
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+ result = self._makeOne({}, {'PYRAMID_DEBUG_TEMPLATES': '1'})
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+ result = self._makeOne(
+ {'debug_templates': 'false', 'pyramid.debug_templates': '1'}
+ )
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+ result = self._makeOne(
+ {'debug_templates': 'false', 'pyramid.debug_templates': 'false'},
+ {'PYRAMID_DEBUG_TEMPLATES': '1'},
+ )
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+
+ def test_debug_all(self):
+ result = self._makeOne({})
+ self.assertEqual(result['debug_notfound'], False)
+ self.assertEqual(result['debug_routematch'], False)
+ self.assertEqual(result['debug_authorization'], False)
+ self.assertEqual(result['debug_templates'], False)
+ self.assertEqual(result['pyramid.debug_notfound'], False)
+ self.assertEqual(result['pyramid.debug_routematch'], False)
+ self.assertEqual(result['pyramid.debug_authorization'], False)
+ self.assertEqual(result['pyramid.debug_templates'], False)
+ result = self._makeOne({'debug_all': 'false'})
+ self.assertEqual(result['debug_notfound'], False)
+ self.assertEqual(result['debug_routematch'], False)
+ self.assertEqual(result['debug_authorization'], False)
+ self.assertEqual(result['debug_templates'], False)
+ self.assertEqual(result['pyramid.debug_notfound'], False)
+ self.assertEqual(result['pyramid.debug_routematch'], False)
+ self.assertEqual(result['pyramid.debug_authorization'], False)
+ self.assertEqual(result['pyramid.debug_templates'], False)
+ result = self._makeOne({'debug_all': 't'})
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+ result = self._makeOne({'debug_all': '1'})
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+ result = self._makeOne({'pyramid.debug_all': '1'})
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+ result = self._makeOne({}, {'PYRAMID_DEBUG_ALL': '1'})
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+ result = self._makeOne(
+ {'debug_all': 'false', 'pyramid.debug_all': '1'}
+ )
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+ result = self._makeOne(
+ {'debug_all': 'false', 'pyramid.debug_all': 'false'},
+ {'PYRAMID_DEBUG_ALL': '1'},
+ )
+ self.assertEqual(result['debug_notfound'], True)
+ self.assertEqual(result['debug_routematch'], True)
+ self.assertEqual(result['debug_authorization'], True)
+ self.assertEqual(result['debug_templates'], True)
+ self.assertEqual(result['pyramid.debug_notfound'], True)
+ self.assertEqual(result['pyramid.debug_routematch'], True)
+ self.assertEqual(result['pyramid.debug_authorization'], True)
+ self.assertEqual(result['pyramid.debug_templates'], True)
+
+ def test_default_locale_name(self):
+ result = self._makeOne({})
+ self.assertEqual(result['default_locale_name'], 'en')
+ self.assertEqual(result['pyramid.default_locale_name'], 'en')
+ result = self._makeOne({'default_locale_name': 'abc'})
+ self.assertEqual(result['default_locale_name'], 'abc')
+ self.assertEqual(result['pyramid.default_locale_name'], 'abc')
+ result = self._makeOne({'pyramid.default_locale_name': 'abc'})
+ self.assertEqual(result['default_locale_name'], 'abc')
+ self.assertEqual(result['pyramid.default_locale_name'], 'abc')
+ result = self._makeOne({}, {'PYRAMID_DEFAULT_LOCALE_NAME': 'abc'})
+ self.assertEqual(result['default_locale_name'], 'abc')
+ self.assertEqual(result['pyramid.default_locale_name'], 'abc')
+ result = self._makeOne(
+ {
+ 'default_locale_name': 'def',
+ 'pyramid.default_locale_name': 'abc',
+ }
+ )
+ self.assertEqual(result['default_locale_name'], 'abc')
+ self.assertEqual(result['pyramid.default_locale_name'], 'abc')
+ result = self._makeOne(
+ {
+ 'default_locale_name': 'def',
+ 'pyramid.default_locale_name': 'ghi',
+ },
+ {'PYRAMID_DEFAULT_LOCALE_NAME': 'abc'},
+ )
+ self.assertEqual(result['default_locale_name'], 'abc')
+ self.assertEqual(result['pyramid.default_locale_name'], 'abc')
+
+ def test_csrf_trusted_origins(self):
+ result = self._makeOne({})
+ self.assertEqual(result['pyramid.csrf_trusted_origins'], [])
+ result = self._makeOne({'pyramid.csrf_trusted_origins': 'example.com'})
+ self.assertEqual(
+ result['pyramid.csrf_trusted_origins'], ['example.com']
+ )
+ result = self._makeOne(
+ {'pyramid.csrf_trusted_origins': ['example.com']}
+ )
+ self.assertEqual(
+ result['pyramid.csrf_trusted_origins'], ['example.com']
+ )
+ result = self._makeOne(
+ {
+ 'pyramid.csrf_trusted_origins': (
+ 'example.com foo.example.com\nasdf.example.com'
+ )
+ }
+ )
+ self.assertEqual(
+ result['pyramid.csrf_trusted_origins'],
+ ['example.com', 'foo.example.com', 'asdf.example.com'],
+ )
+
+ def test_originals_kept(self):
+ result = self._makeOne({'a': 'i am so a'})
+ self.assertEqual(result['a'], 'i am so a')
diff --git a/tests/test_config/test_testing.py b/tests/test_config/test_testing.py
new file mode 100644
index 000000000..ede31e1b6
--- /dev/null
+++ b/tests/test_config/test_testing.py
@@ -0,0 +1,235 @@
+import unittest
+from zope.interface import implementer
+
+from pyramid.compat import text_
+from pyramid.security import AuthenticationAPIMixin, AuthorizationAPIMixin
+from . import IDummy
+
+
+class TestingConfiguratorMixinTests(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_testing_securitypolicy(self):
+ from pyramid.testing import DummySecurityPolicy
+
+ config = self._makeOne(autocommit=True)
+ config.testing_securitypolicy(
+ 'user', ('group1', 'group2'), permissive=False
+ )
+ from pyramid.interfaces import IAuthenticationPolicy
+ from pyramid.interfaces import IAuthorizationPolicy
+
+ ut = config.registry.getUtility(IAuthenticationPolicy)
+ self.assertTrue(isinstance(ut, DummySecurityPolicy))
+ ut = config.registry.getUtility(IAuthorizationPolicy)
+ self.assertEqual(ut.userid, 'user')
+ self.assertEqual(ut.groupids, ('group1', 'group2'))
+ self.assertEqual(ut.permissive, False)
+
+ def test_testing_securitypolicy_remember_result(self):
+ from pyramid.security import remember
+
+ config = self._makeOne(autocommit=True)
+ pol = config.testing_securitypolicy(
+ 'user',
+ ('group1', 'group2'),
+ permissive=False,
+ remember_result=True,
+ )
+ request = DummyRequest()
+ request.registry = config.registry
+ val = remember(request, 'fred')
+ self.assertEqual(pol.remembered, 'fred')
+ self.assertEqual(val, True)
+
+ def test_testing_securitypolicy_forget_result(self):
+ from pyramid.security import forget
+
+ config = self._makeOne(autocommit=True)
+ pol = config.testing_securitypolicy(
+ 'user', ('group1', 'group2'), permissive=False, forget_result=True
+ )
+ request = DummyRequest()
+ request.registry = config.registry
+ val = forget(request)
+ self.assertEqual(pol.forgotten, True)
+ self.assertEqual(val, True)
+
+ def test_testing_resources(self):
+ from pyramid.traversal import find_resource
+ from pyramid.interfaces import ITraverser
+
+ ob1 = object()
+ ob2 = object()
+ resources = {'/ob1': ob1, '/ob2': ob2}
+ config = self._makeOne(autocommit=True)
+ config.testing_resources(resources)
+ adapter = config.registry.getAdapter(None, ITraverser)
+ result = adapter(DummyRequest({'PATH_INFO': '/ob1'}))
+ self.assertEqual(result['context'], ob1)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], (text_('ob1'),))
+ self.assertEqual(result['virtual_root'], ob1)
+ self.assertEqual(result['virtual_root_path'], ())
+ result = adapter(DummyRequest({'PATH_INFO': '/ob2'}))
+ self.assertEqual(result['context'], ob2)
+ self.assertEqual(result['view_name'], '')
+ self.assertEqual(result['subpath'], ())
+ self.assertEqual(result['traversed'], (text_('ob2'),))
+ self.assertEqual(result['virtual_root'], ob2)
+ self.assertEqual(result['virtual_root_path'], ())
+ self.assertRaises(
+ KeyError, adapter, DummyRequest({'PATH_INFO': '/ob3'})
+ )
+ try:
+ config.begin()
+ self.assertEqual(find_resource(None, '/ob1'), ob1)
+ finally:
+ config.end()
+
+ def test_testing_add_subscriber_single(self):
+ config = self._makeOne(autocommit=True)
+ L = config.testing_add_subscriber(IDummy)
+ event = DummyEvent()
+ config.registry.notify(event)
+ self.assertEqual(len(L), 1)
+ self.assertEqual(L[0], event)
+ config.registry.notify(object())
+ self.assertEqual(len(L), 1)
+
+ def test_testing_add_subscriber_dottedname(self):
+ config = self._makeOne(autocommit=True)
+ L = config.testing_add_subscriber('tests.test_config.IDummy')
+ event = DummyEvent()
+ config.registry.notify(event)
+ self.assertEqual(len(L), 1)
+ self.assertEqual(L[0], event)
+ config.registry.notify(object())
+ self.assertEqual(len(L), 1)
+
+ def test_testing_add_subscriber_multiple(self):
+ from zope.interface import Interface
+
+ config = self._makeOne(autocommit=True)
+ L = config.testing_add_subscriber((Interface, IDummy))
+ event = DummyEvent()
+ event.object = 'foo'
+ # the below is the equivalent of z.c.event.objectEventNotify(event)
+ config.registry.subscribers((event.object, event), None)
+ self.assertEqual(len(L), 2)
+ self.assertEqual(L[0], 'foo')
+ self.assertEqual(L[1], event)
+
+ def test_testing_add_subscriber_defaults(self):
+ config = self._makeOne(autocommit=True)
+ L = config.testing_add_subscriber()
+ event = object()
+ config.registry.notify(event)
+ self.assertEqual(L[-1], event)
+ event2 = object()
+ config.registry.notify(event2)
+ self.assertEqual(L[-1], event2)
+
+ def test_testing_add_renderer(self):
+ config = self._makeOne(autocommit=True)
+ renderer = config.testing_add_renderer('templates/foo.pt')
+ from pyramid.testing import DummyTemplateRenderer
+
+ self.assertTrue(isinstance(renderer, DummyTemplateRenderer))
+ from pyramid.renderers import render_to_response
+
+ # must provide request to pass in registry (this is a functest)
+ request = DummyRequest()
+ request.registry = config.registry
+ render_to_response(
+ 'templates/foo.pt', {'foo': 1, 'bar': 2}, request=request
+ )
+ renderer.assert_(foo=1)
+ renderer.assert_(bar=2)
+ renderer.assert_(request=request)
+
+ def test_testing_add_renderer_twice(self):
+ config = self._makeOne(autocommit=True)
+ renderer1 = config.testing_add_renderer('templates/foo.pt')
+ renderer2 = config.testing_add_renderer('templates/bar.pt')
+ from pyramid.testing import DummyTemplateRenderer
+
+ self.assertTrue(isinstance(renderer1, DummyTemplateRenderer))
+ self.assertTrue(isinstance(renderer2, DummyTemplateRenderer))
+ from pyramid.renderers import render_to_response
+
+ # must provide request to pass in registry (this is a functest)
+ request = DummyRequest()
+ request.registry = config.registry
+ render_to_response(
+ 'templates/foo.pt', {'foo': 1, 'bar': 2}, request=request
+ )
+ renderer1.assert_(foo=1)
+ renderer1.assert_(bar=2)
+ renderer1.assert_(request=request)
+ render_to_response(
+ 'templates/bar.pt', {'foo': 1, 'bar': 2}, request=request
+ )
+ renderer2.assert_(foo=1)
+ renderer2.assert_(bar=2)
+ renderer2.assert_(request=request)
+
+ def test_testing_add_renderer_explicitrenderer(self):
+ config = self._makeOne(autocommit=True)
+
+ class E(Exception):
+ pass
+
+ def renderer(kw, system):
+ self.assertEqual(kw, {'foo': 1, 'bar': 2})
+ raise E
+
+ renderer = config.testing_add_renderer('templates/foo.pt', renderer)
+ from pyramid.renderers import render_to_response
+
+ # must provide request to pass in registry (this is a functest)
+ request = DummyRequest()
+ request.registry = config.registry
+ try:
+ render_to_response(
+ 'templates/foo.pt', {'foo': 1, 'bar': 2}, request=request
+ )
+ except E:
+ pass
+ else: # pragma: no cover
+ raise AssertionError
+
+ def test_testing_add_template(self):
+ config = self._makeOne(autocommit=True)
+ renderer = config.testing_add_template('templates/foo.pt')
+ from pyramid.testing import DummyTemplateRenderer
+
+ self.assertTrue(isinstance(renderer, DummyTemplateRenderer))
+ from pyramid.renderers import render_to_response
+
+ # must provide request to pass in registry (this is a functest)
+ request = DummyRequest()
+ request.registry = config.registry
+ render_to_response(
+ 'templates/foo.pt', dict(foo=1, bar=2), request=request
+ )
+ renderer.assert_(foo=1)
+ renderer.assert_(bar=2)
+ renderer.assert_(request=request)
+
+
+@implementer(IDummy)
+class DummyEvent:
+ pass
+
+
+class DummyRequest(AuthenticationAPIMixin, AuthorizationAPIMixin):
+ def __init__(self, environ=None):
+ if environ is None:
+ environ = {}
+ self.environ = environ
diff --git a/tests/test_config/test_tweens.py b/tests/test_config/test_tweens.py
new file mode 100644
index 000000000..805310c9a
--- /dev/null
+++ b/tests/test_config/test_tweens.py
@@ -0,0 +1,484 @@
+import unittest
+
+from . import dummy_tween_factory
+from . import dummy_tween_factory2
+
+from pyramid.exceptions import ConfigurationConflictError
+
+
+class TestTweensConfiguratorMixin(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_add_tweens_names_distinct(self):
+ from pyramid.interfaces import ITweens
+ from pyramid.tweens import excview_tween_factory
+
+ def factory1(handler, registry): # pragma: no cover
+ return handler
+
+ def factory2(handler, registry): # pragma: no cover
+ return handler
+
+ config = self._makeOne()
+ config.add_tween('tests.test_config.dummy_tween_factory')
+ config.add_tween('tests.test_config.dummy_tween_factory2')
+ config.commit()
+ tweens = config.registry.queryUtility(ITweens)
+ implicit = tweens.implicit()
+ self.assertEqual(
+ implicit,
+ [
+ (
+ 'tests.test_config.dummy_tween_factory2',
+ dummy_tween_factory2,
+ ),
+ ('tests.test_config.dummy_tween_factory', dummy_tween_factory),
+ (
+ 'pyramid.tweens.excview_tween_factory',
+ excview_tween_factory,
+ ),
+ ],
+ )
+
+ def test_add_tweens_names_with_underover(self):
+ from pyramid.interfaces import ITweens
+ from pyramid.tweens import excview_tween_factory
+ from pyramid.tweens import MAIN
+
+ config = self._makeOne()
+ config.add_tween('tests.test_config.dummy_tween_factory', over=MAIN)
+ config.add_tween(
+ 'tests.test_config.dummy_tween_factory2',
+ over=MAIN,
+ under='tests.test_config.dummy_tween_factory',
+ )
+ config.commit()
+ tweens = config.registry.queryUtility(ITweens)
+ implicit = tweens.implicit()
+ self.assertEqual(
+ implicit,
+ [
+ (
+ 'pyramid.tweens.excview_tween_factory',
+ excview_tween_factory,
+ ),
+ ('tests.test_config.dummy_tween_factory', dummy_tween_factory),
+ (
+ 'tests.test_config.dummy_tween_factory2',
+ dummy_tween_factory2,
+ ),
+ ],
+ )
+
+ def test_add_tweens_names_with_under_nonstringoriter(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.add_tween,
+ 'tests.test_config.dummy_tween_factory',
+ under=False,
+ )
+
+ def test_add_tweens_names_with_over_nonstringoriter(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.add_tween,
+ 'tests.test_config.dummy_tween_factory',
+ over=False,
+ )
+
+ def test_add_tween_dottedname(self):
+ from pyramid.interfaces import ITweens
+ from pyramid.tweens import excview_tween_factory
+
+ config = self._makeOne()
+ config.add_tween('tests.test_config.dummy_tween_factory')
+ config.commit()
+ tweens = config.registry.queryUtility(ITweens)
+ self.assertEqual(
+ tweens.implicit(),
+ [
+ ('tests.test_config.dummy_tween_factory', dummy_tween_factory),
+ (
+ 'pyramid.tweens.excview_tween_factory',
+ excview_tween_factory,
+ ),
+ ],
+ )
+
+ def test_add_tween_instance(self):
+ from pyramid.exceptions import ConfigurationError
+
+ class ATween(object):
+ pass
+
+ atween = ATween()
+ config = self._makeOne()
+ self.assertRaises(ConfigurationError, config.add_tween, atween)
+
+ def test_add_tween_unsuitable(self):
+ from pyramid.exceptions import ConfigurationError
+ import tests.test_config
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError, config.add_tween, tests.test_config
+ )
+
+ def test_add_tween_name_ingress(self):
+ from pyramid.exceptions import ConfigurationError
+ from pyramid.tweens import INGRESS
+
+ config = self._makeOne()
+ self.assertRaises(ConfigurationError, config.add_tween, INGRESS)
+
+ def test_add_tween_name_main(self):
+ from pyramid.exceptions import ConfigurationError
+ from pyramid.tweens import MAIN
+
+ config = self._makeOne()
+ self.assertRaises(ConfigurationError, config.add_tween, MAIN)
+
+ def test_add_tweens_conflict(self):
+ config = self._makeOne()
+ config.add_tween('tests.test_config.dummy_tween_factory')
+ config.add_tween('tests.test_config.dummy_tween_factory')
+ self.assertRaises(ConfigurationConflictError, config.commit)
+
+ def test_add_tween_over_ingress(self):
+ from pyramid.exceptions import ConfigurationError
+ from pyramid.tweens import INGRESS
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.add_tween,
+ 'tests.test_config.dummy_tween_factory',
+ over=INGRESS,
+ )
+
+ def test_add_tween_over_ingress_iterable(self):
+ from pyramid.exceptions import ConfigurationError
+ from pyramid.tweens import INGRESS
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.add_tween,
+ 'tests.test_config.dummy_tween_factory',
+ over=('a', INGRESS),
+ )
+
+ def test_add_tween_under_main(self):
+ from pyramid.exceptions import ConfigurationError
+ from pyramid.tweens import MAIN
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.add_tween,
+ 'tests.test_config.dummy_tween_factory',
+ under=MAIN,
+ )
+
+ def test_add_tween_under_main_iterable(self):
+ from pyramid.exceptions import ConfigurationError
+ from pyramid.tweens import MAIN
+
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError,
+ config.add_tween,
+ 'tests.test_config.dummy_tween_factory',
+ under=('a', MAIN),
+ )
+
+
+class TestTweens(unittest.TestCase):
+ def _makeOne(self):
+ from pyramid.config.tweens import Tweens
+
+ return Tweens()
+
+ def test_add_explicit(self):
+ tweens = self._makeOne()
+ tweens.add_explicit('name', 'factory')
+ self.assertEqual(tweens.explicit, [('name', 'factory')])
+ tweens.add_explicit('name2', 'factory2')
+ self.assertEqual(
+ tweens.explicit, [('name', 'factory'), ('name2', 'factory2')]
+ )
+
+ def test_add_implicit(self):
+ tweens = self._makeOne()
+ tweens.add_implicit('name', 'factory')
+ tweens.add_implicit('name2', 'factory2')
+ self.assertEqual(
+ tweens.sorter.sorted(),
+ [('name2', 'factory2'), ('name', 'factory')],
+ )
+
+ def test___call___explicit(self):
+ tweens = self._makeOne()
+
+ def factory1(handler, registry):
+ return handler
+
+ def factory2(handler, registry):
+ return '123'
+
+ tweens.explicit = [('name', factory1), ('name', factory2)]
+ self.assertEqual(tweens(None, None), '123')
+
+ def test___call___implicit(self):
+ tweens = self._makeOne()
+
+ def factory1(handler, registry):
+ return handler
+
+ def factory2(handler, registry):
+ return '123'
+
+ tweens.add_implicit('name2', factory2)
+ tweens.add_implicit('name1', factory1)
+ self.assertEqual(tweens(None, None), '123')
+
+ def test_implicit_ordering_1(self):
+ tweens = self._makeOne()
+ tweens.add_implicit('name1', 'factory1')
+ tweens.add_implicit('name2', 'factory2')
+ self.assertEqual(
+ tweens.implicit(), [('name2', 'factory2'), ('name1', 'factory1')]
+ )
+
+ def test_implicit_ordering_2(self):
+ from pyramid.tweens import MAIN
+
+ tweens = self._makeOne()
+ tweens.add_implicit('name1', 'factory1')
+ tweens.add_implicit('name2', 'factory2', over=MAIN)
+ self.assertEqual(
+ tweens.implicit(), [('name1', 'factory1'), ('name2', 'factory2')]
+ )
+
+ def test_implicit_ordering_3(self):
+ from pyramid.tweens import MAIN
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('auth', 'auth_factory', under='browserid')
+ add('dbt', 'dbt_factory')
+ add('retry', 'retry_factory', over='txnmgr', under='exceptionview')
+ add('browserid', 'browserid_factory')
+ add('txnmgr', 'txnmgr_factory', under='exceptionview')
+ add('exceptionview', 'excview_factory', over=MAIN)
+ self.assertEqual(
+ tweens.implicit(),
+ [
+ ('browserid', 'browserid_factory'),
+ ('auth', 'auth_factory'),
+ ('dbt', 'dbt_factory'),
+ ('exceptionview', 'excview_factory'),
+ ('retry', 'retry_factory'),
+ ('txnmgr', 'txnmgr_factory'),
+ ],
+ )
+
+ def test_implicit_ordering_4(self):
+ from pyramid.tweens import MAIN
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('exceptionview', 'excview_factory', over=MAIN)
+ add('auth', 'auth_factory', under='browserid')
+ add('retry', 'retry_factory', over='txnmgr', under='exceptionview')
+ add('browserid', 'browserid_factory')
+ add('txnmgr', 'txnmgr_factory', under='exceptionview')
+ add('dbt', 'dbt_factory')
+ self.assertEqual(
+ tweens.implicit(),
+ [
+ ('dbt', 'dbt_factory'),
+ ('browserid', 'browserid_factory'),
+ ('auth', 'auth_factory'),
+ ('exceptionview', 'excview_factory'),
+ ('retry', 'retry_factory'),
+ ('txnmgr', 'txnmgr_factory'),
+ ],
+ )
+
+ def test_implicit_ordering_5(self):
+ from pyramid.tweens import MAIN, INGRESS
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('exceptionview', 'excview_factory', over=MAIN)
+ add('auth', 'auth_factory', under=INGRESS)
+ add('retry', 'retry_factory', over='txnmgr', under='exceptionview')
+ add('browserid', 'browserid_factory', under=INGRESS)
+ add('txnmgr', 'txnmgr_factory', under='exceptionview', over=MAIN)
+ add('dbt', 'dbt_factory')
+ self.assertEqual(
+ tweens.implicit(),
+ [
+ ('dbt', 'dbt_factory'),
+ ('browserid', 'browserid_factory'),
+ ('auth', 'auth_factory'),
+ ('exceptionview', 'excview_factory'),
+ ('retry', 'retry_factory'),
+ ('txnmgr', 'txnmgr_factory'),
+ ],
+ )
+
+ def test_implicit_ordering_missing_over_partial(self):
+ from pyramid.exceptions import ConfigurationError
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('dbt', 'dbt_factory')
+ add('auth', 'auth_factory', under='browserid')
+ add('retry', 'retry_factory', over='txnmgr', under='exceptionview')
+ add('browserid', 'browserid_factory')
+ self.assertRaises(ConfigurationError, tweens.implicit)
+
+ def test_implicit_ordering_missing_under_partial(self):
+ from pyramid.exceptions import ConfigurationError
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('dbt', 'dbt_factory')
+ add('auth', 'auth_factory', under='txnmgr')
+ add('retry', 'retry_factory', over='dbt', under='exceptionview')
+ add('browserid', 'browserid_factory')
+ self.assertRaises(ConfigurationError, tweens.implicit)
+
+ def test_implicit_ordering_missing_over_and_under_partials(self):
+ from pyramid.exceptions import ConfigurationError
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('dbt', 'dbt_factory')
+ add('auth', 'auth_factory', under='browserid')
+ add('retry', 'retry_factory', over='foo', under='txnmgr')
+ add('browserid', 'browserid_factory')
+ self.assertRaises(ConfigurationError, tweens.implicit)
+
+ def test_implicit_ordering_missing_over_partial_with_fallback(self):
+ from pyramid.tweens import MAIN
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('exceptionview', 'excview_factory', over=MAIN)
+ add('auth', 'auth_factory', under='browserid')
+ add(
+ 'retry',
+ 'retry_factory',
+ over=('txnmgr', MAIN),
+ under='exceptionview',
+ )
+ add('browserid', 'browserid_factory')
+ add('dbt', 'dbt_factory')
+ self.assertEqual(
+ tweens.implicit(),
+ [
+ ('dbt', 'dbt_factory'),
+ ('browserid', 'browserid_factory'),
+ ('auth', 'auth_factory'),
+ ('exceptionview', 'excview_factory'),
+ ('retry', 'retry_factory'),
+ ],
+ )
+
+ def test_implicit_ordering_missing_under_partial_with_fallback(self):
+ from pyramid.tweens import MAIN
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('exceptionview', 'excview_factory', over=MAIN)
+ add('auth', 'auth_factory', under=('txnmgr', 'browserid'))
+ add('retry', 'retry_factory', under='exceptionview')
+ add('browserid', 'browserid_factory')
+ add('dbt', 'dbt_factory')
+ self.assertEqual(
+ tweens.implicit(),
+ [
+ ('dbt', 'dbt_factory'),
+ ('browserid', 'browserid_factory'),
+ ('auth', 'auth_factory'),
+ ('exceptionview', 'excview_factory'),
+ ('retry', 'retry_factory'),
+ ],
+ )
+
+ def test_implicit_ordering_with_partial_fallbacks(self):
+ from pyramid.tweens import MAIN
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('exceptionview', 'excview_factory', over=('wontbethere', MAIN))
+ add('retry', 'retry_factory', under='exceptionview')
+ add('browserid', 'browserid_factory', over=('wont2', 'exceptionview'))
+ self.assertEqual(
+ tweens.implicit(),
+ [
+ ('browserid', 'browserid_factory'),
+ ('exceptionview', 'excview_factory'),
+ ('retry', 'retry_factory'),
+ ],
+ )
+
+ def test_implicit_ordering_with_multiple_matching_fallbacks(self):
+ from pyramid.tweens import MAIN
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('exceptionview', 'excview_factory', over=MAIN)
+ add('retry', 'retry_factory', under='exceptionview')
+ add('browserid', 'browserid_factory', over=('retry', 'exceptionview'))
+ self.assertEqual(
+ tweens.implicit(),
+ [
+ ('browserid', 'browserid_factory'),
+ ('exceptionview', 'excview_factory'),
+ ('retry', 'retry_factory'),
+ ],
+ )
+
+ def test_implicit_ordering_with_missing_fallbacks(self):
+ from pyramid.exceptions import ConfigurationError
+ from pyramid.tweens import MAIN
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('exceptionview', 'excview_factory', over=MAIN)
+ add('retry', 'retry_factory', under='exceptionview')
+ add('browserid', 'browserid_factory', over=('txnmgr', 'auth'))
+ self.assertRaises(ConfigurationError, tweens.implicit)
+
+ def test_implicit_ordering_conflict_direct(self):
+ from pyramid.exceptions import CyclicDependencyError
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('browserid', 'browserid_factory')
+ add('auth', 'auth_factory', over='browserid', under='browserid')
+ self.assertRaises(CyclicDependencyError, tweens.implicit)
+
+ def test_implicit_ordering_conflict_indirect(self):
+ from pyramid.exceptions import CyclicDependencyError
+
+ tweens = self._makeOne()
+ add = tweens.add_implicit
+ add('browserid', 'browserid_factory')
+ add('auth', 'auth_factory', over='browserid')
+ add('dbt', 'dbt_factory', under='browserid', over='auth')
+ self.assertRaises(CyclicDependencyError, tweens.implicit)
diff --git a/tests/test_config/test_views.py b/tests/test_config/test_views.py
new file mode 100644
index 000000000..b72b9b36a
--- /dev/null
+++ b/tests/test_config/test_views.py
@@ -0,0 +1,4360 @@
+import os
+import unittest
+from zope.interface import implementer
+
+from pyramid import testing
+from pyramid.compat import im_func, text_
+from pyramid.exceptions import ConfigurationError
+from pyramid.exceptions import ConfigurationExecutionError
+from pyramid.exceptions import ConfigurationConflictError
+from pyramid.interfaces import IResponse, IRequest, IMultiView
+
+from . import IDummy
+from . import dummy_view
+
+
+class TestViewsConfigurationMixin(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+
+ config = Configurator(*arg, **kw)
+ config.set_default_csrf_options(require_csrf=False)
+ return config
+
+ def _getViewCallable(
+ self,
+ config,
+ ctx_iface=None,
+ exc_iface=None,
+ request_iface=None,
+ name='',
+ ):
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IExceptionViewClassifier
+
+ if exc_iface:
+ classifier = IExceptionViewClassifier
+ ctx_iface = exc_iface
+ else:
+ classifier = IViewClassifier
+ if ctx_iface is None:
+ ctx_iface = Interface
+ if request_iface is None:
+ request_iface = IRequest
+ return config.registry.adapters.lookup(
+ (classifier, request_iface, ctx_iface),
+ IView,
+ name=name,
+ default=None,
+ )
+
+ def _registerRenderer(self, config, name='.txt'):
+ from pyramid.interfaces import IRendererFactory
+
+ class Renderer:
+ def __init__(self, info):
+ self.__class__.info = info
+
+ def __call__(self, *arg):
+ return b'Hello!'
+
+ config.registry.registerUtility(Renderer, IRendererFactory, name=name)
+ return Renderer
+
+ def _makeRequest(self, config):
+ request = DummyRequest()
+ request.registry = config.registry
+ return request
+
+ def _assertNotFound(self, wrapper, *arg):
+ from pyramid.httpexceptions import HTTPNotFound
+
+ self.assertRaises(HTTPNotFound, wrapper, *arg)
+
+ def _getRouteRequestIface(self, config, name):
+ from pyramid.interfaces import IRouteRequest
+
+ iface = config.registry.getUtility(IRouteRequest, name)
+ return iface
+
+ def _assertRoute(self, config, name, path, num_predicates=0):
+ from pyramid.interfaces import IRoutesMapper
+
+ mapper = config.registry.getUtility(IRoutesMapper)
+ routes = mapper.get_routes()
+ route = routes[0]
+ self.assertEqual(len(routes), 1)
+ self.assertEqual(route.name, name)
+ self.assertEqual(route.path, path)
+ self.assertEqual(len(routes[0].predicates), num_predicates)
+ return route
+
+ def test_add_view_view_callable_None_no_renderer(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(ConfigurationError, config.add_view)
+
+ def test_add_view_with_request_type_and_route_name(self):
+ config = self._makeOne(autocommit=True)
+ view = lambda *arg: 'OK'
+ self.assertRaises(
+ ConfigurationError,
+ config.add_view,
+ view,
+ '',
+ None,
+ None,
+ True,
+ True,
+ )
+
+ def test_add_view_with_request_type(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import directlyProvides
+ from pyramid.interfaces import IRequest
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view,
+ request_type='pyramid.interfaces.IRequest',
+ renderer=null_renderer,
+ )
+ wrapper = self._getViewCallable(config)
+ request = DummyRequest()
+ self._assertNotFound(wrapper, None, request)
+ directlyProvides(request, IRequest)
+ result = wrapper(None, request)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_view_callable_None_with_renderer(self):
+ config = self._makeOne(autocommit=True)
+ self._registerRenderer(config, name='dummy')
+ config.add_view(renderer='dummy')
+ view = self._getViewCallable(config)
+ self.assertTrue(b'Hello!' in view(None, None).body)
+
+ def test_add_view_with_tmpl_renderer_factory_introspector_missing(self):
+ config = self._makeOne(autocommit=True)
+ config.introspection = False
+ config.introspector = None
+ config.add_view(renderer='dummy.pt')
+ view = self._getViewCallable(config)
+ self.assertRaises(ValueError, view, None, None)
+
+ def test_add_view_with_tmpl_renderer_factory_no_renderer_factory(self):
+ config = self._makeOne(autocommit=True)
+ introspector = DummyIntrospector()
+ config.introspector = introspector
+ config.add_view(renderer='dummy.pt')
+ self.assertFalse(
+ ('renderer factories', '.pt') in introspector.related[-1]
+ )
+ view = self._getViewCallable(config)
+ self.assertRaises(ValueError, view, None, None)
+
+ def test_add_view_with_tmpl_renderer_factory_with_renderer_factory(self):
+ config = self._makeOne(autocommit=True)
+ introspector = DummyIntrospector(True)
+ config.introspector = introspector
+
+ def dummy_factory(helper):
+ return lambda val, system_vals: 'Hello!'
+
+ config.add_renderer('.pt', dummy_factory)
+ config.add_view(renderer='dummy.pt')
+ self.assertTrue(
+ ('renderer factories', '.pt') in introspector.related[-1]
+ )
+ view = self._getViewCallable(config)
+ self.assertTrue(b'Hello!' in view(None, None).body)
+
+ def test_add_view_wrapped_view_is_decorated(self):
+ def view(request): # request-only wrapper
+ """ """
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view)
+ wrapper = self._getViewCallable(config)
+ self.assertEqual(wrapper.__module__, view.__module__)
+ self.assertEqual(wrapper.__name__, view.__name__)
+ self.assertEqual(wrapper.__doc__, view.__doc__)
+ self.assertEqual(
+ wrapper.__discriminator__(None, None).resolve()[0], 'view'
+ )
+
+ def test_add_view_view_callable_dottedname(self):
+ from pyramid.renderers import null_renderer
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view='tests.test_config.dummy_view', renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(config)
+ self.assertEqual(wrapper(None, None), 'OK')
+
+ def test_add_view_with_function_callable(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ result = wrapper(None, None)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_with_function_callable_requestonly(self):
+ from pyramid.renderers import null_renderer
+
+ def view(request):
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ result = wrapper(None, None)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_with_name(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, name='abc', renderer=null_renderer)
+ wrapper = self._getViewCallable(config, name='abc')
+ result = wrapper(None, None)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_with_name_unicode(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ name = text_(b'La Pe\xc3\xb1a', 'utf-8')
+ config.add_view(view=view, name=name, renderer=null_renderer)
+ wrapper = self._getViewCallable(config, name=name)
+ result = wrapper(None, None)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_with_decorator(self):
+ from pyramid.renderers import null_renderer
+
+ def view(request):
+ """ ABC """
+ return 'OK'
+
+ def view_wrapper(fn):
+ def inner(context, request):
+ return fn(context, request)
+
+ return inner
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view, decorator=view_wrapper, renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(config)
+ self.assertFalse(wrapper is view)
+ self.assertEqual(wrapper.__doc__, view.__doc__)
+ result = wrapper(None, None)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_with_decorator_tuple(self):
+ from pyramid.renderers import null_renderer
+
+ def view(request):
+ """ ABC """
+ return 'OK'
+
+ def view_wrapper1(fn):
+ def inner(context, request):
+ return 'wrapped1' + fn(context, request)
+
+ return inner
+
+ def view_wrapper2(fn):
+ def inner(context, request):
+ return 'wrapped2' + fn(context, request)
+
+ return inner
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view,
+ decorator=(view_wrapper2, view_wrapper1),
+ renderer=null_renderer,
+ )
+ wrapper = self._getViewCallable(config)
+ self.assertFalse(wrapper is view)
+ self.assertEqual(wrapper.__doc__, view.__doc__)
+ result = wrapper(None, None)
+ self.assertEqual(result, 'wrapped2wrapped1OK')
+
+ def test_add_view_with_http_cache(self):
+ import datetime
+ from pyramid.response import Response
+
+ response = Response('OK')
+
+ def view(request):
+ """ ABC """
+ return response
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, http_cache=(86400, {'public': True}))
+ wrapper = self._getViewCallable(config)
+ self.assertFalse(wrapper is view)
+ self.assertEqual(wrapper.__doc__, view.__doc__)
+ request = testing.DummyRequest()
+ when = datetime.datetime.utcnow() + datetime.timedelta(days=1)
+ result = wrapper(None, request)
+ self.assertEqual(result, response)
+ headers = dict(response.headerlist)
+ self.assertEqual(headers['Cache-Control'], 'max-age=86400, public')
+ expires = parse_httpdate(headers['Expires'])
+ assert_similar_datetime(expires, when)
+
+ def test_add_view_as_instance(self):
+ from pyramid.renderers import null_renderer
+
+ class AView:
+ def __call__(self, context, request):
+ """ """
+ return 'OK'
+
+ view = AView()
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ result = wrapper(None, None)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_as_instancemethod(self):
+ from pyramid.renderers import null_renderer
+
+ class View:
+ def index(self, context, request):
+ return 'OK'
+
+ view = View()
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view.index, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ result = wrapper(None, None)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_as_instancemethod_requestonly(self):
+ from pyramid.renderers import null_renderer
+
+ class View:
+ def index(self, request):
+ return 'OK'
+
+ view = View()
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view.index, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ result = wrapper(None, None)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_as_instance_requestonly(self):
+ from pyramid.renderers import null_renderer
+
+ class AView:
+ def __call__(self, request):
+ """ """
+ return 'OK'
+
+ view = AView()
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ result = wrapper(None, None)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_as_oldstyle_class(self):
+ from pyramid.renderers import null_renderer
+
+ class view:
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ def __call__(self):
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ result = wrapper(None, request)
+ self.assertEqual(result, 'OK')
+ self.assertEqual(request.__view__.__class__, view)
+
+ def test_add_view_as_oldstyle_class_requestonly(self):
+ from pyramid.renderers import null_renderer
+
+ class view:
+ def __init__(self, request):
+ self.request = request
+
+ def __call__(self):
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+
+ request = self._makeRequest(config)
+ result = wrapper(None, request)
+ self.assertEqual(result, 'OK')
+ self.assertEqual(request.__view__.__class__, view)
+
+ def test_add_view_context_as_class(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+
+ view = lambda *arg: 'OK'
+
+ class Foo:
+ pass
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(context=Foo, view=view, renderer=null_renderer)
+ foo = implementedBy(Foo)
+ wrapper = self._getViewCallable(config, foo)
+ self.assertEqual(wrapper, view)
+
+ def test_add_view_context_as_iface(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(context=IDummy, view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config, IDummy)
+ self.assertEqual(wrapper, view)
+
+ def test_add_view_context_as_dottedname(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ context='tests.test_config.IDummy',
+ view=view,
+ renderer=null_renderer,
+ )
+ wrapper = self._getViewCallable(config, IDummy)
+ self.assertEqual(wrapper, view)
+
+ def test_add_view_for__as_dottedname(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ for_='tests.test_config.IDummy', view=view, renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(config, IDummy)
+ self.assertEqual(wrapper, view)
+
+ def test_add_view_for_as_class(self):
+ # ``for_`` is older spelling for ``context``
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+
+ view = lambda *arg: 'OK'
+
+ class Foo:
+ pass
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(for_=Foo, view=view, renderer=null_renderer)
+ foo = implementedBy(Foo)
+ wrapper = self._getViewCallable(config, foo)
+ self.assertEqual(wrapper, view)
+
+ def test_add_view_for_as_iface(self):
+ # ``for_`` is older spelling for ``context``
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(for_=IDummy, view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config, IDummy)
+ self.assertEqual(wrapper, view)
+
+ def test_add_view_context_trumps_for(self):
+ # ``for_`` is older spelling for ``context``
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+
+ class Foo:
+ pass
+
+ config.add_view(
+ context=IDummy, for_=Foo, view=view, renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(config, IDummy)
+ self.assertEqual(wrapper, view)
+
+ def test_add_view_register_secured_view(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import ISecuredView
+ from pyramid.interfaces import IViewClassifier
+
+ view = lambda *arg: 'OK'
+ view.__call_permissive__ = view
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, renderer=null_renderer)
+ wrapper = config.registry.adapters.lookup(
+ (IViewClassifier, IRequest, Interface),
+ ISecuredView,
+ name='',
+ default=None,
+ )
+ self.assertEqual(wrapper, view)
+
+ def test_add_view_exception_register_secured_view(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IExceptionViewClassifier
+
+ view = lambda *arg: 'OK'
+ view.__call_permissive__ = view
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view, context=RuntimeError, renderer=null_renderer
+ )
+ wrapper = config.registry.adapters.lookup(
+ (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IView,
+ name='',
+ default=None,
+ )
+ self.assertEqual(wrapper, view)
+
+ def test_add_view_same_phash_overrides_existing_single_view(self):
+ from pyramid.renderers import null_renderer
+ from hashlib import md5
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IMultiView
+
+ phash = md5()
+ phash.update(b'xhr = True')
+ view = lambda *arg: 'NOT OK'
+ view.__phash__ = phash.hexdigest()
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, Interface), IView, name=''
+ )
+
+ def newview(context, request):
+ return 'OK'
+
+ config.add_view(view=newview, xhr=True, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ self.assertFalse(IMultiView.providedBy(wrapper))
+ request = DummyRequest()
+ request.is_xhr = True
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_exc_same_phash_overrides_existing_single_view(self):
+ from pyramid.renderers import null_renderer
+ from hashlib import md5
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IExceptionViewClassifier
+ from pyramid.interfaces import IMultiView
+
+ phash = md5()
+ phash.update(b'xhr = True')
+ view = lambda *arg: 'NOT OK'
+ view.__phash__ = phash.hexdigest()
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view,
+ (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IView,
+ name='',
+ )
+
+ def newview(context, request):
+ return 'OK'
+
+ config.add_view(
+ view=newview,
+ xhr=True,
+ context=RuntimeError,
+ renderer=null_renderer,
+ )
+ wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(RuntimeError)
+ )
+ self.assertFalse(IMultiView.providedBy(wrapper))
+ request = DummyRequest()
+ request.is_xhr = True
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_default_phash_overrides_no_phash(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IMultiView
+
+ view = lambda *arg: 'NOT OK'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, Interface), IView, name=''
+ )
+
+ def newview(context, request):
+ return 'OK'
+
+ config.add_view(view=newview, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ self.assertFalse(IMultiView.providedBy(wrapper))
+ request = DummyRequest()
+ request.is_xhr = True
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_exc_default_phash_overrides_no_phash(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IExceptionViewClassifier
+ from pyramid.interfaces import IMultiView
+
+ view = lambda *arg: 'NOT OK'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view,
+ (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IView,
+ name='',
+ )
+
+ def newview(context, request):
+ return 'OK'
+
+ config.add_view(
+ view=newview, context=RuntimeError, renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(RuntimeError)
+ )
+ self.assertFalse(IMultiView.providedBy(wrapper))
+ request = DummyRequest()
+ request.is_xhr = True
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_default_phash_overrides_default_phash(self):
+ from pyramid.config.predicates import DEFAULT_PHASH
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IMultiView
+
+ view = lambda *arg: 'NOT OK'
+ view.__phash__ = DEFAULT_PHASH
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, Interface), IView, name=''
+ )
+
+ def newview(context, request):
+ return 'OK'
+
+ config.add_view(view=newview, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ self.assertFalse(IMultiView.providedBy(wrapper))
+ request = DummyRequest()
+ request.is_xhr = True
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_exc_default_phash_overrides_default_phash(self):
+ from pyramid.config.predicates import DEFAULT_PHASH
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IExceptionViewClassifier
+ from pyramid.interfaces import IMultiView
+
+ view = lambda *arg: 'NOT OK'
+ view.__phash__ = DEFAULT_PHASH
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view,
+ (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IView,
+ name='',
+ )
+
+ def newview(context, request):
+ return 'OK'
+
+ config.add_view(
+ view=newview, context=RuntimeError, renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(RuntimeError)
+ )
+ self.assertFalse(IMultiView.providedBy(wrapper))
+ request = DummyRequest()
+ request.is_xhr = True
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_multiview_replaces_existing_view(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IMultiView
+
+ view = lambda *arg: 'OK'
+ view.__phash__ = 'abc'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, Interface), IView, name=''
+ )
+ config.add_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ self.assertEqual(wrapper(None, None), 'OK')
+
+ def test_add_view_exc_multiview_replaces_existing_view(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IExceptionViewClassifier
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IMultiView
+
+ view = lambda *arg: 'OK'
+ view.__phash__ = 'abc'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view,
+ (IViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IView,
+ name='',
+ )
+ config.registry.registerAdapter(
+ view,
+ (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IView,
+ name='',
+ )
+ config.add_view(
+ view=view, context=RuntimeError, renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(RuntimeError)
+ )
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ self.assertEqual(wrapper(None, None), 'OK')
+
+ def test_add_view_multiview_replaces_existing_securedview(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import ISecuredView
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+
+ view = lambda *arg: 'OK'
+ view.__phash__ = 'abc'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, Interface), ISecuredView, name=''
+ )
+ config.add_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ self.assertEqual(wrapper(None, None), 'OK')
+
+ def test_add_view_exc_multiview_replaces_existing_securedview(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import ISecuredView
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IExceptionViewClassifier
+
+ view = lambda *arg: 'OK'
+ view.__phash__ = 'abc'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view,
+ (IViewClassifier, IRequest, implementedBy(RuntimeError)),
+ ISecuredView,
+ name='',
+ )
+ config.registry.registerAdapter(
+ view,
+ (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
+ ISecuredView,
+ name='',
+ )
+ config.add_view(
+ view=view, context=RuntimeError, renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(RuntimeError)
+ )
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ self.assertEqual(wrapper(None, None), 'OK')
+
+ def test_add_view_with_accept_multiview_replaces_existing_view(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+
+ def view(context, request):
+ return 'OK'
+
+ def view2(context, request):
+ return 'OK2'
+
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, Interface), IView, name=''
+ )
+ config.add_view(view=view2, accept='text/html', renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ self.assertEqual(len(wrapper.views), 1)
+ self.assertEqual(len(wrapper.media_views), 1)
+ self.assertEqual(wrapper(None, None), 'OK')
+ request = DummyRequest()
+ request.accept = DummyAccept('text/html', 'text/html')
+ self.assertEqual(wrapper(None, request), 'OK2')
+
+ def test_add_view_mixed_case_replaces_existing_view(self):
+ from pyramid.renderers import null_renderer
+
+ def view(context, request):
+ return 'OK'
+
+ def view2(context, request): # pragma: no cover
+ return 'OK2'
+
+ def view3(context, request):
+ return 'OK3'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, renderer=null_renderer)
+ config.add_view(view=view2, accept='text/html', renderer=null_renderer)
+ config.add_view(view=view3, accept='text/HTML', renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ self.assertEqual(len(wrapper.media_views.items()), 1)
+ self.assertFalse('text/HTML' in wrapper.media_views)
+ self.assertEqual(wrapper(None, None), 'OK')
+ request = DummyRequest()
+ request.accept = DummyAccept('text/html', 'text/html')
+ self.assertEqual(wrapper(None, request), 'OK3')
+
+ def test_add_views_with_accept_multiview_replaces_existing(self):
+ from pyramid.renderers import null_renderer
+
+ def view(context, request):
+ return 'OK'
+
+ def view2(context, request): # pragma: no cover
+ return 'OK2'
+
+ def view3(context, request):
+ return 'OK3'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, renderer=null_renderer)
+ config.add_view(view=view2, accept='text/html', renderer=null_renderer)
+ config.add_view(view=view3, accept='text/html', renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ self.assertEqual(len(wrapper.media_views['text/html']), 1)
+ self.assertEqual(wrapper(None, None), 'OK')
+ request = DummyRequest()
+ request.accept = DummyAccept('text/html', 'text/html')
+ self.assertEqual(wrapper(None, request), 'OK3')
+
+ def test_add_view_exc_with_accept_multiview_replaces_existing_view(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IExceptionViewClassifier
+
+ def view(context, request):
+ return 'OK'
+
+ def view2(context, request):
+ return 'OK2'
+
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view,
+ (IViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IView,
+ name='',
+ )
+ config.registry.registerAdapter(
+ view,
+ (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IView,
+ name='',
+ )
+ config.add_view(
+ view=view2,
+ accept='text/html',
+ context=RuntimeError,
+ renderer=null_renderer,
+ )
+ wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(RuntimeError)
+ )
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ self.assertEqual(len(wrapper.views), 1)
+ self.assertEqual(len(wrapper.media_views), 1)
+ self.assertEqual(wrapper(None, None), 'OK')
+ request = DummyRequest()
+ request.accept = DummyAccept('text/html', 'text/html')
+ self.assertEqual(wrapper(None, request), 'OK2')
+
+ def test_add_view_multiview_replaces_existing_view_with___accept__(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+
+ def view(context, request):
+ return 'OK'
+
+ def view2(context, request):
+ return 'OK2'
+
+ view.__accept__ = 'text/html'
+ view.__phash__ = 'abc'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, Interface), IView, name=''
+ )
+ config.add_view(view=view2, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ self.assertEqual(len(wrapper.views), 1)
+ self.assertEqual(len(wrapper.media_views), 1)
+ self.assertEqual(wrapper(None, None), 'OK2')
+ request = DummyRequest()
+ request.accept = DummyAccept('text/html')
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_exc_mulview_replaces_existing_view_with___accept__(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IExceptionViewClassifier
+
+ def view(context, request):
+ return 'OK'
+
+ def view2(context, request):
+ return 'OK2'
+
+ view.__accept__ = 'text/html'
+ view.__phash__ = 'abc'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view,
+ (IViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IView,
+ name='',
+ )
+ config.registry.registerAdapter(
+ view,
+ (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IView,
+ name='',
+ )
+ config.add_view(
+ view=view2, context=RuntimeError, renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(RuntimeError)
+ )
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ self.assertEqual(len(wrapper.views), 1)
+ self.assertEqual(len(wrapper.media_views), 1)
+ self.assertEqual(wrapper(None, None), 'OK2')
+ request = DummyRequest()
+ request.accept = DummyAccept('text/html')
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_multiview_replaces_multiview(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+
+ view = DummyMultiView()
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, Interface), IMultiView, name=''
+ )
+ view2 = lambda *arg: 'OK2'
+ config.add_view(view=view2, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ self.assertEqual(
+ [(x[0], x[2]) for x in wrapper.views], [(view2, None)]
+ )
+ self.assertEqual(wrapper(None, None), 'OK1')
+
+ def test_add_view_exc_multiview_replaces_multiviews(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IExceptionViewClassifier
+
+ hot_view = DummyMultiView()
+ exc_view = DummyMultiView()
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ hot_view,
+ (IViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IMultiView,
+ name='',
+ )
+ config.registry.registerAdapter(
+ exc_view,
+ (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IMultiView,
+ name='',
+ )
+ view2 = lambda *arg: 'OK2'
+ config.add_view(
+ view=view2, context=RuntimeError, renderer=null_renderer
+ )
+ hot_wrapper = self._getViewCallable(
+ config, ctx_iface=implementedBy(RuntimeError)
+ )
+ self.assertTrue(IMultiView.providedBy(hot_wrapper))
+ self.assertEqual(
+ [(x[0], x[2]) for x in hot_wrapper.views], [(view2, None)]
+ )
+ self.assertEqual(hot_wrapper(None, None), 'OK1')
+
+ exc_wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(RuntimeError)
+ )
+ self.assertTrue(IMultiView.providedBy(exc_wrapper))
+ self.assertEqual(
+ [(x[0], x[2]) for x in exc_wrapper.views], [(view2, None)]
+ )
+ self.assertEqual(exc_wrapper(None, None), 'OK1')
+
+ def test_add_view_exc_multiview_replaces_only_exc_multiview(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IExceptionViewClassifier
+
+ hot_view = DummyMultiView()
+ exc_view = DummyMultiView()
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ hot_view,
+ (IViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IMultiView,
+ name='',
+ )
+ config.registry.registerAdapter(
+ exc_view,
+ (IExceptionViewClassifier, IRequest, implementedBy(RuntimeError)),
+ IMultiView,
+ name='',
+ )
+ view2 = lambda *arg: 'OK2'
+ config.add_view(
+ view=view2,
+ context=RuntimeError,
+ exception_only=True,
+ renderer=null_renderer,
+ )
+ hot_wrapper = self._getViewCallable(
+ config, ctx_iface=implementedBy(RuntimeError)
+ )
+ self.assertTrue(IMultiView.providedBy(hot_wrapper))
+ self.assertEqual(len(hot_wrapper.views), 0)
+ self.assertEqual(hot_wrapper(None, None), 'OK1')
+
+ exc_wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(RuntimeError)
+ )
+ self.assertTrue(IMultiView.providedBy(exc_wrapper))
+ self.assertEqual(
+ [(x[0], x[2]) for x in exc_wrapper.views], [(view2, None)]
+ )
+ self.assertEqual(exc_wrapper(None, None), 'OK1')
+
+ def test_add_view_multiview_context_superclass_then_subclass(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+
+ class ISuper(Interface):
+ pass
+
+ class ISub(ISuper):
+ pass
+
+ view = lambda *arg: 'OK'
+ view2 = lambda *arg: 'OK2'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, ISuper), IView, name=''
+ )
+ config.add_view(view=view2, for_=ISub, renderer=null_renderer)
+ wrapper = self._getViewCallable(
+ config, ctx_iface=ISuper, request_iface=IRequest
+ )
+ self.assertFalse(IMultiView.providedBy(wrapper))
+ self.assertEqual(wrapper(None, None), 'OK')
+ wrapper = self._getViewCallable(
+ config, ctx_iface=ISub, request_iface=IRequest
+ )
+ self.assertFalse(IMultiView.providedBy(wrapper))
+ self.assertEqual(wrapper(None, None), 'OK2')
+
+ def test_add_view_multiview_exception_superclass_then_subclass(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IMultiView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IExceptionViewClassifier
+
+ class Super(Exception):
+ pass
+
+ class Sub(Super):
+ pass
+
+ view = lambda *arg: 'OK'
+ view2 = lambda *arg: 'OK2'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, Super), IView, name=''
+ )
+ config.registry.registerAdapter(
+ view, (IExceptionViewClassifier, IRequest, Super), IView, name=''
+ )
+ config.add_view(view=view2, for_=Sub, renderer=null_renderer)
+ wrapper = self._getViewCallable(
+ config, ctx_iface=implementedBy(Super), request_iface=IRequest
+ )
+ wrapper_exc_view = self._getViewCallable(
+ config, exc_iface=implementedBy(Super), request_iface=IRequest
+ )
+ self.assertEqual(wrapper_exc_view, wrapper)
+ self.assertFalse(IMultiView.providedBy(wrapper_exc_view))
+ self.assertEqual(wrapper_exc_view(None, None), 'OK')
+ wrapper = self._getViewCallable(
+ config, ctx_iface=implementedBy(Sub), request_iface=IRequest
+ )
+ wrapper_exc_view = self._getViewCallable(
+ config, exc_iface=implementedBy(Sub), request_iface=IRequest
+ )
+ self.assertEqual(wrapper_exc_view, wrapper)
+ self.assertFalse(IMultiView.providedBy(wrapper_exc_view))
+ self.assertEqual(wrapper_exc_view(None, None), 'OK2')
+
+ def test_add_view_multiview_call_ordering(self):
+ from pyramid.renderers import null_renderer as nr
+ from zope.interface import directlyProvides
+
+ def view1(context, request):
+ return 'view1'
+
+ def view2(context, request):
+ return 'view2'
+
+ def view3(context, request):
+ return 'view3'
+
+ def view4(context, request):
+ return 'view4'
+
+ def view5(context, request):
+ return 'view5'
+
+ def view6(context, request):
+ return 'view6'
+
+ def view7(context, request):
+ return 'view7'
+
+ def view8(context, request):
+ return 'view8'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view1, renderer=nr)
+ config.add_view(view=view2, request_method='POST', renderer=nr)
+ config.add_view(view=view3, request_param='param', renderer=nr)
+ config.add_view(view=view4, containment=IDummy, renderer=nr)
+ config.add_view(
+ view=view5,
+ request_method='POST',
+ request_param='param',
+ renderer=nr,
+ )
+ config.add_view(
+ view=view6, request_method='POST', containment=IDummy, renderer=nr
+ )
+ config.add_view(
+ view=view7, request_param='param', containment=IDummy, renderer=nr
+ )
+ config.add_view(
+ view=view8,
+ request_method='POST',
+ request_param='param',
+ containment=IDummy,
+ renderer=nr,
+ )
+
+ wrapper = self._getViewCallable(config)
+
+ ctx = DummyContext()
+ request = self._makeRequest(config)
+ request.method = 'GET'
+ request.params = {}
+ self.assertEqual(wrapper(ctx, request), 'view1')
+
+ ctx = DummyContext()
+ request = self._makeRequest(config)
+ request.params = {}
+ request.method = 'POST'
+ self.assertEqual(wrapper(ctx, request), 'view2')
+
+ ctx = DummyContext()
+ request = self._makeRequest(config)
+ request.params = {'param': '1'}
+ request.method = 'GET'
+ self.assertEqual(wrapper(ctx, request), 'view3')
+
+ ctx = DummyContext()
+ directlyProvides(ctx, IDummy)
+ request = self._makeRequest(config)
+ request.method = 'GET'
+ request.params = {}
+ self.assertEqual(wrapper(ctx, request), 'view4')
+
+ ctx = DummyContext()
+ request = self._makeRequest(config)
+ request.method = 'POST'
+ request.params = {'param': '1'}
+ self.assertEqual(wrapper(ctx, request), 'view5')
+
+ ctx = DummyContext()
+ directlyProvides(ctx, IDummy)
+ request = self._makeRequest(config)
+ request.params = {}
+ request.method = 'POST'
+ self.assertEqual(wrapper(ctx, request), 'view6')
+
+ ctx = DummyContext()
+ directlyProvides(ctx, IDummy)
+ request = self._makeRequest(config)
+ request.method = 'GET'
+ request.params = {'param': '1'}
+ self.assertEqual(wrapper(ctx, request), 'view7')
+
+ ctx = DummyContext()
+ directlyProvides(ctx, IDummy)
+ request = self._makeRequest(config)
+ request.method = 'POST'
+ request.params = {'param': '1'}
+ self.assertEqual(wrapper(ctx, request), 'view8')
+
+ def test_view_with_most_specific_predicate(self):
+ from pyramid.renderers import null_renderer as nr
+ from pyramid.router import Router
+
+ class OtherBase(object):
+ pass
+
+ class Int1(object):
+ pass
+
+ class Int2(object):
+ pass
+
+ class Resource(OtherBase, Int1, Int2):
+ def __init__(self, request):
+ pass
+
+ def unknown(context, request): # pragma: no cover
+ return 'unknown'
+
+ def view(context, request):
+ return 'hello'
+
+ config = self._makeOne(autocommit=True)
+ config.add_route('root', '/', factory=Resource)
+ config.add_view(unknown, route_name='root', renderer=nr)
+ config.add_view(
+ view,
+ renderer=nr,
+ route_name='root',
+ context=Int1,
+ request_method='GET',
+ )
+ config.add_view(
+ view=view,
+ renderer=nr,
+ route_name='root',
+ context=Int2,
+ request_method='POST',
+ )
+ request = self._makeRequest(config)
+ request.method = 'POST'
+ request.params = {}
+ router = Router(config.registry)
+ response = router.handle_request(request)
+ self.assertEqual(response, 'hello')
+
+ def test_view_with_most_specific_predicate_with_mismatch(self):
+ from pyramid.renderers import null_renderer as nr
+ from pyramid.router import Router
+
+ class OtherBase(object):
+ pass
+
+ class Int1(object):
+ pass
+
+ class Int2(object):
+ pass
+
+ class Resource(OtherBase, Int1, Int2):
+ def __init__(self, request):
+ pass
+
+ def unknown(context, request): # pragma: no cover
+ return 'unknown'
+
+ def view(context, request):
+ return 'hello'
+
+ config = self._makeOne(autocommit=True)
+ config.add_route('root', '/', factory=Resource)
+
+ config.add_view(
+ unknown,
+ route_name='root',
+ renderer=nr,
+ request_method=('POST',),
+ xhr=True,
+ )
+
+ config.add_view(
+ view,
+ renderer=nr,
+ route_name='root',
+ context=Int1,
+ request_method='GET',
+ )
+ config.add_view(
+ view=view,
+ renderer=nr,
+ route_name='root',
+ context=Int2,
+ request_method='POST',
+ )
+ request = self._makeRequest(config)
+ request.method = 'POST'
+ request.params = {}
+ router = Router(config.registry)
+ response = router.handle_request(request)
+ self.assertEqual(response, 'hello')
+
+ def test_add_view_multiview___discriminator__(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+
+ class IFoo(Interface):
+ pass
+
+ class IBar(Interface):
+ pass
+
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+
+ @implementer(IBar)
+ class Bar(object):
+ pass
+
+ foo = Foo()
+ bar = Bar()
+
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IMultiView
+
+ view = lambda *arg: 'OK'
+ view.__phash__ = 'abc'
+ config = self._makeOne(autocommit=True)
+ config.registry.registerAdapter(
+ view, (IViewClassifier, IRequest, Interface), IView, name=''
+ )
+ config.add_view(view=view, renderer=null_renderer, containment=IFoo)
+ config.add_view(view=view, renderer=null_renderer, containment=IBar)
+ wrapper = self._getViewCallable(config)
+ self.assertTrue(IMultiView.providedBy(wrapper))
+ request = self._makeRequest(config)
+ self.assertNotEqual(
+ wrapper.__discriminator__(foo, request),
+ wrapper.__discriminator__(bar, request),
+ )
+
+ def test_add_view_with_template_renderer(self):
+ from tests import test_config
+ from pyramid.interfaces import ISettings
+
+ class view(object):
+ def __init__(self, context, request):
+ self.request = request
+ self.context = context
+
+ def __call__(self):
+ return {'a': '1'}
+
+ config = self._makeOne(autocommit=True)
+ renderer = self._registerRenderer(config)
+ fixture = 'tests.test_config:files/minimal.txt'
+ config.introspection = False
+ config.add_view(view=view, renderer=fixture)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ result = wrapper(None, request)
+ self.assertEqual(result.body, b'Hello!')
+ settings = config.registry.queryUtility(ISettings)
+ result = renderer.info
+ self.assertEqual(result.registry, config.registry)
+ self.assertEqual(result.type, '.txt')
+ self.assertEqual(result.package, test_config)
+ self.assertEqual(result.name, fixture)
+ self.assertEqual(result.settings, settings)
+
+ def test_add_view_with_default_renderer(self):
+ class view(object):
+ def __init__(self, context, request):
+ self.request = request
+ self.context = context
+
+ def __call__(self):
+ return {'a': '1'}
+
+ config = self._makeOne(autocommit=True)
+
+ class moo(object):
+ def __init__(self, *arg, **kw):
+ pass
+
+ def __call__(self, *arg, **kw):
+ return b'moo'
+
+ config.add_renderer(None, moo)
+ config.add_view(view=view)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ result = wrapper(None, request)
+ self.assertEqual(result.body, b'moo')
+
+ def test_add_view_with_template_renderer_no_callable(self):
+ from tests import test_config
+ from pyramid.interfaces import ISettings
+
+ config = self._makeOne(autocommit=True)
+ renderer = self._registerRenderer(config)
+ fixture = 'tests.test_config:files/minimal.txt'
+ config.introspection = False
+ config.add_view(view=None, renderer=fixture)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ result = wrapper(None, request)
+ self.assertEqual(result.body, b'Hello!')
+ settings = config.registry.queryUtility(ISettings)
+ result = renderer.info
+ self.assertEqual(result.registry, config.registry)
+ self.assertEqual(result.type, '.txt')
+ self.assertEqual(result.package, test_config)
+ self.assertEqual(result.name, fixture)
+ self.assertEqual(result.settings, settings)
+
+ def test_add_view_with_request_type_as_iface(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import directlyProvides
+
+ def view(context, request):
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(request_type=IDummy, view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config, None)
+ request = self._makeRequest(config)
+ directlyProvides(request, IDummy)
+ result = wrapper(None, request)
+ self.assertEqual(result, 'OK')
+
+ def test_add_view_with_request_type_as_noniface(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne()
+ self.assertRaises(
+ ConfigurationError, config.add_view, view, '', None, None, object
+ )
+
+ def test_add_view_with_route_name(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_route('foo', '/a/b')
+ config.add_view(view=view, route_name='foo', renderer=null_renderer)
+ request_iface = self._getRouteRequestIface(config, 'foo')
+ self.assertNotEqual(request_iface, None)
+ wrapper = self._getViewCallable(config, request_iface=request_iface)
+ self.assertNotEqual(wrapper, None)
+ self.assertEqual(wrapper(None, None), 'OK')
+
+ def test_add_view_with_nonexistant_route_name(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne()
+ config.add_view(view=view, route_name='foo', renderer=null_renderer)
+ self.assertRaises(ConfigurationExecutionError, config.commit)
+
+ def test_add_view_with_route_name_exception(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_route('foo', '/a/b')
+ config.add_view(
+ view=view,
+ route_name='foo',
+ context=RuntimeError,
+ renderer=null_renderer,
+ )
+ request_iface = self._getRouteRequestIface(config, 'foo')
+ wrapper_exc_view = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(RuntimeError),
+ request_iface=request_iface,
+ )
+ self.assertNotEqual(wrapper_exc_view, None)
+ wrapper = self._getViewCallable(
+ config,
+ ctx_iface=implementedBy(RuntimeError),
+ request_iface=request_iface,
+ )
+ self.assertEqual(wrapper_exc_view, wrapper)
+ self.assertEqual(wrapper_exc_view(None, None), 'OK')
+
+ def test_add_view_with_request_method_true(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view, request_method='POST', renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.method = 'POST'
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_request_method_false(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, request_method='POST')
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.method = 'GET'
+ self._assertNotFound(wrapper, None, request)
+
+ def test_add_view_with_request_method_sequence_true(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view, request_method=('POST', 'GET'), renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.method = 'POST'
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_request_method_sequence_conflict(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne()
+ config.add_view(
+ view=view, request_method=('POST', 'GET'), renderer=null_renderer
+ )
+ config.add_view(
+ view=view, request_method=('GET', 'POST'), renderer=null_renderer
+ )
+ self.assertRaises(ConfigurationConflictError, config.commit)
+
+ def test_add_view_with_request_method_sequence_false(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, request_method=('POST', 'HEAD'))
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.method = 'GET'
+ self._assertNotFound(wrapper, None, request)
+
+ def test_add_view_with_request_method_get_implies_head(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view, request_method='GET', renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.method = 'HEAD'
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_request_param_noval_true(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, request_param='abc', renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.params = {'abc': ''}
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_request_param_noval_false(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, request_param='abc')
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.params = {}
+ self._assertNotFound(wrapper, None, request)
+
+ def test_add_view_with_request_param_val_true(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view, request_param='abc=123', renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.params = {'abc': '123'}
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_request_param_val_false(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, request_param='abc=123')
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.params = {'abc': ''}
+ self._assertNotFound(wrapper, None, request)
+
+ def test_add_view_with_xhr_true(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, xhr=True, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.is_xhr = True
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_xhr_false(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, xhr=True)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.is_xhr = False
+ self._assertNotFound(wrapper, None, request)
+
+ def test_add_view_with_header_badregex(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne()
+ config.add_view(view, header='Host:a\\')
+ self.assertRaises(ConfigurationError, config.commit)
+
+ def test_add_view_with_header_noval_match(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, header='Host', renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.headers = {'Host': 'whatever'}
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_header_noval_nomatch(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, header='Host')
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.headers = {'NotHost': 'whatever'}
+ self._assertNotFound(wrapper, None, request)
+
+ def test_add_view_with_header_val_match(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, header=r'Host:\d', renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.headers = {'Host': '1'}
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_header_val_nomatch(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, header=r'Host:\d')
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.headers = {'Host': 'abc'}
+ self._assertNotFound(wrapper, None, request)
+
+ def test_add_view_with_header_val_missing(self):
+ from pyramid.httpexceptions import HTTPNotFound
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, header=r'Host:\d')
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.headers = {'NoHost': '1'}
+ self.assertRaises(HTTPNotFound, wrapper, None, request)
+
+ def test_add_view_with_accept_match(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, accept='text/xml', renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.accept = DummyAccept('text/xml')
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_accept_nomatch(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, accept='text/xml')
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.accept = DummyAccept('text/html')
+ self._assertNotFound(wrapper, None, request)
+
+ def test_add_view_with_wildcard_accept_raises(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ValueError, lambda: config.add_view(view=view, accept='text/*')
+ )
+
+ def test_add_view_with_containment_true(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import directlyProvides
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, containment=IDummy, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ context = DummyContext()
+ directlyProvides(context, IDummy)
+ self.assertEqual(wrapper(context, None), 'OK')
+
+ def test_add_view_with_containment_false(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, containment=IDummy)
+ wrapper = self._getViewCallable(config)
+ context = DummyContext()
+ self._assertNotFound(wrapper, context, None)
+
+ def test_add_view_with_containment_dottedname(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import directlyProvides
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view,
+ containment='tests.test_config.IDummy',
+ renderer=null_renderer,
+ )
+ wrapper = self._getViewCallable(config)
+ context = DummyContext()
+ directlyProvides(context, IDummy)
+ self.assertEqual(wrapper(context, None), 'OK')
+
+ def test_add_view_with_path_info_badregex(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne()
+ config.add_view(view, path_info='\\')
+ self.assertRaises(ConfigurationError, config.commit)
+
+ def test_add_view_with_path_info_match(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, path_info='/foo', renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.upath_info = text_(b'/foo')
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_path_info_nomatch(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, path_info='/foo')
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.upath_info = text_('/')
+ self._assertNotFound(wrapper, None, request)
+
+ def test_add_view_with_check_csrf_predicates_match(self):
+ import warnings
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ with warnings.catch_warnings(record=True) as w:
+ warnings.filterwarnings('always')
+ config.add_view(view=view, check_csrf=True, renderer=null_renderer)
+ self.assertEqual(len(w), 1)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.method = "POST"
+ request.session = DummySession({'csrf_token': 'foo'})
+ request.POST = {'csrf_token': 'foo'}
+ request.headers = {}
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_custom_predicates_match(self):
+ import warnings
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+
+ def pred1(context, request):
+ return True
+
+ def pred2(context, request):
+ return True
+
+ predicates = (pred1, pred2)
+ with warnings.catch_warnings(record=True) as w:
+ warnings.filterwarnings('always')
+ config.add_view(
+ view=view, custom_predicates=predicates, renderer=null_renderer
+ )
+ self.assertEqual(len(w), 1)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_custom_predicates_nomatch(self):
+ import warnings
+
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+
+ def pred1(context, request):
+ return True
+
+ def pred2(context, request):
+ return False
+
+ predicates = (pred1, pred2)
+ with warnings.catch_warnings(record=True) as w:
+ warnings.filterwarnings('always')
+ config.add_view(view=view, custom_predicates=predicates)
+ self.assertEqual(len(w), 1)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ self._assertNotFound(wrapper, None, request)
+
+ def test_add_view_custom_predicate_bests_standard_predicate(self):
+ import warnings
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ view2 = lambda *arg: 'NOT OK'
+ config = self._makeOne(autocommit=True)
+
+ def pred1(context, request):
+ return True
+
+ with warnings.catch_warnings(record=True) as w:
+ warnings.filterwarnings('always')
+ config.add_view(
+ view=view, custom_predicates=(pred1,), renderer=null_renderer
+ )
+ config.add_view(
+ view=view2, request_method='GET', renderer=null_renderer
+ )
+ self.assertEqual(len(w), 1)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.method = 'GET'
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_custom_more_preds_first_bests_fewer_preds_last(self):
+ from pyramid.renderers import null_renderer
+
+ view = lambda *arg: 'OK'
+ view2 = lambda *arg: 'NOT OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view, request_method='GET', xhr=True, renderer=null_renderer
+ )
+ config.add_view(
+ view=view2, request_method='GET', renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.method = 'GET'
+ request.is_xhr = True
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_same_predicates(self):
+ view2 = lambda *arg: 'second'
+ view1 = lambda *arg: 'first'
+ config = self._makeOne()
+ config.add_view(view=view1)
+ config.add_view(view=view2)
+ self.assertRaises(ConfigurationConflictError, config.commit)
+
+ def test_add_view_with_csrf_param(self):
+ from pyramid.renderers import null_renderer
+
+ def view(request):
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view, require_csrf='st', renderer=null_renderer)
+ view = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.scheme = "http"
+ request.method = 'POST'
+ request.POST = {'st': 'foo'}
+ request.headers = {}
+ request.session = DummySession({'csrf_token': 'foo'})
+ self.assertEqual(view(None, request), 'OK')
+
+ def test_add_view_with_csrf_header(self):
+ from pyramid.renderers import null_renderer
+
+ def view(request):
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view, require_csrf=True, renderer=null_renderer)
+ view = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.scheme = "http"
+ request.method = 'POST'
+ request.POST = {}
+ request.headers = {'X-CSRF-Token': 'foo'}
+ request.session = DummySession({'csrf_token': 'foo'})
+ self.assertEqual(view(None, request), 'OK')
+
+ def test_add_view_with_missing_csrf_header(self):
+ from pyramid.exceptions import BadCSRFToken
+ from pyramid.renderers import null_renderer
+
+ def view(request): # pragma: no cover
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view, require_csrf=True, renderer=null_renderer)
+ view = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.scheme = "http"
+ request.method = 'POST'
+ request.POST = {}
+ request.headers = {}
+ request.session = DummySession({'csrf_token': 'foo'})
+ self.assertRaises(BadCSRFToken, lambda: view(None, request))
+
+ def test_add_view_with_permission(self):
+ from pyramid.renderers import null_renderer
+
+ view1 = lambda *arg: 'OK'
+ outerself = self
+
+ class DummyPolicy(object):
+ def effective_principals(self, r):
+ outerself.assertEqual(r, request)
+ return ['abc']
+
+ def permits(self, context, principals, permission):
+ outerself.assertEqual(context, None)
+ outerself.assertEqual(principals, ['abc'])
+ outerself.assertEqual(permission, 'view')
+ return True
+
+ policy = DummyPolicy()
+ config = self._makeOne(
+ authorization_policy=policy,
+ authentication_policy=policy,
+ autocommit=True,
+ )
+ config.add_view(view=view1, permission='view', renderer=null_renderer)
+ view = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ self.assertEqual(view(None, request), 'OK')
+
+ def test_add_view_with_default_permission_no_explicit_permission(self):
+ from pyramid.renderers import null_renderer
+
+ view1 = lambda *arg: 'OK'
+ outerself = self
+
+ class DummyPolicy(object):
+ def effective_principals(self, r):
+ outerself.assertEqual(r, request)
+ return ['abc']
+
+ def permits(self, context, principals, permission):
+ outerself.assertEqual(context, None)
+ outerself.assertEqual(principals, ['abc'])
+ outerself.assertEqual(permission, 'view')
+ return True
+
+ policy = DummyPolicy()
+ config = self._makeOne(
+ authorization_policy=policy,
+ authentication_policy=policy,
+ default_permission='view',
+ autocommit=True,
+ )
+ config.add_view(view=view1, renderer=null_renderer)
+ view = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ self.assertEqual(view(None, request), 'OK')
+
+ def test_add_view_with_no_default_permission_no_explicit_permission(self):
+ from pyramid.renderers import null_renderer
+
+ view1 = lambda *arg: 'OK'
+
+ class DummyPolicy(object):
+ pass # wont be called
+
+ policy = DummyPolicy()
+ config = self._makeOne(
+ authorization_policy=policy,
+ authentication_policy=policy,
+ autocommit=True,
+ )
+ config.add_view(view=view1, renderer=null_renderer)
+ view = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ self.assertEqual(view(None, request), 'OK')
+
+ def test_add_view_with_mapper(self):
+ from pyramid.renderers import null_renderer
+
+ class Mapper(object):
+ def __init__(self, **kw):
+ self.__class__.kw = kw
+
+ def __call__(self, view):
+ return view
+
+ config = self._makeOne(autocommit=True)
+
+ def view(context, request):
+ return 'OK'
+
+ config.add_view(view=view, mapper=Mapper, renderer=null_renderer)
+ view = self._getViewCallable(config)
+ self.assertEqual(view(None, None), 'OK')
+ self.assertEqual(Mapper.kw['mapper'], Mapper)
+
+ def test_add_view_with_view_defaults(self):
+ from pyramid.renderers import null_renderer
+ from pyramid.exceptions import PredicateMismatch
+ from zope.interface import directlyProvides
+
+ class view(object):
+ __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
+
+ def __init__(self, request):
+ pass
+
+ def __call__(self):
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ context = DummyContext()
+ directlyProvides(context, IDummy)
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(context, request), 'OK')
+ context = DummyContext()
+ request = self._makeRequest(config)
+ self.assertRaises(PredicateMismatch, wrapper, context, request)
+
+ def test_add_view_with_view_defaults_viewname_is_dottedname_kwarg(self):
+ from pyramid.renderers import null_renderer
+ from pyramid.exceptions import PredicateMismatch
+ from zope.interface import directlyProvides
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view='tests.test_config.test_views.DummyViewDefaultsClass',
+ renderer=null_renderer,
+ )
+ wrapper = self._getViewCallable(config)
+ context = DummyContext()
+ directlyProvides(context, IDummy)
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(context, request), 'OK')
+ context = DummyContext()
+ request = self._makeRequest(config)
+ self.assertRaises(PredicateMismatch, wrapper, context, request)
+
+ def test_add_view_with_view_defaults_viewname_is_dottedname_nonkwarg(self):
+ from pyramid.renderers import null_renderer
+ from pyramid.exceptions import PredicateMismatch
+ from zope.interface import directlyProvides
+
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ 'tests.test_config.test_views.DummyViewDefaultsClass',
+ renderer=null_renderer,
+ )
+ wrapper = self._getViewCallable(config)
+ context = DummyContext()
+ directlyProvides(context, IDummy)
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(context, request), 'OK')
+ context = DummyContext()
+ request = self._makeRequest(config)
+ self.assertRaises(PredicateMismatch, wrapper, context, request)
+
+ def test_add_view_with_view_config_and_view_defaults_doesnt_conflict(self):
+ from pyramid.renderers import null_renderer
+
+ class view(object):
+ __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
+
+ class view2(object):
+ __view_defaults__ = {'containment': 'tests.test_config.IFactory'}
+
+ config = self._makeOne(autocommit=False)
+ config.add_view(view=view, renderer=null_renderer)
+ config.add_view(view=view2, renderer=null_renderer)
+ config.commit() # does not raise
+
+ def test_add_view_with_view_config_and_view_defaults_conflicts(self):
+ from pyramid.renderers import null_renderer
+
+ class view(object):
+ __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
+
+ class view2(object):
+ __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
+
+ config = self._makeOne(autocommit=False)
+ config.add_view(view=view, renderer=null_renderer)
+ config.add_view(view=view2, renderer=null_renderer)
+ self.assertRaises(ConfigurationConflictError, config.commit)
+
+ def test_add_view_class_method_no_attr(self):
+ from pyramid.renderers import null_renderer
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne(autocommit=True)
+
+ class DummyViewClass(object):
+ def run(self): # pragma: no cover
+ pass
+
+ def configure_view():
+ config.add_view(view=DummyViewClass.run, renderer=null_renderer)
+
+ self.assertRaises(ConfigurationError, configure_view)
+
+ def test_add_view_exception_only_no_regular_view(self):
+ from zope.interface import implementedBy
+ from pyramid.renderers import null_renderer
+
+ view1 = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view1,
+ context=Exception,
+ exception_only=True,
+ renderer=null_renderer,
+ )
+ view = self._getViewCallable(
+ config, ctx_iface=implementedBy(Exception)
+ )
+ self.assertTrue(view is None)
+
+ def test_add_view_exception_only(self):
+ from zope.interface import implementedBy
+ from pyramid.renderers import null_renderer
+
+ view1 = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(
+ view=view1,
+ context=Exception,
+ exception_only=True,
+ renderer=null_renderer,
+ )
+ view = self._getViewCallable(
+ config, exc_iface=implementedBy(Exception)
+ )
+ self.assertEqual(view1, view)
+
+ def test_add_view_exception_only_misconfiguration(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+
+ class NotAnException(object):
+ pass
+
+ self.assertRaises(
+ ConfigurationError,
+ config.add_view,
+ view,
+ context=NotAnException,
+ exception_only=True,
+ )
+
+ def test_add_exception_view(self):
+ from zope.interface import implementedBy
+ from pyramid.renderers import null_renderer
+
+ view1 = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_exception_view(view=view1, renderer=null_renderer)
+ wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(Exception)
+ )
+ context = Exception()
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(context, request), 'OK')
+
+ def test_add_exception_view_with_subclass(self):
+ from zope.interface import implementedBy
+ from pyramid.renderers import null_renderer
+
+ view1 = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_exception_view(
+ view=view1, context=ValueError, renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(ValueError)
+ )
+ context = ValueError()
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(context, request), 'OK')
+
+ def test_add_exception_view_disallows_name(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError,
+ config.add_exception_view,
+ context=Exception(),
+ name='foo',
+ )
+
+ def test_add_exception_view_disallows_permission(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError,
+ config.add_exception_view,
+ context=Exception(),
+ permission='foo',
+ )
+
+ def test_add_exception_view_disallows_require_csrf(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError,
+ config.add_exception_view,
+ context=Exception(),
+ require_csrf=True,
+ )
+
+ def test_add_exception_view_disallows_for_(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError,
+ config.add_exception_view,
+ context=Exception(),
+ for_='foo',
+ )
+
+ def test_add_exception_view_disallows_exception_only(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError,
+ config.add_exception_view,
+ context=Exception(),
+ exception_only=True,
+ )
+
+ def test_add_exception_view_with_view_defaults(self):
+ from pyramid.renderers import null_renderer
+ from pyramid.exceptions import PredicateMismatch
+ from zope.interface import directlyProvides
+ from zope.interface import implementedBy
+
+ class view(object):
+ __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
+
+ def __init__(self, request):
+ pass
+
+ def __call__(self):
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_exception_view(
+ view=view, context=Exception, renderer=null_renderer
+ )
+ wrapper = self._getViewCallable(
+ config, exc_iface=implementedBy(Exception)
+ )
+ context = DummyContext()
+ directlyProvides(context, IDummy)
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(context, request), 'OK')
+ context = DummyContext()
+ request = self._makeRequest(config)
+ self.assertRaises(PredicateMismatch, wrapper, context, request)
+
+ def test_derive_view_function(self):
+ from pyramid.renderers import null_renderer
+
+ def view(request):
+ return 'OK'
+
+ config = self._makeOne()
+ result = config.derive_view(view, renderer=null_renderer)
+ self.assertFalse(result is view)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_derive_view_dottedname(self):
+ from pyramid.renderers import null_renderer
+
+ config = self._makeOne()
+ result = config.derive_view(
+ 'tests.test_config.dummy_view', renderer=null_renderer
+ )
+ self.assertFalse(result is dummy_view)
+ self.assertEqual(result(None, None), 'OK')
+
+ def test_derive_view_with_default_renderer_no_explicit_renderer(self):
+ config = self._makeOne()
+
+ class moo(object):
+ def __init__(self, view):
+ pass
+
+ def __call__(self, *arg, **kw):
+ return 'moo'
+
+ config.add_renderer(None, moo)
+ config.commit()
+
+ def view(request):
+ return 'OK'
+
+ result = config.derive_view(view)
+ self.assertFalse(result is view)
+ self.assertEqual(result(None, None).body, b'moo')
+
+ def test_derive_view_with_default_renderer_with_explicit_renderer(self):
+ class moo(object):
+ pass
+
+ class foo(object):
+ def __init__(self, view):
+ pass
+
+ def __call__(self, *arg, **kw):
+ return b'foo'
+
+ def view(request):
+ return 'OK'
+
+ config = self._makeOne()
+ config.add_renderer(None, moo)
+ config.add_renderer('foo', foo)
+ config.commit()
+ result = config.derive_view(view, renderer='foo')
+ self.assertFalse(result is view)
+ request = self._makeRequest(config)
+ self.assertEqual(result(None, request).body, b'foo')
+
+ def test_add_static_view_here_no_utility_registered(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import Interface
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IViewClassifier
+
+ config = self._makeOne(autocommit=True)
+ config.add_static_view('static', 'files', renderer=null_renderer)
+ request_type = self._getRouteRequestIface(config, '__static/')
+ self._assertRoute(config, '__static/', 'static/*subpath')
+ wrapped = config.registry.adapters.lookup(
+ (IViewClassifier, request_type, Interface), IView, name=''
+ )
+ from pyramid.request import Request
+
+ request = Request.blank('/static/minimal.txt')
+ request.subpath = ('minimal.txt',)
+ result = wrapped(None, request)
+ self.assertEqual(result.status, '200 OK')
+ self.assertTrue(result.body.startswith(b'<div'))
+
+ def test_add_static_view_package_relative(self):
+ from pyramid.interfaces import IStaticURLInfo
+
+ info = DummyStaticURLInfo()
+ config = self._makeOne(autocommit=True)
+ config.registry.registerUtility(info, IStaticURLInfo)
+ config.add_static_view('static', 'tests.test_config:files')
+ self.assertEqual(
+ info.added, [(config, 'static', 'tests.test_config:files', {})]
+ )
+
+ def test_add_static_view_package_here_relative(self):
+ from pyramid.interfaces import IStaticURLInfo
+
+ info = DummyStaticURLInfo()
+ config = self._makeOne(autocommit=True)
+ config.registry.registerUtility(info, IStaticURLInfo)
+ config.add_static_view('static', 'files')
+ self.assertEqual(
+ info.added, [(config, 'static', 'tests.test_config:files', {})]
+ )
+
+ def test_add_static_view_absolute(self):
+ import os
+ from pyramid.interfaces import IStaticURLInfo
+
+ info = DummyStaticURLInfo()
+ config = self._makeOne(autocommit=True)
+ config.registry.registerUtility(info, IStaticURLInfo)
+ here = os.path.dirname(__file__)
+ static_path = os.path.join(here, 'files')
+ config.add_static_view('static', static_path)
+ self.assertEqual(info.added, [(config, 'static', static_path, {})])
+
+ def test_add_forbidden_view(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.httpexceptions import HTTPForbidden
+
+ config = self._makeOne(autocommit=True)
+ view = lambda *arg: 'OK'
+ config.add_forbidden_view(view, renderer=null_renderer)
+ request = self._makeRequest(config)
+ view = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(HTTPForbidden),
+ request_iface=IRequest,
+ )
+ result = view(None, request)
+ self.assertEqual(result, 'OK')
+
+ def test_add_forbidden_view_no_view_argument(self):
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.httpexceptions import HTTPForbidden
+
+ config = self._makeOne(autocommit=True)
+ config.setup_registry()
+ config.add_forbidden_view()
+ request = self._makeRequest(config)
+ view = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(HTTPForbidden),
+ request_iface=IRequest,
+ )
+ context = HTTPForbidden()
+ result = view(context, request)
+ self.assertEqual(result, context)
+
+ def test_add_forbidden_view_allows_other_predicates(self):
+ from pyramid.renderers import null_renderer
+
+ config = self._makeOne(autocommit=True)
+ # doesnt blow up
+ config.add_view_predicate('dummy', DummyPredicate)
+ config.add_forbidden_view(renderer=null_renderer, dummy='abc')
+
+ def test_add_forbidden_view_disallows_name(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_forbidden_view, name='foo'
+ )
+
+ def test_add_forbidden_view_disallows_permission(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_forbidden_view, permission='foo'
+ )
+
+ def test_add_forbidden_view_disallows_require_csrf(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_forbidden_view, require_csrf=True
+ )
+
+ def test_add_forbidden_view_disallows_context(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_forbidden_view, context='foo'
+ )
+
+ def test_add_forbidden_view_disallows_for_(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_forbidden_view, for_='foo'
+ )
+
+ def test_add_forbidden_view_with_view_defaults(self):
+ from pyramid.interfaces import IRequest
+ from pyramid.renderers import null_renderer
+ from pyramid.exceptions import PredicateMismatch
+ from pyramid.httpexceptions import HTTPForbidden
+ from zope.interface import directlyProvides
+ from zope.interface import implementedBy
+
+ class view(object):
+ __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
+
+ def __init__(self, request):
+ pass
+
+ def __call__(self):
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_forbidden_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(HTTPForbidden),
+ request_iface=IRequest,
+ )
+ context = DummyContext()
+ directlyProvides(context, IDummy)
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(context, request), 'OK')
+ context = DummyContext()
+ request = self._makeRequest(config)
+ self.assertRaises(PredicateMismatch, wrapper, context, request)
+
+ def test_add_notfound_view(self):
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.httpexceptions import HTTPNotFound
+
+ config = self._makeOne(autocommit=True)
+ view = lambda *arg: arg
+ config.add_notfound_view(view, renderer=null_renderer)
+ request = self._makeRequest(config)
+ view = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(HTTPNotFound),
+ request_iface=IRequest,
+ )
+ result = view(None, request)
+ self.assertEqual(result, (None, request))
+
+ def test_add_notfound_view_no_view_argument(self):
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.httpexceptions import HTTPNotFound
+
+ config = self._makeOne(autocommit=True)
+ config.setup_registry()
+ config.add_notfound_view()
+ request = self._makeRequest(config)
+ view = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(HTTPNotFound),
+ request_iface=IRequest,
+ )
+ context = HTTPNotFound()
+ result = view(context, request)
+ self.assertEqual(result, context)
+
+ def test_add_notfound_view_allows_other_predicates(self):
+ from pyramid.renderers import null_renderer
+
+ config = self._makeOne(autocommit=True)
+ # doesnt blow up
+ config.add_view_predicate('dummy', DummyPredicate)
+ config.add_notfound_view(renderer=null_renderer, dummy='abc')
+
+ def test_add_notfound_view_disallows_name(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_notfound_view, name='foo'
+ )
+
+ def test_add_notfound_view_disallows_permission(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_notfound_view, permission='foo'
+ )
+
+ def test_add_notfound_view_disallows_require_csrf(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_notfound_view, require_csrf=True
+ )
+
+ def test_add_notfound_view_disallows_context(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_notfound_view, context='foo'
+ )
+
+ def test_add_notfound_view_disallows_for_(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_notfound_view, for_='foo'
+ )
+
+ def test_add_notfound_view_append_slash(self):
+ from pyramid.response import Response
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.httpexceptions import HTTPTemporaryRedirect, HTTPNotFound
+
+ config = self._makeOne(autocommit=True)
+ config.add_route('foo', '/foo/')
+
+ def view(request): # pragma: no cover
+ return Response('OK')
+
+ config.add_notfound_view(
+ view, renderer=null_renderer, append_slash=True
+ )
+ request = self._makeRequest(config)
+ request.environ['PATH_INFO'] = '/foo'
+ request.query_string = 'a=1&b=2'
+ request.path = '/scriptname/foo'
+ view = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(HTTPNotFound),
+ request_iface=IRequest,
+ )
+ result = view(None, request)
+ self.assertTrue(isinstance(result, HTTPTemporaryRedirect))
+ self.assertEqual(result.location, '/scriptname/foo/?a=1&b=2')
+
+ def test_add_notfound_view_append_slash_custom_response(self):
+ from pyramid.response import Response
+ from pyramid.renderers import null_renderer
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.httpexceptions import HTTPMovedPermanently, HTTPNotFound
+
+ config = self._makeOne(autocommit=True)
+ config.add_route('foo', '/foo/')
+
+ def view(request): # pragma: no cover
+ return Response('OK')
+
+ config.add_notfound_view(
+ view, renderer=null_renderer, append_slash=HTTPMovedPermanently
+ )
+ request = self._makeRequest(config)
+ request.environ['PATH_INFO'] = '/foo'
+ request.query_string = 'a=1&b=2'
+ request.path = '/scriptname/foo'
+ view = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(HTTPNotFound),
+ request_iface=IRequest,
+ )
+ result = view(None, request)
+ self.assertTrue(isinstance(result, HTTPMovedPermanently))
+ self.assertEqual(result.location, '/scriptname/foo/?a=1&b=2')
+
+ def test_add_notfound_view_with_view_defaults(self):
+ from pyramid.interfaces import IRequest
+ from pyramid.renderers import null_renderer
+ from pyramid.exceptions import PredicateMismatch
+ from pyramid.httpexceptions import HTTPNotFound
+ from zope.interface import directlyProvides
+ from zope.interface import implementedBy
+
+ class view(object):
+ __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
+
+ def __init__(self, request):
+ pass
+
+ def __call__(self):
+ return 'OK'
+
+ config = self._makeOne(autocommit=True)
+ config.add_notfound_view(view=view, renderer=null_renderer)
+ wrapper = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(HTTPNotFound),
+ request_iface=IRequest,
+ )
+ context = DummyContext()
+ directlyProvides(context, IDummy)
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(context, request), 'OK')
+ context = DummyContext()
+ request = self._makeRequest(config)
+ self.assertRaises(PredicateMismatch, wrapper, context, request)
+
+ # Since Python 3 has to be all cool and fancy and different...
+ def _assertBody(self, response, value):
+ from pyramid.compat import text_type
+
+ if isinstance(value, text_type): # pragma: no cover
+ self.assertEqual(response.text, value)
+ else: # pragma: no cover
+ self.assertEqual(response.body, value)
+
+ def test_add_notfound_view_with_renderer(self):
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.httpexceptions import HTTPNotFound
+
+ config = self._makeOne(autocommit=True)
+ view = lambda *arg: {}
+ config.introspection = False
+ config.add_notfound_view(view, renderer='json')
+ request = self._makeRequest(config)
+ view = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(HTTPNotFound),
+ request_iface=IRequest,
+ )
+ result = view(None, request)
+ self._assertBody(result, '{}')
+
+ def test_add_forbidden_view_with_renderer(self):
+ from zope.interface import implementedBy
+ from pyramid.interfaces import IRequest
+ from pyramid.httpexceptions import HTTPForbidden
+
+ config = self._makeOne(autocommit=True)
+ view = lambda *arg: {}
+ config.introspection = False
+ config.add_forbidden_view(view, renderer='json')
+ request = self._makeRequest(config)
+ view = self._getViewCallable(
+ config,
+ exc_iface=implementedBy(HTTPForbidden),
+ request_iface=IRequest,
+ )
+ result = view(None, request)
+ self._assertBody(result, '{}')
+
+ def test_set_view_mapper(self):
+ from pyramid.interfaces import IViewMapperFactory
+
+ config = self._makeOne(autocommit=True)
+ mapper = object()
+ config.set_view_mapper(mapper)
+ result = config.registry.getUtility(IViewMapperFactory)
+ self.assertEqual(result, mapper)
+
+ def test_set_view_mapper_dottedname(self):
+ from pyramid.interfaces import IViewMapperFactory
+
+ config = self._makeOne(autocommit=True)
+ config.set_view_mapper('tests.test_config')
+ result = config.registry.getUtility(IViewMapperFactory)
+ from tests import test_config
+
+ self.assertEqual(result, test_config)
+
+ def test_add_normal_and_exception_view_intr_derived_callable(self):
+ from pyramid.renderers import null_renderer
+ from pyramid.exceptions import BadCSRFToken
+
+ config = self._makeOne(autocommit=True)
+ introspector = DummyIntrospector()
+ config.introspector = introspector
+ view = lambda r: 'OK'
+ config.set_default_csrf_options(require_csrf=True)
+ config.add_view(view, context=Exception, renderer=null_renderer)
+ view_intr = introspector.introspectables[-1]
+ self.assertTrue(view_intr.type_name, 'view')
+ self.assertEqual(view_intr['callable'], view)
+ derived_view = view_intr['derived_callable']
+
+ request = self._makeRequest(config)
+ request.method = 'POST'
+ request.scheme = 'http'
+ request.POST = {}
+ request.headers = {}
+ request.session = DummySession({'csrf_token': 'foo'})
+ self.assertRaises(BadCSRFToken, lambda: derived_view(None, request))
+ request.exception = Exception()
+ self.assertEqual(derived_view(None, request), 'OK')
+
+ def test_add_view_does_not_accept_iterable_accept(self):
+ from pyramid.exceptions import ConfigurationError
+
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ConfigurationError, config.add_view, accept=['image/*', 'text/*']
+ )
+
+ def test_default_accept_view_order(self):
+ from pyramid.interfaces import IAcceptOrder
+
+ config = self._makeOne(autocommit=True)
+ order = config.registry.getUtility(IAcceptOrder)
+ result = [v for _, v in order.sorted()]
+ self.assertEqual(
+ result,
+ [
+ 'text/html',
+ 'application/xhtml+xml',
+ 'application/xml',
+ 'text/xml',
+ 'text/plain',
+ 'application/json',
+ ],
+ )
+
+ def test_add_accept_view_order_override(self):
+ from pyramid.interfaces import IAcceptOrder
+
+ config = self._makeOne(autocommit=False)
+ config.add_accept_view_order(
+ 'text/html',
+ weighs_more_than='text/xml',
+ weighs_less_than='application/xml',
+ )
+ config.commit()
+ order = config.registry.getUtility(IAcceptOrder)
+ result = [v for _, v in order.sorted()]
+ self.assertEqual(
+ result,
+ [
+ 'application/xhtml+xml',
+ 'application/xml',
+ 'text/html',
+ 'text/xml',
+ 'text/plain',
+ 'application/json',
+ ],
+ )
+
+ def test_add_accept_view_order_throws_on_wildcard(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(ValueError, config.add_accept_view_order, '*/*')
+
+ def test_add_accept_view_order_throws_on_type_mismatch(self):
+ config = self._makeOne(autocommit=True)
+ self.assertRaises(
+ ValueError,
+ config.add_accept_view_order,
+ 'text/*',
+ weighs_more_than='text/html',
+ )
+ self.assertRaises(
+ ValueError,
+ config.add_accept_view_order,
+ 'text/html',
+ weighs_less_than='application/*',
+ )
+ self.assertRaises(
+ ConfigurationError,
+ config.add_accept_view_order,
+ 'text/html',
+ weighs_more_than='text/html;charset=utf8',
+ )
+ self.assertRaises(
+ ConfigurationError,
+ config.add_accept_view_order,
+ 'text/html;charset=utf8',
+ weighs_more_than='text/plain;charset=utf8',
+ )
+
+
+class Test_runtime_exc_view(unittest.TestCase):
+ def _makeOne(self, view1, view2):
+ from pyramid.config.views import runtime_exc_view
+
+ return runtime_exc_view(view1, view2)
+
+ def test_call(self):
+ def view1(context, request):
+ return 'OK'
+
+ def view2(context, request): # pragma: no cover
+ raise AssertionError
+
+ result_view = self._makeOne(view1, view2)
+ request = DummyRequest()
+ result = result_view(None, request)
+ self.assertEqual(result, 'OK')
+
+ def test_call_dispatches_on_exception(self):
+ def view1(context, request): # pragma: no cover
+ raise AssertionError
+
+ def view2(context, request):
+ return 'OK'
+
+ result_view = self._makeOne(view1, view2)
+ request = DummyRequest()
+ request.exception = Exception()
+ result = result_view(None, request)
+ self.assertEqual(result, 'OK')
+
+ def test_permitted(self):
+ def errfn(context, request): # pragma: no cover
+ raise AssertionError
+
+ def view1(context, request): # pragma: no cover
+ raise AssertionError
+
+ view1.__permitted__ = lambda c, r: 'OK'
+
+ def view2(context, request): # pragma: no cover
+ raise AssertionError
+
+ view2.__permitted__ = errfn
+ result_view = self._makeOne(view1, view2)
+ request = DummyRequest()
+ result = result_view.__permitted__(None, request)
+ self.assertEqual(result, 'OK')
+
+ def test_permitted_dispatches_on_exception(self):
+ def errfn(context, request): # pragma: no cover
+ raise AssertionError
+
+ def view1(context, request): # pragma: no cover
+ raise AssertionError
+
+ view1.__permitted__ = errfn
+
+ def view2(context, request): # pragma: no cover
+ raise AssertionError
+
+ view2.__permitted__ = lambda c, r: 'OK'
+ result_view = self._makeOne(view1, view2)
+ request = DummyRequest()
+ request.exception = Exception()
+ result = result_view.__permitted__(None, request)
+ self.assertEqual(result, 'OK')
+
+
+class Test_requestonly(unittest.TestCase):
+ def _callFUT(self, view, attr=None):
+ from pyramid.config.views import requestonly
+
+ return requestonly(view, attr=attr)
+
+ def test_defaults(self):
+ def aview(request, a=1, b=2): # pragma: no cover
+ pass
+
+ self.assertTrue(self._callFUT(aview))
+
+ def test_otherattr(self):
+ class AView(object):
+ def __init__(self, request, a=1, b=2): # pragma: no cover
+ pass
+
+ def bleh(self): # pragma: no cover
+ pass
+
+ self.assertTrue(self._callFUT(AView, 'bleh'))
+
+
+class Test_isexception(unittest.TestCase):
+ def _callFUT(self, ob):
+ from pyramid.config.views import isexception
+
+ return isexception(ob)
+
+ def test_is_exception_instance(self):
+ class E(Exception):
+ pass
+
+ e = E()
+ self.assertEqual(self._callFUT(e), True)
+
+ def test_is_exception_class(self):
+ class E(Exception):
+ pass
+
+ self.assertEqual(self._callFUT(E), True)
+
+ def test_is_IException(self):
+ from pyramid.interfaces import IException
+
+ self.assertEqual(self._callFUT(IException), True)
+
+ def test_is_IException_subinterface(self):
+ from pyramid.interfaces import IException
+
+ class ISubException(IException):
+ pass
+
+ self.assertEqual(self._callFUT(ISubException), True)
+
+
+class TestMultiView(unittest.TestCase):
+ def _getTargetClass(self):
+ from pyramid.config.views import MultiView
+
+ return MultiView
+
+ def _makeOne(self, name='name'):
+ return self._getTargetClass()(name)
+
+ def test_class_implements_ISecuredView(self):
+ from zope.interface.verify import verifyClass
+ from pyramid.interfaces import ISecuredView
+
+ verifyClass(ISecuredView, self._getTargetClass())
+
+ def test_instance_implements_ISecuredView(self):
+ from zope.interface.verify import verifyObject
+ from pyramid.interfaces import ISecuredView
+
+ verifyObject(ISecuredView, self._makeOne())
+
+ def test_add(self):
+ mv = self._makeOne()
+ mv.add('view', 100)
+ self.assertEqual(mv.views, [(100, 'view', None)])
+ mv.add('view2', 99)
+ self.assertEqual(mv.views, [(99, 'view2', None), (100, 'view', None)])
+ mv.add('view3', 100, accept='text/html')
+ self.assertEqual(mv.media_views['text/html'], [(100, 'view3', None)])
+ mv.add('view4', 99, 'abc', accept='text/html')
+ self.assertEqual(
+ mv.media_views['text/html'],
+ [(99, 'view4', 'abc'), (100, 'view3', None)],
+ )
+ mv.add('view5', 100, accept='text/xml')
+ self.assertEqual(mv.media_views['text/xml'], [(100, 'view5', None)])
+ self.assertEqual(set(mv.accepts), set(['text/xml', 'text/html']))
+ self.assertEqual(mv.views, [(99, 'view2', None), (100, 'view', None)])
+
+ def test_add_with_phash(self):
+ mv = self._makeOne()
+ mv.add('view', 100, phash='abc')
+ self.assertEqual(mv.views, [(100, 'view', 'abc')])
+ mv.add('view', 100, phash='abc')
+ self.assertEqual(mv.views, [(100, 'view', 'abc')])
+ mv.add('view', 100, phash='def')
+ self.assertEqual(
+ mv.views, [(100, 'view', 'abc'), (100, 'view', 'def')]
+ )
+ mv.add('view', 100, phash='abc')
+ self.assertEqual(
+ mv.views, [(100, 'view', 'abc'), (100, 'view', 'def')]
+ )
+
+ def test_add_with_phash_override_accept(self):
+ mv = self._makeOne()
+
+ def view1(): # pragma: no cover
+ pass
+
+ def view2(): # pragma: no cover
+ pass
+
+ def view3(): # pragma: no cover
+ pass
+
+ mv.add(view1, 100, accept='text/html', phash='abc')
+ mv.add(view2, 100, accept='text/html', phash='abc')
+ mv.add(view3, 99, accept='text/html', phash='def')
+ self.assertEqual(
+ mv.media_views['text/html'],
+ [(99, view3, 'def'), (100, view2, 'abc')],
+ )
+
+ def test_add_with_phash_override_accept2(self):
+ mv = self._makeOne()
+
+ def view1(): # pragma: no cover
+ pass
+
+ def view2(): # pragma: no cover
+ pass
+
+ def view3(): # pragma: no cover
+ pass
+
+ mv.add(view1, 100, accept='text/html', phash='abc')
+ mv.add(view2, 100, accept='text/html', phash='def')
+ mv.add(view3, 99, accept='text/html', phash='ghi')
+ self.assertEqual(
+ mv.media_views['text/html'],
+ [(99, view3, 'ghi'), (100, view1, 'abc'), (100, view2, 'def')],
+ )
+
+ def test_multiple_with_functions_as_views(self):
+ # this failed on py3 at one point, because functions aren't orderable
+ # and we were sorting the views via a plain sort() rather than
+ # sort(key=itemgetter(0)).
+ def view1(request): # pragma: no cover
+ pass
+
+ def view2(request): # pragma: no cover
+ pass
+
+ mv = self._makeOne()
+ mv.add(view1, 100, None)
+ self.assertEqual(mv.views, [(100, view1, None)])
+ mv.add(view2, 100, None)
+ self.assertEqual(mv.views, [(100, view1, None), (100, view2, None)])
+
+ def test_get_views_request_has_no_accept(self):
+ request = DummyRequest()
+ mv = self._makeOne()
+ mv.views = [(99, lambda *arg: None)]
+ self.assertEqual(mv.get_views(request), mv.views)
+
+ def test_get_views_no_self_accepts(self):
+ request = DummyRequest()
+ request.accept = True
+ mv = self._makeOne()
+ mv.accepts = []
+ mv.views = [(99, lambda *arg: None)]
+ self.assertEqual(mv.get_views(request), mv.views)
+
+ def test_get_views(self):
+ request = DummyRequest()
+ request.accept = DummyAccept('text/html')
+ mv = self._makeOne()
+ mv.accepts = ['text/html']
+ mv.views = [(99, lambda *arg: None)]
+ html_views = [(98, lambda *arg: None)]
+ mv.media_views['text/html'] = html_views
+ self.assertEqual(mv.get_views(request), html_views + mv.views)
+
+ def test_get_views_best_match_returns_None(self):
+ request = DummyRequest()
+ request.accept = DummyAccept(None)
+ mv = self._makeOne()
+ mv.accepts = ['text/html']
+ mv.views = [(99, lambda *arg: None)]
+ self.assertEqual(mv.get_views(request), mv.views)
+
+ def test_match_not_found(self):
+ from pyramid.httpexceptions import HTTPNotFound
+
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(HTTPNotFound, mv.match, context, request)
+
+ def test_match_predicate_fails(self):
+ from pyramid.httpexceptions import HTTPNotFound
+
+ mv = self._makeOne()
+
+ def view(context, request):
+ """ """
+
+ view.__predicated__ = lambda *arg: False
+ mv.views = [(100, view, None)]
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(HTTPNotFound, mv.match, context, request)
+
+ def test_match_predicate_succeeds(self):
+ mv = self._makeOne()
+
+ def view(context, request):
+ """ """
+
+ view.__predicated__ = lambda *arg: True
+ mv.views = [(100, view, None)]
+ context = DummyContext()
+ request = DummyRequest()
+ result = mv.match(context, request)
+ self.assertEqual(result, view)
+
+ def test_permitted_no_views(self):
+ from pyramid.httpexceptions import HTTPNotFound
+
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(HTTPNotFound, mv.__permitted__, context, request)
+
+ def test_permitted_no_match_with__permitted__(self):
+ mv = self._makeOne()
+
+ def view(context, request):
+ """ """
+
+ mv.views = [(100, view, None)]
+ self.assertEqual(mv.__permitted__(None, None), True)
+
+ def test_permitted(self):
+ mv = self._makeOne()
+
+ def view(context, request):
+ """ """
+
+ def permitted(context, request):
+ return False
+
+ view.__permitted__ = permitted
+ mv.views = [(100, view, None)]
+ context = DummyContext()
+ request = DummyRequest()
+ result = mv.__permitted__(context, request)
+ self.assertEqual(result, False)
+
+ def test__call__not_found(self):
+ from pyramid.httpexceptions import HTTPNotFound
+
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(HTTPNotFound, mv, context, request)
+
+ def test___call__intermediate_not_found(self):
+ from pyramid.exceptions import PredicateMismatch
+
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+
+ def view1(context, request):
+ raise PredicateMismatch
+
+ def view2(context, request):
+ return expected_response
+
+ mv.views = [(100, view1, None), (99, view2, None)]
+ response = mv(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test___call__raise_not_found_isnt_interpreted_as_pred_mismatch(self):
+ from pyramid.httpexceptions import HTTPNotFound
+
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+
+ def view1(context, request):
+ raise HTTPNotFound
+
+ def view2(context, request):
+ """ """
+
+ mv.views = [(100, view1, None), (99, view2, None)]
+ self.assertRaises(HTTPNotFound, mv, context, request)
+
+ def test___call__(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+
+ def view(context, request):
+ return expected_response
+
+ mv.views = [(100, view, None)]
+ response = mv(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test__call_permissive__not_found(self):
+ from pyramid.httpexceptions import HTTPNotFound
+
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ self.assertRaises(HTTPNotFound, mv, context, request)
+
+ def test___call_permissive_has_call_permissive(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+
+ def view(context, request):
+ """ """
+
+ def permissive(context, request):
+ return expected_response
+
+ view.__call_permissive__ = permissive
+ mv.views = [(100, view, None)]
+ response = mv.__call_permissive__(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test___call_permissive_has_no_call_permissive(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.view_name = ''
+ expected_response = DummyResponse()
+
+ def view(context, request):
+ return expected_response
+
+ mv.views = [(100, view, None)]
+ response = mv.__call_permissive__(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test__call__with_accept_match(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.accept = DummyAccept('text/html', 'text/xml')
+ expected_response = DummyResponse()
+
+ def view(context, request):
+ return expected_response
+
+ mv.views = [(100, None)]
+ mv.media_views['text/xml'] = [(100, view, None)]
+ mv.accepts = ['text/xml']
+ response = mv(context, request)
+ self.assertEqual(response, expected_response)
+
+ def test__call__with_accept_miss(self):
+ mv = self._makeOne()
+ context = DummyContext()
+ request = DummyRequest()
+ request.accept = DummyAccept('text/plain', 'text/html')
+ expected_response = DummyResponse()
+
+ def view(context, request):
+ return expected_response
+
+ mv.views = [(100, view, None)]
+ mv.media_views['text/xml'] = [(100, None, None)]
+ mv.accepts = ['text/xml']
+ response = mv(context, request)
+ self.assertEqual(response, expected_response)
+
+
+class TestDefaultViewMapper(unittest.TestCase):
+ def setUp(self):
+ self.config = testing.setUp()
+ self.registry = self.config.registry
+
+ def tearDown(self):
+ del self.registry
+ testing.tearDown()
+
+ def _makeOne(self, **kw):
+ from pyramid.config.views import DefaultViewMapper
+
+ kw['registry'] = self.registry
+ return DefaultViewMapper(**kw)
+
+ def _makeRequest(self):
+ request = DummyRequest()
+ request.registry = self.registry
+ return request
+
+ def test_view_as_function_context_and_request(self):
+ def view(context, request):
+ return 'OK'
+
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.assertTrue(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test__view_as_function_with_attr(self):
+ def view(context, request):
+ """ """
+
+ mapper = self._makeOne(attr='__name__')
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertRaises(TypeError, result, None, request)
+
+ def test_view_as_function_requestonly(self):
+ def view(request):
+ return 'OK'
+
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_function_requestonly_with_attr(self):
+ def view(request):
+ """ """
+
+ mapper = self._makeOne(attr='__name__')
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertRaises(TypeError, result, None, request)
+
+ def test_view_as_newstyle_class_context_and_request(self):
+ class view(object):
+ def __init__(self, context, request):
+ pass
+
+ def __call__(self):
+ return 'OK'
+
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_newstyle_class_context_and_request_with_attr(self):
+ class view(object):
+ def __init__(self, context, request):
+ pass
+
+ def index(self):
+ return 'OK'
+
+ mapper = self._makeOne(attr='index')
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_newstyle_class_requestonly(self):
+ class view(object):
+ def __init__(self, request):
+ pass
+
+ def __call__(self):
+ return 'OK'
+
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_newstyle_class_requestonly_with_attr(self):
+ class view(object):
+ def __init__(self, request):
+ pass
+
+ def index(self):
+ return 'OK'
+
+ mapper = self._makeOne(attr='index')
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_oldstyle_class_context_and_request(self):
+ class view:
+ def __init__(self, context, request):
+ pass
+
+ def __call__(self):
+ return 'OK'
+
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_oldstyle_class_context_and_request_with_attr(self):
+ class view:
+ def __init__(self, context, request):
+ pass
+
+ def index(self):
+ return 'OK'
+
+ mapper = self._makeOne(attr='index')
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_oldstyle_class_requestonly(self):
+ class view:
+ def __init__(self, request):
+ pass
+
+ def __call__(self):
+ return 'OK'
+
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_oldstyle_class_requestonly_with_attr(self):
+ class view:
+ def __init__(self, request):
+ pass
+
+ def index(self):
+ return 'OK'
+
+ mapper = self._makeOne(attr='index')
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_instance_context_and_request(self):
+ class View:
+ def __call__(self, context, request):
+ return 'OK'
+
+ view = View()
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.assertTrue(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_instance_context_and_request_and_attr(self):
+ class View:
+ def index(self, context, request):
+ return 'OK'
+
+ view = View()
+ mapper = self._makeOne(attr='index')
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_instance_requestonly(self):
+ class View:
+ def __call__(self, request):
+ return 'OK'
+
+ view = View()
+ mapper = self._makeOne()
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+ def test_view_as_instance_requestonly_with_attr(self):
+ class View:
+ def index(self, request):
+ return 'OK'
+
+ view = View()
+ mapper = self._makeOne(attr='index')
+ result = mapper(view)
+ self.assertFalse(result is view)
+ request = self._makeRequest()
+ self.assertEqual(result(None, request), 'OK')
+
+
+class Test_preserve_view_attrs(unittest.TestCase):
+ def _callFUT(self, view, wrapped_view):
+ from pyramid.config.views import preserve_view_attrs
+
+ return preserve_view_attrs(view, wrapped_view)
+
+ def test_it_same(self):
+ def view(context, request):
+ """ """
+
+ result = self._callFUT(view, view)
+ self.assertTrue(result is view)
+
+ def test_it_view_is_None(self):
+ def view(context, request):
+ """ """
+
+ result = self._callFUT(None, view)
+ self.assertTrue(result is view)
+
+ def test_it_different_with_existing_original_view(self):
+ def view1(context, request): # pragma: no cover
+ pass
+
+ view1.__original_view__ = 'abc'
+
+ def view2(context, request): # pragma: no cover
+ pass
+
+ result = self._callFUT(view1, view2)
+ self.assertEqual(result.__original_view__, 'abc')
+ self.assertFalse(result is view1)
+
+ def test_it_different(self):
+ class DummyView1:
+ """ 1 """
+
+ __name__ = '1'
+ __module__ = '1'
+
+ def __call__(self, context, request):
+ """ """
+
+ def __call_permissive__(self, context, request):
+ """ """
+
+ def __predicated__(self, context, request):
+ """ """
+
+ def __permitted__(self, context, request):
+ """ """
+
+ class DummyView2:
+ """ 2 """
+
+ __name__ = '2'
+ __module__ = '2'
+
+ def __call__(self, context, request):
+ """ """
+
+ def __call_permissive__(self, context, request):
+ """ """
+
+ def __predicated__(self, context, request):
+ """ """
+
+ def __permitted__(self, context, request):
+ """ """
+
+ view1 = DummyView1()
+ view2 = DummyView2()
+ result = self._callFUT(view2, view1)
+ self.assertEqual(result, view1)
+ self.assertTrue(view1.__original_view__ is view2)
+ self.assertTrue(view1.__doc__ is view2.__doc__)
+ self.assertTrue(view1.__module__ is view2.__module__)
+ self.assertTrue(view1.__name__ is view2.__name__)
+ self.assertTrue(
+ getattr(view1.__call_permissive__, im_func)
+ is getattr(view2.__call_permissive__, im_func)
+ )
+ self.assertTrue(
+ getattr(view1.__permitted__, im_func)
+ is getattr(view2.__permitted__, im_func)
+ )
+ self.assertTrue(
+ getattr(view1.__predicated__, im_func)
+ is getattr(view2.__predicated__, im_func)
+ )
+
+
+class TestStaticURLInfo(unittest.TestCase):
+ def _getTargetClass(self):
+ from pyramid.config.views import StaticURLInfo
+
+ return StaticURLInfo
+
+ def _makeOne(self):
+ return self._getTargetClass()()
+
+ def _makeRequest(self):
+ request = DummyRequest()
+ request.registry = DummyRegistry()
+ return request
+
+ def test_verifyClass(self):
+ from pyramid.interfaces import IStaticURLInfo
+ from zope.interface.verify import verifyClass
+
+ verifyClass(IStaticURLInfo, self._getTargetClass())
+
+ def test_verifyObject(self):
+ from pyramid.interfaces import IStaticURLInfo
+ from zope.interface.verify import verifyObject
+
+ verifyObject(IStaticURLInfo, self._makeOne())
+
+ def test_generate_missing(self):
+ inst = self._makeOne()
+ request = self._makeRequest()
+ self.assertRaises(ValueError, inst.generate, 'path', request)
+
+ def test_generate_registration_miss(self):
+ inst = self._makeOne()
+ inst.registrations = [
+ (None, 'spec', 'route_name'),
+ ('http://example.com/foo/', 'package:path/', None),
+ ]
+ request = self._makeRequest()
+ result = inst.generate('package:path/abc', request)
+ self.assertEqual(result, 'http://example.com/foo/abc')
+
+ def test_generate_slash_in_name1(self):
+ inst = self._makeOne()
+ inst.registrations = [
+ ('http://example.com/foo/', 'package:path/', None)
+ ]
+ request = self._makeRequest()
+ result = inst.generate('package:path/abc', request)
+ self.assertEqual(result, 'http://example.com/foo/abc')
+
+ def test_generate_slash_in_name2(self):
+ inst = self._makeOne()
+ inst.registrations = [
+ ('http://example.com/foo/', 'package:path/', None)
+ ]
+ request = self._makeRequest()
+ result = inst.generate('package:path/', request)
+ self.assertEqual(result, 'http://example.com/foo/')
+
+ def test_generate_quoting(self):
+ from pyramid.interfaces import IStaticURLInfo
+
+ config = testing.setUp()
+ try:
+ config.add_static_view('images', path='mypkg:templates')
+ request = testing.DummyRequest()
+ request.registry = config.registry
+ inst = config.registry.getUtility(IStaticURLInfo)
+ result = inst.generate('mypkg:templates/foo%2Fbar', request)
+ self.assertEqual(result, 'http://example.com/images/foo%252Fbar')
+ finally:
+ testing.tearDown()
+
+ def test_generate_route_url(self):
+ inst = self._makeOne()
+ inst.registrations = [(None, 'package:path/', '__viewname/')]
+
+ def route_url(n, **kw):
+ self.assertEqual(n, '__viewname/')
+ self.assertEqual(kw, {'subpath': 'abc', 'a': 1})
+ return 'url'
+
+ request = self._makeRequest()
+ request.route_url = route_url
+ result = inst.generate('package:path/abc', request, a=1)
+ self.assertEqual(result, 'url')
+
+ def test_generate_url_unquoted_local(self):
+ inst = self._makeOne()
+ inst.registrations = [(None, 'package:path/', '__viewname/')]
+
+ def route_url(n, **kw):
+ self.assertEqual(n, '__viewname/')
+ self.assertEqual(kw, {'subpath': 'abc def', 'a': 1})
+ return 'url'
+
+ request = self._makeRequest()
+ request.route_url = route_url
+ result = inst.generate('package:path/abc def', request, a=1)
+ self.assertEqual(result, 'url')
+
+ def test_generate_url_quoted_remote(self):
+ inst = self._makeOne()
+ inst.registrations = [('http://example.com/', 'package:path/', None)]
+ request = self._makeRequest()
+ result = inst.generate('package:path/abc def', request, a=1)
+ self.assertEqual(result, 'http://example.com/abc%20def')
+
+ def test_generate_url_with_custom_query(self):
+ inst = self._makeOne()
+ registrations = [('http://example.com/', 'package:path/', None)]
+ inst.registrations = registrations
+ request = self._makeRequest()
+ result = inst.generate(
+ 'package:path/abc def', request, a=1, _query='(openlayers)'
+ )
+ self.assertEqual(result, 'http://example.com/abc%20def?(openlayers)')
+
+ def test_generate_url_with_custom_anchor(self):
+ inst = self._makeOne()
+ inst.registrations = [('http://example.com/', 'package:path/', None)]
+ request = self._makeRequest()
+ uc = text_(b'La Pe\xc3\xb1a', 'utf-8')
+ result = inst.generate(
+ 'package:path/abc def', request, a=1, _anchor=uc
+ )
+ self.assertEqual(result, 'http://example.com/abc%20def#La%20Pe%C3%B1a')
+
+ def test_generate_url_cachebust(self):
+ def cachebust(request, subpath, kw):
+ kw['foo'] = 'bar'
+ return 'foo' + '/' + subpath, kw
+
+ inst = self._makeOne()
+ inst.registrations = [(None, 'package:path/', '__viewname')]
+ inst.cache_busters = [('package:path/', cachebust, False)]
+ request = self._makeRequest()
+ called = [False]
+
+ def route_url(n, **kw):
+ called[0] = True
+ self.assertEqual(n, '__viewname')
+ self.assertEqual(
+ kw,
+ {
+ 'subpath': 'foo/abc',
+ 'foo': 'bar',
+ 'pathspec': 'package:path/abc',
+ 'rawspec': 'package:path/abc',
+ },
+ )
+
+ request.route_url = route_url
+ inst.generate('package:path/abc', request)
+ self.assertTrue(called[0])
+
+ def test_generate_url_cachebust_abspath(self):
+ here = os.path.dirname(__file__) + os.sep
+
+ def cachebust(pathspec, subpath, kw):
+ kw['foo'] = 'bar'
+ return 'foo' + '/' + subpath, kw
+
+ inst = self._makeOne()
+ inst.registrations = [(None, here, '__viewname')]
+ inst.cache_busters = [(here, cachebust, False)]
+ request = self._makeRequest()
+ called = [False]
+
+ def route_url(n, **kw):
+ called[0] = True
+ self.assertEqual(n, '__viewname')
+ self.assertEqual(
+ kw,
+ {
+ 'subpath': 'foo/abc',
+ 'foo': 'bar',
+ 'pathspec': here + 'abc',
+ 'rawspec': here + 'abc',
+ },
+ )
+
+ request.route_url = route_url
+ inst.generate(here + 'abc', request)
+ self.assertTrue(called[0])
+
+ def test_generate_url_cachebust_nomatch(self):
+ def fake_cb(*a, **kw): # pragma: no cover
+ raise AssertionError
+
+ inst = self._makeOne()
+ inst.registrations = [(None, 'package:path/', '__viewname')]
+ inst.cache_busters = [('package:path2/', fake_cb, False)]
+ request = self._makeRequest()
+ called = [False]
+
+ def route_url(n, **kw):
+ called[0] = True
+ self.assertEqual(n, '__viewname')
+ self.assertEqual(
+ kw,
+ {
+ 'subpath': 'abc',
+ 'pathspec': 'package:path/abc',
+ 'rawspec': 'package:path/abc',
+ },
+ )
+
+ request.route_url = route_url
+ inst.generate('package:path/abc', request)
+ self.assertTrue(called[0])
+
+ def test_generate_url_cachebust_with_overrides(self):
+ config = testing.setUp()
+ try:
+ request = testing.DummyRequest()
+ config.add_static_view('static', 'path')
+ config.override_asset(
+ 'tests.test_config:path/', 'tests.test_config:other_path/'
+ )
+
+ def cb(val):
+ def cb_(request, subpath, kw):
+ kw['_query'] = {'x': val}
+ return subpath, kw
+
+ return cb_
+
+ config.add_cache_buster('path', cb('foo'))
+ result = request.static_url('path/foo.png')
+ self.assertEqual(result, 'http://example.com/static/foo.png?x=foo')
+ config.add_cache_buster('other_path', cb('bar'), explicit=True)
+ result = request.static_url('path/foo.png')
+ self.assertEqual(result, 'http://example.com/static/foo.png?x=bar')
+ finally:
+ testing.tearDown()
+
+ def test_add_already_exists(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.registrations = [('http://example.com/', 'package:path/', None)]
+ inst.add(config, 'http://example.com', 'anotherpackage:path')
+ expected = [('http://example.com/', 'anotherpackage:path/', None)]
+ self.assertEqual(inst.registrations, expected)
+
+ def test_add_package_root(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.add(config, 'http://example.com', 'package:')
+ expected = [('http://example.com/', 'package:', None)]
+ self.assertEqual(inst.registrations, expected)
+
+ def test_add_url_withendslash(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.add(config, 'http://example.com/', 'anotherpackage:path')
+ expected = [('http://example.com/', 'anotherpackage:path/', None)]
+ self.assertEqual(inst.registrations, expected)
+
+ def test_add_url_noendslash(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.add(config, 'http://example.com', 'anotherpackage:path')
+ expected = [('http://example.com/', 'anotherpackage:path/', None)]
+ self.assertEqual(inst.registrations, expected)
+
+ def test_add_url_noscheme(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.add(config, '//example.com', 'anotherpackage:path')
+ expected = [('//example.com/', 'anotherpackage:path/', None)]
+ self.assertEqual(inst.registrations, expected)
+
+ def test_add_viewname(self):
+ from pyramid.security import NO_PERMISSION_REQUIRED
+ from pyramid.static import static_view
+
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.add(config, 'view', 'anotherpackage:path', cache_max_age=1)
+ expected = [(None, 'anotherpackage:path/', '__view/')]
+ self.assertEqual(inst.registrations, expected)
+ self.assertEqual(config.route_args, ('__view/', 'view/*subpath'))
+ self.assertEqual(config.view_kw['permission'], NO_PERMISSION_REQUIRED)
+ self.assertEqual(config.view_kw['view'].__class__, static_view)
+
+ def test_add_viewname_with_route_prefix(self):
+ config = DummyConfig()
+ config.route_prefix = '/abc'
+ inst = self._makeOne()
+ inst.add(config, 'view', 'anotherpackage:path')
+ expected = [(None, 'anotherpackage:path/', '__/abc/view/')]
+ self.assertEqual(inst.registrations, expected)
+ self.assertEqual(config.route_args, ('__/abc/view/', 'view/*subpath'))
+
+ def test_add_viewname_with_permission(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.add(
+ config,
+ 'view',
+ 'anotherpackage:path',
+ cache_max_age=1,
+ permission='abc',
+ )
+ self.assertEqual(config.view_kw['permission'], 'abc')
+
+ def test_add_viewname_with_context(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.add(
+ config,
+ 'view',
+ 'anotherpackage:path',
+ cache_max_age=1,
+ context=DummyContext,
+ )
+ self.assertEqual(config.view_kw['context'], DummyContext)
+
+ def test_add_viewname_with_for_(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.add(
+ config,
+ 'view',
+ 'anotherpackage:path',
+ cache_max_age=1,
+ for_=DummyContext,
+ )
+ self.assertEqual(config.view_kw['context'], DummyContext)
+
+ def test_add_viewname_with_renderer(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.add(
+ config,
+ 'view',
+ 'anotherpackage:path',
+ cache_max_age=1,
+ renderer='mypackage:templates/index.pt',
+ )
+ self.assertEqual(
+ config.view_kw['renderer'], 'mypackage:templates/index.pt'
+ )
+
+ def test_add_cachebust_prevented(self):
+ config = DummyConfig()
+ config.registry.settings['pyramid.prevent_cachebust'] = True
+ inst = self._makeOne()
+ cachebust = DummyCacheBuster('foo')
+ inst.add_cache_buster(config, 'mypackage:path', cachebust)
+ self.assertEqual(inst.cache_busters, [])
+
+ def test_add_cachebuster(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ inst.add_cache_buster(
+ config, 'mypackage:path', DummyCacheBuster('foo')
+ )
+ cachebust = inst.cache_busters[-1][1]
+ subpath, kw = cachebust(None, 'some/path', {})
+ self.assertEqual(subpath, 'some/path')
+ self.assertEqual(kw['x'], 'foo')
+
+ def test_add_cachebuster_abspath(self):
+ here = os.path.dirname(__file__)
+ config = DummyConfig()
+ inst = self._makeOne()
+ cb = DummyCacheBuster('foo')
+ inst.add_cache_buster(config, here, cb)
+ self.assertEqual(inst.cache_busters, [(here + os.sep, cb, False)])
+
+ def test_add_cachebuster_overwrite(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ cb1 = DummyCacheBuster('foo')
+ cb2 = DummyCacheBuster('bar')
+ inst.add_cache_buster(config, 'mypackage:path/', cb1)
+ inst.add_cache_buster(config, 'mypackage:path', cb2)
+ self.assertEqual(inst.cache_busters, [('mypackage:path/', cb2, False)])
+
+ def test_add_cachebuster_overwrite_explicit(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ cb1 = DummyCacheBuster('foo')
+ cb2 = DummyCacheBuster('bar')
+ inst.add_cache_buster(config, 'mypackage:path/', cb1)
+ inst.add_cache_buster(config, 'mypackage:path', cb2, True)
+ self.assertEqual(
+ inst.cache_busters,
+ [('mypackage:path/', cb1, False), ('mypackage:path/', cb2, True)],
+ )
+
+ def test_add_cachebuster_for_more_specific_path(self):
+ config = DummyConfig()
+ inst = self._makeOne()
+ cb1 = DummyCacheBuster('foo')
+ cb2 = DummyCacheBuster('bar')
+ cb3 = DummyCacheBuster('baz')
+ cb4 = DummyCacheBuster('xyz')
+ cb5 = DummyCacheBuster('w')
+ inst.add_cache_buster(config, 'mypackage:path', cb1)
+ inst.add_cache_buster(config, 'mypackage:path/sub', cb2, True)
+ inst.add_cache_buster(config, 'mypackage:path/sub/other', cb3)
+ inst.add_cache_buster(config, 'mypackage:path/sub/other', cb4, True)
+ inst.add_cache_buster(config, 'mypackage:path/sub/less', cb5, True)
+ self.assertEqual(
+ inst.cache_busters,
+ [
+ ('mypackage:path/', cb1, False),
+ ('mypackage:path/sub/other/', cb3, False),
+ ('mypackage:path/sub/', cb2, True),
+ ('mypackage:path/sub/less/', cb5, True),
+ ('mypackage:path/sub/other/', cb4, True),
+ ],
+ )
+
+
+class Test_view_description(unittest.TestCase):
+ def _callFUT(self, view):
+ from pyramid.config.views import view_description
+
+ return view_description(view)
+
+ def test_with_text(self):
+ def view(): # pragma: no cover
+ pass
+
+ view.__text__ = 'some text'
+ result = self._callFUT(view)
+ self.assertEqual(result, 'some text')
+
+ def test_without_text(self):
+ def view(): # pragma: no cover
+ pass
+
+ result = self._callFUT(view)
+ self.assertEqual(result, 'function tests.test_config.test_views.view')
+
+
+class Test_viewdefaults(unittest.TestCase):
+ def _makeOne(self, wrapped):
+ from pyramid.decorator import reify
+
+ return reify(wrapped)
+
+ def test_dunder_attrs_copied(self):
+ from pyramid.config.views import viewdefaults
+
+ decorator = self._makeOne(viewdefaults)
+ self.assertEqual(decorator.__doc__, viewdefaults.__doc__)
+ self.assertEqual(decorator.__name__, viewdefaults.__name__)
+ self.assertEqual(decorator.__module__, viewdefaults.__module__)
+
+
+class DummyRegistry:
+ utility = None
+
+ def __init__(self):
+ self.settings = {}
+
+ def queryUtility(self, type_or_iface, name=None, default=None):
+ return self.utility or default
+
+
+@implementer(IResponse)
+class DummyResponse(object):
+ content_type = None
+ default_content_type = None
+ body = None
+
+
+class DummyRequest:
+ subpath = ()
+ matchdict = None
+ request_iface = IRequest
+ application_url = 'http://example.com/foo'
+
+ def __init__(self, environ=None):
+ if environ is None:
+ environ = {}
+ self.environ = environ
+ self.params = {}
+ self.cookies = {}
+ self.response = DummyResponse()
+
+
+class DummyContext:
+ pass
+
+
+class DummyAccept(object):
+ def __init__(self, *matches, **kw):
+ self.matches = list(matches)
+ self.contains = kw.pop('contains', False)
+
+ def acceptable_offers(self, offers):
+ results = []
+ for match in self.matches:
+ if match in offers:
+ results.append((match, 1.0))
+ return results
+
+
+class DummyConfig:
+ def __init__(self):
+ self.registry = DummyRegistry()
+
+ route_prefix = ''
+
+ def add_route(self, *args, **kw):
+ self.route_args = args
+ self.route_kw = kw
+
+ def add_view(self, *args, **kw):
+ self.view_args = args
+ self.view_kw = kw
+
+ def action(self, discriminator, callable, introspectables=()):
+ callable()
+
+ def introspectable(self, *arg):
+ return {}
+
+
+@implementer(IMultiView)
+class DummyMultiView:
+ def __init__(self):
+ self.views = []
+ self.name = 'name'
+
+ def add(self, view, order, phash=None, accept=None, accept_order=None):
+ self.views.append((view, phash, accept, accept_order))
+
+ def __call__(self, context, request):
+ return 'OK1'
+
+ def __permitted__(self, context, request):
+ """ """
+
+
+class DummyCacheBuster(object):
+ def __init__(self, token):
+ self.token = token
+
+ def __call__(self, request, subpath, kw):
+ kw['x'] = self.token
+ return subpath, kw
+
+
+def parse_httpdate(s):
+ import datetime
+
+ # cannot use %Z, must use literal GMT; Jython honors timezone
+ # but CPython does not
+ return datetime.datetime.strptime(s, "%a, %d %b %Y %H:%M:%S GMT")
+
+
+def assert_similar_datetime(one, two):
+ for attr in ('year', 'month', 'day', 'hour', 'minute'):
+ one_attr = getattr(one, attr)
+ two_attr = getattr(two, attr)
+ if not one_attr == two_attr: # pragma: no cover
+ raise AssertionError('%r != %r in %s' % (one_attr, two_attr, attr))
+
+
+class DummyStaticURLInfo:
+ def __init__(self):
+ self.added = []
+
+ def add(self, config, name, spec, **kw):
+ self.added.append((config, name, spec, kw))
+
+
+class DummyViewDefaultsClass(object):
+ __view_defaults__ = {'containment': 'tests.test_config.IDummy'}
+
+ def __init__(self, request):
+ pass
+
+ def __call__(self):
+ return 'OK'
+
+
+class DummyPredicate(object):
+ def __init__(self, val, config):
+ self.val = val
+
+ def text(self):
+ return 'dummy'
+
+ phash = text
+
+
+class DummyIntrospector(object):
+ def __init__(self, getval=None):
+ self.related = []
+ self.introspectables = []
+ self.getval = getval
+
+ def add(self, introspectable):
+ self.introspectables.append(introspectable)
+
+ def get(self, name, discrim):
+ return self.getval
+
+ def relate(self, a, b):
+ self.related.append((a, b))
+
+
+class DummySession(dict):
+ def get_csrf_token(self):
+ return self['csrf_token']