Merge branch '34-add-quiet-option-to-not-display-processing-conversion-output' into 'master'
Add 'quiet' option to not display processing/conversion output Closes #34 See merge request micro-ROS/ros_tracing/tracetools_analysis!62
This commit is contained in:
commit
9a01789769
4 changed files with 74 additions and 19 deletions
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Copyright 2019 Apex.AI, Inc.
|
# Copyright 2019 Apex.AI, Inc.
|
||||||
|
# Copyright 2020 Christophe Bedard
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
@ -13,6 +14,8 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
from io import StringIO
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
@ -21,7 +24,7 @@ import unittest
|
||||||
from tracetools_analysis.loading import inspect_input_path
|
from tracetools_analysis.loading import inspect_input_path
|
||||||
|
|
||||||
|
|
||||||
class TestProcessCommand(unittest.TestCase):
|
class TestLoading(unittest.TestCase):
|
||||||
|
|
||||||
def __init__(self, *args) -> None:
|
def __init__(self, *args) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
|
@ -60,31 +63,43 @@ class TestProcessCommand(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
shutil.rmtree(self.test_dir_path)
|
shutil.rmtree(self.test_dir_path)
|
||||||
|
|
||||||
def test_inspect_input_path(self) -> None:
|
def test_inspect_input_path(
|
||||||
|
self,
|
||||||
|
quiet: bool = False,
|
||||||
|
) -> None:
|
||||||
# Should find converted file under directory
|
# Should find converted file under directory
|
||||||
file_path, create_file = inspect_input_path(self.with_converted_file_dir, False)
|
file_path, create_file = inspect_input_path(self.with_converted_file_dir, False, quiet)
|
||||||
self.assertEqual(self.converted_file_path, file_path)
|
self.assertEqual(self.converted_file_path, file_path)
|
||||||
self.assertFalse(create_file)
|
self.assertFalse(create_file)
|
||||||
# Should find it but set it to be re-created
|
# Should find it but set it to be re-created
|
||||||
file_path, create_file = inspect_input_path(self.with_converted_file_dir, True)
|
file_path, create_file = inspect_input_path(self.with_converted_file_dir, True, quiet)
|
||||||
self.assertEqual(self.converted_file_path, file_path)
|
self.assertEqual(self.converted_file_path, file_path)
|
||||||
self.assertTrue(create_file)
|
self.assertTrue(create_file)
|
||||||
|
|
||||||
# Should fail to find converted file under directory
|
# Should fail to find converted file under directory
|
||||||
file_path, create_file = inspect_input_path(self.without_converted_file_dir, False)
|
file_path, create_file = inspect_input_path(self.without_converted_file_dir, False, quiet)
|
||||||
self.assertIsNone(file_path)
|
self.assertIsNone(file_path)
|
||||||
self.assertFalse(create_file)
|
self.assertFalse(create_file)
|
||||||
file_path, create_file = inspect_input_path(self.without_converted_file_dir, True)
|
file_path, create_file = inspect_input_path(self.without_converted_file_dir, True, quiet)
|
||||||
self.assertIsNone(file_path)
|
self.assertIsNone(file_path)
|
||||||
self.assertFalse(create_file)
|
self.assertFalse(create_file)
|
||||||
|
|
||||||
# Should accept any file path if it exists
|
# Should accept any file path if it exists
|
||||||
file_path, create_file = inspect_input_path(self.random_file_path, False)
|
file_path, create_file = inspect_input_path(self.random_file_path, False, quiet)
|
||||||
self.assertEqual(self.random_file_path, file_path)
|
self.assertEqual(self.random_file_path, file_path)
|
||||||
self.assertFalse(create_file)
|
self.assertFalse(create_file)
|
||||||
# Should set it to be re-created
|
# Should set it to be re-created
|
||||||
file_path, create_file = inspect_input_path(self.random_file_path, True)
|
file_path, create_file = inspect_input_path(self.random_file_path, True, quiet)
|
||||||
self.assertEqual(self.random_file_path, file_path)
|
self.assertEqual(self.random_file_path, file_path)
|
||||||
self.assertTrue(create_file)
|
self.assertTrue(create_file)
|
||||||
|
|
||||||
# TODO try with a trace directory
|
# TODO try with a trace directory
|
||||||
|
|
||||||
|
def test_inspect_input_path_quiet(self) -> None:
|
||||||
|
temp_stdout = StringIO()
|
||||||
|
with contextlib.redirect_stdout(temp_stdout):
|
||||||
|
# Just run the other test again
|
||||||
|
self.test_inspect_input_path(quiet=True)
|
||||||
|
# Shouldn't be any output
|
||||||
|
output = temp_stdout.getvalue()
|
||||||
|
self.assertEqual(0, len(output), f'was not quiet: "{output}"')
|
|
@ -12,6 +12,8 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
from io import StringIO
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Set
|
from typing import Set
|
||||||
import unittest
|
import unittest
|
||||||
|
@ -172,6 +174,21 @@ class TestProcessor(unittest.TestCase):
|
||||||
result = processor.get_handler_by_type(StubHandler1)
|
result = processor.get_handler_by_type(StubHandler1)
|
||||||
self.assertTrue(result is handler1)
|
self.assertTrue(result is handler1)
|
||||||
|
|
||||||
|
def test_processor_quiet(self) -> None:
|
||||||
|
handler1 = StubHandler1()
|
||||||
|
mock_event = {
|
||||||
|
'_name': 'myeventname',
|
||||||
|
'_timestamp': 0,
|
||||||
|
'cpu_id': 0,
|
||||||
|
}
|
||||||
|
temp_stdout = StringIO()
|
||||||
|
with contextlib.redirect_stdout(temp_stdout):
|
||||||
|
processor = Processor(handler1, quiet=True)
|
||||||
|
processor.process([mock_event])
|
||||||
|
# Shouldn't be any output
|
||||||
|
output = temp_stdout.getvalue()
|
||||||
|
self.assertEqual(0, len(output), f'Processor was not quiet: "{output}"')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -31,6 +31,7 @@ from ..convert import DEFAULT_CONVERT_FILE_NAME
|
||||||
def inspect_input_path(
|
def inspect_input_path(
|
||||||
input_path: str,
|
input_path: str,
|
||||||
force_conversion: bool = False,
|
force_conversion: bool = False,
|
||||||
|
quiet: bool = False,
|
||||||
) -> Tuple[Optional[str], bool]:
|
) -> Tuple[Optional[str], bool]:
|
||||||
"""
|
"""
|
||||||
Check input path for a converted file or a trace directory.
|
Check input path for a converted file or a trace directory.
|
||||||
|
@ -43,6 +44,7 @@ def inspect_input_path(
|
||||||
|
|
||||||
:param input_path: the path to a converted file or trace directory
|
:param input_path: the path to a converted file or trace directory
|
||||||
:param force_conversion: whether to re-create converted file even if it is found
|
:param force_conversion: whether to re-create converted file even if it is found
|
||||||
|
:param quiet: whether to not print any normal output
|
||||||
:return:
|
:return:
|
||||||
the path to a converted file (or `None` if could not find),
|
the path to a converted file (or `None` if could not find),
|
||||||
`True` if the given converted file should be (re-)created, `False` otherwise
|
`True` if the given converted file should be (re-)created, `False` otherwise
|
||||||
|
@ -59,9 +61,13 @@ def inspect_input_path(
|
||||||
# Use that as the converted input file
|
# Use that as the converted input file
|
||||||
converted_file_path = prospective_converted_file
|
converted_file_path = prospective_converted_file
|
||||||
if force_conversion:
|
if force_conversion:
|
||||||
print(f'found converted file but will re-create it: {prospective_converted_file}')
|
if not quiet:
|
||||||
|
print(
|
||||||
|
f'found converted file but will re-create it: {prospective_converted_file}'
|
||||||
|
)
|
||||||
return prospective_converted_file, True
|
return prospective_converted_file, True
|
||||||
else:
|
else:
|
||||||
|
if not quiet:
|
||||||
print(f'found converted file: {prospective_converted_file}')
|
print(f'found converted file: {prospective_converted_file}')
|
||||||
return prospective_converted_file, False
|
return prospective_converted_file, False
|
||||||
else:
|
else:
|
||||||
|
@ -81,6 +87,7 @@ def inspect_input_path(
|
||||||
converted_file_path = input_path
|
converted_file_path = input_path
|
||||||
if force_conversion:
|
if force_conversion:
|
||||||
# It's a file, but re-create it anyway
|
# It's a file, but re-create it anyway
|
||||||
|
if not quiet:
|
||||||
print(f'found converted file but will re-create it: {converted_file_path}')
|
print(f'found converted file but will re-create it: {converted_file_path}')
|
||||||
return converted_file_path, True
|
return converted_file_path, True
|
||||||
else:
|
else:
|
||||||
|
@ -92,15 +99,21 @@ def inspect_input_path(
|
||||||
def convert_if_needed(
|
def convert_if_needed(
|
||||||
input_path: str,
|
input_path: str,
|
||||||
force_conversion: bool = False,
|
force_conversion: bool = False,
|
||||||
|
quiet: bool = False,
|
||||||
) -> Optional[str]:
|
) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Inspect input path and convert trace directory to file if necessary.
|
Inspect input path and convert trace directory to file if necessary.
|
||||||
|
|
||||||
:param input_path: the path to a converted file or trace directory
|
:param input_path: the path to a converted file or trace directory
|
||||||
:param force_conversion: whether to re-create converted file even if it is found
|
:param force_conversion: whether to re-create converted file even if it is found
|
||||||
|
:param quiet: whether to not print any output
|
||||||
:return: the path to the converted file, or `None` if it failed
|
:return: the path to the converted file, or `None` if it failed
|
||||||
"""
|
"""
|
||||||
converted_file_path, create_converted_file = inspect_input_path(input_path, force_conversion)
|
converted_file_path, create_converted_file = inspect_input_path(
|
||||||
|
input_path,
|
||||||
|
force_conversion,
|
||||||
|
quiet,
|
||||||
|
)
|
||||||
|
|
||||||
if converted_file_path is None:
|
if converted_file_path is None:
|
||||||
return None
|
return None
|
||||||
|
@ -118,6 +131,7 @@ def load_file(
|
||||||
input_path: str,
|
input_path: str,
|
||||||
do_convert_if_needed: bool = True,
|
do_convert_if_needed: bool = True,
|
||||||
force_conversion: bool = False,
|
force_conversion: bool = False,
|
||||||
|
quiet: bool = False,
|
||||||
) -> List[Dict]:
|
) -> List[Dict]:
|
||||||
"""
|
"""
|
||||||
Load file containing converted trace events.
|
Load file containing converted trace events.
|
||||||
|
@ -125,10 +139,11 @@ def load_file(
|
||||||
:param input_path: the path to a converted file or trace directory
|
:param input_path: the path to a converted file or trace directory
|
||||||
:param do_convert_if_needed: whether to create the converted file if needed (else, let it fail)
|
:param do_convert_if_needed: whether to create the converted file if needed (else, let it fail)
|
||||||
:param force_conversion: whether to re-create converted file even if it is found
|
:param force_conversion: whether to re-create converted file even if it is found
|
||||||
|
:param quiet: whether to not print any output
|
||||||
:return: the list of events read from the file
|
:return: the list of events read from the file
|
||||||
"""
|
"""
|
||||||
if do_convert_if_needed or force_conversion:
|
if do_convert_if_needed or force_conversion:
|
||||||
file_path = convert_if_needed(input_path, force_conversion)
|
file_path = convert_if_needed(input_path, force_conversion, quiet)
|
||||||
else:
|
else:
|
||||||
file_path = input_path
|
file_path = input_path
|
||||||
|
|
||||||
|
|
|
@ -289,12 +289,14 @@ class Processor():
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*handlers: EventHandler,
|
*handlers: EventHandler,
|
||||||
|
quiet: bool = False,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Create a Processor.
|
Create a Processor.
|
||||||
|
|
||||||
:param handlers: the `EventHandler`s to use for processing
|
:param handlers: the `EventHandler`s to use for processing
|
||||||
|
:param quiet: whether to not print any output, like progress information
|
||||||
:param kwargs: the parameters to pass on to new handlers
|
:param kwargs: the parameters to pass on to new handlers
|
||||||
"""
|
"""
|
||||||
self._initial_handlers = list(handlers)
|
self._initial_handlers = list(handlers)
|
||||||
|
@ -303,9 +305,10 @@ class Processor():
|
||||||
self._expanded_handlers = self._expand_dependencies(*handlers, **kwargs)
|
self._expanded_handlers = self._expand_dependencies(*handlers, **kwargs)
|
||||||
self._handler_multimap = self._get_handler_maps(self._expanded_handlers)
|
self._handler_multimap = self._get_handler_maps(self._expanded_handlers)
|
||||||
self._register_with_handlers(self._expanded_handlers)
|
self._register_with_handlers(self._expanded_handlers)
|
||||||
|
self._quiet = quiet
|
||||||
self._progress_display = ProcessingProgressDisplay(
|
self._progress_display = ProcessingProgressDisplay(
|
||||||
[type(handler).__name__ for handler in self._expanded_handlers],
|
[type(handler).__name__ for handler in self._expanded_handlers],
|
||||||
)
|
) if not self._quiet else None
|
||||||
self._processing_done = False
|
self._processing_done = False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -401,12 +404,17 @@ class Processor():
|
||||||
self._check_required_events(events)
|
self._check_required_events(events)
|
||||||
|
|
||||||
if not self._processing_done:
|
if not self._processing_done:
|
||||||
|
# Split into two versions so that performance is optimal
|
||||||
|
if self._progress_display is None:
|
||||||
|
for event in events:
|
||||||
|
self._process_event(event)
|
||||||
|
else:
|
||||||
self._progress_display.set_work_total(len(events))
|
self._progress_display.set_work_total(len(events))
|
||||||
for event in events:
|
for event in events:
|
||||||
self._process_event(event)
|
self._process_event(event)
|
||||||
self._progress_display.did_work()
|
self._progress_display.did_work()
|
||||||
self._processing_done = True
|
|
||||||
self._progress_display.done(erase=erase_progress)
|
self._progress_display.done(erase=erase_progress)
|
||||||
|
self._processing_done = True
|
||||||
|
|
||||||
def _process_event(self, event: DictEvent) -> None:
|
def _process_event(self, event: DictEvent) -> None:
|
||||||
"""Process a single event."""
|
"""Process a single event."""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue