Statistics
| Branch: | Tag: | Revision:

root / snf-common / synnefo / lib / commissioning / utils / argmap.py @ f78e128d

History | View | Annotate | Download (8.1 kB)

1
# Copyright 2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
try:
35
    from collections import OrderedDict
36
except ImportError:
37
    from .ordereddict import OrderedDict
38
from itertools import chain
39
from cStringIO import StringIO
40

    
41
ARGMAP_MAGIC = '[=ARGMAP=]'
42

    
43
class arguments(object):
44
    __slots__ = ('args', 'kw')
45

    
46
    def __init__(self, *args, **kwargs):
47
        self.args = list(args)
48
        kw = OrderedDict()
49
        kwitems = kw.pop('kwitems', None)
50
        if kwitems is not None:
51
            kw.update(kwitems)
52
        kw.update(kwargs)
53
        self.kw = kw
54

    
55
    def __str__(self):
56
        return str(self.args) + '+' + str(self.kw)
57

    
58
    def __repr__(self):
59
        return repr(self.args) + '+' + repr(self.kw)
60

    
61
    def __getitem__(self, key):
62
        if (isinstance(key, int)
63
            or isinstance(key, long)
64
            or isinstance(key, slice)):
65
                return self.args[key]
66
        else:
67
            return self.kw[key]
68

    
69
    def __setitem__(self, key, value):
70
        if (isinstance(key, int)
71
            or isinstance(key, long)
72
            or isinstance(key, slice)):
73
                self.args[key] = value
74
        else:
75
            self.kw[key] = value
76

    
77
    def __delitem__(self, key):
78
        if (isinstance(key, int)
79
            or isinstance(key, long)
80
            or isinstance(key, slice)):
81
                del self.args[key]
82
        else:
83
                del self.kw[key]
84

    
85
    def iteritems(self):
86
        for item in self.args:
87
            yield None, item
88
        for k, v in self.kw:
89
            yield k, v
90

    
91
    def items(self):
92
        return list(self.iteritems())
93

    
94
    def iterkeys(self):
95
        return self.kw.iterkeys()
96

    
97
    def keys(self):
98
        return self.kw.keys()
99

    
100
    def itervalues(self):
101
        return chain(self.args, self.kw.itervalues())
102

    
103
    def values(self):
104
        return list(self.itervalues)
105

    
106
    def append(self, value):
107
        self.args.append(value)
108

    
109

    
110
def argmap_encode(obj, output):
111
    if obj is None:
112
        output('[=null]')
113
        return
114

    
115
    if isinstance(obj, basestring):
116
        if not obj:
117
            output('""')
118
        if isinstance(obj, unicode):
119
            obj = obj.encode('utf-8')
120
        output('"')
121
        start = 0
122
        while 1:
123
            end = obj.find(start) + 1
124
            if end < 0:
125
                break
126
            output(obj[start:end] + '"')
127
            start = end
128
        output(obj[start:])
129
        output('"')
130
        return
131

    
132
    if isinstance(obj, int) or isinstance(obj, long):
133
        output(str(obj))
134
        return
135

    
136
    if hasattr(obj, 'iteritems'):
137
        output('[')
138
        once = 1
139
        for k, v in obj.iteritems():
140
            if once:
141
                once = 0
142
            else:
143
                output(' ')
144
            if k is not None:
145
                argmap_encode(k)
146
                output('=')
147
            argmap_encode(v)
148
        output(']')
149
        
150
    if hasattr(obj, '__iter__'):
151
        output('[')
152
        once = 1
153
        for item in obj:
154
            if once:
155
                once = 0
156
            else:
157
                output(' ')
158
            argmap_encode(item)
159
        output(']')
160

    
161
    m = "Unsupported type '%s'" % (type(obj))
162

    
163

    
164
def argmap_decode(inputf, s=None):
165
    if isinstance(inputf, str):
166
        inputf = StringIO(inputf).read
167

    
168
    if s is None:
169
        s = inputf(1)
170

    
171
    while 1:
172
        if not s.isspace():
173
            break
174
        s = inputf(1)
175

    
176
    item = ''
177
    if s == '"':
178
        s = inputf(1)
179
        while 1:
180
            if s == '"':
181
                s = inputf(1)
