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