Skip to content

BUG: IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy test failures with PyPy3.10 #25164

@mgorny

Description

@mgorny

Describe the issue:

When running the test suite using PyPy3.10 7.3.13, the following 3 tests fail:

FAILED IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_normalization - ValueError: cannot convert floa...
FAILED IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_without_normalization - ValueError: Audio data ...
FAILED IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_from_numpy_array - ValueError: cannot convert float ...

Reproduce the code example:

pypy3.10 -m venv .venv
. .venv/bin/activate
pip install '.[test]' numpy
python -m pytest -vv IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy

Error message:

========================================================= test session starts =========================================================
platform linux -- Python 3.10.13[pypy-7.3.13-final], pytest-7.0.1, pluggy-1.3.0 -- /tmp/ipython/.venv/bin/python
cachedir: .pytest_cache
rootdir: /tmp/ipython, configfile: pyproject.toml
plugins: asyncio-0.21.1
asyncio: mode=strict
collected 7 items                                                                                                                     

IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_normalization FAILED                              [ 14%]
IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_without_normalization FAILED                      [ 28%]
IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_without_normalization_raises_for_invalid_data PASSED [ 42%]
IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_from_list PASSED                                       [ 57%]
IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_from_numpy_array FAILED                                [ 71%]
IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_from_numpy_array_without_rate_raises PASSED            [ 85%]
IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_raises_for_nested_list PASSED                          [100%]

============================================================== FAILURES ===============================================================
_______________________________________ TestAudioDataWithoutNumpy.test_audio_data_normalization _______________________________________

data = array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14])
rate = 44100, normalize = True

    @staticmethod
    def _make_wav(data, rate, normalize):
        """ Transform a numpy array to a PCM bytestring """
        from io import BytesIO
        import wave
    
        try:
>           scaled, nchan = Audio._validate_and_normalize_with_numpy(data, normalize)

IPython/lib/display.py:152: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

data = array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14])
normalize = True

    @staticmethod
    def _validate_and_normalize_with_numpy(data, normalize) -> Tuple[bytes, int]:
        import numpy as np
    
>       data = np.array(data, dtype=float)

IPython/lib/display.py:172: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <MagicMock id='94611245842056'>
args = (array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14]),)
kwargs = {'dtype': <class 'float'>}

    def __call__(self, /, *args, **kwargs):
        # can't use self in-case a function / method we are mocking uses self
        # in the signature
        self._mock_check_sig(*args, **kwargs)
        self._increment_mock_call(*args, **kwargs)
>       return self._mock_call(*args, **kwargs)

/usr/lib/pypy3.10/unittest/mock.py:1114: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <MagicMock id='94611245842056'>
args = (array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14]),)
kwargs = {'dtype': <class 'float'>}

    def _mock_call(self, /, *args, **kwargs):
>       return self._execute_mock_call(*args, **kwargs)

/usr/lib/pypy3.10/unittest/mock.py:1118: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <MagicMock id='94611245842056'>
args = (array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14]),)
kwargs = {'dtype': <class 'float'>}, effect = <class 'ImportError'>

    def _execute_mock_call(self, /, *args, **kwargs):
        # separate from _increment_mock_call so that awaited functions are
        # executed separately from their call, also AsyncMock overrides this method
    
        effect = self.side_effect
        if effect is not None:
            if _is_exception(effect):
>               raise effect
E               ImportError

/usr/lib/pypy3.10/unittest/mock.py:1173: ImportError

During handling of the above exception, another exception occurred:

self = <IPython.lib.tests.test_display.TestAudioDataWithoutNumpy testMethod=test_audio_data_normalization>

    @skipif_not_numpy
    def test_audio_data_normalization(self):
        expected_max_value = numpy.iinfo(numpy.int16).max
        for scale in [1, 0.5, 2]:
>           audio = display.Audio(get_test_tone(scale), rate=44100)

IPython/lib/tests/test_display.py:220: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
IPython/lib/display.py:130: in __init__
    self.data = Audio._make_wav(data, rate, normalize)
IPython/lib/display.py:154: in _make_wav
    scaled, nchan = Audio._validate_and_normalize_without_numpy(data, normalize)
IPython/lib/display.py:204: in _validate_and_normalize_without_numpy
    scaled = array.array('h', [int(x / normalization_factor * 32767) for x in data])
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

.0 = <sequenceiterator object at 0x0000560c64c9bd60>

>   scaled = array.array('h', [int(x / normalization_factor * 32767) for x in data])
E   ValueError: cannot convert float NaN to integer

