Revision e3d4d442

b/kamaki/cli/__init__.py
53 53
    from ordereddict import OrderedDict
54 54

  
55 55
#from kamaki import clients
56
from .errors import CLIError, CLISyntaxError, CLICmdIncompleteError
56
from .errors import CLIError, CLISyntaxError, CLICmdIncompleteError, CLICmdSpecError
57 57
from .config import Config #TO BE REMOVED
58 58
from .utils import bold, magenta, red, yellow, CommandTree, print_list, print_dict
59 59
from argument import _arguments, parse_known_args
b/kamaki/cli/argument.py
151 151
    def __init__(self, help='', parsed_name=None, default=None):
152 152
        super(ValueArgument, self).__init__(1, help, parsed_name, default)
153 153

  
154
class IntArgument(ValueArgument):
155
    @property 
156
    def value(self):
157
        return getattr(self, '_value', self.default)
158
    @value.setter
159
    def value(self, newvalue):
160
        if newvalue == self.default:
161
            self._value = self.default
162
            return
163
        try:
164
            self._value = int(newvalue)
165
        except ValueError:
166
            raise CLISyntaxError('IntArgument Error', details='Value %s not an int'%newvalue)
167

  
154 168
class VersionArgument(FlagArgument):
155 169
    @property 
156 170
    def value(self):
b/kamaki/cli/commands/pithos_cli.py
35 35
from kamaki.clients.utils import filter_in
36 36
from kamaki.cli.errors import CLIError, raiseCLIError
37 37
from kamaki.cli.utils import format_size, print_dict, pretty_keys, print_list
38
from kamaki.cli.argument import FlagArgument, ValueArgument
38
from kamaki.cli.argument import FlagArgument, ValueArgument, IntArgument
39 39
#set_api_description('store', 'Pithos+ storage commands')
40 40
API_DESCRIPTION = {'store':'Pithos+ storage commands'}
41 41
from kamaki.clients.pithos import PithosClient, ClientError
......
43 43
from sys import stdout, exit
44 44
import signal
45 45
from time import localtime, strftime, strptime, mktime
46
from datetime import datetime as dtm
46 47

  
47 48
from progress.bar import IncrementalBar
48 49

  
......
60 61
    def value(self, newvalue):
61 62
        self._value = newvalue
62 63

  
63
class UntilArgument(ValueArgument):
64
    def __init__(self, caller_obj, help='', parsed_name=None, default=None):
65
        super(UntilArgument, self).__init__(help, parsed_name, default)
66
        self.caller_obj = caller_obj
67

  
68
    @property 
69
    def value(self):
70
        _value = getattr(self, '_value', self.default)
71
        if _value is None:
72
            return None
73
        format = self.caller_obj.get_argument('format')
74
        try:
75
            t = strptime(_value, format)
76
        except ValueError as err:
77
            raise CLIError(message='in --until: '+unicode(err), importance=1)
78
        return int(mktime(t))
79
    @value.setter 
80
    def value(self, newvalue):
81
        self._value = newvalue
82

  
83 64
class MetaArgument(ValueArgument):
84 65
    @property 
85 66
    def value(self):
......
114 95
            yield
115 96
        return progress_gen
116 97

  
98
class SharingArgument(ValueArgument):
99
    @property 
100
    def value(self):
101
        return getattr(self, '_value', self.default)
102
    @value.setter
103
    def value(self, newvalue):
104
        perms = {}
105
        try:
106
            permlist = newvalue.split(' ')
107
        except AttributeError:
108
            return
109
        for p in permlist:
110
            try:
111
                (key,val) = p.split('=')
112
            except ValueError:
113
                raise CLIError(message='Error in --sharing', details='Incorrect format', importance=1)
114
            if key.lower() not in ('read', 'write'):
115
                raise CLIError(message='Error in --sharing', details='Invalid permition key %s'%key, importance=1)
116
            val_list = val.split(',')
117
            if not perms.has_key(key):
118
                perms[key]=[]
119
            for item in val_list:
120
                if item not in perms[key]:
121
                    perms[key].append(item)
122
        self._value = perms
123

  
124
class RangeArgument(ValueArgument):
125
    @property 
126
    def value(self):
127
        return getattr(self, '_value', self.default)
128
    @value.setter
129
    def value(self, newvalue):
130
        if newvalue is None:
131
            self._value = self.default
