diff --git a/crank/dispatchstate.py b/crank/dispatchstate.py index a776705..844656d 100644 --- a/crank/dispatchstate.py +++ b/crank/dispatchstate.py @@ -34,7 +34,7 @@ class DispatchState(object): can be None to perform no escaping or True to use default escaping function. """ - def __init__(self, request, dispatcher=None, params=None, path_info=None, + def __init__(self, request, dispatcher, params=None, path_info=None, ignore_parameters=None, strip_extension=True, path_translator=None): self._request = request diff --git a/crank/objectdispatcher.py b/crank/objectdispatcher.py index 2f22b2c..77d2078 100644 --- a/crank/objectdispatcher.py +++ b/crank/objectdispatcher.py @@ -78,9 +78,6 @@ class ObjectDispatcher(Dispatcher): """ return ismethod(getattr(controller, name, False)) - def __call__(self, state, remainder=None): - return self._dispatch(state, remainder) - def _perform_security_check(self, controller): #xxx do this better obj = getattr(controller, 'im_self', controller) @@ -144,12 +141,9 @@ class ObjectDispatcher(Dispatcher): This method defines how the object dispatch mechanism works, including checking for security along the way. """ - if state.root_dispatcher is None: - state._root_dispatcher = self - state.add_controller('/', self) if remainder is None: remainder = state.path - + current_controller = state.controller #skip any empty urls diff --git a/crank/restdispatcher.py b/crank/restdispatcher.py index d526213..609cb17 100644 --- a/crank/restdispatcher.py +++ b/crank/restdispatcher.py @@ -202,9 +202,6 @@ class RestDispatcher(ObjectDispatcher): This method defines how the object dispatch mechanism works, including checking for security along the way. """ - if state.root_dispatcher is None: - state._root_dispatcher = self - state.add_controller('/', self) if remainder is None: remainder = state.path diff --git a/tests/test_dispachstate.py b/tests/test_dispachstate.py index 45be2ac..2812a5f 100644 --- a/tests/test_dispachstate.py +++ b/tests/test_dispachstate.py @@ -69,12 +69,12 @@ class TestDispatchState: def test_init_with_extension(self): r = MockRequest() r.path_info = 'something.json' - state = DispatchState(r) + state = DispatchState(r, dispatcher=None) assert state.extension == 'json' def test_init_with_string_path(self): r = MockRequest() r.path_info = 'something.json' - state = DispatchState(r, path_info='s1/s2') + state = DispatchState(r, dispatcher=None, path_info='s1/s2') assert state.path == ['s1', 's2'] diff --git a/tests/test_objectdispatcher.py b/tests/test_objectdispatcher.py index e1fa116..62a1f2f 100644 --- a/tests/test_objectdispatcher.py +++ b/tests/test_objectdispatcher.py @@ -118,56 +118,56 @@ class TestDispatcher: def test_call(self): req = MockRequest('/') - state = DispatchState(req) - state = self.dispatcher(state, []) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'index', state.method def test_dispatch_index(self): req = MockRequest('/') - state = DispatchState(req) + state = DispatchState(req, self.dispatcher) state = self.dispatcher._dispatch(state, []) assert state.method.__name__ == 'index', state.method def test_dispatch_default(self): req = MockRequest('/', params={'a':1}) state = DispatchState(req, self.dispatcher) - state = self.dispatcher._dispatch(state) + state = state.resolve() assert state.method.__name__ == '_default', state.method def test_dispatch_default_with_unicode(self): req = MockRequest('/', params={u('å'):u('ß')}) - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == '_default', state.method def test_controller_method_dispatch_no_args(self): req = MockRequest('/no_args') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'no_args', state.method def test_controller_method_with_unicode_args(self): req = MockRequest(u('/with_args/å/ß')) - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'with_args', state.method def test_controller_method_with_empty_args(self): req = MockRequest('/with_args//a/b') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == '_default', state.method def test_controller_method_with_args(self): req = MockRequest('/with_args/a/b') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'with_args', state.method def test_controller_method_with_args_missing_args_default(self): req = MockRequest('/with_args/a') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == '_default', state.method @raises(HTTPNotFound) @@ -209,27 +209,27 @@ class TestDispatcher: def test_sub_dispatcher(self): req = MockRequest('/sub') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'index', state.method assert state.controller.__class__.__name__ == 'MockSubDispatcher', state.controller def test_sub_dispatcher_bad_remainder_call_parent_default(self): req = MockRequest('/sub/a') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == '_default', state.method def test_sub_dispatcher_bad_params_call_parent_default(self): req = MockRequest('/sub', params={'a':1}) - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == '_default', state.method def test_sub_dispatcher_override_dispatch(self): req = MockRequest('/override_dispatch', params={'a':1}) - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'wacky', state.method def test_lookup_dispatch(self): diff --git a/tests/test_restdispatcher.py b/tests/test_restdispatcher.py index 3f060e7..a27cad2 100644 --- a/tests/test_restdispatcher.py +++ b/tests/test_restdispatcher.py @@ -117,70 +117,70 @@ class TestDispatcher: def test_get_all(self): req = MockRequest('/') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get_all' def test_get_one(self): req = MockRequest('/asdf') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get_one' assert state.params == {}, state.params assert state.remainder == ['asdf'], state.remainder def test_post(self): req = MockRequest('/', method='post') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'post' def test_post_delete(self): req = MockRequest('/', method='delete') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'post_delete' def test_post_delete_hacky(self): req = MockRequest('/', params={'_method':'delete'}, method='post') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'post_delete' def test_get_delete(self): req = MockRequest('/delete', method='get') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get_delete' @raises(HTTPMethodNotAllowed) def test_delete_hack_bad_get(self): req = MockRequest('/', params={'_method':'delete'}, method='get') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() @raises(HTTPMethodNotAllowed) def test_put_hack_bad_get(self): req = MockRequest('/', params={'_method':'put'}, method='get') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() def test_put(self): req = MockRequest('/', params={'_method':'put'}, method='post') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'put', state.method def test_put(self): req = MockRequest('/', method='put') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'put', state.method def test_other_method(self): req = MockRequest('/other') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'other', state.method class TestSimpleDispatcher: @@ -190,26 +190,26 @@ class TestSimpleDispatcher: def test_get(self): req = MockRequest('/') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get' def test_post(self): req = MockRequest('/', method='post') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'post' def test_delete(self): req = MockRequest('/', method='delete') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'delete' def test_delete_hacky(self): req = MockRequest('/', params={'_method':'delete'}, method='post') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'delete' class TestEmbeddedRestDispatcher: @@ -222,8 +222,8 @@ class TestEmbeddedRestDispatcher: def test_delete_hacky(self): req = MockRequest('/asdf/sub', params={'_method':'delete'}, method='post') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'post_delete', state.method assert state.controller.__class__.__name__ == 'MockDispatcher', state.controller assert state.params == {}, state.params @@ -238,8 +238,8 @@ class TestMinimalRestDispatcher: def test_get_all_fallback_on_get_one(self): req = MockRequest('/') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get_one' class TestDispatcherWithArgs: @@ -252,59 +252,59 @@ class TestDispatcherWithArgs: def test_post(self): req = MockRequest('/asdf', method='post') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'post' def test_put(self): req = MockRequest('/sub/asdf', method='put') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'put', state.method def test_delete(self): req = MockRequest('/sub/asdf', method='delete') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'delete', state.method def test_other(self): req = MockRequest('/other', method='post') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'other' def test_other_with_get_method(self): req = MockRequest('/other/something', params={'_method':'get'}, method='get') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'other', state.method @raises(HTTPNotFound) def test_post_bad(self): req = MockRequest('/aaa/aaa', method='post') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'pos', state.method @raises(HTTPMethodNotAllowed) def test_other_delete_bad(self): req = MockRequest('/other/asdf', method='delete') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'other' @raises(HTTPNotFound) def test_other_delete_not_found(self): req = MockRequest('/not_found', method='delete') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'other' def test_sub_get_one(self): req = MockRequest('/sub/mid', method='get') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get_one' @@ -318,8 +318,8 @@ class TestDispatcherWithVarArgs: def test_delete(self): req = MockRequest('/asdf1/asdf2/asdf3/asdf4/sub') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get_all', state.method class MockCustomMethodDispatcher(RestDispatcher): @@ -342,33 +342,33 @@ class TestCustomMethodDispatcher: def test_post(self): req = MockRequest('/', method='custom') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'post_custom', state.method def test_post_hacky(self): req = MockRequest('/', params={'_method':'custom'}, method='post') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'post_custom', state.method def test_get_hacky(self): req = MockRequest('/', params={'_method':'custom'}, method='get') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get_custom', state.method def test_get_url(self): req = MockRequest('/custom') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get_custom', state.method @raises(HTTPNotFound) def test_get_fail(self): req = MockRequest('/not_found', params={'_method':'custom'}, method='get') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get_custom', state.method class SubCustomMethodDispatcher(MockDispatcher): @@ -385,8 +385,8 @@ class TestSubCustomMethodDispatcher: def test_get_url(self): req = MockRequest('/sub', params={'_method':'custom'}, method='get') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.method.__name__ == 'get_custom', state.method class SubNoGet(RestDispatcher): @@ -406,8 +406,8 @@ class TestSubNoGetDispatcher: @raises(HTTPNotFound) def test_get_not_found(self): req = MockRequest('/sub', method='get') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() class TestEmptyDispatcher: def setup(self): @@ -419,8 +419,8 @@ class TestEmptyDispatcher: @raises(HTTPNotFound) def test_get_not_found(self): req = MockRequest('/sub', method='get') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() class TestRestWithSecurity: def setup(self): @@ -429,14 +429,14 @@ class TestRestWithSecurity: @raises(MockError) def test_check_security_with_lookup(self): req = MockRequest('/direct/a') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() @raises(MockError) def test_check_security_with_nested_lookup(self): req = MockRequest('/nested/withsec/a') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() class TestRestWithLookup: class RootController(ObjectDispatcher): @@ -458,22 +458,22 @@ class TestRestWithLookup: def test_rest_with_lookup(self): req = MockRequest('/rest/somethingelse/method') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.controller.__class__.__name__ == 'sub', state.controller assert state.method.__name__ == 'method', state.method def test_rest_lookup_doesnt_mess_with_get(self): req = MockRequest('/rest/25') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.controller.__class__.__name__ == 'rest', state.controller assert state.method.__name__ == 'get', state.method def test_rest_lookup_doesnt_mess_with_subcontroller(self): req = MockRequest('/rest/sub/method') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.controller.__class__.__name__ == 'sub', state.controller assert state.method.__name__ == 'method', state.method @@ -496,8 +496,8 @@ class TestRestCheckSecurity: def test_rest_security_check_only_once(self): req = MockRequest('/rest/25') - state = DispatchState(req) - state = self.dispatcher._dispatch(state) + state = DispatchState(req, self.dispatcher) + state = state.resolve() assert state.controller.__class__.__name__ == 'rest', state.controller assert state.method.__name__ == 'get', state.method assert len(self.security_tracing) == 1, self.security_tracing \ No newline at end of file