Repository: rabitt/pysox

Issue:
Support using same file path for input & output
Sox doesn't support using the same file as both input and output - doing this will result in an empty, invalid audio file. While this is sox behavior and not pysox, it would be nice if pysox took care of this behind the scenes. Right now the user needs to worry about this logic themselves, e.g. like this:

```python
import tempfile
import shutil
from scaper.util import _close_temp_files

audio_infile = '/Users/justin/Downloads/trimtest.wav'
audio_outfile = '/Users/justin/Downloads/trimtest.wav'
start_time = 2
end_time = 3

tfm = sox.Transformer()
tfm.trim(start_time, end_time)
if audio_outfile != audio_infile:
    tfm.build(audio_infile, audio_outfile)
else:
    # must use temp file in order to save to same file
    tmpfiles = []
    with _close_temp_files(tmpfiles):
        # Create tmp file
        tmpfiles.append(
            tempfile.NamedTemporaryFile(
                suffix='.wav', delete=True))
        # Save trimmed result to temp file
        tfm.build(audio_infile, tmpfiles[-1].name)
        # Copy result back to original file
        shutil.copyfile(tmpfiles[-1].name, audio_outfile)
```

Pysox *does* issue a warning when a file is about to be overwritten, which is even more confusing under this scenario since the user (who might be unfamiliar with the quirks of sox) has no reason to think that the overwritten file will be invalid.

Discussion:

Patch:
diff --git a/setup.py b/setup.py
index eee03d9..d0cd01c 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ if __name__ == "__main__":
     setup(
         name='sox',
 
-        version='1.2.1',
+        version='1.2.2',
 
         description='Python wrapper around SoX.',
 
diff --git a/sox/core.py b/sox/core.py
index 2b14d01..64a70cd 100644
--- a/sox/core.py
+++ b/sox/core.py
@@ -67,7 +67,6 @@ def sox(args):
 class SoxError(Exception):
     '''Exception to be raised when SoX exits with non-zero status.
     '''
-
     def __init__(self, *args, **kwargs):
         Exception.__init__(self, *args, **kwargs)
 
diff --git a/sox/transform.py b/sox/transform.py
index 438a3c3..f4eb248 100644
--- a/sox/transform.py
+++ b/sox/transform.py
@@ -395,6 +395,11 @@ class Transformer(object):
         file_info.validate_input_file(input_filepath)
         file_info.validate_output_file(output_filepath)
 
+        if input_filepath == output_filepath:
+            raise ValueError(
+                "input_filepath must be different from output_filepath."
+            )
+
         args = []
         args.extend(self.globals)
         args.extend(self.input_format)


Test patch:
diff --git a/tests/test_transform.py b/tests/test_transform.py
index aa357d1..056676c 100644
--- a/tests/test_transform.py
+++ b/tests/test_transform.py
@@ -386,6 +386,10 @@ class TestTransformerBuild(unittest.TestCase):
         with self.assertRaises(IOError):
             self.tfm.build('blah/asdf.wav', OUTPUT_FILE)
 
+    def test_input_output_equal(self):
+        with self.assertRaises(ValueError):
+            self.tfm.build(INPUT_FILE, INPUT_FILE)
+
     def test_failed_sox(self):
         self.tfm.effects = ['channels', '-1']
         with self.assertRaises(SoxError):