132
            return
133
        (start, end) = newvalue.split('_')
134
        (start, end) = (int(start), int(end))
135
        self._value = '%s-%s'%(start, end)
136

  
137
class DateArgument(ValueArgument):
138
    DATE_FORMATS = ["%a %b %d %H:%M:%S %Y",
139
        "%A, %d-%b-%y %H:%M:%S GMT",
140
        "%a, %d %b %Y %H:%M:%S GMT"]
141

  
142
    INPUT_FORMATS = DATE_FORMATS + ["%d-%m-%Y", "%H:%M:%S %d-%m-%Y"]
143

  
144
    @property 
145
    def value(self):
146
        return getattr(self, '_value', self.default)
147
    @value.setter
148
    def value(self, newvalue):
149
        if newvalue is None:
150
            return
151
        self._value = self.format_date(newvalue)
152

  
153
    def format_date(self, datestr):
154
        for format in self.INPUT_FORMATS:
155
            try:
156
                t = dtm.strptime(datestr, format)
157
            except ValueError:
158
                continue
159
            self._value = t.strftime(self.DATE_FORMATS[0])
160
            return
161
        raise CLIError('Date Argument Error',
162
            details='%s not a valid date. correct formats:\n\t%s'%(datestr, self.INPUT_FORMATS))
163

  
117 164
class _pithos_init(object):
118 165
    def __init__(self, arguments={}):
119 166
        self.arguments = arguments
......
211 258
        super(store_list, self).__init__(arguments)
212 259
        self.arguments['detail'] = FlagArgument('show detailed output', '-l')
213 260
        self.arguments['show_size'] = ValueArgument('print output in chunks of size N', '-N')
214
        self.arguments['limit'] = ValueArgument('show limited output', '-n')
261
        self.arguments['limit'] = IntArgument('show limited output', '-n')
215 262
        self.arguments['marker'] = ValueArgument('show output greater that marker', '--marker')
216 263
        self.arguments['prefix'] = ValueArgument('show output staritng with prefix', '--prefix')
217 264
        self.arguments['delimiter'] = ValueArgument('show output up to delimiter', '--delimiter')
......
222 269
            '--if-modified-since')
223 270
        self.arguments['if_unmodified_since'] = ValueArgument('show output not modified since then',
224 271
            '--if-unmodified-since')
225
        self.arguments['until'] = UntilArgument(self, 'show metadata until then', '--until')
272
        self.arguments['until'] = DateArgument('show metadata until then', '--until')
226 273
        self.arguments['format'] = ValueArgument('format to parse until data (default: d/m/Y H:M:S',
227 274
            '--format')
228 275
        self.arguments['shared'] = FlagArgument('show only shared', '--shared')
......
332 379
        super(self.__class__, self).__init__(arguments)
333 380
        self.arguments['versioning'] = ValueArgument('set container versioning (auto/none)',
334 381
            '--versioning')
335
        self.arguments['quota'] = ValueArgument('set default container quota', '--quota')
382
        self.arguments['quota'] = IntArgument('set default container quota', '--quota')
336 383
        self.arguments['meta'] = MetaArgument('set container metadata', '---meta')
337 384

  
338 385
    def main(self, container____directory__):
......
381 428
    """Copy an object"""
382 429

  
383 430
    def __init__(self, arguments={}):
384
        super(self.__class__, self).__init(arguments)
431
        super(self.__class__, self).__init__(arguments)
385 432

  
386 433
        self.arguments['source_version']=ValueArgument('copy specific version', '--source-version')
387
        self.arguments['public']=ValueArgument('make object publicly accessible', '--public')
434
        self.arguments['public']=FlagArgument('make object publicly accessible', '--public')
388 435
        self.arguments['content_type']=ValueArgument('change object\'s content type',
389 436
            '--content-type')
