Revision 439826ec kamaki/cli/commands/pithos_cli.py

b/kamaki/cli/commands/pithos_cli.py
34 34
from kamaki.cli import command
35 35
from kamaki.cli.command_tree import CommandTree
36 36
from kamaki.cli.errors import raiseCLIError, CLISyntaxError
37
from kamaki.cli.utils import format_size, print_dict, pretty_keys
37
from kamaki.cli.utils import format_size, print_dict, pretty_keys, page_hold
38 38
from kamaki.cli.argument import FlagArgument, ValueArgument, IntArgument
39 39
from kamaki.cli.argument import KeyValueArgument, DateArgument
40 40
from kamaki.cli.argument import ProgressBarArgument
41 41
from kamaki.cli.commands import _command_init
42 42
from kamaki.clients.pithos import PithosClient, ClientError
43 43
from kamaki.cli.utils import bold
44
from sys import stdout
44
from sys import stdout, stdin
45 45
from time import localtime, strftime
46 46
from logging import getLogger
47 47

  
......
77 77

  
78 78
class SharingArgument(ValueArgument):
79 79
    """Set sharing (read and/or write) groups
80

  
80
    .
81 81
    :value type: "read=term1,term2,... write=term1,term2,..."
82

  
82
    .
83 83
    :value returns: {'read':['term1', 'term2', ...],
84
        'write':['term1', 'term2', ...]}
84
    .   'write':['term1', 'term2', ...]}
85 85
    """
86 86

  
87 87
    @property
......
117 117

  
118 118
class RangeArgument(ValueArgument):
119 119
    """
120
    :value type: string of the form <start>-<end>
121
        where <start> and <end> are integers
122

  
120
    :value type: string of the form <start>-<end> where <start> and <end> are
121
        integers
123 122
    :value returns: the input string, after type checking <start> and <end>
124 123
    """
125 124

  
......
162 161

  
163 162
    def __init__(self, arguments={}):
164 163
        super(_store_account_command, self).__init__(arguments)
