From c39ad09173501b09708517a980ac3f02c87083d8 Mon Sep 17 00:00:00 2001 From: Matthias Geier Date: Thu, 20 Feb 2014 15:59:24 +0100 Subject: [PATCH] Refactor the sequence interface Refactoring: * factor-out duplicate code to separate method _get_slice_bounds() * replace 4 if-clauses with one call to slice.indices() * issue #6 is still not solved because __len__() is still broken (#11) Change behavior to be more sane: * raise error if step != 1 * this was silently ignored before Change behavior to be closer to Python indexing: * if start > stop (assuming step==1), an empty array is returned * before, the two values were flipped * if negative values exceed length, they are set to maximum * something strange happened before ... --- pysoundfile.py | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/pysoundfile.py b/pysoundfile.py index cd58020..568ae21 100644 --- a/pysoundfile.py +++ b/pysoundfile.py @@ -423,25 +423,25 @@ def __len__(self): self.seek_absolute(curr) return(length) + def _get_slice_bounds(self, frame): + # get start and stop index from slice, asserting step==1 + if not isinstance(frame, slice): + frame = slice(frame, frame + 1) + start, stop, step = frame.indices(len(self)) + if step != 1: + raise RuntimeError("Step size must be 1!") + if start > stop: + stop = start + return start, stop + def __getitem__(self, frame): # access the file as if it where a one-dimensional Numpy # array. Data must be in the form (frames x channels). # Both open slice bounds and negative values are allowed. - if not isinstance(frame, slice): - frame = slice(frame, frame+1) - if frame.start is None: - frame = slice(0, frame.stop) - if frame.stop is None: - frame = slice(frame.start, len(self)) - if frame.start < 0: - frame = slice(len(self)+frame.start, frame.stop) - if frame.stop < 0: - frame = slice(frame.start, len(self)+frame.stop) - if frame.start > frame.stop: - frame = slice(frame.stop, frame.start) + start, stop = self._get_slice_bounds(frame) curr = self.seek(0) - self.seek_absolute(frame.start) - data = self.read(frame.stop-frame.start) + self.seek_absolute(start) + data = self.read(stop - start) self.seek(curr) return data @@ -451,22 +451,13 @@ def __setitem__(self, frame, data): # Both open slice bounds and negative values are allowed. if self._file_mode == read_mode: raise RuntimeError("Can not write to read-only file") - if not isinstance(frame, slice): - frame = slice(frame, frame+1) - if frame.start is None: - frame = slice(0, frame.stop) - if frame.stop is None: - frame = slice(frame.start, len(self)) - if frame.start < 0: - frame = slice(len(self)+frame.start, frame.stop) - if frame.stop < 0: - frame = slice(frame.start, len(self)+frame.stop) - if frame.stop-frame.start != len(data): + start, stop = self._get_slice_bounds(frame) + if stop - start != len(data): raise IndexError( "Could not fit data of length %i into slice of length %i" % - (len(data), frame.stop-frame.start)) + (len(data), stop - start)) curr = self.seek(0) - self.seek_absolute(frame.start) + self.seek_absolute(start) self.write(data) self.seek(curr) return data