390 437
        self.arguments['delimiter']=DelimiterArgument(self, parsed_name='--delimiter',
......
454 501
        except ClientError as err:
455 502
            raiseCLIError(err)
456 503

  
457
class SharingArgument(ValueArgument):
458
    @property 
459
    def value(self):
460
        return getattr(self, '_value', self.default)
461
    @value.setter
462
    def value(self, newvalue):
463
        perms = {}
464
        try:
465
            permlist = newvalue.split(' ')
466
        except AttributeError:
467
            return
468
        for p in permlist:
469
            try:
470
                (key,val) = p.split('=')
471
            except ValueError:
472
                raise CLIError(message='Error in --sharing', details='Incorrect format', importance=1)
473
            if key.lower() not in ('read', 'write'):
474
                raise CLIError(message='Error in --sharing', details='Invalid permition key %s'%key, importance=1)
475
            val_list = val.split(',')
476
            if not perms.has_key(key):
477
                perms[key]=[]
478
            for item in val_list:
479
                if item not in perms[key]:
480
                    perms[key].append(item)
481
        self._value = perms
482

  
483 504
@command()
484 505
class store_manifest(_store_container_command):
485 506
    """Create a remote file with uploaded parts by manifestation"""
......
495 516
            '--content-type')
496 517
        self.arguments['sharing']=SharingArgument(parsed_name='--sharing',
497 518
            help='define sharing object policy ( "read=user1,grp1,user2,... write=user1,grp2,...')
498
        self.arguments['public']=ValueArgument('make object publicly accessible', '--public')
519
        self.arguments['public']=FlagArgument('make object publicly accessible', '--public')
499 520
        
500 521
    def main(self, container___path):
501 522
        super(self.__class__, self).main(container___path, path_is_optional=False)
......
512 533
class store_upload(_store_container_command):
513 534
    """Upload a file"""
514 535

  
515
    def update_parser(self, parser):
516
        super(self.__class__, self).update_parser(parser)
517
        parser.add_argument('--use_hashes', action='store_true', dest='use_hashes', default=False,
518
            help='provide hashmap file instead of data')
519
        parser.add_argument('--unchunked', action='store_true', dest='unchunked', default=False,
520
            help='avoid chunked transfer mode')
521
        parser.add_argument('--etag', action='store', dest='etag', default=None,
522
            help='check written data')
523
        parser.add_argument('--content-encoding', action='store', dest='content_encoding',
524
            default=None, help='provide the object MIME content type')
525
        parser.add_argument('--content-disposition', action='store', dest='content_disposition',
526
            default=None, help='provide the presentation style of the object')
527
        parser.add_argument('--content-type', action='store', dest='content_type', default=None,
528
            help='create object with specific content type')
529
        parser.add_argument('--sharing', action='store', dest='sharing', default=None,
536
    def __init__(self, arguments={}):
537
        super(self.__class__, self).__init__(arguments)
538
        self.arguments['use_hashes'] = FlagArgument('provide hashmap file instead of data',
539
            '--use-hashes')
540
        self.arguments['etag'] = ValueArgument('check written data', '--etag')
541
        self.arguments['unchunked'] = FlagArgument('avoid chunked transfer mode', '--unchunked')
542
        self.arguments['content_encoding']=ValueArgument('provide the object MIME content type',
543
            '--content-encoding')
544
        self.arguments['content_disposition'] = ValueArgument('provide the presentation style of the object',
545
            '--content-disposition')
546
        self.arguments['content_type']=ValueArgument('create object with specific content type',
547
            '--content-type')
548
        self.arguments['sharing']=SharingArgument(parsed_name='--sharing',
530 549
            help='define sharing object policy ( "read=user1,grp1,user2,... write=user1,grp2,...')
531
        parser.add_argument('--public', action='store_true', dest='public', default=False,
532
            help='make object publicly accessible')
533
        parser.add_argument('--with-pool-size', action='store', dest='poolsize', default=None,
534
            help='Set the greenlet pool size (advanced)')
535

  
536
    def getsharing(self, orelse={}):
537
        permstr = getattr(self.args, 'sharing')
538
        if permstr is None:
539
            return orelse
540
        perms = {}
541
        for p in permstr.split(' '):
542
            (key, val) = p.split('=')
543
            if key.lower() not in ('read', 'write'):
544
                raise CLIError(message='in --sharing: Invalid permition key', importance=1)
545
            val_list = val.split(',')
546
            if not perms.has_key(key):
547
                perms[key]=[]
548
            for item in val_list:
549
                if item not in perms[key]:
550
                    perms[key].append(item)
551
        return perms
550
        self.arguments['public']=FlagArgument('make object publicly accessible', '--public')
551
        self.arguments['poolsize']=IntArgument('set pool size', '--with-pool-size')
552
        self.arguments['progress_bar'] = ProgressBarArgument('do not show progress bar',
553
            '--no-progress-bar')
552 554

  
553 555
    def main(self, local_path, container____path__):
554 556
        super(self.__class__, self).main(container____path__)
555 557
        remote_path = local_path if self.path is None else self.path
556
        poolsize = getattr(self.args, 'poolsize')
558
        poolsize = self.get_argument('poolsize')
557 559
        if poolsize is not None:
558
            self.POOL_SIZE = int(poolsize)
560
            self.POOL_SIZE = poolsize
559 561
        try:
560 562
            with open(local_path) as f:
561
                if getattr(self.args, 'unchunked'):
563
                if self.get_argument('unchunked'):
562 564
                    self.client.upload_object_unchunked(remote_path, f,
563
                    etag=getattr(self.args, 'etag'), withHashFile=getattr(self.args, 'use_hashes'),
564
                    content_encoding=getattr(self.args, 'content_encoding'),
565
                    content_disposition=getattr(self.args, 'content_disposition'),
566
                    content_type=getattr(self.args, 'content_type'), sharing=self.getsharing(),
567
                    public=getattr(self.args, 'public'))
565
                    etag=self.get_argument('etag'), withHashFile=self.get_argument('use_hashes'),
566
                    content_encoding=self.get_argument('content_encoding'),
567
                    content_disposition=self.get_argument('content_disposition'),
568
                    content_type=self.get_argument('content_type'),
569
                    sharing=self.get_argument('sharing'), public=self.get_argument('public'))
