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