diff options
Diffstat (limited to 'swiftclient/utils.py')
-rw-r--r-- | swiftclient/utils.py | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/swiftclient/utils.py b/swiftclient/utils.py index 9d94b6b..0abaed6 100644 --- a/swiftclient/utils.py +++ b/swiftclient/utils.py @@ -202,27 +202,36 @@ class LengthWrapper(object): def __init__(self, readable, length, md5=False): """ :param readable: The filelike object to read from. - :param length: The maximum amount of content to that can be read from + :param length: The maximum amount of content that can be read from the filelike object before it is simulated to be empty. :param md5: Flag to enable calculating the MD5 of the content as it is read. """ - self.md5sum = hashlib.md5() if md5 else NoopMD5() + self._md5 = md5 + self._reset_md5() self._length = self._remaining = length self._readable = readable + self._can_reset = all(hasattr(readable, attr) + for attr in ('seek', 'tell')) + if self._can_reset: + self._start = readable.tell() def __len__(self): return self._length + def _reset_md5(self): + self.md5sum = hashlib.md5() if self._md5 else NoopMD5() + def get_md5sum(self): return self.md5sum.hexdigest() - def read(self, *args, **kwargs): + def read(self, size=-1): if self._remaining <= 0: return '' - chunk = self._readable.read(*args, **kwargs)[:self._remaining] + to_read = self._remaining if size < 0 else min(size, self._remaining) + chunk = self._readable.read(to_read) self._remaining -= len(chunk) try: @@ -232,6 +241,21 @@ class LengthWrapper(object): return chunk + @property + def reset(self): + if self._can_reset: + return self._reset + raise AttributeError("%r object has no attribute 'reset'" % + type(self).__name__) + + def _reset(self, *args, **kwargs): + if not self._can_reset: + raise TypeError('%r object cannot be reset; needs both seek and ' + 'tell methods' % type(self._readable).__name__) + self._readable.seek(self._start) + self._reset_md5() + self._remaining = self._length + def iter_wrapper(iterable): for chunk in iterable: @@ -240,3 +264,13 @@ def iter_wrapper(iterable): # causing the server to close the connection continue yield chunk + + +def n_at_a_time(seq, n): + for i in range(0, len(seq), n): + yield seq[i:i + n] + + +def n_groups(seq, n): + items_per_group = ((len(seq) - 1) // n) + 1 + return n_at_a_time(seq, items_per_group) |