568 570
                else:
569
                    hash_cb = self.progress('Calculating block hashes')
570
                    upload_cb = self.progress('Uploading blocks')
571
                    hash_cb=self.arguments['progress_bar'].get_generator('Calculating block hashes')
572
                    upload_cb=self.arguments['progress_bar'].get_generator('Uploading')
571 573
                    self.client.upload_object(remote_path, f, hash_cb=hash_cb, upload_cb=upload_cb,
572
                    content_encoding=getattr(self.args, 'content_encoding'),
573
                    content_disposition=getattr(self.args, 'content_disposition'),
574
                    content_type=getattr(self.args, 'content_type'), sharing=self.getsharing(),
575
                    public=getattr(self.args, 'public'))
574
                    content_encoding=self.get_argument('content_encoding'),
575
                    content_disposition=self.get_argument('content_disposition'),
576
                    content_type=self.get_argument('content_type'),
577
                    sharing=self.get_argument('sharing'), public=self.get_argument('public'))
576 578
        except ClientError as err:
577 579
            raiseCLIError(err)
578 580
        print 'Upload completed'
......
581 583
class store_download(_store_container_command):
582 584
    """Download a file"""
583 585

  
584
    def update_parser(self, parser):
585
        super(self.__class__, self).update_parser(parser)
586
        parser.add_argument('--no-progress-bar', action='store_true', dest='no_progress_bar',
587
            default=False, help='Dont display progress bars')
588
        parser.add_argument('--resume', action='store_true', dest='resume', default=False,
589
            help='Resume a previous download instead of overwritting it')
590
        parser.add_argument('--range', action='store', dest='range', default=None,
591
            help='show range of data')
592
        parser.add_argument('--if-match', action='store', dest='if_match', default=None,
593
            help='show output if ETags match')
594
        parser.add_argument('--if-none-match', action='store', dest='if_none_match', default=None,
595
            help='show output if ETags don\'t match')
596
        parser.add_argument('--if-modified-since', action='store', dest='if_modified_since',
597
            default=None, help='show output if modified since then')
598
        parser.add_argument('--if-unmodified-since', action='store', dest='if_unmodified_since',
599
            default=None, help='show output if not modified since then')
600
        parser.add_argument('--object-version', action='store', dest='object_version', default=None,
601
            help='get the specific version')
602
        parser.add_argument('--with-pool-size', action='store', dest='poolsize', default=None,
603
            help='Set the greenlet pool size (advanced)')
586
    def __init__(self, arguments={}):
587
        super(self.__class__, self).__init__(arguments)
588
        self.arguments['resume'] = FlagArgument(parsed_name='--resume',
589
            help = 'Resume a previous download instead of overwritting it')
590
        self.arguments['range'] = RangeArgument('show range of data', '--range')
591
        self.arguments['if_match'] = ValueArgument('show output if ETags match', '--if-match')
592
        self.arguments['if_none_match'] = ValueArgument('show output if ETags match',
593
            '--if-none-match')
