def _unquoted_list_parse(cls, keys, value): """Split comma separated list, and unquote each value. Examples: >>> list(ParsecValidator._unquoted_list_parse(None, '"1", 2')) ['1', '2'] """ # http://stackoverflow.com/questions/4982531/ # how-do-i-split-a-comma-delimited-string-in-python-except- # for-the-commas-that-are # First detect multi-parameter lists like <m,n>. if cls._REC_MULTI_PARAM.search(value): raise ListValueError( keys, value, msg="names containing commas must be quoted" "(e.g. 'foo<m,n>')") pos = 0 while True: match = cls._REC_UQLP.search(value, pos) result = match.group(2).strip() separator = match.group(3) yield result if not separator: break pos = match.end(0)
def coerce_spaceless_str_list(cls, value, keys): """Coerce value to a list of strings ensuring no values contain spaces. Examples: >>> ParsecValidator.coerce_spaceless_str_list( ... 'a, b, c', None) ['a', 'b', 'c'] >>> ParsecValidator.coerce_spaceless_str_list( ... 'a, b c, d', ['foo']) # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): cylc.flow.parsec.exceptions.ListValueError: \ (type=list) foo = a, b c, d - \ (list item "b c" cannot contain a space character) """ lst = cls.strip_and_unquote_list(keys, value) for item in lst: if ' ' in item: raise ListValueError( keys, value, msg='list item "%s" cannot contain a space character' % item) return lst
def coerce_absolute_host_list(cls, value, keys): """Do not permit self reference in host names. Examples: >>> ParsecValidator.coerce_absolute_host_list( ... 'foo, bar, baz', None) ['foo', 'bar', 'baz'] >>> ParsecValidator.coerce_absolute_host_list( ... 'foo, bar, 127.0.0.1:8080, baz', ['pub'] ... ) # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): cylc.flow.parsec.exceptions.ListValueError: \ (type=list) pub = foo, bar, 127.0.0.1:8080, baz - \ (ambiguous host "127.0.0.1:8080") """ hosts = cls.coerce_spaceless_str_list(value, keys) for host in hosts: if any( host.startswith(pattern) for pattern in cls.SELF_REFERENCE_PATTERNS): raise ListValueError(keys, value, msg='ambiguous host "%s"' % host) return hosts
def coerce_range(cls, value, keys): """A single min/max pair defining an integer range. Examples: >>> ParsecValidator.coerce_range('1..3', None) (1, 3) >>> ParsecValidator.coerce_range('1..3, 5', 'k') Traceback (most recent call last): cylc.flow.parsec.exceptions.ListValueError: \ (type=list) k = 1..3, 5 - (Only one min..max pair is permitted) >>> ParsecValidator.coerce_range('1..z', None) Traceback (most recent call last): cylc.flow.parsec.exceptions.ListValueError: \ (type=list) k = 1..3, 5 - \ (Integer range must be in the format min..max) >>> ParsecValidator.coerce_range('1', 'k') Traceback (most recent call last): cylc.flow.parsec.exceptions.ListValueError: \ (type=list) k = 1..3, 5 - \ (Integer range must be in the format min..max) """ items = cls.strip_and_unquote_list(keys, value) if len(items) != 1: raise ListValueError( keys, value, msg='Only one min..max pair is permitted', ) item = items[0] match = cls._REC_INT_RANGE.match(item) if not match: raise ListValueError( keys, value, msg='Integer range must be in the format min..max', ) min_, max_ = match.groups()[0:2] return Range((int(min_), int(max_)))