From 680c7b8f79854c3006891b3d11263632b281ef70 Mon Sep 17 00:00:00 2001 From: Gautzilla Date: Mon, 18 May 2026 15:30:33 +0200 Subject: [PATCH 1/6] replace mocked AudioData with mocked child class --- tests/conftest.py | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 70663b2b..81b6bbfd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -167,17 +167,12 @@ def mock_open(self: SoundFileBackend, path: Path) -> None: return opened_files -@pytest.fixture -def patch_audio_data(monkeypatch: pytest.MonkeyPatch) -> None: - original_init = AudioData.__init__ - original_get_raw_value = AudioData.get_raw_value - original_length = AudioData.length - - def mocked_init( - self: AudioData, - *args: list, - mocked_value: list[float] | np.ndarray | None = None, - **kwargs: dict, +class MockedAudioData(AudioData): + def __init__( + self, + mocked_value: list[float] | np.ndarray, + *args: typing.Any, + **kwargs: typing.Any, ) -> None: defaults = { "begin": Timestamp("2000-01-01 00:00:00"), @@ -188,7 +183,7 @@ def mocked_init( if key not in kwargs: kwargs.update(**{key: value}) - original_init(self, *args, **kwargs) + super().__init__(*args, **kwargs) if mocked_value is not None: self.mocked_value = mocked_value if type(mocked_value) is list or len(mocked_value.shape) == 1: @@ -197,23 +192,12 @@ def mocked_init( 1, ) - def mocked_length(self: AudioData) -> int: - if hasattr(self, "mocked_value"): - return len(self.mocked_value) - return original_length.fget(self) - - def mocked_get_raw_value(self: AudioData) -> np.ndarray: - if hasattr(self, "mocked_value"): - return self.mocked_value - return original_get_raw_value(self) - - monkeypatch.setattr(AudioData, "__init__", mocked_init) - monkeypatch.setattr(AudioData, "length", property(mocked_length)) - monkeypatch.setattr( - AudioData, - "get_raw_value", - mocked_get_raw_value, - ) + @property + def length(self) -> int: + return len(self.mocked_value) + + def get_raw_value(self) -> np.ndarray: + return self.mocked_value @pytest.fixture(autouse=True) From 95fc3f26d3e85981bdf76c41aab2c1c712a8b5ea Mon Sep 17 00:00:00 2001 From: Gautzilla Date: Mon, 18 May 2026 16:20:31 +0200 Subject: [PATCH 2/6] use new MockedAudioData class in tests instead of the removed fixture --- tests/test_audio.py | 26 ++++++++++++++--------- tests/test_spectro.py | 48 +++++++++++++++++++------------------------ 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/tests/test_audio.py b/tests/test_audio.py index c15422b9..4962dc72 100644 --- a/tests/test_audio.py +++ b/tests/test_audio.py @@ -9,6 +9,7 @@ import pandas as pd import pytest import soundfile as sf +from conftest import MockedAudioData from pandas import Timedelta, Timestamp import osekit @@ -28,9 +29,9 @@ from osekit.utils.audio import Normalization, generate_sample_audio, normalize -def test_patch_audio_data(patch_audio_data: None) -> None: +def test_mocked_audio_data() -> None: mocked_value = [1.0, 2.0, 3.0] - audio_data = AudioData( + audio_data = MockedAudioData( mocked_value=mocked_value, # Type: ignore # Unexpected argument ) assert np.array_equal( @@ -1534,10 +1535,16 @@ def test_audio_dataset_from_folder_errors_warnings( assert all(f in caplog.text for f in corrupted_audio_files) -def test_audio_dataset_instrument(patch_audio_data: None) -> None: +def test_audio_dataset_instrument() -> None: ad = [ - AudioData(mocked_value=[1, 2, 3], instrument=Instrument(end_to_end_db=150.0)), - AudioData(mocked_value=[4, 5, 6], instrument=Instrument(end_to_end_db=150.0)), + MockedAudioData( + mocked_value=[1, 2, 3], + instrument=Instrument(end_to_end_db=150.0), + ), + MockedAudioData( + mocked_value=[4, 5, 6], + instrument=Instrument(end_to_end_db=150.0), + ), ] ads = AudioDataset(data=ad) @@ -1807,9 +1814,8 @@ def test_split_data( assert subsubdata.normalization == subdata.normalization -def test_split_data_normalization_pass(patch_audio_data: None) -> None: - ad = AudioData() - ad.mocked_value = [1, 2, 3] +def test_split_data_normalization_pass() -> None: + ad = MockedAudioData(mocked_value=[1, 2, 3]) original_normalization_values = ad.get_normalization_values() assert all(original_normalization_values.values()) @@ -1926,9 +1932,9 @@ def test_split_data_frames( assert np.array_equal(ad.get_value()[:, 0], expected_data) -def test_split_frames_errors(patch_audio_data: None) -> None: +def test_split_frames_errors() -> None: mocked_value = [1, 2, 3] - ad = AudioData(mocked_value=mocked_value) + ad = MockedAudioData(mocked_value=mocked_value) error_msgs = [ "Start_frame must be greater than or equal to 0.", "Stop_frame must be lower than the length of the data.", diff --git a/tests/test_spectro.py b/tests/test_spectro.py index 55c30913..d91b6d90 100644 --- a/tests/test_spectro.py +++ b/tests/test_spectro.py @@ -9,6 +9,7 @@ import numpy as np import pandas as pd import pytest +from conftest import MockedAudioData from matplotlib.dates import num2date from pandas import Timedelta, Timestamp from scipy.signal import ShortTimeFFT @@ -84,9 +85,9 @@ def test_spectrogram_shape( assert spectro.nb_bytes == nb_points * 8 -def test_spectro_data_sx_dtype(patch_audio_data: None) -> None: +def test_spectro_data_sx_dtype() -> None: sd = SpectroData.from_audio_data( - data=AudioData(mocked_value=[0.0 for _ in range(48_000)]), + data=MockedAudioData(mocked_value=[0.0 for _ in range(48_000)]), fft=ShortTimeFFT(hamming(1024), 512, 48_000), ) assert sd.sx_dtype is complex @@ -97,11 +98,10 @@ def test_spectro_data_sx_dtype(patch_audio_data: None) -> None: def test_spectro_data_db_ref( - patch_audio_data: None, monkeypatch: pytest.MonkeyPatch, ) -> None: sd = SpectroData.from_audio_data( - data=AudioData(mocked_value=[0.0 for _ in range(48_000)]), + data=MockedAudioData(mocked_value=[0.0 for _ in range(48_000)]), fft=ShortTimeFFT(hamming(1024), 512, 48_000), ) @@ -991,7 +991,6 @@ def test_link_audio_data( ], ) def test_link_audio_dataset( - patch_audio_data: None, audio_data_params: list[ tuple[Timestamp, Timestamp, float] ], # begin, end, sample_rate @@ -1005,7 +1004,7 @@ def test_link_audio_dataset( ) -> None: ads_origin = AudioDataset( [ - AudioData( + MockedAudioData( begin=sd_params[0], end=sd_params[1], sample_rate=sd_params[2], @@ -1017,7 +1016,7 @@ def test_link_audio_dataset( ads_dest = AudioDataset( [ - AudioData( + MockedAudioData( begin=ad_params[0], end=ad_params[1], sample_rate=ad_params[2], @@ -1349,11 +1348,11 @@ def test_ltas(audio_files: tuple[list[AudioFile], None], tmp_path: Path) -> None assert np.array_equal(ltas_ds.data[0].get_value(), ltas_ds2.data[0].get_value()) -def test_ltas_dataset(patch_audio_data: None) -> None: +def test_ltas_dataset() -> None: ads = AudioDataset( [ - AudioData(mocked_value=[0] * 48_000), - AudioData(mocked_value=[0] * 48_000), + MockedAudioData(mocked_value=[0] * 48_000), + MockedAudioData(mocked_value=[0] * 48_000), ], ) @@ -1504,10 +1503,9 @@ def patch_collect() -> None: def test_spectrodataset_scale( tmp_path: Path, - patch_audio_data: None, monkeypatch: pytest.MonkeyPatch, ) -> None: - ad = AudioData( + ad = MockedAudioData( mocked_value=np.linspace(0.0, 1.0, 1000), # Type: ignore # Unexpected argument ) @@ -1543,8 +1541,8 @@ def mock_empty_method(*args: list[...], **kwargs: dict) -> None: ltas_ds.save_all(tmp_path, tmp_path) -def test_spectro_dataset_properties_propagate(patch_audio_data: None) -> None: - ad1, ad2 = AudioData( +def test_spectro_dataset_properties_propagate() -> None: + ad1, ad2 = MockedAudioData( mocked_value=[0.0 for _ in range(48_000)], # Type: ignore # Unexpected argument ).split() @@ -1567,10 +1565,9 @@ def test_spectro_dataset_properties_propagate(patch_audio_data: None) -> None: def test_spectro_dataset_folder_moves_files( - patch_audio_data: None, monkeypatch: pytest.MonkeyPatch, ) -> None: - ad1, ad2 = AudioData( + ad1, ad2 = MockedAudioData( mocked_value=[0.0 for _ in range(48_000)], # Type: ignore # Unexpected argument ).split() @@ -1648,9 +1645,10 @@ def patch_sd_from_dict(dictionary: dict, *args: list, **kwargs: dict) -> str: def test_spectro_multichannel_audio_file( monkeypatch: pytest.MonkeyPatch, - patch_audio_data: pytest.MonkeyPatch, ) -> None: - ad = AudioData(mocked_value=np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])) + ad = MockedAudioData( + mocked_value=np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]), + ) sft = ShortTimeFFT(win=hamming(512), hop=128, fs=48_000) @@ -1706,7 +1704,6 @@ def mocked_ad_init( def test_spectro_write_welch( - patch_audio_data: None, monkeypatch: pytest.MonkeyPatch, ) -> None: created_dir_calls = [] @@ -1732,7 +1729,7 @@ def mocked_savez(**kwargs: dict) -> None: monkeypatch.setattr(np, "savez", mocked_savez) sd = SpectroData.from_audio_data( - data=AudioData(mocked_value=[0.0 for _ in range(48_000)]), + data=MockedAudioData(mocked_value=[0.0 for _ in range(48_000)]), fft=ShortTimeFFT(win=hamming(512), hop=128, fs=48_000), ) @@ -1748,7 +1745,6 @@ def mocked_savez(**kwargs: dict) -> None: def test_spectro_get_value_from_items_errors( - patch_audio_data: None, monkeypatch: pytest.MonkeyPatch, ) -> None: def mocked_read_metadata(self: SpectroFile, *args: list, **kwargs: dict) -> None: @@ -1795,7 +1791,6 @@ def mocked_read_metadata(self: SpectroFile, *args: list, **kwargs: dict) -> None def test_spectro_populated_duration( - patch_audio_data: None, monkeypatch: pytest.MonkeyPatch, ) -> None: ad_sentinel = object() @@ -1820,7 +1815,7 @@ def test_spectro_populated_duration( ) assert ( SpectroData.from_audio_data( - data=AudioData(mocked_value=[0, 1, 2]), + data=MockedAudioData(mocked_value=[0, 1, 2]), fft=sft, ).populated_duration == bd_sentinel @@ -1830,7 +1825,7 @@ def test_spectro_populated_duration( monkeypatch.setattr(SpectroData, "files", property(lambda _: None)) assert ( SpectroData.from_audio_data( - data=AudioData(mocked_value=[0, 1, 2]), + data=MockedAudioData(mocked_value=[0, 1, 2]), fft=sft, ).populated_duration == ad_sentinel @@ -1838,7 +1833,7 @@ def test_spectro_populated_duration( # SD With no files or audio data return 0. sd = SpectroData.from_audio_data( - data=AudioData(mocked_value=[0, 1, 2]), + data=MockedAudioData(mocked_value=[0, 1, 2]), fft=sft, ) sd.audio_data = None @@ -1846,7 +1841,6 @@ def test_spectro_populated_duration( def test_spectro_get_db_value( - patch_audio_data: None, monkeypatch: pytest.MonkeyPatch, ) -> None: get_value_calls = [] @@ -1862,7 +1856,7 @@ def mock_to_db(self: SpectroData | None, sx: np.ndarray) -> np.ndarray: monkeypatch.setattr(SpectroData, "_to_db", mock_to_db) sd = SpectroData.from_audio_data( - data=AudioData(mocked_value=[0, 1, 2]), + data=MockedAudioData(mocked_value=[0, 1, 2]), fft=ShortTimeFFT(hamming(512), hop=128, fs=48_000), ) From 1a2664d3cc90e143c920d3a8cff8338d415a2cce Mon Sep 17 00:00:00 2001 From: Gautzilla Date: Mon, 18 May 2026 16:20:43 +0200 Subject: [PATCH 3/6] add Ruff exception --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 08dbf69f..7836d3f2 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,6 +70,9 @@ lint.select = ["ALL"] "docs/source/*.ipynb" = [ "E402", # Module level import not at top of cell in doc notebooks ] +"*" = [ + "ANN401" # typing.Any type hint for *args and **kwargs +] [tool.pytest.ini_options] From a6bdad963447231ea73d447071742941c4625329 Mon Sep 17 00:00:00 2001 From: Gautzilla Date: Mon, 18 May 2026 17:09:22 +0200 Subject: [PATCH 4/6] move MockedAudioData class to test helpers module --- tests/conftest.py | 38 +------------------------------------- tests/helpers/audio.py | 39 +++++++++++++++++++++++++++++++++++++++ tests/test_audio.py | 2 +- tests/test_spectro.py | 2 +- 4 files changed, 42 insertions(+), 39 deletions(-) create mode 100644 tests/helpers/audio.py diff --git a/tests/conftest.py b/tests/conftest.py index 81b6bbfd..9180c581 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,11 +7,9 @@ from pathlib import Path from unittest.mock import MagicMock -import numpy as np import pandas as pd import pytest import soundfile as sf -from pandas import Timestamp from osekit import config from osekit.audio_backend.soundfile_backend import SoundFileBackend @@ -19,7 +17,6 @@ TIMESTAMP_FORMAT_EXPORTED_FILES_LOCALIZED, TIMESTAMP_FORMAT_EXPORTED_FILES_UNLOCALIZED, ) -from osekit.core.audio_data import AudioData from osekit.core.audio_file import AudioFile from osekit.utils.audio import generate_sample_audio @@ -110,7 +107,7 @@ def patch_filehandlers( if "allow_log_write_to_file" in request.keywords: return - def disabled_filewrite(self: any, record: any) -> None: + def disabled_filewrite(self: typing.Any, record: typing.Any) -> None: """Prevent the logger from actually writing files.""" monkeypatch.setattr(logging.FileHandler, "emit", disabled_filewrite) @@ -167,39 +164,6 @@ def mock_open(self: SoundFileBackend, path: Path) -> None: return opened_files -class MockedAudioData(AudioData): - def __init__( - self, - mocked_value: list[float] | np.ndarray, - *args: typing.Any, - **kwargs: typing.Any, - ) -> None: - defaults = { - "begin": Timestamp("2000-01-01 00:00:00"), - "end": Timestamp("2000-01-01 00:00:01"), - "sample_rate": 48000, - } - for key, value in defaults.items(): - if key not in kwargs: - kwargs.update(**{key: value}) - - super().__init__(*args, **kwargs) - if mocked_value is not None: - self.mocked_value = mocked_value - if type(mocked_value) is list or len(mocked_value.shape) == 1: - self.mocked_value = np.array(self.mocked_value).reshape( - len(mocked_value), - 1, - ) - - @property - def length(self) -> int: - return len(self.mocked_value) - - def get_raw_value(self) -> np.ndarray: - return self.mocked_value - - @pytest.fixture(autouse=True) def restore_config() -> typing.Generator: resample_quality_settings = {**config.resample_quality_settings} diff --git a/tests/helpers/audio.py b/tests/helpers/audio.py new file mode 100644 index 00000000..726126a8 --- /dev/null +++ b/tests/helpers/audio.py @@ -0,0 +1,39 @@ +import typing + +import numpy as np +from pandas import Timestamp + +from osekit.core.audio_data import AudioData + + +class MockedAudioData(AudioData): + def __init__( + self, + mocked_value: list[float] | np.ndarray, + *args: typing.Any, + **kwargs: typing.Any, + ) -> None: + defaults = { + "begin": Timestamp("2000-01-01 00:00:00"), + "end": Timestamp("2000-01-01 00:00:01"), + "sample_rate": 48000, + } + for key, value in defaults.items(): + if key not in kwargs: + kwargs.update(**{key: value}) + + super().__init__(*args, **kwargs) + if mocked_value is not None: + self.mocked_value = mocked_value + if type(mocked_value) is list or len(mocked_value.shape) == 1: + self.mocked_value = np.array(self.mocked_value).reshape( + len(mocked_value), + 1, + ) + + @property + def length(self) -> int: + return len(self.mocked_value) + + def get_raw_value(self) -> np.ndarray: + return self.mocked_value diff --git a/tests/test_audio.py b/tests/test_audio.py index 4962dc72..e20c8ea2 100644 --- a/tests/test_audio.py +++ b/tests/test_audio.py @@ -9,7 +9,6 @@ import pandas as pd import pytest import soundfile as sf -from conftest import MockedAudioData from pandas import Timedelta, Timestamp import osekit @@ -27,6 +26,7 @@ from osekit.core.instrument import Instrument from osekit.utils import audio from osekit.utils.audio import Normalization, generate_sample_audio, normalize +from tests.helpers.audio import MockedAudioData def test_mocked_audio_data() -> None: diff --git a/tests/test_spectro.py b/tests/test_spectro.py index d91b6d90..a18a3756 100644 --- a/tests/test_spectro.py +++ b/tests/test_spectro.py @@ -9,7 +9,6 @@ import numpy as np import pandas as pd import pytest -from conftest import MockedAudioData from matplotlib.dates import num2date from pandas import Timedelta, Timestamp from scipy.signal import ShortTimeFFT @@ -33,6 +32,7 @@ from osekit.core.spectro_file import SpectroFile from osekit.core.spectro_item import SpectroItem from osekit.utils.audio import Normalization, generate_sample_audio +from tests.helpers.audio import MockedAudioData from tests.helpers.dummy import DummyFile From 98e1cdc7ccf692f32217235386cff90d44cb1be8 Mon Sep 17 00:00:00 2001 From: Gautzilla Date: Mon, 18 May 2026 17:34:34 +0200 Subject: [PATCH 5/6] remove duplicated lines --- src/osekit/audio_backend/audio_file_manager.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/osekit/audio_backend/audio_file_manager.py b/src/osekit/audio_backend/audio_file_manager.py index da0bbdbb..8b18c448 100644 --- a/src/osekit/audio_backend/audio_file_manager.py +++ b/src/osekit/audio_backend/audio_file_manager.py @@ -85,9 +85,6 @@ def read( """ _, frames, _ = self.info(path) - if stop is None: - stop = frames - if stop is None: stop = frames From 6ab26d66932cdd7c8b0efc4ac959cf1ec9e34145 Mon Sep 17 00:00:00 2001 From: Gautzilla Date: Mon, 18 May 2026 17:42:52 +0200 Subject: [PATCH 6/6] remove type ignore comments --- tests/test_audio.py | 4 ++-- tests/test_spectro.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_audio.py b/tests/test_audio.py index e20c8ea2..37374847 100644 --- a/tests/test_audio.py +++ b/tests/test_audio.py @@ -32,10 +32,10 @@ def test_mocked_audio_data() -> None: mocked_value = [1.0, 2.0, 3.0] audio_data = MockedAudioData( - mocked_value=mocked_value, # Type: ignore # Unexpected argument + mocked_value=mocked_value, ) assert np.array_equal( - audio_data.mocked_value[:, 0], # Type: ignore # Unresolved attribute + audio_data.mocked_value[:, 0], mocked_value, ) diff --git a/tests/test_spectro.py b/tests/test_spectro.py index a18a3756..9fc38ae3 100644 --- a/tests/test_spectro.py +++ b/tests/test_spectro.py @@ -1506,7 +1506,7 @@ def test_spectrodataset_scale( monkeypatch: pytest.MonkeyPatch, ) -> None: ad = MockedAudioData( - mocked_value=np.linspace(0.0, 1.0, 1000), # Type: ignore # Unexpected argument + mocked_value=np.linspace(0.0, 1.0, 1000), ) fft = ShortTimeFFT(win=hamming(512), hop=128, fs=ad.sample_rate) @@ -1543,7 +1543,7 @@ def mock_empty_method(*args: list[...], **kwargs: dict) -> None: def test_spectro_dataset_properties_propagate() -> None: ad1, ad2 = MockedAudioData( - mocked_value=[0.0 for _ in range(48_000)], # Type: ignore # Unexpected argument + mocked_value=[0.0 for _ in range(48_000)], ).split() fft = ShortTimeFFT(win=hamming(512), hop=128, fs=ad1.sample_rate) @@ -1568,7 +1568,7 @@ def test_spectro_dataset_folder_moves_files( monkeypatch: pytest.MonkeyPatch, ) -> None: ad1, ad2 = MockedAudioData( - mocked_value=[0.0 for _ in range(48_000)], # Type: ignore # Unexpected argument + mocked_value=[0.0 for _ in range(48_000)], ).split() fft = ShortTimeFFT(win=hamming(512), hop=128, fs=ad1.sample_rate)