594
        self.arguments['if_modified_since'] = DateArgument('show output modified since then',
595
            '--if-modified-since')
596
        self.arguments['if_unmodified_since'] = DateArgument('show output unmodified since then',
597
            '--if-unmodified-since')
598
        self.arguments['object_version'] = ValueArgument('get the specific version',
599
            '--object-version')
600
        self.arguments['poolsize']=IntArgument('set pool size', '--with-pool-size')
601
        self.arguments['progress_bar'] = ProgressBarArgument('do not show progress bar',
602
            '--no-progress-bar')
604 603

  
605 604
    def main(self, container___path, local_path=None):
606 605
        super(self.__class__, self).main(container___path, path_is_optional=False)
......
611 610
            out = stdout
612 611
        else:
613 612
            try:
614
                if hasattr(self.args, 'resume') and getattr(self.args, 'resume'):
613
                if self.get_argument('resume'):
615 614
                    out=open(local_path, 'rwb+')
616 615
                else:
617 616
                    out=open(local_path, 'wb+')
618 617
            except IOError as err:
619 618
                raise CLIError(message='Cannot write to file %s - %s'%(local_path,unicode(err)),
620 619
                    importance=1)
621
        download_cb = None if getattr(self.args, 'no_progress_bar') \
622
        else self.progress('Downloading')
623
        poolsize = getattr(self.args, 'poolsize')
620
        download_cb = self.arguments['progress_bar'].get_generator('Downloading')
621
        poolsize = self.get_argument('poolsize')
624 622
        if poolsize is not None:
625 623
            self.POOL_SIZE = int(poolsize)
626 624

  
627 625
        try:
628 626
            self.client.download_object(self.path, out, download_cb,
629
                range=getattr(self.args, 'range'), version=getattr(self.args,'object_version'),
630
                if_match=getattr(self.args, 'if_match'), resume=getattr(self.args, 'resume'),
631
                if_none_match=getattr(self.args, 'if_none_match'),
632
                if_modified_since=getattr(self.args, 'if_modified_since'),
633
                if_unmodified_since=getattr(self.args, 'if_unmodified_since'))
627
                range=self.get_argument('range'), version=self.get_argument('object_version'),
628
                if_match=self.get_argument('if_match'), resume=self.get_argument('resume'),
629
                if_none_match=self.get_argument('if_none_match'),
630
                if_modified_since=self.get_argument('if_modified_since'),
631
                if_unmodified_since=self.get_argument('if_unmodified_since'))
634 632
        except ClientError as err:
635 633
            raiseCLIError(err)
636 634
        except KeyboardInterrupt:
......
643 641
class store_hashmap(_store_container_command):
644 642
    """Get the hashmap of an object"""
645 643

  
646
    def update_parser(self, parser):
647
        super(self.__class__, self).update_parser(parser)
648
        parser.add_argument('--if-match', action='store', dest='if_match', default=None,
649
            help='show output if ETags match')
650
        parser.add_argument('--if-none-match', action='store', dest='if_none_match', default=None,
651
            help='show output if ETags dont match')
652
        parser.add_argument('--if-modified-since', action='store', dest='if_modified_since',
653
            default=None, help='show output if modified since then')
654
        parser.add_argument('--if-unmodified-since', action='store', dest='if_unmodified_since',
655
            default=None, help='show output if not modified since then')
656
        parser.add_argument('--object-version', action='store', dest='object_version', default=None,
657
            help='get the specific version')
644
    def __init__(self, arguments={}):
645
        super(self.__class__, self).__init__(arguments)
646
        self.arguments['if_match'] = ValueArgument('show output if ETags match', '--if-match')
647
        self.arguments['if_none_match'] = ValueArgument('show output if ETags match',
648
            '--if-none-match')
649
        self.arguments['if_modified_since'] = DateArgument('show output modified since then',
650
            '--if-modified-since')
651
        self.arguments['if_unmodified_since'] = DateArgument('show output unmodified since then',
652
            '--if-unmodified-since')
653
        self.arguments['object_version'] = ValueArgument('get the specific version',
654
            '--object-version')
658 655

  
659 656
    def main(self, container___path):
660 657
        super(self.__class__, self).main(container___path, path_is_optional=False)
661 658
        try:
