Skip to content

Commit c91e4c3

Browse files
Add stubs for qwen_tts and torchcodec modules in audio test configuration
1 parent c7c248c commit c91e4c3

File tree

2 files changed

+143
-28
lines changed

2 files changed

+143
-28
lines changed

tests/conftest.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import sys
2+
import types
3+
import importlib.machinery
4+
from types import SimpleNamespace
5+
6+
import numpy as np
7+
8+
9+
def _install_qwen_tts_stub() -> None:
10+
try:
11+
__import__("qwen_tts")
12+
return
13+
except ImportError:
14+
pass
15+
16+
class _FakeQwen3TTSModel:
17+
def __init__(self, *args, **kwargs):
18+
self.args = args
19+
self.kwargs = kwargs
20+
21+
@classmethod
22+
def from_pretrained(cls, *args, **kwargs):
23+
return cls(*args, **kwargs)
24+
25+
def generate_custom_voice(self, text, speaker=None, **kwargs):
26+
return [np.zeros(24_000, dtype=np.float32)], 24_000
27+
28+
def generate_voice_clone(self, text, **kwargs):
29+
return [np.zeros(24_000, dtype=np.float32)], 24_000
30+
31+
def generate_voice_design(self, text, language=None, instruct=None, **kwargs):
32+
return [np.zeros(24_000, dtype=np.float32)], 24_000
33+
34+
def create_voice_clone_prompt(self, ref_audio=None, ref_text=None, **kwargs):
35+
return {
36+
"ref_audio": ref_audio,
37+
"ref_text": ref_text,
38+
}
39+
40+
qwen_tts_module = types.ModuleType("qwen_tts")
41+
qwen_tts_module.Qwen3TTSModel = _FakeQwen3TTSModel
42+
qwen_tts_module.__spec__ = importlib.machinery.ModuleSpec("qwen_tts", loader=None)
43+
sys.modules["qwen_tts"] = qwen_tts_module
44+
45+
46+
_install_qwen_tts_stub()
47+
48+
49+
def _install_torchcodec_stub() -> None:
50+
try:
51+
__import__("torchcodec")
52+
return
53+
except ImportError:
54+
pass
55+
56+
class _FakeTensor:
57+
def __init__(self, array):
58+
self._array = array
59+
60+
def cpu(self):
61+
return self
62+
63+
def numpy(self):
64+
return self._array
65+
66+
class _FakeAudioSamples:
67+
def __init__(self, data=None, sample_rate: int = 16_000):
68+
_arr = np.zeros((1, sample_rate), dtype=np.float32) if data is None else data
69+
self.data = _FakeTensor(_arr)
70+
self.sample_rate = sample_rate
71+
72+
class _FakeAudioDecoder:
73+
def __init__(self, source=None, *args, **kwargs):
74+
self.source = source
75+
self.args = args
76+
self.kwargs = kwargs
77+
_path = None
78+
if isinstance(source, dict):
79+
_path = source.get("path")
80+
else:
81+
_path = getattr(source, "path", None)
82+
83+
self.metadata = SimpleNamespace(
84+
sample_rate=16_000,
85+
path=_path,
86+
)
87+
88+
def __getitem__(self, key: str):
89+
if key == "path":
90+
return self.metadata.path
91+
if key == "sampling_rate":
92+
return self.metadata.sample_rate
93+
if key == "array":
94+
y = self.get_all_samples().data.cpu().numpy()
95+
return np.mean(y, axis=tuple(range(y.ndim - 1))) if y.ndim > 1 else y
96+
raise KeyError(key)
97+
98+
def get_all_samples(self):
99+
return _FakeAudioSamples()
100+
101+
def get_samples_played_in_range(self, *_args, **_kwargs):
102+
return SimpleNamespace(sample_rate=self.metadata.sample_rate)
103+
104+
torchcodec_module = types.ModuleType("torchcodec")
105+
decoders_module = types.ModuleType("torchcodec.decoders")
106+
decoders_module.AudioDecoder = _FakeAudioDecoder
107+
torchcodec_module.decoders = decoders_module
108+
torchcodec_module.__spec__ = importlib.machinery.ModuleSpec("torchcodec", loader=None)
109+
decoders_module.__spec__ = importlib.machinery.ModuleSpec("torchcodec.decoders", loader=None)
110+
111+
sys.modules["torchcodec"] = torchcodec_module
112+
sys.modules["torchcodec.decoders"] = decoders_module
113+
114+
115+
_install_torchcodec_stub()

