Move method split_path into oslo.utils

Method split_path was used in project keystonemiddleware, sahara.
So it's good to accept it by oslo.utils.

http://git.openstack.org/cgit/openstack/keystonemiddleware/tree/keystonemiddleware/s3_token.py#n50
http://git.openstack.org/cgit/openstack/sahara/tree/sahara/openstack/commons.py#n24

Change-Id: I8507a7c406d12e459809442601f3ecf919e62311
This commit is contained in:
ChangBo Guo(gcb) 2016-05-09 14:54:35 +08:00
parent 406c753a72
commit daf4681766
2 changed files with 89 additions and 0 deletions

View File

@ -22,6 +22,7 @@ import re
import unicodedata
import six
from six.moves import urllib
from oslo_utils._i18n import _
from oslo_utils import encodeutils
@ -412,3 +413,52 @@ def check_string_length(value, name=None, min_length=0, max_length=None):
"%(max_length)s.") % {'name': name, 'length': length,
'max_length': max_length}
raise ValueError(msg)
def split_path(path, minsegs=1, maxsegs=None, rest_with_last=False):
"""Validate and split the given HTTP request path.
**Examples**::
['a'] = _split_path('/a')
['a', None] = _split_path('/a', 1, 2)
['a', 'c'] = _split_path('/a/c', 1, 2)
['a', 'c', 'o/r'] = _split_path('/a/c/o/r', 1, 3, True)
:param path: HTTP Request path to be split
:param minsegs: Minimum number of segments to be extracted
:param maxsegs: Maximum number of segments to be extracted
:param rest_with_last: If True, trailing data will be returned as part
of last segment. If False, and there is
trailing data, raises ValueError.
:returns: list of segments with a length of maxsegs (non-existent
segments will return as None)
:raises: ValueError if given an invalid path
.. versionadded:: 3.9
"""
if not maxsegs:
maxsegs = minsegs
if minsegs > maxsegs:
raise ValueError(_('minsegs > maxsegs: %(min)d > %(max)d)') %
{'min': minsegs, 'max': maxsegs})
if rest_with_last:
segs = path.split('/', maxsegs)
minsegs += 1
maxsegs += 1
count = len(segs)
if (segs[0] or count < minsegs or count > maxsegs or
'' in segs[1:minsegs]):
raise ValueError(_('Invalid path: %s') % urllib.parse.quote(path))
else:
minsegs += 1
maxsegs += 1
segs = path.split('/', maxsegs)
count = len(segs)
if (segs[0] or count < minsegs or count > maxsegs + 1 or
'' in segs[1:minsegs] or
(count == maxsegs + 1 and segs[maxsegs])):
raise ValueError(_('Invalid path: %s') % urllib.parse.quote(path))
segs = segs[1:maxsegs]
segs.extend([None] * (maxsegs - 1 - len(segs)))
return segs

View File

@ -694,3 +694,42 @@ class StringLengthTestCase(test_base.BaseTestCase):
self.assertRaises(TypeError,
strutils.check_string_length,
dict(), max_length=255)
class SplitPathTestCase(test_base.BaseTestCase):
def test_split_path_failed(self):
self.assertRaises(ValueError, strutils.split_path, '')
self.assertRaises(ValueError, strutils.split_path, '/')
self.assertRaises(ValueError, strutils.split_path, '//')
self.assertRaises(ValueError, strutils.split_path, '//a')
self.assertRaises(ValueError, strutils.split_path, '/a/c')
self.assertRaises(ValueError, strutils.split_path, '//c')
self.assertRaises(ValueError, strutils.split_path, '/a/c/')
self.assertRaises(ValueError, strutils.split_path, '/a//')
self.assertRaises(ValueError, strutils.split_path, '/a', 2)
self.assertRaises(ValueError, strutils.split_path, '/a', 2, 3)
self.assertRaises(ValueError, strutils.split_path, '/a', 2, 3, True)
self.assertRaises(ValueError, strutils.split_path, '/a/c/o/r', 3, 3)
self.assertRaises(ValueError, strutils.split_path, '/a', 5, 4)
def test_split_path_success(self):
self.assertEqual(strutils.split_path('/a'), ['a'])
self.assertEqual(strutils.split_path('/a/'), ['a'])
self.assertEqual(strutils.split_path('/a/c', 2), ['a', 'c'])
self.assertEqual(strutils.split_path('/a/c/o', 3), ['a', 'c', 'o'])
self.assertEqual(strutils.split_path('/a/c/o/r', 3, 3, True),
['a', 'c', 'o/r'])
self.assertEqual(strutils.split_path('/a/c', 2, 3, True),
['a', 'c', None])
self.assertEqual(strutils.split_path('/a/c/', 2), ['a', 'c'])
self.assertEqual(strutils.split_path('/a/c/', 2, 3), ['a', 'c', ''])
def test_split_path_invalid_path(self):
try:
strutils.split_path('o\nn e', 2)
except ValueError as err:
self.assertEqual(str(err), 'Invalid path: o%0An%20e')
try:
strutils.split_path('o\nn e', 2, 3, True)
except ValueError as err:
self.assertEqual(str(err), 'Invalid path: o%0An%20e')