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@331
|
78 save_detections_as=(
|
amine@331
|
79 "stream.ogg",
|
amine@331
|
80 "{id}.wav",
|
amine@331
|
81 False,
|
amine@331
|
82 None,
|
amine@331
|
83 None,
|
amine@331
|
84 None,
|
amine@331
|
85 False,
|
amine@331
|
86 ),
|
amine@267
|
87 )
|
amine@267
|
88 def test_make_kwargs(
|
amine@267
|
89 self,
|
amine@267
|
90 save_stream,
|
amine@292
|
91 save_detections_as,
|
amine@267
|
92 plot,
|
amine@267
|
93 save_image,
|
amine@267
|
94 use_channel,
|
amine@267
|
95 exp_use_channel,
|
amine@267
|
96 exp_record,
|
amine@267
|
97 ):
|
amine@267
|
98
|
amine@267
|
99 args = (
|
amine@267
|
100 "file",
|
amine@267
|
101 30,
|
amine@267
|
102 0.01,
|
amine@267
|
103 16000,
|
amine@267
|
104 2,
|
amine@267
|
105 2,
|
amine@267
|
106 use_channel,
|
amine@267
|
107 "raw",
|
amine@267
|
108 "ogg",
|
amine@267
|
109 True,
|
amine@267
|
110 None,
|
amine@267
|
111 1,
|
amine@267
|
112 save_stream,
|
amine@292
|
113 save_detections_as,
|
amine@267
|
114 plot,
|
amine@267
|
115 save_image,
|
amine@267
|
116 0.2,
|
amine@267
|
117 10,
|
amine@267
|
118 0.3,
|
amine@267
|
119 False,
|
amine@267
|
120 False,
|
amine@267
|
121 55,
|
amine@267
|
122 )
|
amine@331
|
123 misc = (
|
amine@331
|
124 False,
|
amine@331
|
125 False,
|
amine@331
|
126 None,
|
amine@331
|
127 True,
|
amine@331
|
128 None,
|
amine@331
|
129 "TIME_FORMAT",
|
amine@331
|
130 "TIMESTAMP_FORMAT",
|
amine@331
|
131 )
|
amine@267
|
132 args_ns = _ArgsNamespece(*(args + misc))
|
amine@267
|
133
|
amine@267
|
134 io_kwargs = {
|
amine@267
|
135 "input": "file",
|
amine@267
|
136 "max_read": 30,
|
amine@267
|
137 "block_dur": 0.01,
|
amine@267
|
138 "sampling_rate": 16000,
|
amine@267
|
139 "sample_width": 2,
|
amine@267
|
140 "channels": 2,
|
amine@267
|
141 "use_channel": exp_use_channel,
|
amine@267
|
142 "save_stream": save_stream,
|
amine@292
|
143 "save_detections_as": save_detections_as,
|
amine@267
|
144 "audio_format": "raw",
|
amine@267
|
145 "export_format": "ogg",
|
amine@267
|
146 "large_file": True,
|
amine@267
|
147 "frames_per_buffer": None,
|
amine@267
|
148 "input_device_index": 1,
|
amine@267
|
149 "record": exp_record,
|
amine@267
|
150 }
|
amine@267
|
151
|
amine@267
|
152 split_kwargs = {
|
amine@267
|
153 "min_dur": 0.2,
|
amine@267
|
154 "max_dur": 10,
|
amine@267
|
155 "max_silence": 0.3,
|
amine@267
|
156 "drop_trailing_silence": False,
|
amine@267
|
157 "strict_min_dur": False,
|
amine@267
|
158 "energy_threshold": 55,
|
amine@267
|
159 }
|
amine@267
|
160
|
amine@267
|
161 miscellaneous = {
|
amine@267
|
162 "echo": False,
|
amine@267
|
163 "command": None,
|
amine@292
|
164 "progress_bar": False,
|
amine@267
|
165 "quiet": True,
|
amine@267
|
166 "printf": None,
|
amine@267
|
167 "time_format": "TIME_FORMAT",
|
amine@267
|
168 "timestamp_format": "TIMESTAMP_FORMAT",
|
amine@267
|
169 }
|
amine@267
|
170
|
amine@267
|
171 expected = KeywordArguments(io_kwargs, split_kwargs, miscellaneous)
|
amine@267
|
172 kwargs = make_kwargs(args_ns)
|
amine@267
|
173 self.assertEqual(kwargs, expected)
|
amine@268
|
174
|
amine@268
|
175 @genty_dataset(
|
amine@268
|
176 only_seconds=("%S", 5400, "5400.000"),
|
amine@268
|
177 only_millis=("%I", 5400, "5400000"),
|
amine@268
|
178 full=("%h:%m:%s.%i", 3725.365, "01:02:05.365"),
|
amine@268
|
179 full_zero_hours=("%h:%m:%s.%i", 1925.075, "00:32:05.075"),
|
amine@268
|
180 full_zero_minutes=("%h:%m:%s.%i", 3659.075, "01:00:59.075"),
|
amine@268
|
181 full_zero_seconds=("%h:%m:%s.%i", 3720.075, "01:02:00.075"),
|
amine@268
|
182 full_zero_millis=("%h:%m:%s.%i", 3725, "01:02:05.000"),
|
amine@268
|
183 duplicate_directive=(
|
amine@268
|
184 "%h %h:%m:%s.%i %s",
|
amine@268
|
185 3725.365,
|
amine@268
|
186 "01 01:02:05.365 05",
|
amine@268
|
187 ),
|
amine@268
|
188 no_millis=("%h:%m:%s", 3725, "01:02:05"),
|
amine@268
|
189 no_seconds=("%h:%m", 3725, "01:02"),
|
amine@268
|
190 no_minutes=("%h", 3725, "01"),
|
amine@268
|
191 no_hours=("%m:%s.%i", 3725, "02:05.000"),
|
amine@268
|
192 )
|
amine@291
|
193 def test_make_duration_formatter(self, fmt, duration, expected):
|
amine@291
|
194 formatter = make_duration_formatter(fmt)
|
amine@268
|
195 result = formatter(duration)
|
amine@268
|
196 self.assertEqual(result, expected)
|
amine@268
|
197
|
amine@268
|
198 @genty_dataset(
|
amine@268
|
199 duplicate_only_seconds=("%S %S",),
|
amine@268
|
200 duplicate_only_millis=("%I %I",),
|
amine@268
|
201 unknown_directive=("%x",),
|
amine@268
|
202 )
|
amine@291
|
203 def test_make_duration_formatter_error(self, fmt):
|
amine@268
|
204 with self.assertRaises(TimeFormatError):
|
amine@291
|
205 make_duration_formatter(fmt)
|
amine@269
|
206
|
amine@273
|
207 def test_make_logger_stderr_and_file(self):
|
amine@269
|
208 with TemporaryDirectory() as tmpdir:
|
amine@269
|
209 file = os.path.join(tmpdir, "file.log")
|
amine@273
|
210 logger = make_logger(stderr=True, file=file)
|
amine@273
|
211 self.assertEqual(logger.name, _AUDITOK_LOGGER)
|
amine@269
|
212 self.assertEqual(len(logger.handlers), 2)
|
amine@273
|
213 self.assertEqual(logger.handlers[0].stream.name, "<stderr>")
|
amine@269
|
214 self.assertEqual(logger.handlers[1].stream.name, file)
|
amine@269
|
215
|
amine@269
|
216 def test_make_logger_None(self):
|
amine@273
|
217 logger = make_logger(stderr=False, file=None)
|
amine@269
|
218 self.assertIsNone(logger)
|
amine@271
|
219
|
amine@271
|
220 def test_initialize_workers_all(self):
|
amine@271
|
221 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@285
|
222 with TemporaryDirectory() as tmpdir:
|
amine@285
|
223 export_filename = os.path.join(tmpdir, "output.wav")
|
amine@285
|
224 reader, observers = initialize_workers(
|
amine@285
|
225 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@285
|
226 save_stream=export_filename,
|
amine@285
|
227 export_format="wave",
|
amine@285
|
228 save_detections_as="{id}.wav",
|
amine@285
|
229 echo=True,
|
amine@285
|
230 progress_bar=False,
|
amine@285
|
231 command="some command",
|
amine@285
|
232 quiet=False,
|
amine@285
|
233 printf="abcd",
|
amine@285
|
234 time_format="%S",
|
amine@285
|
235 timestamp_format="%h:%M:%S",
|
amine@285
|
236 )
|
amine@285
|
237 reader.stop()
|
amine@285
|
238 self.assertTrue(patched_player_for.called)
|
amine@285
|
239 self.assertIsInstance(reader, StreamSaverWorker)
|
amine@285
|
240 for obs, cls in zip(
|
amine@285
|
241 observers,
|
amine@285
|
242 [
|
amine@285
|
243 RegionSaverWorker,
|
amine@285
|
244 PlayerWorker,
|
amine@285
|
245 CommandLineWorker,
|
amine@285
|
246 PrintWorker,
|
amine@285
|
247 ],
|
amine@285
|
248 ):
|
amine@285
|
249 self.assertIsInstance(obs, cls)
|
amine@271
|
250
|
amine@271
|
251 def test_initialize_workers_no_RegionSaverWorker(self):
|
amine@271
|
252 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@285
|
253 with TemporaryDirectory() as tmpdir:
|
amine@285
|
254 export_filename = os.path.join(tmpdir, "output.wav")
|
amine@285
|
255 reader, observers = initialize_workers(
|
amine@285
|
256 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@285
|
257 save_stream=export_filename,
|
amine@285
|
258 export_format="wave",
|
amine@285
|
259 save_detections_as=None,
|
amine@285
|
260 echo=True,
|
amine@285
|
261 progress_bar=False,
|
amine@285
|
262 command="some command",
|
amine@285
|
263 quiet=False,
|
amine@285
|
264 printf="abcd",
|
amine@285
|
265 time_format="%S",
|
amine@285
|
266 timestamp_format="%h:%M:%S",
|
amine@285
|
267 )
|
amine@285
|
268 reader.stop()
|
amine@285
|
269 self.assertTrue(patched_player_for.called)
|
amine@285
|
270 self.assertIsInstance(reader, StreamSaverWorker)
|
amine@285
|
271 for obs, cls in zip(
|
amine@285
|
272 observers, [PlayerWorker, CommandLineWorker, PrintWorker]
|
amine@285
|
273 ):
|
amine@285
|
274 self.assertIsInstance(obs, cls)
|
amine@271
|
275
|
amine@271
|
276 def test_initialize_workers_no_PlayerWorker(self):
|
amine@271
|
277 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@285
|
278 with TemporaryDirectory() as tmpdir:
|
amine@285
|
279 export_filename = os.path.join(tmpdir, "output.wav")
|
amine@285
|
280 reader, observers = initialize_workers(
|
amine@285
|
281 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@285
|
282 save_stream=export_filename,
|
amine@285
|
283 export_format="wave",
|
amine@285
|
284 save_detections_as="{id}.wav",
|
amine@285
|
285 echo=False,
|
amine@285
|
286 progress_bar=False,
|
amine@285
|
287 command="some command",
|
amine@285
|
288 quiet=False,
|
amine@285
|
289 printf="abcd",
|
amine@285
|
290 time_format="%S",
|
amine@285
|
291 timestamp_format="%h:%M:%S",
|
amine@285
|
292 )
|
amine@285
|
293 reader.stop()
|
amine@285
|
294 self.assertFalse(patched_player_for.called)
|
amine@285
|
295 self.assertIsInstance(reader, StreamSaverWorker)
|
amine@285
|
296 for obs, cls in zip(
|
amine@285
|
297 observers,
|
amine@285
|
298 [RegionSaverWorker, CommandLineWorker, PrintWorker],
|
amine@285
|
299 ):
|
amine@285
|
300 self.assertIsInstance(obs, cls)
|
amine@271
|
301
|
amine@271
|
302 def test_initialize_workers_no_CommandLineWorker(self):
|
amine@271
|
303 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@285
|
304 with TemporaryDirectory() as tmpdir:
|
amine@285
|
305 export_filename = os.path.join(tmpdir, "output.wav")
|
amine@285
|
306 reader, observers = initialize_workers(
|
amine@285
|
307 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@285
|
308 save_stream=export_filename,
|
amine@285
|
309 export_format="wave",
|
amine@285
|
310 save_detections_as="{id}.wav",
|
amine@285
|
311 echo=True,
|
amine@285
|
312 progress_bar=False,
|
amine@285
|
313 command=None,
|
amine@285
|
314 quiet=False,
|
amine@285
|
315 printf="abcd",
|
amine@285
|
316 time_format="%S",
|
amine@285
|
317 timestamp_format="%h:%M:%S",
|
amine@285
|
318 )
|
amine@285
|
319 reader.stop()
|
amine@285
|
320 self.assertTrue(patched_player_for.called)
|
amine@285
|
321 self.assertIsInstance(reader, StreamSaverWorker)
|
amine@285
|
322 for obs, cls in zip(
|
amine@285
|
323 observers, [RegionSaverWorker, PlayerWorker, PrintWorker]
|
amine@285
|
324 ):
|
amine@285
|
325 self.assertIsInstance(obs, cls)
|
amine@271
|
326
|
amine@271
|
327 def test_initialize_workers_no_PrintWorker(self):
|
amine@271
|
328 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@285
|
329 with TemporaryDirectory() as tmpdir:
|
amine@285
|
330 export_filename = os.path.join(tmpdir, "output.wav")
|
amine@285
|
331 reader, observers = initialize_workers(
|
amine@285
|
332 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@285
|
333 save_stream=export_filename,
|
amine@285
|
334 export_format="wave",
|
amine@285
|
335 save_detections_as="{id}.wav",
|
amine@285
|
336 echo=True,
|
amine@285
|
337 progress_bar=False,
|
amine@285
|
338 command="some command",
|
amine@285
|
339 quiet=True,
|
amine@285
|
340 printf="abcd",
|
amine@285
|
341 time_format="%S",
|
amine@285
|
342 timestamp_format="%h:%M:%S",
|
amine@285
|
343 )
|
amine@285
|
344 reader.stop()
|
amine@285
|
345 self.assertTrue(patched_player_for.called)
|
amine@285
|
346 self.assertIsInstance(reader, StreamSaverWorker)
|
amine@285
|
347 for obs, cls in zip(
|
amine@285
|
348 observers,
|
amine@285
|
349 [RegionSaverWorker, PlayerWorker, CommandLineWorker],
|
amine@285
|
350 ):
|
amine@285
|
351 self.assertIsInstance(obs, cls)
|
amine@271
|
352
|
amine@271
|
353 def test_initialize_workers_no_observers(self):
|
amine@271
|
354 with patch("auditok.cmdline_util.player_for") as patched_player_for:
|
amine@271
|
355 reader, observers = initialize_workers(
|
amine@271
|
356 input="tests/data/test_16KHZ_mono_400Hz.wav",
|
amine@271
|
357 save_stream=None,
|
amine@271
|
358 export_format="wave",
|
amine@271
|
359 save_detections_as=None,
|
amine@271
|
360 echo=True,
|
amine@271
|
361 progress_bar=False,
|
amine@271
|
362 command=None,
|
amine@271
|
363 quiet=True,
|
amine@271
|
364 printf="abcd",
|
amine@271
|
365 time_format="%S",
|
amine@271
|
366 timestamp_format="%h:%M:%S",
|
amine@271
|
367 )
|
amine@271
|
368 self.assertTrue(patched_player_for.called)
|
amine@271
|
369 self.assertFalse(isinstance(reader, StreamSaverWorker))
|
amine@271
|
370 self.assertTrue(len(observers), 0)
|