amine@269
|
1 import os
|
amine@267
|
2 from unittest import TestCase
|
amine@271
|
3 from unittest.mock import patch
|
amine@269
|
4 from tempfile import TemporaryDirectory
|
amine@267
|
5 from collections import namedtuple
|
amine@267
|
6 from genty import genty, genty_dataset
|
amine@267
|
7
|
amine@267
|
8 from auditok.cmdline_util import (
|
amine@273
|
9 _AUDITOK_LOGGER,
|
amine@267
|
10 make_kwargs,
|
amine@291
|
11 make_duration_formatter,
|
amine@267
|
12 make_logger,
|
amine@267
|
13 initialize_workers,
|
amine@267
|
14 KeywordArguments,
|
amine@267
|
15 )
|
amine@271
|
16 from auditok.workers import (
|
amine@271
|
17 StreamSaverWorker,
|
amine@271
|
18 RegionSaverWorker,
|
amine@271
|
19 PlayerWorker,
|
amine@271
|
20 CommandLineWorker,
|
amine@271
|
21 PrintWorker,
|
amine@271
|
22 )
|
amine@267
|
23 from auditok.exceptions import TimeFormatError
|
amine@267
|
24
|
amine@267
|
25 _ArgsNamespece = namedtuple(
|
amine@267
|
26 "_ArgsNamespece",
|
amine@267
|
27 [
|
amine@267
|
28 "input",
|
amine@292
|
29 "max_read",
|
amine@267
|
30 "analysis_window",
|
amine@267
|
31 "sampling_rate",
|
amine@267
|
32 "sample_width",
|
amine@267
|
33 "channels",
|
amine@267
|
34 "use_channel",
|
amine@267
|
35 "input_format",
|
amine@267
|
36 "output_format",
|
amine@267
|
37 "large_file",
|
amine@267
|
38 "frame_per_buffer",
|
amine@267
|
39 "input_device_index",
|
amine@267
|
40 "save_stream",
|
amine@292
|
41 "save_detections_as",
|
amine@267
|
42 "plot",
|
amine@267
|
43 "save_image",
|
amine@267
|
44 "min_duration",
|
amine@267
|
45 "max_duration",
|
amine@267
|
46 "max_silence",
|
amine@267
|
47 "drop_trailing_silence",
|
amine@267
|
48 "strict_min_duration",
|
amine@267
|
49 "energy_threshold",
|
amine@267
|
50 "echo",
|
amine@292
|
51 "progress_bar",
|
amine@267
|
52 "command",
|
amine@267
|
53 "quiet",
|
amine@267
|
54 "printf",
|
amine@267
|
55 "time_format",
|
amine@267
|
56 "timestamp_format",
|
amine@267
|
57 ],
|
amine@267
|
58 )
|
amine@267
|
59
|
amine@267
|
60
|
amine@267
|
61 @genty
|
amine@292
|
62 class TestCmdLineUtil(TestCase):
|
amine@267
|
63 @genty_dataset(
|
amine@292
|
64 no_record=("stream.ogg", None, False, None, "mix", "mix", False),
|
amine@292
|
65 no_record_plot=("stream.ogg", None, True, None, None, None, False),
|
amine@267
|
66 no_record_save_image=(
|
amine@267
|
67 "stream.ogg",
|
amine@292
|
68 None,
|
amine@267
|
69 True,
|
amine@267
|
70 "image.png",
|
amine@267
|
71 None,
|
amine@267
|
72 None,
|
amine@267
|
73 False,
|
amine@267
|
74 ),
|
amine@292
|
75 record_plot=(None, None, True, None, None, None, True),
|
amine@292
|
76 record_save_image=(None, None, False, "image.png", None, None, True),
|
amine@292
|
77 int_use_channel=("stream.ogg", None, False, None, "1", 1, False),
|
amine@292
|
78 save_detections_as=("stream.ogg", "{id}.wav", False, None, None, None, False)
|
amine@267
|
79 )
|
amine@267
|
80 def test_make_kwargs(
|
amine@267
|
81 self,
|
amine@267
|
82 save_stream,
|
amine@292
|
83 save_detections_as,
|
amine@267
|
84 plot,
|
amine@267
|
85 save_image,
|
amine@267
|
86 use_channel,
|
amine@267
|
87 exp_use_channel,
|
amine@267
|
88 exp_record,
|
amine@267
|
89 ):
|
amine@267
|
90
|
amine@267
|
91 args = (
|
amine@267
|
92 "file",
|
amine@267
|
93 30,
|
amine@267
|
94 0.01,
|
amine@267
|
95 16000,
|
amine@267
|
96 2,
|
amine@267
|
97 2,
|
amine@267
|
98 use_channel,
|
amine@267
|
99 "raw",
|
amine@267
|
100 "ogg",
|
amine@267
|
101 True,
|
amine@267
|
102 None,
|
amine@267
|
103 1,
|
amine@267
|
104 save_stream,
|
amine@292
|
105 save_detections_as,
|
amine@267
|
106 plot,
|
amine@267
|
107 save_image,
|
amine@267
|
108 0.2,
|
amine@267
|
109 10,
|
amine@267
|
110 0.3,
|
amine@267
|
111 False,
|
amine@267
|
112 False,
|
amine@267
|
113 55,
|
amine@267
|
114 )
|
amine@292
|
115 misc = (False, False, None, True, None, "TIME_FORMAT", "TIMESTAMP_FORMAT")
|
amine@267
|
116 args_ns = _ArgsNamespece(*(args + misc))
|
amine@267
|
117
|
amine@267
|
118 io_kwargs = {
|
amine@267
|
119 "input": "file",
|
amine@267
|
120 "max_read": 30,
|
amine@267
|
121 "block_dur": 0.01,
|
amine@267
|
122 "sampling_rate": 16000,
|
amine@267
|
123 "sample_width": 2,
|
amine@267
|
124 "channels": 2,
|
amine@267
|
125 "use_channel": exp_use_channel,
|
amine@267
|
126 "save_stream": save_stream,
|
amine@292
|
127 "save_detections_as": save_detections_as,
|
amine@267
|
128 "audio_format": "raw",
|
amine@267
|
129 "export_format": "ogg",
|
amine@267
|
130 "large_file": True,
|
amine@267
|
131 "frames_per_buffer": None,
|
amine@267
|
132 "input_device_index": 1,
|
amine@267
|
133 "record": exp_record,
|
amine@267
|
134 }
|
amine@267
|
135
|
amine@267
|
136 split_kwargs = {
|
amine@267
|
137 "min_dur": 0.2,
|
amine@267
|
138 "max_dur": 10,
|
amine@267
|
139 "max_silence": 0.3,
|
amine@267
|
140 "drop_trailing_silence": False,
|
amine@267
|
141 "strict_min_dur": False,
|
amine@267
|
142 "energy_threshold": 55,
|
amine@267
|
143 }
|
amine@267
|
144
|
amine@267
|
145 miscellaneous = {
|
amine@267
|
146 "echo": False,
|
amine@267
|
147 "command": None,
|
amine@292
|
148 "progress_bar": False,
|
amine@267
|
149 "quiet": True,
|
amine@267
|
150 "printf": None,
|
amine@267
|
151 "time_format": "TIME_FORMAT",
|
amine@267
|
152 "timestamp_format": "TIMESTAMP_FORMAT",
|
amine@267
|
153 }
|
amine@267
|
154
|
amine@267
|
155 expected = KeywordArguments(io_kwargs, split_kwargs, miscellaneous)
|
amine@267
|
156 kwargs = make_kwargs(args_ns)
|
amine@267
|
157 self.assertEqual(kwargs, expected)
|
amine@268
|
158
|
amine@268
|
159 @genty_dataset(
|
amine@268
|
160 only_seconds=("%S", 5400, "5400.000"),
|
amine@268
|
161 only_millis=("%I", 5400, "5400000"),
|
amine@268
|
162 full=("%h:%m:%s.%i", 3725.365, "01:02:05.365"),
|
amine@268
|
163 full_zero_hours=("%h:%m:%s.%i", 1925.075, "00:32:05.075"),
|
amine@268
|
164 full_zero_minutes=("%h:%m:%s.%i", 3659.075, "01:00:59.075"),
|
amine@268
|
165 full_zero_seconds=("%h:%m:%s.%i", 3720.075, "01:02:00.075"),
|
amine@268
|
166 full_zero_millis=("%h:%m:%s.%i", 3725, "01:02:05.000"),
|
amine@268
|
167 duplicate_directive=(
|
amine@268
|
168 "%h %h:%m:%s.%i %s",
|
amine@268
|
169 3725.365,
|
amine@268
|
170 "01 01:02:05.365 05",
|
amine@268
|
171 ),
|
amine@268
|
172 no_millis=("%h:%m:%s", 3725, "01:02:05"),
|
amine@268
|
173 no_seconds=("%h:%m", 3725, "01:02"),
|
amine@268
|
174 no_minutes=("%h", 3725, "01"),
|
amine@268
|
175 no_hours=("%m:%s.%i", 3725, "02:05.000"),
|
amine@268
|
176 )
|
amine@291
|
177 def test_make_duration_formatter(self, fmt, duration, expected):
|
amine@291
|
178 formatter = make_duration_formatter(fmt)
|
amine@268
|
179 result = formatter(duration)
|
amine@268
|
180 self.assertEqual(result, expected)
|
amine@268
|
181
|
amine@268
|
182 @genty_dataset(
|
amine@268
|
183 duplicate_only_seconds=("%S %S",),
|
amine@268
|
184 duplicate_only_millis=("%I %I",),
|
amine@268
|
185 unknown_directive=("%x",),
|
amine@268
|
186 )
|
amine@291
|
187 def test_make_duration_formatter_error(self, fmt):
|
amine@268
|
188 with self.assertRaises(TimeFormatError):
|
amine@291
|
189 make_duration_formatter(fmt)
|
amine@269
|
190
|
amine@273
|
191 def test_make_logger_stderr_and_file(self):
|
amine@269
|
192 with TemporaryDirectory() as tmpdir:
|
amine@269
|
193 file = os.path.join(tmpdir, "file.log")
|
amine@273
|
194 logger = make_logger(stderr=True, file=file)
|
amine@273
|
195 self.assertEqual(logger.name, _AUDITOK_LOGGER)
|
amine@269
|
196 self.assertEqual(len(logger.handlers), 2)
|
amine@273
|
197 self.assertEqual(logger.handlers[0].stream.name, "<stderr>")
|
amine@269
|
198 self.assertEqual(logger.handlers[1].stream.name, file)
|
amine@269
|
199
|
amine@269
|
200 def test_make_logger_None(self):
|
amine@273
|
201 logger = make_logger(stderr=False, file=None)
|
amine@269
|
202 self.assertIsNone(logger)
|
amine@271
|
203
|
amine@271
|
204 def test_initialize_workers_all(self):
|
amine@271
|
205 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@285
|
206 with TemporaryDirectory() as tmpdir:
|
amine@285
|
207 export_filename = os.path.join(tmpdir, "output.wav")
|
amine@285
|
208 reader, observers = initialize_workers(
|
amine@285
|
209 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@285
|
210 save_stream=export_filename,
|
amine@285
|
211 export_format="wave",
|
amine@285
|
212 save_detections_as="{id}.wav",
|
amine@285
|
213 echo=True,
|
amine@285
|
214 progress_bar=False,
|
amine@285
|
215 command="some command",
|
amine@285
|
216 quiet=False,
|
amine@285
|
217 printf="abcd",
|
amine@285
|
218 time_format="%S",
|
amine@285
|
219 timestamp_format="%h:%M:%S",
|
amine@285
|
220 )
|
amine@285
|
221 reader.stop()
|
amine@285
|
222 self.assertTrue(patched_player_for.called)
|
amine@285
|
223 self.assertIsInstance(reader, StreamSaverWorker)
|
amine@285
|
224 for obs, cls in zip(
|
amine@285
|
225 observers,
|
amine@285
|
226 [
|
amine@285
|
227 RegionSaverWorker,
|
amine@285
|
228 PlayerWorker,
|
amine@285
|
229 CommandLineWorker,
|
amine@285
|
230 PrintWorker,
|
amine@285
|
231 ],
|
amine@285
|
232 ):
|
amine@285
|
233 self.assertIsInstance(obs, cls)
|
amine@271
|
234
|
amine@271
|
235 def test_initialize_workers_no_RegionSaverWorker(self):
|
amine@271
|
236 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@285
|
237 with TemporaryDirectory() as tmpdir:
|
amine@285
|
238 export_filename = os.path.join(tmpdir, "output.wav")
|
amine@285
|
239 reader, observers = initialize_workers(
|
amine@285
|
240 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@285
|
241 save_stream=export_filename,
|
amine@285
|
242 export_format="wave",
|
amine@285
|
243 save_detections_as=None,
|
amine@285
|
244 echo=True,
|
amine@285
|
245 progress_bar=False,
|
amine@285
|
246 command="some command",
|
amine@285
|
247 quiet=False,
|
amine@285
|
248 printf="abcd",
|
amine@285
|
249 time_format="%S",
|
amine@285
|
250 timestamp_format="%h:%M:%S",
|
amine@285
|
251 )
|
amine@285
|
252 reader.stop()
|
amine@285
|
253 self.assertTrue(patched_player_for.called)
|
amine@285
|
254 self.assertIsInstance(reader, StreamSaverWorker)
|
amine@285
|
255 for obs, cls in zip(
|
amine@285
|
256 observers, [PlayerWorker, CommandLineWorker, PrintWorker]
|
amine@285
|
257 ):
|
amine@285
|
258 self.assertIsInstance(obs, cls)
|
amine@271
|
259
|
amine@271
|
260 def test_initialize_workers_no_PlayerWorker(self):
|
amine@271
|
261 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@285
|
262 with TemporaryDirectory() as tmpdir:
|
amine@285
|
263 export_filename = os.path.join(tmpdir, "output.wav")
|
amine@285
|
264 reader, observers = initialize_workers(
|
amine@285
|
265 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@285
|
266 save_stream=export_filename,
|
amine@285
|
267 export_format="wave",
|
amine@285
|
268 save_detections_as="{id}.wav",
|
amine@285
|
269 echo=False,
|
amine@285
|
270 progress_bar=False,
|
amine@285
|
271 command="some command",
|
amine@285
|
272 quiet=False,
|
amine@285
|
273 printf="abcd",
|
amine@285
|
274 time_format="%S",
|
amine@285
|
275 timestamp_format="%h:%M:%S",
|
amine@285
|
276 )
|
amine@285
|
277 reader.stop()
|
amine@285
|
278 self.assertFalse(patched_player_for.called)
|
amine@285
|
279 self.assertIsInstance(reader, StreamSaverWorker)
|
amine@285
|
280 for obs, cls in zip(
|
amine@285
|
281 observers,
|
amine@285
|
282 [RegionSaverWorker, CommandLineWorker, PrintWorker],
|
amine@285
|
283 ):
|
amine@285
|
284 self.assertIsInstance(obs, cls)
|
amine@271
|
285
|
amine@271
|
286 def test_initialize_workers_no_CommandLineWorker(self):
|
amine@271
|
287 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@285
|
288 with TemporaryDirectory() as tmpdir:
|
amine@285
|
289 export_filename = os.path.join(tmpdir, "output.wav")
|
amine@285
|
290 reader, observers = initialize_workers(
|
amine@285
|
291 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@285
|
292 save_stream=export_filename,
|
amine@285
|
293 export_format="wave",
|
amine@285
|
294 save_detections_as="{id}.wav",
|
amine@285
|
295 echo=True,
|
amine@285
|
296 progress_bar=False,
|
amine@285
|
297 command=None,
|
amine@285
|
298 quiet=False,
|
amine@285
|
299 printf="abcd",
|
amine@285
|
300 time_format="%S",
|
amine@285
|
301 timestamp_format="%h:%M:%S",
|
amine@285
|
302 )
|
amine@285
|
303 reader.stop()
|
amine@285
|
304 self.assertTrue(patched_player_for.called)
|
amine@285
|
305 self.assertIsInstance(reader, StreamSaverWorker)
|
amine@285
|
306 for obs, cls in zip(
|
amine@285
|
307 observers, [RegionSaverWorker, PlayerWorker, PrintWorker]
|
amine@285
|
308 ):
|
amine@285
|
309 self.assertIsInstance(obs, cls)
|
amine@271
|
310
|
amine@271
|
311 def test_initialize_workers_no_PrintWorker(self):
|
amine@271
|
312 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@285
|
313 with TemporaryDirectory() as tmpdir:
|
amine@285
|
314 export_filename = os.path.join(tmpdir, "output.wav")
|
amine@285
|
315 reader, observers = initialize_workers(
|
amine@285
|
316 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@285
|
317 save_stream=export_filename,
|
amine@285
|
318 export_format="wave",
|
amine@285
|
319 save_detections_as="{id}.wav",
|
amine@285
|
320 echo=True,
|
amine@285
|
321 progress_bar=False,
|
amine@285
|
322 command="some command",
|
amine@285
|
323 quiet=True,
|
amine@285
|
324 printf="abcd",
|
amine@285
|
325 time_format="%S",
|
amine@285
|
326 timestamp_format="%h:%M:%S",
|
amine@285
|
327 )
|
amine@285
|
328 reader.stop()
|
amine@285
|
329 self.assertTrue(patched_player_for.called)
|
amine@285
|
330 self.assertIsInstance(reader, StreamSaverWorker)
|
amine@285
|
331 for obs, cls in zip(
|
amine@285
|
332 observers,
|
amine@285
|
333 [RegionSaverWorker, PlayerWorker, CommandLineWorker],
|
amine@285
|
334 ):
|
amine@285
|
335 self.assertIsInstance(obs, cls)
|
amine@271
|
336
|
amine@271
|
337 def test_initialize_workers_no_observers(self):
|
amine@271
|
338 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@271
|
339 reader, observers = initialize_workers(
|
amine@271
|
340 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@271
|
341 save_stream=None,
|
amine@271
|
342 export_format="wave",
|
amine@271
|
343 save_detections_as=None,
|
amine@271
|
344 echo=True,
|
amine@271
|
345 progress_bar=False,
|
amine@271
|
346 command=None,
|
amine@271
|
347 quiet=True,
|
amine@271
|
348 printf="abcd",
|
amine@271
|
349 time_format="%S",
|
amine@271
|
350 timestamp_format="%h:%M:%S",
|
amine@271
|
351 )
|
amine@271
|
352 self.assertTrue(patched_player_for.called)
|
amine@271
|
353 self.assertFalse(isinstance(reader, StreamSaverWorker))
|
amine@271
|
354 self.assertTrue(len(observers), 0)
|