Add utils for validating and splitting quotes

Now Murano and Glance have similiar implementations of validating
and splitting quotes for using operator 'in' in their API [1],[2].

The style of this functionality should be common as they follow
appropriate api-wg style [3]. So it would be great to have them
implemented in one place and reuse in different projects.

TBD: add appropriate commits to Murano and Glance if this patch
isn't revoked.

[1]: https://github.com/openstack/glance/blob/master/glance/common/utils.py#L601-L644
[2]: https://github.com/openstack/murano/blob/master/murano/common/utils.py#L250-L301
[3]: https://specs.openstack.org/openstack/api-wg/guidelines/pagination_filter_sort.html#filtering

Change-Id: I15236d28b2136153db093590fb4dae65a87eb3e3
Co-Authored-By: Alexis Lee <lxsli@hpe.com>
This commit is contained in:
Omar Shykhkerimov 2016-08-02 11:42:03 +03:00
parent f43d78d358
commit d1e08f533d
2 changed files with 45 additions and 0 deletions

View File

@ -22,6 +22,7 @@ import math
import re
import unicodedata
import pyparsing as pp
import six
from six.moves import urllib
@ -468,3 +469,20 @@ def split_path(path, minsegs=1, maxsegs=None, rest_with_last=False):
segs = segs[1:maxsegs]
segs.extend([None] * (maxsegs - 1 - len(segs)))
return segs
def split_by_commas(value):
"""Split values by commas and quotes according to api-wg
:param value: value to be split
.. versionadded:: 3.17
"""
word = (pp.QuotedString(quoteChar='"', escChar='\\')
| pp.Word(pp.printables, excludeChars='",'))
grammar = pp.stringStart + pp.delimitedList(word) + pp.stringEnd
try:
return list(grammar.parseString(value))
except pp.ParseException:
raise ValueError("Invalid value: %s" % value)

View File

@ -762,3 +762,30 @@ class SplitPathTestCase(test_base.BaseTestCase):
strutils.split_path('o\nn e', 2, 3, True)
except ValueError as err:
self.assertEqual(str(err), 'Invalid path: o%0An%20e')
class SplitByCommas(test_base.BaseTestCase):
def test_not_closed_quotes(self):
self.assertRaises(ValueError, strutils.split_by_commas, '"ab","b""')
def test_no_comma_before_opening_quotes(self):
self.assertRaises(ValueError, strutils.split_by_commas, '"ab""b"')
def test_quote_inside_unquoted(self):
self.assertRaises(ValueError, strutils.split_by_commas, 'a"b,cd')
def check(self, expect, input):
self.assertEqual(expect, strutils.split_by_commas(input))
def test_plain(self):
self.check(["a,b", "ac"], '"a,b",ac')
def test_with_backslash_inside_quoted(self):
self.check(['abc"', 'de', 'fg,h', 'klm\\', '"nop'],
r'"abc\"","de","fg,h","klm\\","\"nop"')
def test_with_backslash_inside_unquoted(self):
self.check([r'a\bc', 'de'], r'a\bc,de')
def test_with_escaped_quotes_in_row_inside_quoted(self):
self.check(['a"b""c', 'd'], r'"a\"b\"\"c",d')