662 659
            data = self.client.get_object_hashmap(self.path,
663
                version=getattr(self.args, 'object_version'),
664
                if_match=getattr(self.args, 'if_match'),
665
                if_none_match=getattr(self.args, 'if_none_match'),
666
                if_modified_since=getattr(self.args, 'if_modified_since'),
667
                if_unmodified_since=getattr(self.args, 'if_unmodified_since'))
660
                version=self.arguments('object_version'),
661
                if_match=self.arguments('if_match'),
662
                if_none_match=self.arguments('if_none_match'),
663
                if_modified_since=self.arguments('if_modified_since'),
664
                if_unmodified_since=self.arguments('if_unmodified_since'))
668 665
        except ClientError as err:
669 666
            raiseCLIError(err)
670 667
        print_dict(data)
......
673 670
class store_delete(_store_container_command):
674 671
    """Delete a container [or an object]"""
675 672

  
676
    def update_parser(self, parser):
677
        super(self.__class__, self).update_parser(parser)
678
        parser.add_argument('--until', action='store', dest='until', default=None,
679
            help='remove history until that date')
680
        parser.add_argument('--format', action='store', dest='format', default='%d/%m/%Y %H:%M:%S',
681
            help='format to parse until date (default: d/m/Y H:M:S)')
682
        parser.add_argument('--delimiter', action='store', dest='delimiter',
683
            default=None, 
684
            help='mass delete objects with path staring with <object><delimiter>')
685
        parser.add_argument('-r', action='store_true', dest='recursive', default=False,
686
            help='empty dir or container and delete (if dir)')
687
    
688
    def getuntil(self, orelse=None):
689
        if hasattr(self.args, 'until'):
690
            import time
691
            until = getattr(self.args, 'until')
692
            if until is None:
693
                return None
694
            format = getattr(self.args, 'format')
695
            try:
696
                t = time.strptime(until, format)
697
            except ValueError as err:
698
                raise CLIError(message='in --until: '+unicode(err), importance=1)
699
            return int(time.mktime(t))
700
        return orelse
701

  
702
    def getdelimiter(self, orelse=None):
703
        try:
704
            dlm = getattr(self.args, 'delimiter')
705
            if dlm is None:
706
                return '/' if getattr(self.args, 'recursive') else orelse
707
        except AttributeError:
708
            return orelse
709
        return dlm
673
    def __init__(self, arguments={}):
674
        super(self.__class__, self).__init__(arguments)
675
        self.arguments['until'] = DateArgument('remove history until that date', '--until')
676
        self.arguments['recursive'] = FlagArgument('empty dir or container and delete (if dir)',
677
            '--recursive')
678
        self.arguments['delimiter'] = DelimiterArgument(self, parsed_name='--delimiter',
679
            help = 'mass delete objects with path staring with <object><delimiter>')
710 680

  
711 681
    def main(self, container____path__):
712 682
        super(self.__class__, self).main(container____path__)
713 683
        try:
714 684
            if self.path is None:
715
                self.client.del_container(until=self.getuntil(), delimiter=self.getdelimiter())
685
                self.client.del_container(until=self.get_argument('until'),
686
                    delimiter=self.get_argument('delimiter'))
716 687
            else:
717 688
                #self.client.delete_object(self.path)
718
                self.client.del_object(self.path, until=self.getuntil(),
719
                    delimiter=self.getdelimiter())
689
                self.client.del_object(self.path, until=self.get_argument('until'),
690
                    delimiter=self.get_argument('delimiter'))
720 691
        except ClientError as err:
721 692
            raiseCLIError(err)
722 693

  
......
830 801
class store_meta(_store_container_command):
831 802
    """Get custom meta-content for account [, container [or object]]"""
832 803

  
833
    def update_parser(self, parser):
834
        super(self.__class__, self).update_parser(parser)
835
        parser.add_argument('-l', action='store_true', dest='detail', default=False,
836
            help='show detailed output')
837
        parser.add_argument('--until', action='store', dest='until', default=None,
838
            help='show metadata until that date')
839
        dateformat='%d/%m/%Y %H:%M:%S'
840
        parser.add_argument('--format', action='store', dest='format', default=dateformat,
841
            help='format to parse until date (default: "d/m/Y H:M:S")')
