parse_single()   B
last analyzed

Complexity

Conditions 6

Size

Total Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
dl 0
loc 44
rs 7.8906
c 0
b 0
f 0
1
#
2
# Copyright (C) 2011 - 2013 Satoru SATOH <ssato @ redhat.com>
3
# License: MIT
4
#
5
"""Misc parsers
6
"""
7
from __future__ import absolute_import
8
9
import re
10
11
12
INT_PATTERN = re.compile(r"^(\d|([1-9]\d+))$")
13
BOOL_PATTERN = re.compile(r"^(true|false)$", re.I)
14
STR_PATTERN = re.compile(r"^['\"](.*)['\"]$")
15
16
17
def 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
63
def 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
85
def 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
107
def 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
134
def 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
150
def parse(str_, lsep=",", avsep=":", vssep=",", avssep=";"):
151
    """Generic parser"""
152
    if avsep in str_:
153
        return parse_attrlist(str_, avsep, vssep, avssep)
154
    elif lsep in str_:
155
        return parse_list(str_, lsep)
156
157
    return parse_single(str_)
158
159
# vim:sw=4:ts=4:et:
160