#  Copyright 2008-2011 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 sys
from threading import Event

if sys.platform.startswith('java'):
    from java.lang import Thread, Runnable
else:
    from stoppablethread import Thread
    Runnable = object


class ThreadedRunner(Runnable):

    def __init__(self, runnable, args=None, kwargs=None, notifier=None):
        self._runnable = lambda: runnable(*(args or ()), **(kwargs or {}))
        self._notifier = Event()
        self._result = None
        self._error = None
        self._traceback = None
        self._thread = None

    def run(self):
        try:
            self._result = self._runnable()
        except:
            self._error, self._traceback = sys.exc_info()[1:]
        self._notifier.set()

    __call__ = run

    def run_in_thread(self, timeout):
        self._thread = Thread(self)
        self._thread.setDaemon(True)
        self._thread.start()
        self._notifier.wait(timeout)
        return self._notifier.isSet()

    def get_result(self):
        if self._error:
            raise self._error, None, self._traceback
        return self._result

    def stop_thread(self):
        self._thread.stop()

#  Copyright 2008-2011 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 sys
from threading import Event

if sys.platform.startswith('java'):
    from java.lang import Thread, Runnable
else:
    from stoppablethread import Thread
    Runnable = object


class ThreadedRunner(Runnable):

    def __init__(self, runnable, args=None, kwargs=None, notifier=None):
        self._runnable = lambda: runnable(*(args or ()), **(kwargs or {}))
        self._result = None
        self._error = None
        self._traceback = None
        self._thread = None
        self._exception_occurred = False

    def run(self):
        try:
            self._result = self._runnable()
        except:
            self._exception_occurred = True
            self._error, self._traceback = sys.exc_info()[1:]

    __call__ = run

    def run_in_thread(self, timeout):
        self._thread = Thread(self)
        self._thread.setDaemon(True)
        self._thread.start()
        self._thread.join(timeout)
        return not self._thread.isAlive() and not self._exception_occurred

    def get_result(self):
        if self._error:
            raise self._error, None, self._traceback
        return self._result

    def stop_thread(self):
        self._thread.stop()

Use thread.join instead of Event.wait