IPython/lib/display.py:204: ValueError
___________________________________ TestAudioDataWithoutNumpy.test_audio_data_without_normalization ___________________________________

data = array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14])
rate = 44100, normalize = False

    @staticmethod
    def _make_wav(data, rate, normalize):
        """ Transform a numpy array to a PCM bytestring """
        from io import BytesIO
        import wave
    
        try:
>           scaled, nchan = Audio._validate_and_normalize_with_numpy(data, normalize)

IPython/lib/display.py:152: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

data = array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14])
normalize = False

    @staticmethod
    def _validate_and_normalize_with_numpy(data, normalize) -> Tuple[bytes, int]:
        import numpy as np
    
>       data = np.array(data, dtype=float)

IPython/lib/display.py:172: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <MagicMock id='94611245842056'>
args = (array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14]),)
kwargs = {'dtype': <class 'float'>}

    def __call__(self, /, *args, **kwargs):
        # can't use self in-case a function / method we are mocking uses self
        # in the signature
        self._mock_check_sig(*args, **kwargs)
        self._increment_mock_call(*args, **kwargs)
>       return self._mock_call(*args, **kwargs)

/usr/lib/pypy3.10/unittest/mock.py:1114: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <MagicMock id='94611245842056'>
args = (array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14]),)
kwargs = {'dtype': <class 'float'>}

    def _mock_call(self, /, *args, **kwargs):
>       return self._execute_mock_call(*args, **kwargs)

/usr/lib/pypy3.10/unittest/mock.py:1118: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <MagicMock id='94611245842056'>
args = (array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14]),)
kwargs = {'dtype': <class 'float'>}, effect = <class 'ImportError'>

    def _execute_mock_call(self, /, *args, **kwargs):
        # separate from _increment_mock_call so that awaited functions are
        # executed separately from their call, also AsyncMock overrides this method
    
        effect = self.side_effect
        if effect is not None:
            if _is_exception(effect):
>               raise effect
E               ImportError

/usr/lib/pypy3.10/unittest/mock.py:1173: ImportError

During handling of the above exception, another exception occurred:

self = <IPython.lib.tests.test_display.TestAudioDataWithoutNumpy testMethod=test_audio_data_without_normalization>

    @skipif_not_numpy
    def test_audio_data_without_normalization(self):
        max_int16 = numpy.iinfo(numpy.int16).max
        for scale in [1, 0.5, 0.2]:
            test_tone = get_test_tone(scale)
            test_tone_max_abs = numpy.max(numpy.abs(test_tone))
            expected_max_value = int(max_int16 * test_tone_max_abs)
>           audio = display.Audio(test_tone, rate=44100, normalize=False)

IPython/lib/tests/test_display.py:231: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
IPython/lib/display.py:130: in __init__
    self.data = Audio._make_wav(data, rate, normalize)
IPython/lib/display.py:154: in _make_wav
    scaled, nchan = Audio._validate_and_normalize_without_numpy(data, normalize)
IPython/lib/display.py:203: in _validate_and_normalize_without_numpy
    normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

max_abs_value = 2.462040934143973e+38, normalize = False

    @staticmethod
    def _get_normalization_factor(max_abs_value, normalize):
        if not normalize and max_abs_value > 1:
>           raise ValueError('Audio data must be between -1 and 1 when normalize=False.')
E           ValueError: Audio data must be between -1 and 1 when normalize=False.

IPython/lib/display.py:213: ValueError
________________________________________ TestAudioDataWithoutNumpy.test_audio_from_numpy_array ________________________________________

data = array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14])
rate = 44100, normalize = True

    @staticmethod
    def _make_wav(data, rate, normalize):
        """ Transform a numpy array to a PCM bytestring """
        from io import BytesIO
        import wave
    
        try:
>           scaled, nchan = Audio._validate_and_normalize_with_numpy(data, normalize)

IPython/lib/display.py:152: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

data = array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14])
normalize = True

    @staticmethod
    def _validate_and_normalize_with_numpy(data, normalize) -> Tuple[bytes, int]:
        import numpy as np
    
>       data = np.array(data, dtype=float)

IPython/lib/display.py:172: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <MagicMock id='94611245842056'>
args = (array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14]),)
kwargs = {'dtype': <class 'float'>}

    def __call__(self, /, *args, **kwargs):
        # can't use self in-case a function / method we are mocking uses self
        # in the signature
        self._mock_check_sig(*args, **kwargs)
        self._increment_mock_call(*args, **kwargs)
>       return self._mock_call(*args, **kwargs)

