From f09cd960d61fa98d267e5a666dcfde39e6aa7565 Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Sun, 13 Oct 2019 14:39:21 -0700 Subject: [PATCH] Add ros2trace_analysis command and process/convert verbs --- .gitlab-ci.yml | 2 +- ros2trace_analysis/.gitignore | 3 ++ ros2trace_analysis/package.xml | 23 ++++++++++ .../ros2trace_analysis/__init__.py | 13 ++++++ .../ros2trace_analysis/api/__init__.py | 13 ++++++ .../ros2trace_analysis/command/__init__.py | 13 ++++++ .../command/trace_analysis.py | 41 +++++++++++++++++ .../ros2trace_analysis/verb/__init__.py | 13 ++++++ .../ros2trace_analysis/verb/convert.py | 30 +++++++++++++ .../ros2trace_analysis/verb/process.py | 30 +++++++++++++ ros2trace_analysis/setup.py | 44 +++++++++++++++++++ ros2trace_analysis/test/test_copyright.py | 23 ++++++++++ ros2trace_analysis/test/test_flake8.py | 23 ++++++++++ ros2trace_analysis/test/test_pep257.py | 23 ++++++++++ ros2trace_analysis/test/test_xmllint.py | 23 ++++++++++ .../tracetools_analysis/convert.py | 15 ++++--- .../tracetools_analysis/process.py | 13 ++++-- 17 files changed, 335 insertions(+), 10 deletions(-) create mode 100644 ros2trace_analysis/.gitignore create mode 100644 ros2trace_analysis/package.xml create mode 100644 ros2trace_analysis/ros2trace_analysis/__init__.py create mode 100644 ros2trace_analysis/ros2trace_analysis/api/__init__.py create mode 100644 ros2trace_analysis/ros2trace_analysis/command/__init__.py create mode 100644 ros2trace_analysis/ros2trace_analysis/command/trace_analysis.py create mode 100644 ros2trace_analysis/ros2trace_analysis/verb/__init__.py create mode 100644 ros2trace_analysis/ros2trace_analysis/verb/convert.py create mode 100644 ros2trace_analysis/ros2trace_analysis/verb/process.py create mode 100644 ros2trace_analysis/setup.py create mode 100644 ros2trace_analysis/test/test_copyright.py create mode 100644 ros2trace_analysis/test/test_flake8.py create mode 100644 ros2trace_analysis/test/test_pep257.py create mode 100644 ros2trace_analysis/test/test_xmllint.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 35597ae..06a0fa3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,6 @@ variables: DOCKER_DRIVER: overlay2 - PACKAGES_LIST: tracetools_analysis + PACKAGES_LIST: tracetools_analysis ros2trace_analysis base_image_id: registry.gitlab.com/micro-ros/ros_tracing/ci_base .global_artifacts: &global_artifacts diff --git a/ros2trace_analysis/.gitignore b/ros2trace_analysis/.gitignore new file mode 100644 index 0000000..eef29c1 --- /dev/null +++ b/ros2trace_analysis/.gitignore @@ -0,0 +1,3 @@ +*~ +*.pyc + diff --git a/ros2trace_analysis/package.xml b/ros2trace_analysis/package.xml new file mode 100644 index 0000000..9fa17c0 --- /dev/null +++ b/ros2trace_analysis/package.xml @@ -0,0 +1,23 @@ + + + + ros2trace_analysis + 0.1.1 + The trace analysis command for ROS 2 command line tools. + Christophe Bedard + Apache 2.0 + Christophe Bedard + + ros2cli + tracetools_analysis + + ament_copyright + ament_flake8 + ament_pep257 + ament_xmllint + python3-pytest + + + ament_python + + diff --git a/ros2trace_analysis/ros2trace_analysis/__init__.py b/ros2trace_analysis/ros2trace_analysis/__init__.py new file mode 100644 index 0000000..35ffb6e --- /dev/null +++ b/ros2trace_analysis/ros2trace_analysis/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019 Apex.AI, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/ros2trace_analysis/ros2trace_analysis/api/__init__.py b/ros2trace_analysis/ros2trace_analysis/api/__init__.py new file mode 100644 index 0000000..35ffb6e --- /dev/null +++ b/ros2trace_analysis/ros2trace_analysis/api/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019 Apex.AI, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/ros2trace_analysis/ros2trace_analysis/command/__init__.py b/ros2trace_analysis/ros2trace_analysis/command/__init__.py new file mode 100644 index 0000000..35ffb6e --- /dev/null +++ b/ros2trace_analysis/ros2trace_analysis/command/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019 Apex.AI, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/ros2trace_analysis/ros2trace_analysis/command/trace_analysis.py b/ros2trace_analysis/ros2trace_analysis/command/trace_analysis.py new file mode 100644 index 0000000..0ae2f1f --- /dev/null +++ b/ros2trace_analysis/ros2trace_analysis/command/trace_analysis.py @@ -0,0 +1,41 @@ +# Copyright 2019 Apex.AI, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Module for trace analysis command extension implementation.""" + +from ros2cli.command import add_subparsers +from ros2cli.command import CommandExtension +from ros2cli.verb import get_verb_extensions + + +class TraceAnalysisCommand(CommandExtension): + """Analyze traces to extract useful execution data.""" + + def add_arguments(self, parser, cli_name): + self._subparser = parser + # get verb extensions and let them add their arguments + verb_extensions = get_verb_extensions('ros2trace_analysis.verb') + add_subparsers( + parser, cli_name, '_verb', verb_extensions, required=False) + + def main(self, *, parser, args): + if not hasattr(args, '_verb'): + # in case no verb was passed + self._subparser.print_help() + return 0 + + extension = getattr(args, '_verb') + + # call the verb's main method + return extension.main(args=args) diff --git a/ros2trace_analysis/ros2trace_analysis/verb/__init__.py b/ros2trace_analysis/ros2trace_analysis/verb/__init__.py new file mode 100644 index 0000000..35ffb6e --- /dev/null +++ b/ros2trace_analysis/ros2trace_analysis/verb/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019 Apex.AI, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/ros2trace_analysis/ros2trace_analysis/verb/convert.py b/ros2trace_analysis/ros2trace_analysis/verb/convert.py new file mode 100644 index 0000000..62ea13f --- /dev/null +++ b/ros2trace_analysis/ros2trace_analysis/verb/convert.py @@ -0,0 +1,30 @@ +# Copyright 2019 Apex.AI, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ros2cli.verb import VerbExtension +from tracetools_analysis.convert import add_args +from tracetools_analysis.convert import convert + + +class ConvertVerb(VerbExtension): + """Convert trace data to a file.""" + + def add_arguments(self, parser, cli_name): + add_args(parser) + + def main(self, *, args): + return convert( + args.trace_directory, + args.output_file_name, + ) diff --git a/ros2trace_analysis/ros2trace_analysis/verb/process.py b/ros2trace_analysis/ros2trace_analysis/verb/process.py new file mode 100644 index 0000000..9d650e8 --- /dev/null +++ b/ros2trace_analysis/ros2trace_analysis/verb/process.py @@ -0,0 +1,30 @@ +# Copyright 2019 Apex.AI, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ros2cli.verb import VerbExtension +from tracetools_analysis.process import add_args +from tracetools_analysis.process import process + + +class ProcessVerb(VerbExtension): + """Process a file converted from a trace directory and output model data.""" + + def add_arguments(self, parser, cli_name): + add_args(parser) + + def main(self, *, args): + return process( + args.input_path, + args.force_conversion, + ) diff --git a/ros2trace_analysis/setup.py b/ros2trace_analysis/setup.py new file mode 100644 index 0000000..744965f --- /dev/null +++ b/ros2trace_analysis/setup.py @@ -0,0 +1,44 @@ +from setuptools import find_packages +from setuptools import setup + +package_name = 'ros2trace_analysis' + +setup( + name=package_name, + version='0.1.1', + packages=find_packages(exclude=['test']), + data_files=[ + ('share/' + package_name, ['package.xml']), + ], + install_requires=['ros2cli'], + zip_safe=True, + maintainer=( + 'Christophe Bedard' + ), + maintainer_email=( + 'christophe.bedard@apex.ai' + ), + author='Christophe Bedard', + author_email='christophe.bedard@apex.ai', + url='https://gitlab.com/micro-ROS/ros_tracing/tracetools_analysis', + keywords=[], + description='The trace analysis command for ROS 2 command line tools.', + long_description=( + 'The package provides the trace analysis ' + 'command for the ROS 2 command line tools.' + ), + license='Apache 2.0', + tests_require=['pytest'], + entry_points={ + 'ros2cli.command': [ + f'trace-analysis = {package_name}.command.trace_analysis:TraceAnalysisCommand', + ], + 'ros2cli.extension_point': [ + f'{package_name}.verb = {package_name}.verb:VerbExtension', + ], + f'{package_name}.verb': [ + f'convert = {package_name}.verb.convert:ConvertVerb', + f'process = {package_name}.verb.process:ProcessVerb', + ], + } +) diff --git a/ros2trace_analysis/test/test_copyright.py b/ros2trace_analysis/test/test_copyright.py new file mode 100644 index 0000000..cf0fae3 --- /dev/null +++ b/ros2trace_analysis/test/test_copyright.py @@ -0,0 +1,23 @@ +# Copyright 2017 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_copyright.main import main +import pytest + + +@pytest.mark.copyright +@pytest.mark.linter +def test_copyright(): + rc = main(argv=['.', 'test']) + assert rc == 0, 'Found errors' diff --git a/ros2trace_analysis/test/test_flake8.py b/ros2trace_analysis/test/test_flake8.py new file mode 100644 index 0000000..eff8299 --- /dev/null +++ b/ros2trace_analysis/test/test_flake8.py @@ -0,0 +1,23 @@ +# Copyright 2017 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_flake8.main import main +import pytest + + +@pytest.mark.flake8 +@pytest.mark.linter +def test_flake8(): + rc = main(argv=[]) + assert rc == 0, 'Found errors' diff --git a/ros2trace_analysis/test/test_pep257.py b/ros2trace_analysis/test/test_pep257.py new file mode 100644 index 0000000..0e38a6c --- /dev/null +++ b/ros2trace_analysis/test/test_pep257.py @@ -0,0 +1,23 @@ +# Copyright 2017 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_pep257.main import main +import pytest + + +@pytest.mark.linter +@pytest.mark.pep257 +def test_pep257(): + rc = main(argv=[]) + assert rc == 0, 'Found code style errors / warnings' diff --git a/ros2trace_analysis/test/test_xmllint.py b/ros2trace_analysis/test/test_xmllint.py new file mode 100644 index 0000000..f46285e --- /dev/null +++ b/ros2trace_analysis/test/test_xmllint.py @@ -0,0 +1,23 @@ +# Copyright 2019 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ament_xmllint.main import main +import pytest + + +@pytest.mark.linter +@pytest.mark.xmllint +def test_xmllint(): + rc = main(argv=[]) + assert rc == 0, 'Found errors' diff --git a/tracetools_analysis/tracetools_analysis/convert.py b/tracetools_analysis/tracetools_analysis/convert.py index 7ae73a5..545bc73 100644 --- a/tracetools_analysis/tracetools_analysis/convert.py +++ b/tracetools_analysis/tracetools_analysis/convert.py @@ -18,6 +18,7 @@ import argparse import os import time +from typing import Optional from tracetools_analysis.conversion import ctf @@ -25,24 +26,28 @@ from tracetools_analysis.conversion import ctf DEFAULT_CONVERT_FILE_NAME = 'converted' -def parse_args(): - parser = argparse.ArgumentParser( - description='Convert CTF trace data to a file.') +def add_args(parser: argparse.ArgumentParser) -> None: parser.add_argument( 'trace_directory', - help='the path to the main CTF trace directory') + help='the path to the main trace directory') parser.add_argument( '-o', '--output-file-name', dest='output_file_name', default=DEFAULT_CONVERT_FILE_NAME, help='the name of the output file to generate, ' 'under $trace_directory (default: %(default)s)') + + +def parse_args(): + parser = argparse.ArgumentParser( + description='Convert trace data to a file.') + add_args(parser) return parser.parse_args() def convert( trace_directory: str, output_file_name: str = DEFAULT_CONVERT_FILE_NAME, -) -> None: +) -> Optional[int]: """ Convert trace directory to a file. diff --git a/tracetools_analysis/tracetools_analysis/process.py b/tracetools_analysis/tracetools_analysis/process.py index 90fb615..77f7714 100644 --- a/tracetools_analysis/tracetools_analysis/process.py +++ b/tracetools_analysis/tracetools_analysis/process.py @@ -19,6 +19,7 @@ import argparse import os import sys import time +from typing import Optional from typing import Tuple from tracetools_analysis.convert import convert @@ -28,9 +29,7 @@ from tracetools_analysis.processor.ros2 import Ros2Handler from tracetools_read.trace import is_trace_directory -def parse_args(): - parser = argparse.ArgumentParser(description='Process a file converted from a trace ' - 'directory and output model data.') +def add_args(parser: argparse.ArgumentParser) -> None: parser.add_argument( 'input_path', help='the path to a converted file to import and process, ' @@ -39,6 +38,12 @@ def parse_args(): '-f', '--force-conversion', dest='force_conversion', action='store_true', default=False, help='re-convert trace directory even if converted file is found') + + +def parse_args(): + parser = argparse.ArgumentParser(description='Process a file converted from a trace ' + 'directory and output model data.') + add_args(parser) return parser.parse_args() @@ -106,7 +111,7 @@ def inspect_input_path( def process( input_path: str, force_conversion: bool = False, -) -> None: +) -> Optional[int]: """ Process converted trace file.