File 0001-Skip-tests-that-use-unavailable-codecs.patch of Package python-pydub

From 01383a88fe6bd574e3e47547ee6b7828af52a344 Mon Sep 17 00:00:00 2001
From: Antonio Larrosa <antonio.larrosa@gmail.com>
Date: Tue, 19 Feb 2019 20:01:39 +0100
Subject: [PATCH] Skip tests that use unavailable codecs

In openSUSE, ffmpeg doesn't support aac audio and some other codecs due
to legal reasons. When building the pydub packages and running tests,
some of these fail because the files format_test.m4a, creative_common.mp4
wrong_extension.aac can't be read since they use aac audio.

This commit adds two functions get_supported_decoders and
get_supported_encoders that return a set with the decoders/encoders that
are supported. Then it also adds some decorators to the tests to skip
the tests that use unsupported codecs.

Note that functools.lru_cache was added in python 3.3, so it can't be
used and that's the reason I added a small implementation of a cache
decorator so we don't have to execute ffmpeg for every call to get
the supported codecs.

https://github.com/jiaaro/pydub/pull/362
---
 pydub/utils.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
 test/test.py   | 22 ++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/pydub/utils.py b/pydub/utils.py
index def1a72..8cf0262 100644
--- a/pydub/utils.py
+++ b/pydub/utils.py
@@ -8,6 +8,7 @@ from subprocess import Popen, PIPE
 from math import log, ceil
 from tempfile import TemporaryFile
 from warnings import warn
+from functools import wraps
 
 try:
     import audioop
@@ -351,3 +352,56 @@ def mediainfo(filepath):
                 info[key] = value
 
     return info
