From 5897f567f554e087ae526509e4c6a27f2354662f Mon Sep 17 00:00:00 2001 From: ivanpauno Date: Fri, 6 Sep 2019 11:45:26 -0700 Subject: [PATCH] Avoid the limitation of not being able to import rclpy C extensions at module level Signed-off-by: ivanpauno --- rclpy/CMakeLists.txt | 13 +++++++++---- rclpy/rclpy/__init__.py | 3 +-- rclpy/rclpy/context.py | 9 ++------- rclpy/rclpy/impl/__init__.py | 2 +- rclpy/rclpy/utilities.py | 5 +---- rclpy/test/__init__.py | 29 ----------------------------- 6 files changed, 14 insertions(+), 47 deletions(-) diff --git a/rclpy/CMakeLists.txt b/rclpy/CMakeLists.txt index 288bbdee0..6d568c25b 100644 --- a/rclpy/CMakeLists.txt +++ b/rclpy/CMakeLists.txt @@ -29,15 +29,15 @@ if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug") endif() # enables using the Python extensions from the build space for testing -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_rclpy/__init__.py" "") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_impl/__init__.py" "") ament_python_install_package(${PROJECT_NAME}) function(set_properties _targetname _build_type) set_target_properties(${_targetname} PROPERTIES PREFIX "" - LIBRARY_OUTPUT_DIRECTORY${_build_type} "${CMAKE_CURRENT_BINARY_DIR}/test_${PROJECT_NAME}" - RUNTIME_OUTPUT_DIRECTORY${_build_type} "${CMAKE_CURRENT_BINARY_DIR}/test_${PROJECT_NAME}" + LIBRARY_OUTPUT_DIRECTORY${_build_type} "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_impl" + RUNTIME_OUTPUT_DIRECTORY${_build_type} "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_impl" OUTPUT_NAME "_${_targetname}${PythonExtra_EXTENSION_SUFFIX}" SUFFIX "${PythonExtra_EXTENSION_EXTENSION}") endfunction() @@ -67,7 +67,7 @@ function(configure_python_c_extension_library _library_name) ) install(TARGETS ${_library_name} - DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}" + DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}_impl" ) endfunction() @@ -97,6 +97,11 @@ install(TARGETS rclpy_common RUNTIME DESTINATION bin ) +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_impl/__init__.py" + DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}_impl" +) + add_library( rclpy SHARED src/rclpy/_rclpy.c diff --git a/rclpy/rclpy/__init__.py b/rclpy/rclpy/__init__.py index 38f6cd406..8c0a62bb8 100644 --- a/rclpy/rclpy/__init__.py +++ b/rclpy/rclpy/__init__.py @@ -45,6 +45,7 @@ from typing import TYPE_CHECKING from rclpy.context import Context +from rclpy.impl.implementation_singleton import rclpy_implementation from rclpy.parameter import Parameter from rclpy.task import Future from rclpy.utilities import get_default_context @@ -68,8 +69,6 @@ def init(*, args: List[str] = None, context: Context = None) -> None: (see :func:`.get_default_context`). """ context = get_default_context() if context is None else context - # imported locally to avoid loading extensions on module import - from rclpy.impl.implementation_singleton import rclpy_implementation return rclpy_implementation.rclpy_init(args if args is not None else sys.argv, context.handle) diff --git a/rclpy/rclpy/context.py b/rclpy/rclpy/context.py index ac628572c..8222b7b5f 100644 --- a/rclpy/rclpy/context.py +++ b/rclpy/rclpy/context.py @@ -15,6 +15,8 @@ import threading from typing import Callable +from rclpy.impl.implementation_singleton import rclpy_implementation + class Context: """ @@ -26,7 +28,6 @@ class Context: """ def __init__(self): - from rclpy.impl.implementation_singleton import rclpy_implementation self._handle = rclpy_implementation.rclpy_create_context() self._lock = threading.Lock() self._callbacks = [] @@ -38,8 +39,6 @@ def handle(self): def ok(self): """Check if context hasn't been shut down.""" - # imported locally to avoid loading extensions on module import - from rclpy.impl.implementation_singleton import rclpy_implementation with self._lock: return rclpy_implementation.rclpy_ok(self._handle) @@ -51,16 +50,12 @@ def _call_on_shutdown_callbacks(self): def shutdown(self): """Shutdown this context.""" - # imported locally to avoid loading extensions on module import - from rclpy.impl.implementation_singleton import rclpy_implementation with self._lock: rclpy_implementation.rclpy_shutdown(self._handle) self._call_on_shutdown_callbacks() def try_shutdown(self): """Shutdown this context, if not already shutdown.""" - # imported locally to avoid loading extensions on module import - from rclpy.impl.implementation_singleton import rclpy_implementation with self._lock: if rclpy_implementation.rclpy_ok(self._handle): rclpy_implementation.rclpy_shutdown(self._handle) diff --git a/rclpy/rclpy/impl/__init__.py b/rclpy/rclpy/impl/__init__.py index 92926f7e6..e4e1d95a0 100644 --- a/rclpy/rclpy/impl/__init__.py +++ b/rclpy/rclpy/impl/__init__.py @@ -18,7 +18,7 @@ def _import(name): try: - return importlib.import_module(name, package='rclpy') + return importlib.import_module(name, package='rclpy_impl') except ImportError as e: if e.path is not None and os.path.isfile(e.path): e.msg += \ diff --git a/rclpy/rclpy/utilities.py b/rclpy/rclpy/utilities.py index bba7ed731..b63af3827 100644 --- a/rclpy/rclpy/utilities.py +++ b/rclpy/rclpy/utilities.py @@ -17,6 +17,7 @@ from rclpy.constants import S_TO_NS from rclpy.context import Context +from rclpy.impl.implementation_singleton import rclpy_implementation g_default_context = None g_context_lock = threading.Lock() @@ -37,8 +38,6 @@ def get_default_context(*, shutting_down=False): def remove_ros_args(args=None): - # imported locally to avoid loading extensions on module import - from rclpy.impl.implementation_singleton import rclpy_implementation return rclpy_implementation.rclpy_remove_ros_args( args if args is not None else sys.argv) @@ -63,8 +62,6 @@ def try_shutdown(*, context=None): def get_rmw_implementation_identifier(): - # imported locally to avoid loading extensions on module import - from rclpy.impl.implementation_singleton import rclpy_implementation return rclpy_implementation.rclpy_get_rmw_implementation_identifier() diff --git a/rclpy/test/__init__.py b/rclpy/test/__init__.py index 8f1a3098a..e69de29bb 100644 --- a/rclpy/test/__init__.py +++ b/rclpy/test/__init__.py @@ -1,29 +0,0 @@ -# Copyright 2016-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. - -import importlib -import sys - -assert 'rclpy' not in sys.modules, 'rclpy should not have been imported before running tests' - -# this will make the extensions load from the build folder -import rclpy.impl # noqa -import test_rclpy # noqa - - -def _custom_import(name): - return importlib.import_module(name, package='test_rclpy') - - -rclpy.impl._import = _custom_import