182
                if s != '"':
183
                    return item, s
184
            item += s
185
            s = inputf(1)
186
    elif s == '[':
187
        item, s = argmap_decode_args(inputf)
188
        return item, s
189
    else:
190
        while 1:
191
            item += s
192
            s = inputf(1)
193
            if s in ' =]':
194
                return item, s
195

    
196

    
197
def argmap_decode_atom(inputf):
198
    s = inputf(4)
199
    if s != 'null':
200
        m = "Invalid atom '%s'" % (s,)
201
        raise ValueError(m)
202
    return None, None
203

    
204

    
205
def argmap_decode_args(inputf):
206
    append = args.append
207
    s = inputf(1)
208
    key = None
209

    
210
    while 1:
211
        if s is None:
212
            s = inputf(1)
213

    
214
        if s == ']':
215
            if key is not None:
216
                append((None, key))
217
            args.append(ARGMAP_MAGIC)
218
            return args, None
219

    
220
        if s == '=':
221
            if key is None:
222
                atom, s = argmap_decode_atom(inputf)
223
                append((None, atom))
224
            else:
225
                value, s = argmap_decode(inputf)
226
                append((key, value))
227
                key = None
228
        elif s == ' ':
229
            if key is not None:
230
                append((None, key))
231
                key = None
232
            s = inputf(1)
233
        elif s == '':
234
            m = "EOF while scanning for ']'"
235
            raise ValueError(m)
236
        else:
237
            if key is not None:
238
                append((None, key))
239
            key, s = argmap_decode(inputf, s=s)
240

    
241

    
242
def argmap_check(obj):
243
    if hasattr(obj, 'keys'):
244
        # this could cover both cases
245
        return ARGMAP_MAGIC in obj
246
    return hasattr(obj, '__len__') and len(obj) and obj[-1] == ARGMAP_MAGIC
247

    
248
def argmap_unzip_dict(argmap):
249
    if not hasattr(argmap, 'keys'):
250
        m = "argmap unzip dict: not a dict"
251
        raise TypeError(m)
252
    if ARGMAP_MAGIC not in argmap:
253
        m = "argmap unzip dict: magic not found"
254
        raise ValueError(m)
255
    args = argmap.pop(None, [])
256
    kw = OrderedDict(argmap)
257
    del kw[ARGMAP_MAGIC]
258
    return args, kw
259

    
260
def argmap_unzip_list(argmap):
261
    if not argmap or argmap[-1] != ARGMAP_MAGIC:
262
        m = "argmap unzip list: magic not found"
263
        raise ValueError(m)
264

    
265
    iter_argmap = iter(argmap)
266
    for magic in iter_argmap:
267
        break
268

    
269
    args = []
270
    append = args.append
271
    kw = OrderedDict()
272
    for k, v in iter_argmap:
273
        if k is None:
274
            append(v)
275
        else:
276
            kw[k] = v
277

    
278
    return args, kw
279

    
280
def argmap_unzip(argmap):
281
    if hasattr(argmap, 'keys'):
282
        return argmap_unzip_dict(argmap)
283
    elif hasattr(argmap, '__iter__'):
284
        return argmap_unzip_list(argmap)
285
    else:
286
        m = "argmap: cannot unzip type %s" % (type(argmap),)
287
        raise ValueError(m)
288

    
289
def argmap_zip_list(args, kw):
290
    return [(None, a) for a in args] + kw.items() + [ARGMAP_MAGIC]
291

    
292
def argmap_zip_dict(args, kw):
293
    argmap = OrderedDict()
294
    argmap.update(kw)
295
    argmap[ARGMAP_MAGIC] = ARGMAP_MAGIC
296
    argmap[None] = list(args) + (argmap[None] if None in argmap else [])
297
    return argmap
298

    
299
argmap_zip = argmap_zip_list
300

    
301
def argmap_list_to_dict(argmap):
302
    args, kw = argmap_unzip_list(argmap)
303
    kw[ARGMAP_MAGIC] = ARGMAP_MAGIC
304
    kw[None] = args
305
    return kw
306

    
307
def argmap_dict_to_list(argmap):
308
    args, kw = argmap_unzip_dict(argmap)
309
    return args + kw.items() + [ARGMAP_MAGIC]
310