diff options
author | Steve Alexander <steve@z3u.com> | 2002-06-25 12:38:12 +0000 |
---|---|---|
committer | Steve Alexander <steve@z3u.com> | 2002-06-25 12:38:12 +0000 |
commit | dc9c587bfee2359d89fcf29022170f2d361ec6db (patch) | |
tree | b33db924ea6053754ebe0f294bd1a08bf06d0008 | |
parent | 2677b463c305af08e2e37c7d521612edc4b25691 (diff) | |
download | zope-traversing-dc9c587bfee2359d89fcf29022170f2d361ec6db.tar.gz |
Added convenience functions to Zope.App.Traversing to get a canonical
location from a tuple of strings or a string.
A canonical location is a slash-delimited unicode string, or a
tuple of unicode strings.
Location strings must not end in a slash (except the root), nor contain
more than one consecutive slashes, nor be of zero length.
Location tuples must not end with an empty string (except the root), nor
contain more than one consecutive empty string, nor be of zero length.
The root location is given as u'/' or (u'',)
-rw-r--r-- | __init__.py | 48 | ||||
-rw-r--r-- | tests/testConvenienceFunctions.py | 57 |
2 files changed, 104 insertions, 1 deletions
diff --git a/__init__.py b/__init__.py index 546d6c3..eb01c62 100644 --- a/__init__.py +++ b/__init__.py @@ -21,6 +21,7 @@ from ITraverser import ITraverser as _ITraverser from Traverser import WrapperChain as _WrapperChain from Zope.Proxy.ContextWrapper import getWrapperContext as _getWrapperContext from Zope.Proxy.ContextWrapper import isWrapper as _isWrapper +from types import StringTypes _marker = object() # XXX: this probably shouldn't have "request" in its signature, nor @@ -111,3 +112,50 @@ def getPhysicalRoot(obj): return _getAdapter(obj, _ITraverser).getPhysicalRoot() +def locationAsTuple(location): + """Given a location as a unicode or ascii string or as a tuple of + unicode or ascii strings, returns the location as a tuple of + unicode strings. + + Raises a ValueError if a poorly formed location is given. + """ + if not location: + raise ValueError, "location must be non-empty." + if isinstance(location, tuple): + t = tuple(map(unicode, location)) + elif isinstance(location, StringTypes): + if location == u'/': # matches '/' or u'/' + return (u'',) + t = tuple(location.split(u'/')) + else: + raise ValueError, \ + "location %s must be a string or a tuple of strings." % (location,) + + if t[-1] == u'': # matches '' or u'' + raise ValueError, \ + "location tuple %s must not end with empty string." % (t,) + # don't usually need this, so just an assertion rather than a value error + assert '' not in t[1:] + return t + +def locationAsUnicode(location): + """Given a location as a unicode or ascii string or as a tuple of + unicode or ascii strings, returns the location as a slash-separated + unicode string. + + Raises ValueError if a poorly formed location is given. + """ + if not location: + raise ValueError, "location must be non-empty." + if isinstance(location, tuple): + u = u'/'.join(location) + elif isinstance(location, StringTypes): + u = unicode(location) + else: + raise ValueError, \ + "location %s must be a string or a tuple of strings." % (location,) + if u != '/' and u[-1] == u'/': + raise ValueError, "location %s must not end with a slash." % u + # don't usually need this, so just an assertion rather than a value error + assert u.find(u'//') == -1 + return u diff --git a/tests/testConvenienceFunctions.py b/tests/testConvenienceFunctions.py index 4bf2021..477396c 100644 --- a/tests/testConvenienceFunctions.py +++ b/tests/testConvenienceFunctions.py @@ -13,7 +13,7 @@ ############################################################################## """ -$Id: testConvenienceFunctions.py,v 1.2 2002/06/18 22:14:16 stevea Exp $ +$Id: testConvenienceFunctions.py,v 1.3 2002/06/25 12:38:12 stevea Exp $ """ from unittest import TestCase, TestSuite, main, makeSuite from Zope.App.OFS.Services.ServiceManager.tests.PlacefulSetup \ @@ -185,6 +185,61 @@ class Test(PlacefulSetup, TestCase): self.unwrapped_item ) + def testLocationAsTuple(self): + # TODO: put these assertions in a less random order + from Zope.App.Traversing import locationAsTuple as lat + loc = (u'xx',u'yy',u'zz') + self.assertEqual(lat((u'xx',u'yy',u'zz')), loc) + self.assertEqual(lat((u'', u'xx',u'yy',u'zz')), (u'',)+loc) + self.assertEqual(lat(('xx','yy','zz')), loc) + self.assertRaises(ValueError, lat, ()) + self.assertEqual(lat(('xx',)), (u'xx',)) + self.assertRaises(ValueError, lat, 23) + self.assertRaises(UnicodeError, lat, ('', u'123', '£23')) + self.assertRaises(UnicodeError, lat, '£23') + self.assertEqual(lat(u'xx/yy/zz'), loc) + self.assertEqual(lat(u'/xx/yy/zz'), (u'',)+loc) + self.assertEqual(lat('xx/yy/zz'), loc) + self.assertRaises(ValueError, lat, '') + self.assertEqual(lat('/'), (u'',)) + self.assertEqual(lat('xx'), (u'xx',)) + self.assertRaises(ValueError, lat, '//') + self.assertRaises(AssertionError, lat, '/foo//bar') + # having a trailing slash on a location is undefined. + # we might want to give it a particular meaning for zope3 later + # for now, it is an invalid location identifier + self.assertRaises(ValueError, lat, '/foo/bar/') + self.assertRaises(ValueError, lat, 'foo/bar/') + self.assertRaises(ValueError, lat, ('','foo','bar','')) + self.assertRaises(ValueError, lat, ('foo','bar','')) + + def testLocationAsUnicode(self): + from Zope.App.Traversing import locationAsUnicode as lau + loc = u'xx/yy/zz' + self.assertEqual(lau((u'xx',u'yy',u'zz')), loc) + self.assertEqual(lau((u'', u'xx',u'yy',u'zz')), '/'+loc) + self.assertEqual(lau(('xx','yy','zz')), loc) + self.assertRaises(ValueError, lau, ()) + self.assertEqual(lau(('xx',)), u'xx') + self.assertRaises(ValueError, lau, 23) + self.assertRaises(UnicodeError, lau, ('', u'123', '£23')) + self.assertRaises(UnicodeError, lau, '£23') + self.assertEqual(lau(u'xx/yy/zz'), loc) + self.assertEqual(lau(u'/xx/yy/zz'), u'/'+loc) + self.assertEqual(lau('xx/yy/zz'), loc) + self.assertRaises(ValueError, lau, '') + self.assertEqual(lau('/'), u'/') + self.assertEqual(lau('xx'), u'xx') + self.assertRaises(ValueError, lau, '//') + self.assertRaises(AssertionError, lau, '/foo//bar') + # having a trailing slash on a location is undefined. + # we might want to give it a particular meaning for zope3 later + # for now, it is an invalid location identifier + self.assertRaises(ValueError, lau, '/foo/bar/') + self.assertRaises(ValueError, lau, 'foo/bar/') + self.assertRaises(ValueError, lau, ('','foo','bar','')) + self.assertRaises(ValueError, lau, ('foo','bar','')) + def test_suite(): return TestSuite(( makeSuite(Test), |