tests/test_audio.py

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,34 @@
66
import pandas as pd
77

88
# Try to import audio dependencies
9-
try:
10-
import soundfile as sf
11-
12-
from sdialog.audio.turn import AudioTurn
13-
from sdialog.audio.room_generator import BasicRoomGenerator
14-
from sdialog.audio.utils import Role, AudioUtils, Furniture, SpeakerSide
15-
from sdialog.audio.room import Position3D, Dimensions3D, DirectivityType, Room
16-
from sdialog.audio.voice_database import Voice, is_a_audio_file
17-
from sdialog.audio.voice_database import BaseVoiceDatabase, LocalVoiceDatabase, VoiceDatabase
18-
from sdialog.audio.tts import BaseTTS
19-
from sdialog.audio.jsalt import MedicalRoomGenerator, RoomRole
20-
from sdialog.audio.acoustics_simulator import AcousticsSimulator, AudioSource
21-
from sdialog.audio.dialog import AudioDialog
22-
from sdialog.audio.pipeline import AudioPipeline, to_audio
23-
from sdialog.audio.dscaper_utils import send_utterances_to_dscaper, generate_dscaper_timeline
24-
from sdialog.audio.impulse_response_database import LocalImpulseResponseDatabase, RecordingDevice
25-
from sdialog.audio.processing import AudioProcessor
26-
except ImportError:
27-
print("\n" + "=" * 80)
28-
print("Audio dependencies are not installed. All audio tests will be skipped.")
29-
print("=" * 80 + "\n")
30-
31-
# Skip the entire module - pytest will not collect any tests from this file
32-
pytest.skip(
33-
"Audio dependencies not installed. If you are working with audio, install them with: "
34-
"pip install sdialog[audio]",
35-
allow_module_level=True
36-
)
9+
# try:
10+
import soundfile as sf
11+
12+
from sdialog.audio.turn import AudioTurn
13+
from sdialog.audio.room_generator import BasicRoomGenerator
14+
from sdialog.audio.utils import Role, AudioUtils, Furniture, SpeakerSide
15+
from sdialog.audio.room import Position3D, Dimensions3D, DirectivityType, Room
16+
from sdialog.audio.voice_database import Voice, is_a_audio_file
17+
from sdialog.audio.voice_database import BaseVoiceDatabase, LocalVoiceDatabase, VoiceDatabase
18+
from sdialog.audio.tts import BaseTTS
19+
from sdialog.audio.jsalt import MedicalRoomGenerator, RoomRole
20+
from sdialog.audio.acoustics_simulator import AcousticsSimulator, AudioSource
21+
from sdialog.audio.dialog import AudioDialog
22+
from sdialog.audio.pipeline import AudioPipeline, to_audio
23+
from sdialog.audio.dscaper_utils import send_utterances_to_dscaper, generate_dscaper_timeline
24+
from sdialog.audio.impulse_response_database import LocalImpulseResponseDatabase, RecordingDevice
25+
from sdialog.audio.processing import AudioProcessor
26+
# except ImportError:
27+
# print("\n" + "=" * 80)
28+
# print("Audio dependencies are not installed. All audio tests will be skipped.")
29+
# print("=" * 80 + "\n")
30+
31+
# # Skip the entire module - pytest will not collect any tests from this file
32+
# pytest.skip(
33+
# "Audio dependencies not installed. If you are working with audio, install them with: "
34+
# "pip install sdialog[audio]",
35+
# allow_module_level=True
36+
# )
3737

3838
from sdialog import Turn, Dialog
3939
from unittest.mock import MagicMock, patch

0 commit comments

Comments
 (0)