+
+
+def cache_codecs(function):
+    cache = {}
+
+    @wraps(function)
+    def wrapper():
+        try:
+            return cache[0]
+        except:
+            cache[0] = function()
+            return cache[0]
+
+    return wrapper
+
+
+@cache_codecs
+def get_supported_codecs():
+    encoder = get_encoder_name()
+    command = [encoder, "-codecs"]
+    res = Popen(command, stdout=PIPE, stderr=PIPE)
+    output = res.communicate()[0].decode("utf-8")
+    if res.returncode != 0:
+        return []
+
+    if sys.platform == 'win32':
+        output = output.replace("\r", "")
+
+
+    rgx = re.compile(r"^([D.][E.][AVS.][I.][L.][S.]) (\w*) +(.*)")
+    decoders = set()
+    encoders = set()
+    for line in output.split('\n'):
+        match = rgx.match(line.strip())
+        if not match:
+            continue
+        flags, codec, name = match.groups()
+
+        if flags[0] == 'D':
+            decoders.add(codec)
+
+        if flags[1] == 'E':
+            encoders.add(codec)
+
+    return (decoders, encoders)
+
+
+def get_supported_decoders():
+    return get_supported_codecs()[0]
+
+
+def get_supported_encoders():
+    return get_supported_codecs()[1]
diff --git a/test/test.py b/test/test.py
index 415f14c..bc5d0c7 100644
--- a/test/test.py
+++ b/test/test.py
@@ -18,6 +18,8 @@ from pydub.utils import (
     make_chunks,
     mediainfo,
     get_encoder_name,
+    get_supported_decoders,
+    get_supported_encoders,
 )
 from pydub.exceptions import (
     InvalidTag,
@@ -670,6 +672,8 @@ class AudioSegmentTests(unittest.TestCase):
             if sys.platform == 'win32':
                 os.remove(tmp_mp3_file.name)
 
+    @unittest.skipUnless('aac' in get_supported_decoders(),
+                         "Unsupported codecs")
     def test_formats(self):
         seg_m4a = AudioSegment.from_file(
             os.path.join(data_dir, 'format_test.m4a'), "m4a")
@@ -688,6 +692,8 @@ class AudioSegmentTests(unittest.TestCase):
         wav = AudioSegment.from_wav(wav_file)
         self.assertEqual(wav.duration_seconds, self.seg1.duration_seconds)
 
+    @unittest.skipUnless('aac' in get_supported_decoders(),
+                         "Unsupported codecs")
     def test_autodetect_format(self):
         aac_path = os.path.join(data_dir, 'wrong_extension.aac')
         fn = partial(AudioSegment.from_file, aac_path, "aac")
@@ -720,21 +726,29 @@ class AudioSegmentTests(unittest.TestCase):
             AudioSegment.from_file(self.mp3_file_path).export(tmp_webm_file,
                                                               format="webm")
 
+    @unittest.skipUnless('aac' in get_supported_decoders(),
+                         "Unsupported codecs")
     def test_export_mp4_as_ogg(self):
         with NamedTemporaryFile('w+b', suffix='.ogg') as tmp_ogg_file:
             AudioSegment.from_file(self.mp4_file_path).export(tmp_ogg_file,
                                                               format="ogg")
 
+    @unittest.skipUnless('aac' in get_supported_decoders(),
+                         "Unsupported codecs")
     def test_export_mp4_as_mp3(self):
         with NamedTemporaryFile('w+b', suffix='.mp3') as tmp_mp3_file:
             AudioSegment.from_file(self.mp4_file_path).export(tmp_mp3_file,
                                                               format="mp3")
 
+    @unittest.skipUnless('aac' in get_supported_decoders(),
+                         "Unsupported codecs")
     def test_export_mp4_as_wav(self):
         with NamedTemporaryFile('w+b', suffix='.wav') as tmp_wav_file:
             AudioSegment.from_file(self.mp4_file_path).export(tmp_wav_file,
                                                               format="mp3")
 
+    @unittest.skipUnless('aac' in get_supported_decoders(),
+                         "Unsupported codecs")
     def test_export_mp4_as_mp3_with_tags(self):
         with NamedTemporaryFile('w+b', suffix='.mp3') as tmp_mp3_file:
             tags_dict = {
@@ -746,6 +760,8 @@ class AudioSegmentTests(unittest.TestCase):
                                                               format="mp3",
                                                               tags=tags_dict)
 
+    @unittest.skipUnless('aac' in get_supported_decoders(),
+                         "Unsupported codecs")
     def test_export_mp4_as_mp3_with_tags_raises_exception_when_tags_are_not_a_dictionary(self):
         with NamedTemporaryFile('w+b', suffix='.mp3') as tmp_mp3_file:
             json = '{"title": "The Title You Want", "album": "Name of the Album", "artist": "Artist\'s name"}'
@@ -754,6 +770,8 @@ class AudioSegmentTests(unittest.TestCase):
                 format="mp3", tags=json)
             self.assertRaises(InvalidTag, func)
 
+    @unittest.skipUnless('aac' in get_supported_decoders(),
+                         "Unsupported codecs")
     def test_export_mp4_as_mp3_with_tags_raises_exception_when_id3version_is_wrong(self):
         tags = {'artist': 'Artist', 'title': 'Title'}
         with NamedTemporaryFile('w+b', suffix='.mp3') as tmp_mp3_file:
@@ -766,6 +784,8 @@ class AudioSegmentTests(unittest.TestCase):
             )
             self.assertRaises(InvalidID3TagVersion, func)
 
+    @unittest.skipUnless('aac' in get_supported_decoders(),
+                         "Unsupported codecs")
     def test_export_mp3_with_tags(self):
         tags = {'artist': 'Mozart', 'title': 'The Magic Flute'}
 
@@ -883,6 +903,8 @@ class AudioSegmentTests(unittest.TestCase):
         # average volume should be reduced
         self.assertTrue(compressed.rms < self.seg1.rms)
 
+    @unittest.skipUnless('aac' in get_supported_decoders(),
+                         "Unsupported codecs")
     def test_exporting_to_ogg_uses_default_codec_when_codec_param_is_none(self):
         delete = sys.platform != 'win32'
 
-- 
2.20.1

openSUSE Build Service is sponsored by