Revision 2d1202ee

b/kamaki/cli/argument/__init__.py
280 280
    :syntax: --<arg> key1=value1 --<arg> key2=value2 ...
281 281
    """
282 282

  
283
    def __init__(self, help='', parsed_name=None, default={}):
283
    def __init__(self, help='', parsed_name=None, default=[]):
284 284
        super(KeyValueArgument, self).__init__(-1, help, parsed_name, default)
285 285

  
286 286
    @property
......
295 295
        """
296 296
        :param keyvalue_pairs: (str) ['key1=val1', 'key2=val2', ...]
297 297
        """
298
        self._value = {}
298
        self._value = getattr(self, '_value', self.value) or {}
299 299
        try:
300 300
            for pair in keyvalue_pairs:
301 301
                key, sep, val = pair.partition('=')
b/kamaki/cli/argument/test.py
302 302

  
303 303
    def test_value(self):
304 304
        kva = argument.KeyValueArgument(parsed_name='--keyval')
305
        self.assertEqual(kva.value, {})
305
        self.assertEqual(kva.value, [])
306 306
        for kvpairs in (
307 307
                'strval', 'key=val', 2.8, 42, None,
308 308
                ('key', 'val'), ('key val'), ['=val', 'key=val'],
......
311 311
                kva.value = kvpairs
312 312
            except Exception as e:
313 313
                self.assertTrue(isinstance(e, errors.CLIError))
314
        old = dict()
315
        kva = argument.KeyValueArgument(parsed_name='--keyval')
314 316
        for kvpairs, exp in (
315 317
                (('key=val', ), {'key': 'val'}),
316 318
                (['key1=val1', 'key2=val2'], {'key1': 'val1', 'key2': 'val2'}),
......
320 322
                (('k=v1', 'k=v2', 'k=v3'), {'k': 'v3'})
321 323
            ):
322 324
            kva.value = kvpairs
323
            assert_dicts_are_equal(self, kva.value, exp)
325
            old.update(exp)
326
            assert_dicts_are_equal(self, kva.value, old)
324 327

  
325 328

  
326 329
class ProgressBarArgument(TestCase):
b/kamaki/cli/commands/image.py
175 175
class image_list(_init_image, _optional_json):
176 176
    """List images accessible by user"""
177 177

  
178
    PERMANENTS = (
179
        'id', 'name',
180
        'status', 'container_format', 'disk_format', 'size')
181

  
178 182
    arguments = dict(
179 183
        detail=FlagArgument('show detailed output', ('-l', '--details')),
180 184
        container_format=ValueArgument(
......
203 207
        more=FlagArgument(
204 208
            'output results in pages (-n to set items per page, default 10)',
205 209
            '--more'),
206
        enum=FlagArgument('Enumerate results', '--enumerate')
210
        enum=FlagArgument('Enumerate results', '--enumerate'),
211
        prop=KeyValueArgument('filter by property key=value', ('--property'))
207 212
    )
208 213

  
209 214
    def _filtered_by_owner(self, detail, *list_params):
......
225 230
            (not ns) or img['name'].lower().endswith(ns.lower())) and (
226 231
            (not nl) or nl.lower() in img['name'].lower())]
227 232

  
233
    def _filtered_by_properties(self, images):
234
        new_images = []
235
        for img in images:
236
            if set(self['prop'].items()).difference(img['properties'].items()):
237
                continue
238
            if self['detail']:
239
                new_images.append(dict(img))
240
            else:
241
                new_images.append(dict())
242
                for k in set(img).intersection(self.PERMANENTS):
243
                    new_images[-1][k] = img[k]
244
        return new_images
245

  
228 246
    @errors.generic.all
229 247
    @errors.cyclades.connection
230 248
    def _run(self):
......
240 258
            filters[arg] = self[arg]
241 259

  
242 260
        order = self['order']
243
        detail = self['detail']
261
        detail = self['detail'] or self['prop']
244 262
        if self['owner']:
245 263
            images = self._filtered_by_owner(detail, filters, order)
246 264
        else:
247 265
            images = self.client.list_public(detail, filters, order)
248 266

  
249 267
        images = self._filtered_by_name(images)
268
        if self['prop']:
269
            images = self._filtered_by_properties(images)
250 270
        kwargs = dict(with_enumeration=self['enum'])
251 271
        if self['more']:
252 272
            kwargs['page_size'] = self['limit'] or 10
b/kamaki/cli/utils/test.py
248 248
            print_items(*args)
249 249
            if not (isinstance(items, dict) or isinstance(
250 250
                    items, list) or isinstance(items, tuple)):
251
                self.assertEqual(PR.mock_calls[-1], call(
252
                    '%s' % items if items is not None else ''))
251
                if items:
252
                    self.assertEqual(PR.mock_calls[-1], call('%s' % items))
253 253
            else:
254 254
                for i, item in enumerate(items):
255 255
                    if with_enumeration:

Also available in: Unified diff