From 1da614e3dab88f4a7ccf97630e808c1c119a0f90 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sat, 5 Jul 2008 00:43:33 +0000 Subject: policy -> traversal. --- repoze/bfg/policy.py | 47 --------------- repoze/bfg/router.py | 10 ++-- repoze/bfg/tests/test_policy.py | 115 ------------------------------------- repoze/bfg/tests/test_traversal.py | 115 +++++++++++++++++++++++++++++++++++++ repoze/bfg/traversal.py | 47 +++++++++++++++ setup.py | 10 +++- 6 files changed, 175 insertions(+), 169 deletions(-) delete mode 100644 repoze/bfg/policy.py delete mode 100644 repoze/bfg/tests/test_policy.py create mode 100644 repoze/bfg/tests/test_traversal.py create mode 100644 repoze/bfg/traversal.py diff --git a/repoze/bfg/policy.py b/repoze/bfg/policy.py deleted file mode 100644 index 697350b16..000000000 --- a/repoze/bfg/policy.py +++ /dev/null @@ -1,47 +0,0 @@ -import urllib - -from zope.interface import implements - -from repoze.bfg.interfaces import ITraversalPolicy -from repoze.bfg.interfaces import ITraverser - -def split_path(path): - if path.startswith('/'): - path = path[1:] - if path.endswith('/'): - path = path[:-1] - clean=[] - for item in path.split('/'): - item = urllib.unquote(item) # deal with spaces in path segment - if not item or item=='.': - continue - elif item == '..': - del clean[-1] - else: - clean.append(item) - return clean - -class NaiveTraversalPolicy: - implements(ITraversalPolicy) - - def __call__(self, environ, root): - path = split_path(environ['PATH_INFO']) - - ob = root - name = '' - - while path: - element = pop(path) - traverser = ITraverser(ob) - next = traverser(environ, element) - if next is None: - if path: - name = pop(path) - break - ob = next - - return ob, name, path - -def pop(path): - return path.pop(0) - diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py index 12d3d4ac4..68e85d50c 100644 --- a/repoze/bfg/router.py +++ b/repoze/bfg/router.py @@ -2,14 +2,14 @@ from zope.component import getAdapter from repoze.bfg.interfaces import IWSGIApplication class Router: - def __init__(self, app, root_finder, policy): + def __init__(self, app, root_policy, traversal_policy): self.app = app - self.root_finder = root_finder - self.policy = policy + self.root_policy = root_policy + self.traversal_policy = traversal_policy def __call__(self, environ, start_response): - root = self.root_finder(environ) - context, name, subpath = self.policy(root, environ) + root = self.root_policy(environ) + context, name, subpath = self.traversal_policy(root, environ) app = getAdapter(context, IWSGIApplication, name) environ['repoze.bfg.context'] = context environ['repoze.bfg.subpath'] = subpath diff --git a/repoze/bfg/tests/test_policy.py b/repoze/bfg/tests/test_policy.py deleted file mode 100644 index 3623d43f5..000000000 --- a/repoze/bfg/tests/test_policy.py +++ /dev/null @@ -1,115 +0,0 @@ -import unittest - -from zope.component.testing import PlacelessSetup - -class SplitPathTests(unittest.TestCase): - def _getFUT(self): - from repoze.bfg.policy import split_path - return split_path - - def test_cleanPath_path_startswith_endswith(self): - f = self._getFUT() - self.assertEqual(f('/foo/'), ['foo']) - - def test_cleanPath_empty_elements(self): - f = self._getFUT() - self.assertEqual(f('foo///'), ['foo']) - - def test_cleanPath_onedot(self): - f = self._getFUT() - self.assertEqual(f('foo/./bar'), ['foo', 'bar']) - - def test_cleanPath_twodots(self): - f = self._getFUT() - self.assertEqual(f('foo/../bar'), ['bar']) - - def test_cleanPath_element_urllquoted(self): - f = self._getFUT() - self.assertEqual(f('/foo/space%20thing/bar'), ['foo', 'space thing', - 'bar']) - -class NaivePolicyTests(unittest.TestCase, PlacelessSetup): - def setUp(self): - PlacelessSetup.setUp(self) - - def tearDown(self): - PlacelessSetup.tearDown(self) - - def _getTargetClass(self): - from repoze.bfg.policy import NaiveTraversalPolicy - return NaiveTraversalPolicy - - def _makeOne(self, *arg, **kw): - import zope.component - gsm = zope.component.getGlobalSiteManager() - from repoze.bfg.interfaces import ITraverser - gsm.registerAdapter(DummyTraverser, (None,), ITraverser, '') - klass = self._getTargetClass() - return klass(*arg, **kw) - - def test_class_conforms_to_IPolicy(self): - from zope.interface.verify import verifyClass - from repoze.bfg.interfaces import ITraversalPolicy - verifyClass(ITraversalPolicy, self._getTargetClass()) - - def test_instance_conforms_to_IPolicy(self): - from zope.interface.verify import verifyObject - from repoze.bfg.interfaces import ITraversalPolicy - verifyObject(ITraversalPolicy, self._makeOne()) - - def test_call_nonkeyerror_raises(self): - policy = self._makeOne() - environ = {'PATH_INFO':'/foo'} - root = None - self.assertRaises(TypeError, policy, environ, root) - - def test_call_withconn_getitem_emptypath_nosubpath(self): - policy = self._makeOne() - context = DummyContext() - environ = {'PATH_INFO':''} - root = context - ctx, name, subpath = policy(environ, root) - self.assertEqual(context, ctx) - self.assertEqual(name, '') - self.assertEqual(subpath, []) - - def test_call_withconn_getitem_withpath_nosubpath(self): - policy = self._makeOne() - context = DummyContext() - context2 = DummyContext(context) - environ = {'PATH_INFO':'/foo/bar'} - root = context - ctx, name, subpath = policy(environ, root) - self.assertEqual(context, ctx) - self.assertEqual(name, 'bar') - self.assertEqual(subpath, []) - - def test_call_withconn_getitem_withpath_withsubpath(self): - policy = self._makeOne() - context = DummyContext() - context2 = DummyContext(context) - environ = {'PATH_INFO':'/foo/bar/baz/buz'} - root = context - ctx, name, subpath = policy(environ, root) - self.assertEqual(context, ctx) - self.assertEqual(name, 'bar') - self.assertEqual(subpath, ['baz', 'buz']) - -class DummyContext: - def __init__(self, next=None): - self.next = next - - def __getitem__(self, name): - if self.next is None: - raise KeyError, name - return self.next - -class DummyTraverser: - def __init__(self, context): - self.context = context - - def __call__(self, environ, name): - try: - return self.context[name] - except KeyError: - return None diff --git a/repoze/bfg/tests/test_traversal.py b/repoze/bfg/tests/test_traversal.py new file mode 100644 index 000000000..bb0b98b79 --- /dev/null +++ b/repoze/bfg/tests/test_traversal.py @@ -0,0 +1,115 @@ +import unittest + +from zope.component.testing import PlacelessSetup + +class SplitPathTests(unittest.TestCase): + def _getFUT(self): + from repoze.bfg.traversal import split_path + return split_path + + def test_cleanPath_path_startswith_endswith(self): + f = self._getFUT() + self.assertEqual(f('/foo/'), ['foo']) + + def test_cleanPath_empty_elements(self): + f = self._getFUT() + self.assertEqual(f('foo///'), ['foo']) + + def test_cleanPath_onedot(self): + f = self._getFUT() + self.assertEqual(f('foo/./bar'), ['foo', 'bar']) + + def test_cleanPath_twodots(self): + f = self._getFUT() + self.assertEqual(f('foo/../bar'), ['bar']) + + def test_cleanPath_element_urllquoted(self): + f = self._getFUT() + self.assertEqual(f('/foo/space%20thing/bar'), ['foo', 'space thing', + 'bar']) + +class NaivePolicyTests(unittest.TestCase, PlacelessSetup): + def setUp(self): + PlacelessSetup.setUp(self) + + def tearDown(self): + PlacelessSetup.tearDown(self) + + def _getTargetClass(self): + from repoze.bfg.traversal import NaiveTraversalPolicy + return NaiveTraversalPolicy + + def _makeOne(self, *arg, **kw): + import zope.component + gsm = zope.component.getGlobalSiteManager() + from repoze.bfg.interfaces import ITraverser + gsm.registerAdapter(DummyTraverser, (None,), ITraverser, '') + klass = self._getTargetClass() + return klass(*arg, **kw) + + def test_class_conforms_to_ITraversalPolicy(self): + from zope.interface.verify import verifyClass + from repoze.bfg.interfaces import ITraversalPolicy + verifyClass(ITraversalPolicy, self._getTargetClass()) + + def test_instance_conforms_to_ITraversalPolicy(self): + from zope.interface.verify import verifyObject + from repoze.bfg.interfaces import ITraversalPolicy + verifyObject(ITraversalPolicy, self._makeOne()) + + def test_call_nonkeyerror_raises(self): + policy = self._makeOne() + environ = {'PATH_INFO':'/foo'} + root = None + self.assertRaises(TypeError, policy, environ, root) + + def test_call_withconn_getitem_emptypath_nosubpath(self): + policy = self._makeOne() + context = DummyContext() + environ = {'PATH_INFO':''} + root = context + ctx, name, subpath = policy(environ, root) + self.assertEqual(context, ctx) + self.assertEqual(name, '') + self.assertEqual(subpath, []) + + def test_call_withconn_getitem_withpath_nosubpath(self): + policy = self._makeOne() + context = DummyContext() + context2 = DummyContext(context) + environ = {'PATH_INFO':'/foo/bar'} + root = context + ctx, name, subpath = policy(environ, root) + self.assertEqual(context, ctx) + self.assertEqual(name, 'bar') + self.assertEqual(subpath, []) + + def test_call_withconn_getitem_withpath_withsubpath(self): + policy = self._makeOne() + context = DummyContext() + context2 = DummyContext(context) + environ = {'PATH_INFO':'/foo/bar/baz/buz'} + root = context + ctx, name, subpath = policy(environ, root) + self.assertEqual(context, ctx) + self.assertEqual(name, 'bar') + self.assertEqual(subpath, ['baz', 'buz']) + +class DummyContext: + def __init__(self, next=None): + self.next = next + + def __getitem__(self, name): + if self.next is None: + raise KeyError, name + return self.next + +class DummyTraverser: + def __init__(self, context): + self.context = context + + def __call__(self, environ, name): + try: + return self.context[name] + except KeyError: + return None diff --git a/repoze/bfg/traversal.py b/repoze/bfg/traversal.py new file mode 100644 index 000000000..1b9cfb332 --- /dev/null +++ b/repoze/bfg/traversal.py @@ -0,0 +1,47 @@ +import urllib + +from zope.interface import implements + +from repoze.bfg.interfaces import ITraversalPolicy +from repoze.bfg.interfaces import ITraverser + +def split_path(path): + if path.startswith('/'): + path = path[1:] + if path.endswith('/'): + path = path[:-1] + clean=[] + for segment in path.split('/'): + segment = urllib.unquote(segment) # deal with spaces in path segment + if not segment or segment=='.': + continue + elif segment == '..': + del clean[-1] + else: + clean.append(segment) + return clean + +class NaiveTraversalPolicy: + implements(ITraversalPolicy) + + def __call__(self, environ, root): + path = split_path(environ['PATH_INFO']) + + ob = root + name = '' + + while path: + segment = pop(path) + traverser = ITraverser(ob) + next = traverser(environ, segment) + if next is None: + if path: + name = pop(path) + break + ob = next + + return ob, name, path + +def pop(path): + return path.pop(0) + diff --git a/setup.py b/setup.py index 8cf61678e..8b39301a1 100644 --- a/setup.py +++ b/setup.py @@ -48,8 +48,14 @@ setup(name='repoze.bfg', include_package_data=True, namespace_packages=['repoze', 'repoze.bfg'], zip_safe=False, - tests_require = ['zope.interface', 'zope.component', 'zope.testing'], - install_requires=['zope.interface', 'zope.component', 'zope.testing'], + install_requires=[ + 'zope.interface', + 'zope.component', + 'zope.testing'], + tests_require=[ + 'zope.interface', + 'zope.component', + 'zope.testing'], test_suite="repoze.bfg.tests", entry_points = """\ """ -- cgit v1.2.3