842
        parser.add_argument('--object_version', action='store', dest='object_version', default=None,
804
    def __init__(self, arguments = {}):
805
        super(self.__class__, self).__init__(arguments)
806
        self.arguments['detail'] = FlagArgument('show detailed output', '-l')
807
        self.arguments['until'] = DateArgument('show metadata until then', '--until')
808
        self.arguments['object_version'] = ValueArgument(parsed_name='--object-version',
843 809
            help='show specific version \ (applies only for objects)')
844 810

  
845
    def getuntil(self, orelse=None):
846
        if hasattr(self.args, 'until'):
847
            import time
848
            until = getattr(self.args, 'until')
849
            if until is None:
850
                return None
851
            format = getattr(self.args, 'format')
852
            #except TypeError:
853
            try:
854
                t = time.strptime(until, format)
855
            except ValueError as err:
856
                raise CLIError(message='in --until: '+unicode(err), importance=1)
857
            return int(time.mktime(t))
858
        return orelse
859

  
860 811
    def main(self, container____path__ = None):
861 812
        super(self.__class__, self).main(container____path__)
862 813

  
863
        detail = getattr(self.args, 'detail')
814
        detail = self.get_argument('detail')
864 815
        try:
865 816
            if self.container is None:
866 817
                print(bold(self.client.account))
867 818
                if detail:
868
                    reply = self.client.get_account_info(until=self.getuntil())
819
                    reply = self.client.get_account_info(until=self.get_argument('until'))
869 820
                else:
870
                    reply = self.client.get_account_meta(until=self.getuntil())
821
                    reply = self.client.get_account_meta(until=self.get_argument('until'))
871 822
                    reply = pretty_keys(reply, '-')
872 823
            elif self.path is None:
873 824
                print(bold(self.client.account+': '+self.container))
874 825
                if detail:
875
                    reply = self.client.get_container_info(until = self.getuntil())
826
                    reply = self.client.get_container_info(until = self.get_argument('until'))
876 827
                else:
877
                    cmeta = self.client.get_container_meta(until=self.getuntil())
878
                    ometa = self.client.get_container_object_meta(until=self.getuntil())
828
                    cmeta = self.client.get_container_meta(until=self.get_argument('until'))
829
                    ometa = self.client.get_container_object_meta(until=self.get_argument('until'))
879 830
                    reply = {'container-meta':pretty_keys(cmeta, '-'),
880 831
                        'object-meta':pretty_keys(ometa, '-')}
881 832
            else:
882 833
                print(bold(self.client.account+': '+self.container+':'+self.path))
883
                version=getattr(self.args, 'object_version')
834
                version=self.get_argument('object_version')
884 835
                if detail:
885 836
                    reply = self.client.get_object_info(self.path, version = version)
886 837
                else:
......
1025 976
class store_sharers(_store_account_command):
1026 977
    """List the accounts that share objects with default account"""
1027 978

  
1028
    def update_parser(self, parser):
1029
        super(store_sharers, self).update_parser(parser)
1030
        parser.add_argument('-l', action='store_true', dest='detail', default=False,
1031
            help='show detailed output')
1032
        parser.add_argument('-n', action='store',  dest='limit', default=10000,
1033
            help='show limited output')
1034
        parser.add_argument('--marker', action='store', dest='marker', default=None,
1035
            help='show output greater then marker')
979
    def __init__(self, arguments = {}):
980
        super(self.__class__, self).__init__(arguments)
981
        self.arguments['detail'] = FlagArgument('show detailed output', '-l')
982
        self.arguments['limit'] = IntArgument('show limited output', '--n', default=1000)
983
        self.arguments['marker'] = ValueArgument('show output greater then marker', '--marker')
1036 984

  
1037 985
    def main(self):
1038 986
        super(self.__class__, self).main()
1039 987
        try:
1040
            accounts = self.client.get_sharing_accounts(marker=getattr(self.args, 'marker'))
988
            accounts = self.client.get_sharing_accounts(marker=self.get_argument('marker'))
1041 989
        except ClientError as err:
1042 990
            raiseCLIError(err)
1043 991

  
1044 992
        for acc in accounts:
1045 993
            stdout.write(bold(acc['name'])+' ')
1046
            if getattr(self.args, 'detail'):
994
            if self.get_argument('detail'):
1047 995
                print_dict(acc, exclude='name', ident=18)
1048
        if not getattr(self.args, 'detail'):
996
        if not self.get_argument('detail'):
1049 997
            print
1050 998

  
1051 999
@command()

Also available in: Unified diff