/usr/lib/pypy3.10/unittest/mock.py:1114: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <MagicMock id='94611245842056'>
args = (array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14]),)
kwargs = {'dtype': <class 'float'>}

    def _mock_call(self, /, *args, **kwargs):
>       return self._execute_mock_call(*args, **kwargs)

/usr/lib/pypy3.10/unittest/mock.py:1118: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <MagicMock id='94611245842056'>
args = (array([ 0.00000000e+00,  6.26497429e-02,  1.25053344e-01, ...,
       -1.25053344e-01, -6.26497429e-02,  6.27613383e-14]),)
kwargs = {'dtype': <class 'float'>}, effect = <class 'ImportError'>

    def _execute_mock_call(self, /, *args, **kwargs):
        # separate from _increment_mock_call so that awaited functions are
        # executed separately from their call, also AsyncMock overrides this method
    
        effect = self.side_effect
        if effect is not None:
            if _is_exception(effect):
>               raise effect
E               ImportError

/usr/lib/pypy3.10/unittest/mock.py:1173: ImportError

During handling of the above exception, another exception occurred:

self = <IPython.lib.tests.test_display.TestAudioDataWithoutNumpy testMethod=test_audio_from_numpy_array>

    @skipif_not_numpy
    def test_audio_from_numpy_array(self):
        test_tone = get_test_tone()
>       audio = display.Audio(test_tone, rate=44100)

IPython/lib/tests/test_display.py:203: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
IPython/lib/display.py:130: in __init__
    self.data = Audio._make_wav(data, rate, normalize)
IPython/lib/display.py:154: in _make_wav
    scaled, nchan = Audio._validate_and_normalize_without_numpy(data, normalize)
IPython/lib/display.py:204: in _validate_and_normalize_without_numpy
    scaled = array.array('h', [int(x / normalization_factor * 32767) for x in data])
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

.0 = <sequenceiterator object at 0x0000560c682fe740>

>   scaled = array.array('h', [int(x / normalization_factor * 32767) for x in data])
E   ValueError: cannot convert float NaN to integer

IPython/lib/display.py:204: ValueError
======================================================== slowest 10 durations =========================================================
0.03s call     IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_from_list
0.02s call     IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_raises_for_nested_list
0.01s call     IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_normalization
0.00s call     IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_without_normalization
0.00s call     IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_from_numpy_array
0.00s teardown IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_raises_for_nested_list
0.00s call     IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_from_numpy_array_without_rate_raises
0.00s setup    IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_normalization
0.00s setup    IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_from_numpy_array
0.00s call     IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_without_normalization_raises_for_invalid_data
======================================================= short test summary info =======================================================
FAILED IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_normalization - ValueError: cannot convert floa...
FAILED IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_data_without_normalization - ValueError: Audio data ...
FAILED IPython/lib/tests/test_display.py::TestAudioDataWithoutNumpy::test_audio_from_numpy_array - ValueError: cannot convert float ...
===================================================== 3 failed, 4 passed in 1.14s =====================================================

Runtime information:

1.26.2
3.10.13 (f1607341da97ff5a1e93430b6e8c4af0ad1aa019, Sep 30 2023, 03:58:56)
[PyPy 7.3.13 with GCC 12.3.1 20230526]
WARNING: `threadpoolctl` not found in system! Install it by `pip install threadpoolctl`. Once installed, try `np.show_runtime` again for more detailed build information
[{'numpy_version': '1.26.2',
  'python': '3.10.13 (f1607341da97ff5a1e93430b6e8c4af0ad1aa019, Sep 30 2023, '
            '03:58:56)\n'
            '[PyPy 7.3.13 with GCC 12.3.1 20230526]',
  'uname': uname_result(system='Linux', node='pomiot', release='6.6.1-gentoo-dist', version='#1 SMP PREEMPT_DYNAMIC Fri Nov 10 16:04:08 -00 2023', machine='x86_64')},
 {'simd_extensions': {'baseline': ['SSE', 'SSE2', 'SSE3'],
                      'found': ['SSSE3',
                                'SSE41',
                                'POPCNT',
                                'SSE42',
                                'AVX',
                                'F16C',
                                'FMA3',
                                'AVX2'],
                      'not_found': ['AVX512F',
                                    'AVX512CD',
                                    'AVX512_KNL',
                                    'AVX512_KNM',
                                    'AVX512_SKX',
                                    'AVX512_CLX',
                                    'AVX512_CNL',
                                    'AVX512_ICL',
                                    'AVX512_SPR']}}]
None

Context for the issue:

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions