Revision: 3094
Author: jussi.ao.malinen
Date: Mon Apr 26 06:26:12 2010
Log: Implemented stopping test execution gracefully with ctrl-c, issue 108
http://code.google.com/p/robotframework/source/detail?r=3094
Added:
/trunk/src/robot/utils/signalhandler.py
Modified:
/trunk/src/robot/__init__.py
/trunk/src/robot/running/handlers.py
=======================================
--- /dev/null
+++ /trunk/src/robot/utils/signalhandler.py Mon Apr 26 06:26:12 2010
@@ -0,0 +1,55 @@
+# Copyright 2008-2009 Nokia Siemens Networks Oyj
+#
+# 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 signal
+import sys
+
+from robot.errors import ExecutionFailed
+
+
+class _RobotSignalHandler(object):
+
+ def __init__(self):
+ self._signal_count = 0
+ self._running_keyword = False
+
+ def __call__(self,signum, frame):
+ self._signal_count += 1
+ if self._signal_count > 1:
+ sys.__stderr__.write("Execution forcefully stopped.")
+ raise SystemExit()
+ sys.__stderr__.write("Stopping execution. Second signal will force
exit.")
+ if self._running_keyword:
+ self._stop_execution_gracefully()
+
+ def _stop_execution_gracefully(self):
+ raise ExecutionFailed("Execution terminated by signal", exit=True)
+
+ def start(self):
+ signal.signal(signal.SIGINT, self)
+ signal.signal(signal.SIGTERM, self)
+
+ def start_running_keyword(self):
+ self._running_keyword = True
+ if self._signal_count:
+ self._stop_execution_gracefully()
+
+ def stop_running_keyword(self):
+ self._running_keyword = False
+
+ def is_break_signaled(self):
+ return self.count > 0
+
+
+ROBOT_SIGNAL_HANDLER = _RobotSignalHandler()
=======================================
--- /trunk/src/robot/__init__.py Tue Mar 2 02:57:25 2010
+++ /trunk/src/robot/__init__.py Mon Apr 26 06:26:12 2010
@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-
import sys
if __name__ == '__main__':
@@ -29,6 +28,7 @@
DATA_ERROR, STOPPED_BY_USER, FRAMEWORK_ERROR
from variables import init_global_variables
import utils
+from utils.signalhandler import ROBOT_SIGNAL_HANDLER
__version__ = utils.version
@@ -91,6 +91,7 @@
pybot /path/to/tests.html
pybot --log mylog.html /path/to/tests.html /path/to/tests2.html
"""
+ ROBOT_SIGNAL_HANDLER.start()
settings = RobotSettings(options)
LOGGER.register_console_logger(settings['MonitorWidth'],
settings['MonitorColors'])
=======================================
--- /trunk/src/robot/running/handlers.py Tue Apr 20 06:46:51 2010
+++ /trunk/src/robot/running/handlers.py Mon Apr 26 06:26:12 2010
@@ -20,6 +20,7 @@
from arguments import PythonKeywordArguments, JavaKeywordArguments, \
DynamicKeywordArguments, PythonInitArguments, JavaInitArguments, \
RunKeywordArguments
+from robot.utils.signalhandler import ROBOT_SIGNAL_HANDLER
if utils.is_jython:
@@ -92,10 +93,22 @@
return self._run_handler_with_output_captured(runner, output)
def _runner_for(self, handler, output, positional, named, timeout):
+ wrapped_handler = self._wrap_with_signal_handling(handler)
if timeout and timeout.active():
- return lambda: timeout.run(handler, args=positional,
kwargs=named,
+ return lambda: timeout.run(wrapped_handler, args=positional,
kwargs=named,
logger=output)
- return lambda: handler(*positional, **named)
+ return lambda: wrapped_handler(*positional, **named)
+
+ def _wrap_with_signal_handling(self, runnable):
+ def _signal_wrapper(runnable):
+ def _wrapped_function(*wrapped_positional, **wrapped_named):
+ try:
+ ROBOT_SIGNAL_HANDLER.start_running_keyword()
+ return runnable(*wrapped_positional, **wrapped_named)
+ finally:
+ ROBOT_SIGNAL_HANDLER.stop_running_keyword()
+ return _wrapped_function
+ return _signal_wrapper(runnable)
def _run_handler_with_output_captured(self, runner, output):
utils.capture_output()
@@ -178,6 +191,9 @@
class _RunKeywordHandler(_PythonHandler):
+ def _wrap_with_signal_handling(self, runnable):
+ return runnable
+
def _parse_arguments(self, handler_method):
arg_index =
RUN_KW_REGISTER.get_args_to_process(self.library.orig_name,
self.name)
--
Subscription settings:
http://groups.google.com/group/robotframework-commit/subscribe?hl=en