Permalink
Browse files

Refactoring TurboGears hooks and expose a public API to manage custom…

… hooks
  • Loading branch information...
1 parent 3b4c2db commit 9547ee18a85cee23f934431f64c54d68eba993da @amol- amol- committed Sep 3, 2013
View
@@ -159,7 +159,6 @@ def setup(self):
config["use_sqlalchemy"] = False
config["global_conf"] = Bunch()
config["package"] = "test"
- config["call_on_shutdown"] = "foo"
config["render_functions"] = Bunch()
config['beaker.session.secret'] = 'some_secret'
@@ -604,11 +603,13 @@ def test_register_hooks(self):
def dummy(*args):
pass
+ milestones.config_ready._reset()
self.config.register_hook('startup', dummy)
self.config.register_hook('shutdown', dummy)
self.config.register_hook('controller_wrapper', dummy)
for hook_name in self.config.hooks.keys():
self.config.register_hook(hook_name, dummy)
+ milestones.config_ready.reach()
for hooks in self.config.hooks.values():
assert hooks
@@ -639,6 +640,87 @@ def call(*args, **kw):
self.config._setup_controller_wrappers()
assert config['controller_caller'].__name__ == controller_wrapper(self.config, orig_caller).__name__
+ def test_global_controller_wrapper(self):
+ milestones._reset_all()
+
+ class RootController(TGController):
+ @expose()
+ def test(self):
+ return 'HI!'
+
+ wrapper_has_been_visited = []
+ def controller_wrapper(app_config, caller):
+ def call(*args, **kw):
+ wrapper_has_been_visited.append(True)
+ return caller(*args, **kw)
+ return call
+
+ conf = AppConfig(minimal=True, root_controller=RootController())
+ conf.register_hook('controller_wrapper', controller_wrapper)
+ conf.package = PackageWithModel()
+ app = conf.make_wsgi_app()
+ app = TestApp(app)
+
+ assert 'HI!' in app.get('/test')
+ assert wrapper_has_been_visited[0] is True
+
+ def test_dedicated_controller_wrapper(self):
+ milestones._reset_all()
+
+ class RootController(TGController):
+ @expose()
+ def test(self):
+ return 'HI!'
+
+ wrapper_has_been_visited = []
+ def controller_wrapper(app_config, caller):
+ def call(*args, **kw):
+ wrapper_has_been_visited.append(True)
+ return caller(*args, **kw)
+ return call
+
+ conf = AppConfig(minimal=True, root_controller=RootController())
+ tg.hooks.wrap_controller(controller_wrapper, controller=RootController.test)
+ conf.package = PackageWithModel()
+ app = conf.make_wsgi_app()
+ app = TestApp(app)
+
+ assert 'HI!' in app.get('/test')
+ assert wrapper_has_been_visited[0] is True
+
+ def test_mixed_controller_wrapper(self):
+ milestones._reset_all()
+
+ class RootController(TGController):
+ @expose()
+ def test(self):
+ return 'HI!'
+
+ app_wrapper_has_been_visited = []
+ def app_controller_wrapper(app_config, caller):
+ def call(*args, **kw):
+ app_wrapper_has_been_visited.append(True)
+ return caller(*args, **kw)
+ return call
+
+ wrapper_has_been_visited = []
+ def controller_wrapper(app_config, caller):
+ def call(*args, **kw):
+ wrapper_has_been_visited.append(True)
+ return caller(*args, **kw)
+ return call
+
+ conf = AppConfig(minimal=True, root_controller=RootController())
+ tg.hooks.wrap_controller(app_controller_wrapper)
+ tg.hooks.wrap_controller(controller_wrapper, controller=RootController.test)
+ conf.package = PackageWithModel()
+ app = conf.make_wsgi_app()
+ app = TestApp(app)
+
+ assert 'HI!' in app.get('/test')
+ assert wrapper_has_been_visited[0] is True
+ assert app_wrapper_has_been_visited[0] is True
+
def test_application_wrapper_setup(self):
class RootController(TGController):
@expose()
@@ -1011,6 +1093,9 @@ def fake_make_middleware(app, twconfig):
assert tw.api.resources.registry.ACTIVE_VARIANT == 'min'
def test_config_hooks(self):
+ # Reset milestone so that registered hooks
+ milestones._reset_all()
+
class RootController(TGController):
@expose()
def test(self):
@@ -1034,6 +1119,61 @@ def after_config_hook(app):
assert 'before_config' in visited_hooks
assert 'after_config' in visited_hooks
+ def test_controller_hooks_with_value(self):
+ # Reset milestone so that registered hooks
+ milestones._reset_all()
+
+ class RootController(TGController):
+ @expose()
+ def test(self):
+ return tg.hooks.notify_with_value('test_hook', 'BO',
+ controller=RootController.test)
+
+ def value_hook(value):
+ return value*2
+
+ tg.hooks.register('test_hook', value_hook, controller=RootController.test)
+
+ conf = AppConfig(minimal=True, root_controller=RootController())
+ app = conf.make_wsgi_app()
+ app = TestApp(app)
+
+ resp = app.get('/test')
+ assert 'BOBO' in resp, resp
+
+ @raises(TGConfigError)
+ def test_config_hooks_startup_on_controller(self):
+ def f():
+ pass
+
+ tg.hooks.register('startup', None, controller=f)
+
+ @raises(TGConfigError)
+ def test_config_hooks_shutdown_on_controller(self):
+ def f():
+ pass
+
+ tg.hooks.register('shutdown', None, controller=f)
+
+ @raises(TGConfigError)
+ def test_controller_wrapper_using_register(self):
+ milestones.config_ready.reach()
+ tg.hooks.register('controller_wrapper', None)
+
+ @raises(TGConfigError)
+ def test_global_controller_wrapper_after_config_ready(self):
+ milestones.config_ready.reach()
+ tg.hooks.wrap_controller(None)
+
+ @raises(TGConfigError)
+ def test_dedicated_controller_wrapper_after_config_ready(self):
+ milestones.config_ready.reach()
+
+ def f():
+ pass
+
+ tg.hooks.wrap_controller(None, controller=f)
+
def test_error_middleware_disabled_with_optimize(self):
class RootController(TGController):
@expose()
@@ -48,15 +48,16 @@ def setup_helpers_and_globals(self):
g = tg.config['tg.app_globals']
g.dotted_filename_finder = DottedFileNameFinder()
-def app_from_config(base_config, deployment_config=None):
+def app_from_config(base_config, deployment_config=None, reset_milestones=True):
if not deployment_config:
deployment_config = {'debug': 'true',
'error_email_from': 'paste@localhost',
'smtp_server': 'localhost'}
# Reset milestones so that they can be reached again
# on next configuration initialization
- milestones._reset_all()
+ if reset_milestones:
+ milestones._reset_all()
env_loader = base_config.make_load_environment()
app_maker = base_config.setup_tg_wsgi_app(env_loader)
@@ -8,8 +8,13 @@
from nose.tools import eq_
from nose import SkipTest
from tg._compat import PY3, u_
+from tg.util import Bunch
+
class TestHooks(object):
+ def setUp(self):
+ milestones._reset_all()
+
def test_hooks_syswide(self):
base_config = TestConfig(folder = 'dispatch',
values = {'use_sqlalchemy': False,
@@ -22,11 +27,28 @@ def hook(*args, **kw):
tg.tmpl_context.echo = 'WORKED'
base_config.register_hook('before_call', hook)
- app = app_from_config(base_config)
+ app = app_from_config(base_config, reset_milestones=False)
ans = app.get('/echo')
assert 'WORKED' in ans
+ def test_decoration_run_hooks_backward_compatibility(self):
+ # TODO: Remove test when Decoration.run_hooks gets removed
+
+ def func(*args, **kw):
+ pass
+
+ def hook(*args, **kw):
+ hook.did_run = True
+ hook.did_run = False
+
+ milestones.renderers_ready.reach()
+ tg.hooks.register('before_call', hook, controller=func)
+
+ deco = Decoration.get_decoration(func)
+ deco.run_hooks(Bunch(config=None), 'before_call')
+
+ assert hook.did_run is True
class TestExpose(object):
def setUp(self):
@@ -3,8 +3,7 @@
import shutil, os
import json
import tg
-#import tg.configuration
-
+from tg.configuration import milestones
#tg.configuration.reqlocal_config.push_process_config({})
from tests.test_stack import TestConfig, app_from_config
@@ -561,9 +560,11 @@ def render_call_hook(*args, **kw):
'use_toscawidgets': False,
'use_toscawidgets2': False
})
+
+ milestones._reset_all()
base_config.register_hook('before_render_call', render_call_hook)
base_config.register_hook('after_render_call', render_call_hook)
- app = app_from_config(base_config)
+ app = app_from_config(base_config, reset_milestones=False)
app.get('/')
assert len(calls) == 2
View
@@ -65,6 +65,7 @@
from tg.controllers.util import use_wsgi_app
from tg.controllers.dispatcher import dispatched_controller
from tg.render import render as render_template
+from tg.configuration.hooks import hooks
__version__ = version
View
@@ -43,6 +43,12 @@ def im_func(f):
else:
return getattr(f, 'im_func', None)
+def default_im_func(f):
+ if PY3: # pragma: no cover
+ return getattr(f, '__func__', f)
+ else:
+ return getattr(f, 'im_func', f)
+
def im_self(f):
if PY3: # pragma: no cover
return getattr(f, '__self__', None)
Oops, something went wrong.

0 comments on commit 9547ee1

Please sign in to comment.