summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-05-12 22:36:37 +0000
committerGerrit Code Review <review@openstack.org>2016-05-12 22:36:37 +0000
commit6cf8386cc7278a98f9ba9260d7ea61e519e93975 (patch)
treef2ca0012a01c73de3e0746d6ca2834088c8533f7
parent12d4936f12ffaef1d8d1f753b2dc359e78205b34 (diff)
parentdaf468176662efb5fc399cf7e12a79d46ad1f771 (diff)
downloadoslo-utils-6cf8386cc7278a98f9ba9260d7ea61e519e93975.tar.gz
Merge "Move method split_path into oslo.utils"3.11.0
-rw-r--r--oslo_utils/strutils.py50
-rw-r--r--oslo_utils/tests/test_strutils.py39
2 files changed, 89 insertions, 0 deletions
diff --git a/oslo_utils/strutils.py b/oslo_utils/strutils.py
index 7d15a34..d52542b 100644
--- a/oslo_utils/strutils.py
+++ b/oslo_utils/strutils.py
@@ -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
diff --git a/oslo_utils/tests/test_strutils.py b/oslo_utils/tests/test_strutils.py
index 51aad0a..da807df 100644
--- a/oslo_utils/tests/test_strutils.py
+++ b/oslo_utils/tests/test_strutils.py
@@ -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')