1# 2# Copyright (C) 2011 - 2013 Satoru SATOH <ssato @ redhat.com> 3# License: MIT 4# 5"""Misc parsers 6""" 7from __future__ import absolute_import 8 9import re 10 11 12INT_PATTERN = re.compile(r"^(\d|([1-9]\d+))$") 13BOOL_PATTERN = re.compile(r"^(true|false)$", re.I) 14STR_PATTERN = re.compile(r"^['\"](.*)['\"]$") 15 16 17def parse_single(str_): 18 """ 19 Very simple parser to parse expressions represent some single values. 20 21 :param str_: a string to parse 22 :return: Int | Bool | String 23 24 >>> parse_single(None) 25 '' 26 >>> parse_single("0") 27 0 28 >>> parse_single("123") 29 123 30 >>> parse_single("True") 31 True 32 >>> parse_single("a string") 33 'a string' 34 >>> parse_single('"a string"') 35 'a string' 36 >>> parse_single("'a string'") 37 'a string' 38 >>> parse_single("0.1") 39 '0.1' 40 >>> parse_single(" a string contains extra whitespaces ") 41 'a string contains extra whitespaces' 42 """ 43 if str_ is None: 44 return '' 45 46 str_ = str_.strip() 47 48 if not str_: 49 return '' 50 51 if BOOL_PATTERN.match(str_) is not None: 52 return bool(str_) 53 54 if INT_PATTERN.match(str_) is not None: 55 return int(str_) 56 57 if STR_PATTERN.match(str_) is not None: 58 return str_[1:-1] 59 60 return str_ 61 62 63def parse_list(str_, sep=","): 64 """ 65 Simple parser to parse expressions reprensent some list values. 66 67 :param str_: a string to parse 68 :param sep: Char to separate items of list 69 :return: [Int | Bool | String] 70 71 >>> parse_list("") 72 [] 73 >>> parse_list("1") 74 [1] 75 >>> parse_list("a,b") 76 ['a', 'b'] 77 >>> parse_list("1,2") 78 [1, 2] 79 >>> parse_list("a,b,") 80 ['a', 'b'] 81 """ 82 return [parse_single(x) for x in str_.split(sep) if x] 83 84 85def attr_val_itr(str_, avs_sep=":", vs_sep=",", as_sep=";"): 86 """ 87 Atrribute and value pair parser. 88 89 :param str_: String represents a list of pairs of attribute and value 90 :param avs_sep: char to separate attribute and values 91 :param vs_sep: char to separate values 92 :param as_sep: char to separate attributes 93 """ 94 for rel in parse_list(str_, as_sep): 95 if avs_sep not in rel or rel.endswith(avs_sep): 96 continue 97 98 (_attr, _values) = parse_list(rel, avs_sep) 99 100 if vs_sep in str(_values): 101 _values = parse_list(_values, vs_sep) 102 103 if _values: 104 yield (_attr, _values) 105 106 107def parse_attrlist_0(str_, avs_sep=":", vs_sep=",", as_sep=";"): 108 """ 109 Simple parser to parse expressions in the form of 110 [ATTR1:VAL0,VAL1,...;ATTR2:VAL0,VAL2,..]. 111 112 :param str_: input string 113 :param avs_sep: char to separate attribute and values 114 :param vs_sep: char to separate values 115 :param as_sep: char to separate attributes 116 117 :return: 118 a list of tuples of (key, value | [value]) 119 where key = (Int | String | ...), 120 value = (Int | Bool | String | ...) | [Int | Bool | String | ...] 121 122 >>> parse_attrlist_0("a:1") 123 [('a', 1)] 124 >>> parse_attrlist_0("a:1;b:xyz") 125 [('a', 1), ('b', 'xyz')] 126 >>> parse_attrlist_0("requires:bash,zsh") 127 [('requires', ['bash', 'zsh'])] 128 >>> parse_attrlist_0("obsoletes:sysdata;conflicts:sysdata-old") 129 [('obsoletes', 'sysdata'), ('conflicts', 'sysdata-old')] 130 """ 131 return [(a, vs) for a, vs in attr_val_itr(str_, avs_sep, vs_sep, as_sep)] 132 133 134def parse_attrlist(str_, avs_sep=":", vs_sep=",", as_sep=";"): 135 """ 136 Simple parser to parse expressions in the form of 137 [ATTR1:VAL0,VAL1,...;ATTR2:VAL0,VAL2,..]. 138 139 :param str_: input string 140 :param avs_sep: char to separate attribute and values 141 :param vs_sep: char to separate values 142 :param as_sep: char to separate attributes 143 144 >>> parse_attrlist("requires:bash,zsh") 145 {'requires': ['bash', 'zsh']} 146 """ 147 return dict(parse_attrlist_0(str_, avs_sep, vs_sep, as_sep)) 148 149 150def parse(str_, lsep=",", avsep=":", vssep=",", avssep=";"): 151 """Generic parser""" 152 if avsep in str_: 153 return parse_attrlist(str_, avsep, vssep, avssep) 154 if lsep in str_: 155 return parse_list(str_, lsep) 156 157 return parse_single(str_) 158 159# vim:sw=4:ts=4:et: 160