165
        self['account']=ValueArgument(
164
        self['account'] = ValueArgument(
166 165
            'Set user account (not permanent)',
167 166
            '--account')
168 167

  
......
175 174
class _store_container_command(_store_account_command):
176 175
    """Base class for container level storage commands"""
177 176

  
178
    generic_err_details = ['Choose one of the following options:',
177
    generic_err_details = ['To specify a container:',
179 178
    '  1. Set store.container variable (permanent)',
180 179
    '     /config set store.container <container>',
181 180
    '  2. --container=<container> (temporary, overrides 1)',
182
    '  3. Use <container>:<path> (temporary, overrides all)']
181
    '  3. Use the container:path format (temporary, overrides all)']
183 182
    container = None
184 183
    path = None
185 184

  
186 185
    def __init__(self, arguments={}):
187 186
        super(_store_container_command, self).__init__(arguments)
188
        self['container']=ValueArgument(
187
        self['container'] = ValueArgument(
189 188
            'Set container to work with (temporary)',
190 189
            '--container')
191 190

  
......
250 249
    1 no parameters : containers in set account
251 250
    2. one parameter (container) or --container : contents of container
252 251
    3. <container>:<prefix> or --container=<container> <prefix>: objects in
253
        container starting with prefix
252
    .   container starting with prefix
254 253
    """
255 254

  
256 255
    arguments = dict(
257 256
        detail=FlagArgument('show detailed output', '-l'),
258
        show_size=ValueArgument('print output in chunks of size N', '-N'),
259
        limit=IntArgument('show limited output', '-n'),
257
        limit=IntArgument('limit the number of listed items', '-n'),
260 258
        marker=ValueArgument('show output greater that marker', '--marker'),
261
        prefix=ValueArgument('show output staritng with prefix', '--prefix'),
259
        prefix=ValueArgument('show output starting with prefix', '--prefix'),
262 260
        delimiter=ValueArgument('show output up to delimiter', '--delimiter'),
263 261
        path=ValueArgument(
264 262
            'show output starting with prefix up to /',
......
279 277
            '--format'),
280 278
        shared=FlagArgument('show only shared', '--shared'),
281 279
        public=FlagArgument('show only public', '--public'),
280
        more=FlagArgument(
281
            'output results in pages (-n to set items per page, default 10)',
282
            '--more')
282 283
    )
283 284

  
284 285
    def print_objects(self, object_list):
285
        import sys
286
        try:
287
            limit = int(self['show_size'])
288
        except (AttributeError, TypeError):
289
            limit = len(object_list) + 1
286
        limit = int(self['limit']) if self['limit'] > 0 else len(object_list)
290 287
        for index, obj in enumerate(object_list):
291 288
            if 'content_type' not in obj:
292 289
                continue
......
309 306
                oname = '%s%s. %6s %s' % (empty_space, index, size, oname)
310 307
                oname += '/' if isDir else ''
311 308
                print(oname)
312
            if limit <= index < len(object_list) and index % limit == 0:
313
                print('(press "enter" to continue)')
314
                sys.stdin.read(1)
309
            if self['more']:
310
                page_hold(index, limit, len(object_list))
315 311

  
316 312
    def print_containers(self, container_list):
317
        import sys
318
        try:
319
            limit = self['show_size']
320
            limit = int(limit)
321
        except (AttributeError, TypeError):
322
            limit = len(container_list) + 1
313
        limit = int(self['limit']) if self['limit'] > 0\
314
            else len(container_list)
323 315
        for index, container in enumerate(container_list):
324 316
            if 'bytes' in container:
325 317
                size = format_size(container['bytes'])
......
337 329
                    % (cname, size, container['count']))
338 330
                else:
339 331
                    print(cname)
340
            if limit <= index < len(container_list) and index % limit == 0:
341
                print('(press "enter" to continue)')
342
                sys.stdin.read(1)
332
            if self['more']:
333
                page_hold(index + 1, limit, len(container_list))
343 334

  
344 335
    def main(self, container____path__=None):
345 336
        super(self.__class__, self).main(container____path__)
346 337
        try:
347 338
            if self.container is None:
348 339
                r = self.client.account_get(
349
                    limit=self['limit'],
340
                    limit=False if self['more'] else self['limit'],
350 341
                    marker=self['marker'],
351 342
                    if_modified_since=self['if_modified_since'],
352 343
                    if_unmodified_since=self['if_unmodified_since'],
......
357 348
                prefix = self.path if self.path\
358 349
                else self['prefix']
359 350
                r = self.client.container_get(
360
                    limit=self['limit'],
351
                    limit=False if self['more'] else self['limit'],
361 352
                    marker=self['marker'],
362 353
                    prefix=prefix,
363 354
                    delimiter=self['delimiter'],
......
370 361
                self.print_objects(r.json)
371 362
        except ClientError as err:
372 363
            if err.status == 404:
373
                if 'Container does not exist' in ('%s' % err):
364
                if 'container' in ('%s' % err).lower():
374 365
                    raiseCLIError(
375 366
                        err,
376 367
                        'No container %s in account %s'\
377 368
                        % (self.container, self.account),
378 369
                        details=self.generic_err_details)
379
                elif 'Object does not exist' in ('%s' % err):
370
                elif 'object' in ('%s' % err).lower():
380 371
                    raiseCLIError(
381 372
                        err,
382 373
                        'No object %s in %s\'s container %s'\
383 374
                        % (self.path, self.account, self.container),
384 375
                        details=self.generic_err_details)
385 376
            raiseCLIError(err)
377
        except Exception as e:
378
            raiseCLIError(e)
386 379

  
387 380

  
388 381
@command(pithos_cmds)
......
430 423
    """Copy an object from container to (another) container
431 424
    Use options:
432 425
    1. <container1>:<path1> <container2>[:path2] : from container1 to 2, if
433
        path2 is not given, target path will be container2:path1
426
    path2 is not given, target path will be container2:path1
434 427
    2. <container>:<path1> <container>:<path2> : make a copy in the same
435
        container
428
    container
436 429
    3. Use --container= instead of <container1>, but only for the first
437
        parameter
430
    parameter
438 431
    """
439 432

  
440 433
    arguments = dict(
......
481 474
    """Copy an object
482 475
    Use options:
483 476
    1. <container1>:<path1> <container2>[:path2] : from container1 to 2, if
484
        path2 is not given, target path will be container2:path1
477
    path2 is not given, target path will be container2:path1
485 478
    2. <container>:<path1> <container>:<path2> : rename
486 479
    3. Use --container= instead of <container1>, but only for the first
487
        parameter
480
    parameter
488 481
    """
489 482

  
490 483
    arguments = dict(
......
571 564
    arguments = dict(
572 565
        progress_bar=ProgressBarArgument(
573 566
            'do not show progress bar',
574
            '--no-progress-bar', 
567
            '--no-progress-bar',
575 568
            default=False)
576 569
    )
577 570

  
......
727 720
            '--object-version')
728 721
    )
729 722

  
730

  
731 723
    def main(self, container___path):
732 724
        super(self.__class__,
733 725
            self).main(container___path, path_is_optional=False)
......
866 858
    """Delete a container [or an object]"""
867 859

  
868 860
    arguments = dict(
869
        until=DateArgument( 'remove history until that date', '--until'),
861
        until=DateArgument('remove history until that date', '--until'),
870 862
        recursive=FlagArgument(
871 863
            'empty dir or container and delete (if dir)',
872 864
            ('-r', '--recursive'))
......
874 866

  
875 867
    def __init__(self, arguments={}):
876 868
        super(self.__class__, self).__init__(arguments)
877
        self['delimiter']=DelimiterArgument(
869
        self['delimiter'] = DelimiterArgument(
878 870
            self,
879 871
            parsed_name='--delimiter',
880 872
            help='delete objects prefixed with <object><delimiter>')
......
900 892
class store_purge(_store_container_command):
901 893
    """Purge a container
902 894
    To completely erase a container:
903
    /store delete -r <container>
904
    /store purge <container
895
    .   /store delete -r <container>
896
    .   /store purge <container
905 897
    """
906 898

  
907 899
    def main(self, container):
......
1260 1252

  
1261 1253
@command(pithos_cmds)
1262 1254
class store_touch(_store_container_command):
1263
    """Create an empty file of type application/octet-stream
1264
    If object exists, this command will make reset it to 0 length
1255
    """Create an empty file
1256
    If object exists, this command will reset it to 0 length
1265 1257
    """
1266 1258

  
1267
    def main(self, container___path, content_type='application/octet-stream'):
1259
    arguments = dict(
1260
        content_type=ValueArgument(
1261
            'Set content type (default: application/octet-stream)',
1262
            '--content-type',
1263
            default='application/octet-stream')
1264
    )
1265

  
1266
    def main(self, container___path):
1268 1267
        super(store_touch, self).main(container___path)
1269 1268
        try:
1270
            self.client.create_object(self.path, content_type)
1269
            self.client.create_object(self.path, self['content_type'])
1271 1270
        except ClientError as err:
1272 1271
            raiseCLIError(err)

Also available in: Unified diff