Revision 49cc29b2

b/Changelog
32 32
- Add a -l option to upload, for listing uploaded objects details [#3730]
33 33
- Add option to cache container info for upload_object [#3707]
34 34
- Add enumeration to all listing commands, make it optional [#3739]
35
- Add a download_to_string method in pithos client [#3608]
35 36

  
b/kamaki/clients/livetest/pithos.py
677 677
        self.client.download_object(trg_fname, dnl_f)
678 678

  
679 679
        print('\tCheck if files match...')
680
        for pos in (0, f_size / 2, f_size - 20):
680
        for pos in (0, f_size / 2, f_size - 128):
681 681
            src_f.seek(pos)
682 682
            dnl_f.seek(pos)
683
            self.assertEqual(src_f.read(10), dnl_f.read(10))
683
            self.assertEqual(src_f.read(64), dnl_f.read(64))
684

  
685
        print('\tDownload KiBs to string and check again...')
686
        for pos in (0, f_size / 2, f_size - 256):
687
            src_f.seek(pos)
688
            tmp_s = self.client.download_to_string(
689
                trg_fname,
690
                range_str='%s-%s' % (pos, (pos + 128)))
691
            self.assertEqual(tmp_s, src_f.read(len(tmp_s)))
684 692

  
685 693
        """Upload a boring file"""
686 694
        trg_fname = 'boringfile_%s' % self.now
b/kamaki/clients/pithos/__init__.py
36 36
from os import fstat
37 37
from hashlib import new as newhashlib
38 38
from time import time
39
from StringIO import StringIO
39 40

  
40 41
from binascii import hexlify
41 42

  
......
43 44
from kamaki.clients.pithos.rest_api import PithosRestClient
44 45
from kamaki.clients.storage import ClientError
45 46
from kamaki.clients.utils import path4url, filter_in
46
from StringIO import StringIO
47 47

  
48 48

  
49 49
def _pithos_hash(block, blockhash):
......
623 623

  
624 624
        self._complete_cb()
625 625

  
626
    def download_to_string(
627
            self, obj,
628
            download_cb=None,
629
            version=None,
630
            range_str=None,
631
            if_match=None,
632
            if_none_match=None,
633
            if_modified_since=None,
634
            if_unmodified_since=None):
635
        """Download an object to a string (multiple connections)
636

  
637
        :param obj: (str) remote object path
638

  
639
        :param download_cb: optional progress.bar object for downloading
640

  
641
        :param version: (str) file version
642

  
643
        :param range_str: (str) from, to are file positions (int) in bytes
644

  
645
        :param if_match: (str)
646

  
647
        :param if_none_match: (str)
648

  
649
        :param if_modified_since: (str) formated date
650

  
651
        :param if_unmodified_since: (str) formated date
652

  
653
        :returns: (str) the whole object contents
654
        """
655
        restargs = dict(
656
            version=version,
657
            data_range=None if range_str is None else 'bytes=%s' % range_str,
658
            if_match=if_match,
659
            if_none_match=if_none_match,
660
            if_modified_since=if_modified_since,
661
            if_unmodified_since=if_unmodified_since)
662

  
663
        (
664
            blocksize,
665
            blockhash,
666
            total_size,
667
            hash_list,
668
            remote_hashes) = self._get_remote_blocks_info(obj, **restargs)
669
        assert total_size >= 0
670

  
671
        if download_cb:
672
            self.progress_bar_gen = download_cb(len(hash_list))
673
            self._cb_next()
674

  
675
        ret = ''
676
        for blockid, blockhash in enumerate(remote_hashes):
677
            start = blocksize * blockid
678
            is_last = start + blocksize > total_size
679
            end = (total_size - 1) if is_last else (start + blocksize - 1)
680
            (start, end) = _range_up(start, end, range_str)
681
            if start == end:
682
                continue
683
            restargs['data_range'] = 'bytes=%s-%s' % (start, end)
684
            r = self.object_get(obj, success=(200, 206), **restargs)
685
            ret += r.content
686
            self._cb_next()
687

  
688
        self._complete_cb()
689
        return ret
690

  
626 691
    #Command Progress Bar method
627 692
    def _cb_next(self, step=1):
628 693
        if hasattr(self, 'progress_bar_gen'):
b/kamaki/clients/pithos/test.py
1103 1103

  
1104 1104
    @patch('%s.get_object_hashmap' % pithos_pkg, return_value=object_hashmap)
1105 1105
    @patch('%s.object_get' % pithos_pkg, return_value=FR())
1106
    def test_download_to_string(self, GET, GOH):
1107
        FR.content = 'some sample content'
1108
        num_of_blocks = len(object_hashmap['hashes'])
1109
        r = self.client.download_to_string(obj)
1110
        expected_content = FR.content * num_of_blocks
1111
        self.assertEqual(expected_content, r)
1112
        self.assertEqual(len(GET.mock_calls), num_of_blocks)
1113
        self.assertEqual(GET.mock_calls[-1][1], (obj,))
1114

  
1115
        kwargs = dict(
1116
            version='version',
1117
            range_str='10-20',
1118
            if_match='if and only if',
1119
            if_none_match='if and only not',
1120
            if_modified_since='what if not?',
1121
            if_unmodified_since='this happens if not!')
1122
        expargs = dict(kwargs)
1123
        expargs.pop('range_str')
1124
        for k in expargs:
1125
            expargs[k] = None
1126
        GOH.assert_called_once_with(obj, **expargs)
1127

  
1128
        r = self.client.download_to_string(obj, **kwargs)
1129
        expargs['data_range'] = 'bytes=%s' % kwargs['range_str']
1130
        for k, v in expargs.items():
1131
            self.assertEqual(
1132
                GET.mock_calls[-1][2][k],
1133
                v or kwargs.get(k))
1134

  
1135
    @patch('%s.get_object_hashmap' % pithos_pkg, return_value=object_hashmap)
1136
    @patch('%s.object_get' % pithos_pkg, return_value=FR())
1106 1137
    def test_download_object(self, GET, GOH):
1107 1138
        num_of_blocks = 8
1108 1139
        tmpFile = self._create_temp_file(num_of_blocks)

Also available in: Unified diff