Revision e8051c20

b/snf-common/synnefo/lib/commissioning/specificator.py
35 35
from random import random, choice, randint
36 36
from math import log
37 37
from inspect import isclass
38
from .utils.betteron import betteron_decode
38
from .utils.argmap import argmap_decode
39 39

  
40 40
try:
41 41
    from collections import OrderedDict
......
760 760
        return self.output_canonical(name)(the_output)
761 761

  
762 762
    def parse(self, method, arglist):
763
        args, rest = betteron_decode(arglist)
763
        args, rest = argmap_decode(arglist)
764 764
        argdict = self.input_canonical(method).parse(args)
765 765
        return argdict
766 766

  
b/snf-common/synnefo/lib/commissioning/utils/argmap.py
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
    args = [ARGMAP_MAGIC]
207
    append = args.append
208
    s = inputf(1)
209
    key = None
210

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

  
215
        if s == ']':
216
            if key is not None:
217
                append((None, key))
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[0] == 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[0] != 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 [ARGMAP_MAGIC] + [(None, a) for a in args] + kw.items()
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

  
/dev/null
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
class arguments(object):
42
    __slots__ = ('args', 'kw')
43

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

  
53
    def __str__(self):
54
        return str(self.args) + '+' + str(self.kw)
55

  
56
    def __repr__(self):
57
        return repr(self.args) + '+' + repr(self.kw)
58

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

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

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

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

  
89
    def items(self):
90
        return list(self.iteritems())
91

  
92
    def iterkeys(self):
93
        return self.kw.iterkeys()
94

  
95
    def keys(self):
96
        return self.kw.keys()
97

  
98
    def itervalues(self):
99
        return chain(self.args, self.kw.itervalues())
100

  
101
    def values(self):
102
        return list(self.itervalues)
103

  
104
    def append(self, value):
105
        self.args.append(value)
106

  
107

  
108
def betteron_encode(obj, output):
109
    if obj is None:
110
        output('[=null]')
111
        return
112

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

  
130
    if isinstance(obj, int) or isinstance(obj, long):
131
        output(str(obj))
132
        return
133

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

  
159
    m = "Unsupported type '%s'" % (type(obj))
160

  
161

  
162
def betteron_decode(inputf, s=None):
163
    if isinstance(inputf, str):
164
        inputf = StringIO(inputf).read
165

  
166
    if s is None:
167
        s = inputf(1)
168

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

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

  
194

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

  
202

  
203
def betteron_decode_args(inputf):
204
    args = []
205
    append = args.append
206
    s = inputf(1)
207
    key = None
208

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

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

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

  

Also available in: Unified diff