From 5b483f7224d068e7a80f9bfa85c6ffd47bca2876 Mon Sep 17 00:00:00 2001 From: mmatera Date: Fri, 3 Jan 2025 23:51:02 -0300 Subject: [PATCH 01/16] fix nested timers when using Threads --- src/stopit/threadstop.py | 53 ++++++++++++++++++++---- tests.py | 88 ++++++++++++++++++++++++++++++++++------ 2 files changed, 120 insertions(+), 21 deletions(-) diff --git a/src/stopit/threadstop.py b/src/stopit/threadstop.py index a991750..eb59c04 100644 --- a/src/stopit/threadstop.py +++ b/src/stopit/threadstop.py @@ -12,7 +12,7 @@ import sys import threading -from .utils import TimeoutException, BaseTimeout, base_timeoutable +from .utils import LOG, TimeoutException, BaseTimeout, base_timeoutable if sys.version_info < (3, 7): tid_ctype = ctypes.c_long @@ -30,8 +30,9 @@ def async_raise(target_tid, exception): """ # Ensuring and releasing GIL are useless since we're not in C # gil_state = ctypes.pythonapi.PyGILState_Ensure() - ret = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid_ctype(target_tid), - ctypes.py_object(exception)) + ret = ctypes.pythonapi.PyThreadState_SetAsyncExc( + tid_ctype(target_tid), ctypes.py_object(exception) + ) # ctypes.pythonapi.PyGILState_Release(gil_state) if ret == 0: raise ValueError("Invalid thread ID {}".format(target_tid)) @@ -46,36 +47,72 @@ class ThreadingTimeout(BaseTimeout): See :class:`stopit.utils.BaseTimeout` for more information """ + + # This class property keep track about who produced the + # exception. + exception_source = None + def __init__(self, seconds, swallow_exc=True): + # Ensure that any new handler find a clear + # pointer super(ThreadingTimeout, self).__init__(seconds, swallow_exc) self.target_tid = threading.current_thread().ident self.timer = None # PEP8 + def __enter__(self): + self.__class__.exception_source = None + self.state = BaseTimeout.EXECUTING + self.setup_interrupt() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + exc_src = self.__class__.exception_source + if exc_type is TimeoutException: + if self.state != BaseTimeout.TIMED_OUT: + self.state = BaseTimeout.INTERRUPTED + self.suppress_interrupt() + LOG.warning( + "Code block execution exceeded {0} seconds timeout".format( + self.seconds + ), + exc_info=(exc_type, exc_val, exc_tb), + ) + if exc_src is self: + if self.swallow_exc: + self.__class__.exception_source = None + return True + return False + else: + if exc_type is None: + self.state = BaseTimeout.EXECUTED + self.suppress_interrupt() + return False + def stop(self): """Called by timer thread at timeout. Raises a Timeout exception in the caller thread """ self.state = BaseTimeout.TIMED_OUT + self.__class__.exception_source = self async_raise(self.target_tid, TimeoutException) # Required overrides def setup_interrupt(self): - """Setting up the resource that interrupts the block - """ + """Setting up the resource that interrupts the block""" self.timer = threading.Timer(self.seconds, self.stop) self.timer.start() def suppress_interrupt(self): - """Removing the resource that interrupts the block - """ + """Removing the resource that interrupts the block""" self.timer.cancel() -class threading_timeoutable(base_timeoutable): #noqa +class threading_timeoutable(base_timeoutable): # noqa """A function or method decorator that raises a ``TimeoutException`` to decorated functions that should not last a certain amount of time. this one uses ``ThreadingTimeout`` context manager. See :class:`.utils.base_timoutable`` class for further comments. """ + to_ctx_mgr = ThreadingTimeout diff --git a/tests.py b/tests.py index 9b1ce5f..c735eee 100644 --- a/tests.py +++ b/tests.py @@ -1,30 +1,92 @@ # -*- coding: utf-8 -*- +import time import doctest import os import unittest -from stopit import ThreadingTimeout, threading_timeoutable, SignalTimeout, signal_timeoutable +from stopit import ( + TimeoutException, + ThreadingTimeout, + threading_timeoutable, + SignalTimeout, + signal_timeoutable, +) # We run twice the same doctest with two distinct sets of globs # This one is for testing signals based timeout control -signaling_globs = { - 'Timeout': SignalTimeout, - 'timeoutable': signal_timeoutable -} +signaling_globs = {"Timeout": SignalTimeout, "timeoutable": signal_timeoutable} # And this one is for testing threading based timeout control -threading_globs = { - 'Timeout': ThreadingTimeout, - 'timeoutable': threading_timeoutable -} +threading_globs = {"Timeout": ThreadingTimeout, "timeoutable": threading_timeoutable} + + +class TestNesting(unittest.TestCase): + handlers = ( + (ThreadingTimeout,) # SignalTimeout, + if os.name == "posix" + else (ThreadingTimeOut,) + ) + + def aware_wait(self, duration): + remaining = duration * 100 + while remaining > 0: + time.sleep(0.01) + remaining = remaining - 1 + return 0 + + def check_nest(self, t1, t2, duration, HandlerClass): + try: + with HandlerClass(t1, swallow_exc=False) as to_ctx_mgr1: + assert to_ctx_mgr1.state == to_ctx_mgr1.EXECUTING + with HandlerClass(t2, swallow_exc=False) as to_ctx_mgr2: + assert to_ctx_mgr2.state == to_ctx_mgr2.EXECUTING + self.aware_wait(duration) + return "success" + except TimeoutException: + if ThreadingTimeout.exception_source is to_ctx_mgr1: + return "outer" + elif ThreadingTimeout.exception_source is to_ctx_mgr2: + return "inner" + else: + print(ThreadingTimeout.exception_source) + return "unknown source" + + def check_nest_swallow(self, t1, t2, duration, HandlerClass): + with HandlerClass(t1) as to_ctx_mgr1: + assert to_ctx_mgr1.state == to_ctx_mgr1.EXECUTING + with HandlerClass(t2) as to_ctx_mgr2: + assert to_ctx_mgr2.state == to_ctx_mgr2.EXECUTING + self.aware_wait(duration) + return "success" + return "inner" + return "outer" + + def test_nested_long_inner(self): + for handler in self.handlers: + self.assertEqual(self.check_nest(1.0, 10.0, 5.0, handler), "outer") + self.assertEqual(self.check_nest_swallow(1.0, 10.0, 5.0, handler), "outer") + + def test_nested_success(self): + for handler in self.handlers: + self.assertEqual(self.check_nest(5.0, 10.0, 1.0, handler), "success") + self.assertEqual( + self.check_nest_swallow(5.0, 10.0, 1.0, handler), "success" + ) + + def test_nested_long_outer(self): + for handler in self.handlers: + self.assertEqual(self.check_nest(10.0, 1.0, 5.0, handler), "inner") + self.assertEqual(self.check_nest_swallow(10.0, 1.0, 5.0, handler), "inner") def suite(): # Func for setuptools.setup(test_suite=xxx) test_suite = unittest.TestSuite() - test_suite.addTest(doctest.DocFileSuite('README.rst', globs=signaling_globs)) - if os.name == 'posix': # Other OS have no support for signal.SIGALRM - test_suite.addTest(doctest.DocFileSuite('README.rst', globs=threading_globs)) + test_suite.addTest(doctest.DocFileSuite("README.rst", globs=threading_globs)) + if os.name == "posix": # Other OS have no support for signal.SIGALRM + test_suite.addTest(doctest.DocFileSuite("README.rst", globs=signaling_globs)) return test_suite -if __name__ == '__main__': + +if __name__ == "__main__": unittest.TextTestRunner(verbosity=2).run(suite()) + unittest.main() From cab0ff1a1dcc93b7d53144b2df27f8b18b4b572e Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 01:24:57 -0300 Subject: [PATCH 02/16] fix nexted timeout contexts using signals --- src/stopit/signalstop.py | 37 ++++++++++++++++++++++++++++++++----- src/stopit/threadstop.py | 30 ------------------------------ src/stopit/utils.py | 15 ++++++++++++--- tests.py | 9 +++++---- 4 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/stopit/signalstop.py b/src/stopit/signalstop.py index 377c1a0..3c72cf9 100644 --- a/src/stopit/signalstop.py +++ b/src/stopit/signalstop.py @@ -13,29 +13,56 @@ from .utils import TimeoutException, BaseTimeout, base_timeoutable +ALARMS = [] + + + +def handle_alarms(signum, frame): + global ALARMS + new_alarms = [(ctx, max(0, remaining-1),) for ctx, remaining in ALARMS] + expired = [ctx for ctx, remaining in new_alarms if remaining==0] + ALARMS = [(ctx, remaining,) for ctx, remaining in new_alarms if remaining>0] + if ALARMS: + signal.alarm(1) + for task in expired: + task.stop() + break + + class SignalTimeout(BaseTimeout): """Context manager for limiting in the time the execution of a block using signal.SIGALRM Unix signal. See :class:`stopit.utils.BaseTimeout` for more information """ + def __init__(self, seconds, swallow_exc=True): seconds = int(seconds) # alarm delay for signal MUST be int super(SignalTimeout, self).__init__(seconds, swallow_exc) - def handle_timeout(self, signum, frame): + def stop(self): self.state = BaseTimeout.TIMED_OUT + self.__class__.exception_source = self raise TimeoutException('Block exceeded maximum timeout ' 'value (%d seconds).' % self.seconds) # Required overrides def setup_interrupt(self): - signal.signal(signal.SIGALRM, self.handle_timeout) - signal.alarm(self.seconds) + global ALARMS + for ctx, remaining in ALARMS: + if ctx is self: + return + if len(ALARMS)==0: + signal.signal(signal.SIGALRM, handle_alarms) + signal.alarm(1) + ALARMS.append((self, int(self.seconds),)) def suppress_interrupt(self): - signal.alarm(0) - signal.signal(signal.SIGALRM, signal.SIG_DFL) + global ALARMS + ALARMS = [(ctx, remaining) for ctx, remaining in ALARMS if ctx is not self] + if len(ALARMS)==0: + signal.alarm(0) + signal.signal(signal.SIGALRM, signal.SIG_DFL) class signal_timeoutable(base_timeoutable): #noqa diff --git a/src/stopit/threadstop.py b/src/stopit/threadstop.py index eb59c04..fa59878 100644 --- a/src/stopit/threadstop.py +++ b/src/stopit/threadstop.py @@ -50,7 +50,6 @@ class ThreadingTimeout(BaseTimeout): # This class property keep track about who produced the # exception. - exception_source = None def __init__(self, seconds, swallow_exc=True): # Ensure that any new handler find a clear @@ -59,35 +58,6 @@ def __init__(self, seconds, swallow_exc=True): self.target_tid = threading.current_thread().ident self.timer = None # PEP8 - def __enter__(self): - self.__class__.exception_source = None - self.state = BaseTimeout.EXECUTING - self.setup_interrupt() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - exc_src = self.__class__.exception_source - if exc_type is TimeoutException: - if self.state != BaseTimeout.TIMED_OUT: - self.state = BaseTimeout.INTERRUPTED - self.suppress_interrupt() - LOG.warning( - "Code block execution exceeded {0} seconds timeout".format( - self.seconds - ), - exc_info=(exc_type, exc_val, exc_tb), - ) - if exc_src is self: - if self.swallow_exc: - self.__class__.exception_source = None - return True - return False - else: - if exc_type is None: - self.state = BaseTimeout.EXECUTED - self.suppress_interrupt() - return False - def stop(self): """Called by timer thread at timeout. Raises a Timeout exception in the caller thread diff --git a/src/stopit/utils.py b/src/stopit/utils.py index ea31fbb..2209a8a 100644 --- a/src/stopit/utils.py +++ b/src/stopit/utils.py @@ -69,18 +69,27 @@ def __repr__(self): return "<{0} in state: {1}>".format(self.__class__.__name__, self.state) def __enter__(self): + self.__class__.exception_source = None self.state = BaseTimeout.EXECUTING self.setup_interrupt() return self def __exit__(self, exc_type, exc_val, exc_tb): + exc_src = self.__class__.exception_source if exc_type is TimeoutException: if self.state != BaseTimeout.TIMED_OUT: self.state = BaseTimeout.INTERRUPTED self.suppress_interrupt() - LOG.warning("Code block execution exceeded {0} seconds timeout".format(self.seconds), - exc_info=(exc_type, exc_val, exc_tb)) - return self.swallow_exc + LOG.warning( + "Code block execution exceeded {0} seconds timeout".format( + self.seconds + ), + exc_info=(exc_type, exc_val, exc_tb), + ) + if exc_src is self: + if self.swallow_exc: + self.__class__.exception_source = None + return True else: if exc_type is None: self.state = BaseTimeout.EXECUTED diff --git a/tests.py b/tests.py index c735eee..bd71f40 100644 --- a/tests.py +++ b/tests.py @@ -22,7 +22,8 @@ class TestNesting(unittest.TestCase): handlers = ( - (ThreadingTimeout,) # SignalTimeout, + (ThreadingTimeout, + SignalTimeout,) if os.name == "posix" else (ThreadingTimeOut,) ) @@ -43,12 +44,12 @@ def check_nest(self, t1, t2, duration, HandlerClass): self.aware_wait(duration) return "success" except TimeoutException: - if ThreadingTimeout.exception_source is to_ctx_mgr1: + if HandlerClass.exception_source is to_ctx_mgr1: return "outer" - elif ThreadingTimeout.exception_source is to_ctx_mgr2: + elif HandlerClass.exception_source is to_ctx_mgr2: return "inner" else: - print(ThreadingTimeout.exception_source) + print(HandlerClass.exception_source) return "unknown source" def check_nest_swallow(self, t1, t2, duration, HandlerClass): From 65bd13fec2bb8473194ce19e5999c4954ab0d984 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 12:54:49 -0300 Subject: [PATCH 03/16] comment out the warning when the timout is reached. --- src/stopit/utils.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/stopit/utils.py b/src/stopit/utils.py index 2209a8a..6a21d83 100644 --- a/src/stopit/utils.py +++ b/src/stopit/utils.py @@ -80,12 +80,12 @@ def __exit__(self, exc_type, exc_val, exc_tb): if self.state != BaseTimeout.TIMED_OUT: self.state = BaseTimeout.INTERRUPTED self.suppress_interrupt() - LOG.warning( - "Code block execution exceeded {0} seconds timeout".format( - self.seconds - ), - exc_info=(exc_type, exc_val, exc_tb), - ) + # LOG.warning( + # "Code block execution exceeded {0} seconds timeout".format( + # self.seconds + # ), + # exc_info=(exc_type, exc_val, exc_tb), + #) if exc_src is self: if self.swallow_exc: self.__class__.exception_source = None From 21b2af242996375bf5cbe07d2f4a813c861f4da0 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 13:47:03 -0300 Subject: [PATCH 04/16] workflows --- .github/workflows/ubuntu.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/ubuntu.yml diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml new file mode 100644 index 0000000..a33cffe --- /dev/null +++ b/.github/workflows/ubuntu.yml @@ -0,0 +1,27 @@ +name: Mathics3 (ubuntu) + +on: + push: + branches: [ master ] + pull_request: + branches: '**' + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.12', '3.11', '3.8', '3.9', '3.10'] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install stopit + run: | + python -m pip install --upgrade pip + pip install -e . + - name: Test Mathics + run: | + python tests.py From c50923044dfcd5c885ae23a1be9b531cd4e5ea9a Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 13:49:59 -0300 Subject: [PATCH 05/16] adding dependencies --- .github/workflows/ubuntu.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index a33cffe..41f5418 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -21,7 +21,8 @@ jobs: - name: Install stopit run: | python -m pip install --upgrade pip + pip install "setuptools>=70.0.0" packaging pytest pip install -e . - - name: Test Mathics + - name: Test stopit run: | python tests.py From 6e7cb254ec05345deb8d790b939198b1dbdd6bfc Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 15:08:04 -0300 Subject: [PATCH 06/16] macos and windows workflows --- .github/workflows/macos.yml | 34 ++++++++++++++++++++++++++++++++++ .github/workflows/windows.yml | 31 +++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 .github/workflows/macos.yml create mode 100755 .github/workflows/windows.yml diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml new file mode 100644 index 0000000..f07496c --- /dev/null +++ b/.github/workflows/macos.yml @@ -0,0 +1,34 @@ +name: Mathics3 (macOS) + +on: + push: + branches: [ master ] + pull_request: + branches: '**' + +jobs: + build: + env: + LDFLAGS: "-L/usr/local/opt/llvm@14/lib" + CPPFLAGS: "-I/usr/local/opt/llvm@14/include" + runs-on: macos-latest + strategy: + matrix: + os: [macOS] + python-version: ['3.10', '3.11'] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install OS dependencies + run: | + python -m pip install --upgrade pip + - name: Install stopit + run: | + pip install "setuptools>=70.0.0" packaging pytest + pip install -e . + - name: Test Stopit + run: | + python tests.py diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100755 index 0000000..511d7ff --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,31 @@ +name: Mathics3 (Windows) + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: windows-latest + strategy: + matrix: + os: [windows] + # "make doctest" on MS Windows fails without showing much of a + # trace of where things went wrong on Python before 3.11. + python-version: ['3.12'] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install stopit + run: | + python -m pip install --upgrade pip + pip install "setuptools>=70.0.0" packaging pytest + pip install -e . + - name: Test stopit + run: | + python tests.py From 5dd0fea95c05fa3cdc77f5ac103c2c6a4e63dc78 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 15:09:38 -0300 Subject: [PATCH 07/16] pyodide workflow --- .github/workflows/pyodide.yml | 59 +++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 .github/workflows/pyodide.yml diff --git a/.github/workflows/pyodide.yml b/.github/workflows/pyodide.yml new file mode 100644 index 0000000..3d9eee9 --- /dev/null +++ b/.github/workflows/pyodide.yml @@ -0,0 +1,59 @@ +# Copied from SymPy https://github.com/sympy/sympy/pull/27183 + +name: Mathics3 (Pyodide) + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + pyodide-test: + runs-on: ubuntu-latest + env: + PYODIDE_VERSION: 0.27.0a2 + # PYTHON_VERSION and EMSCRIPTEN_VERSION are determined by PYODIDE_VERSION. + # The appropriate versions can be found in the Pyodide repodata.json + # "info" field, or in Makefile.envs: + # https://github.com/pyodide/pyodide/blob/main/Makefile.envs#L2 + PYTHON_VERSION: 3.12.1 + EMSCRIPTEN_VERSION: 3.1.58 + NODE_VERSION: 20 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Set up Emscripten toolchain + uses: mymindstorm/setup-emsdk@v14 + with: + version: ${{ env.EMSCRIPTEN_VERSION }} + actions-cache-folder: emsdk-cache + + - name: Install pyodide-build + run: pip install pyodide-build + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Set up Pyodide virtual environment and run tests + run: | + # Set up Pyodide virtual environment + pyodide xbuildenv install ${{ env.PYODIDE_VERSION }} + pyodide venv .venv-pyodide + + # Activate the virtual environment + source .venv-pyodide/bin/activate + + pip install "setuptools>=70.0.0" PyYAML click packaging pytest + pip install -e . + - name: Test stopit + run: | + python tests.py From da574a93125415a65e5188807102c63592772415 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 15:22:49 -0300 Subject: [PATCH 08/16] fix typo --- tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests.py b/tests.py index bd71f40..58d7152 100644 --- a/tests.py +++ b/tests.py @@ -25,7 +25,7 @@ class TestNesting(unittest.TestCase): (ThreadingTimeout, SignalTimeout,) if os.name == "posix" - else (ThreadingTimeOut,) + else (ThreadingTimeout,) ) def aware_wait(self, duration): From e2cffa9827856e570c5fe98cdc7b4d9f1a09f110 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 15:28:28 -0300 Subject: [PATCH 09/16] no build isolation --- .github/workflows/pyodide.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pyodide.yml b/.github/workflows/pyodide.yml index 3d9eee9..a3f441f 100644 --- a/.github/workflows/pyodide.yml +++ b/.github/workflows/pyodide.yml @@ -53,7 +53,7 @@ jobs: source .venv-pyodide/bin/activate pip install "setuptools>=70.0.0" PyYAML click packaging pytest - pip install -e . + pip install --no-build-isolation -e . - name: Test stopit run: | python tests.py From 847374b78d2a0eda366489cc595b8bf0a32a6275 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 17:37:38 -0300 Subject: [PATCH 10/16] show duration in test --- tests.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests.py b/tests.py index 58d7152..da4836e 100644 --- a/tests.py +++ b/tests.py @@ -69,9 +69,18 @@ def test_nested_long_inner(self): def test_nested_success(self): for handler in self.handlers: - self.assertEqual(self.check_nest(5.0, 10.0, 1.0, handler), "success") + start_time = time.time() + result = self.check_nest(5.0, 10.0, 1.0, handler) + duration = time.time() - start_time + print(" execution took", duration) + start_time = time.time() + self.assertEqual(result, "success") + duration = time.time() - start_time + print(" execution took", duration) + + result = self.check_nest_swallow(5.0, 10.0, 1.0, handler) self.assertEqual( - self.check_nest_swallow(5.0, 10.0, 1.0, handler), "success" + result, "success" ) def test_nested_long_outer(self): From 47dcfc0421a35e0733b7b6b578ee7359ff75ddd9 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 17:41:32 -0300 Subject: [PATCH 11/16] check time --- tests.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests.py b/tests.py index da4836e..fe4a2ca 100644 --- a/tests.py +++ b/tests.py @@ -72,13 +72,13 @@ def test_nested_success(self): start_time = time.time() result = self.check_nest(5.0, 10.0, 1.0, handler) duration = time.time() - start_time - print(" execution took", duration) - start_time = time.time() + print(" execution took", duration, "for ", handler) self.assertEqual(result, "success") - duration = time.time() - start_time - print(" execution took", duration) + start_time = time.time() result = self.check_nest_swallow(5.0, 10.0, 1.0, handler) + duration = time.time() - start_time + print(" execution took", duration, "for ", handler) self.assertEqual( result, "success" ) From 9d8a65700f9cfa94171e967e44a8e132f12ec2a4 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 20:07:52 -0300 Subject: [PATCH 12/16] reordering tests --- tests.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests.py b/tests.py index fe4a2ca..54c0d6a 100644 --- a/tests.py +++ b/tests.py @@ -22,8 +22,9 @@ class TestNesting(unittest.TestCase): handlers = ( - (ThreadingTimeout, - SignalTimeout,) + (SignalTimeout, + ThreadingTimeout, + ) if os.name == "posix" else (ThreadingTimeout,) ) @@ -69,12 +70,6 @@ def test_nested_long_inner(self): def test_nested_success(self): for handler in self.handlers: - start_time = time.time() - result = self.check_nest(5.0, 10.0, 1.0, handler) - duration = time.time() - start_time - print(" execution took", duration, "for ", handler) - self.assertEqual(result, "success") - start_time = time.time() result = self.check_nest_swallow(5.0, 10.0, 1.0, handler) duration = time.time() - start_time @@ -82,6 +77,13 @@ def test_nested_success(self): self.assertEqual( result, "success" ) + start_time = time.time() + result = self.check_nest(5.0, 10.0, 1.0, handler) + duration = time.time() - start_time + print(" execution took", duration, "for ", handler) + self.assertEqual(result, "success") + + def test_nested_long_outer(self): for handler in self.handlers: From 07914bb717796ac6293a504e35ee6fb46f9b7fe3 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 21:23:43 -0300 Subject: [PATCH 13/16] improve await function --- tests.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests.py b/tests.py index 54c0d6a..6154fef 100644 --- a/tests.py +++ b/tests.py @@ -31,8 +31,11 @@ class TestNesting(unittest.TestCase): def aware_wait(self, duration): remaining = duration * 100 + t_start = time.time() while remaining > 0: time.sleep(0.01) + if time.time() - t_start > duration: + return 0 remaining = remaining - 1 return 0 From 7c2ddde3be3efcc33b5740f4d69610ad6dc67f74 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 21:46:31 -0300 Subject: [PATCH 14/16] removing control prints --- tests.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/tests.py b/tests.py index 6154fef..923b379 100644 --- a/tests.py +++ b/tests.py @@ -22,9 +22,10 @@ class TestNesting(unittest.TestCase): handlers = ( - (SignalTimeout, - ThreadingTimeout, - ) + ( + SignalTimeout, + ThreadingTimeout, + ) if os.name == "posix" else (ThreadingTimeout,) ) @@ -73,20 +74,10 @@ def test_nested_long_inner(self): def test_nested_success(self): for handler in self.handlers: - start_time = time.time() - result = self.check_nest_swallow(5.0, 10.0, 1.0, handler) - duration = time.time() - start_time - print(" execution took", duration, "for ", handler) self.assertEqual( - result, "success" + self.check_nest_swallow(5.0, 10.0, 1.0, handler), "success" ) - start_time = time.time() - result = self.check_nest(5.0, 10.0, 1.0, handler) - duration = time.time() - start_time - print(" execution took", duration, "for ", handler) - self.assertEqual(result, "success") - - + self.assertEqual(self.check_nest(5.0, 10.0, 1.0, handler), "success") def test_nested_long_outer(self): for handler in self.handlers: From ebfe9071c4f057c0f38281acd93408a8e41a7459 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sat, 4 Jan 2025 21:47:56 -0300 Subject: [PATCH 15/16] pip through python --- .github/workflows/pyodide.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pyodide.yml b/.github/workflows/pyodide.yml index a3f441f..c7fc574 100644 --- a/.github/workflows/pyodide.yml +++ b/.github/workflows/pyodide.yml @@ -53,7 +53,7 @@ jobs: source .venv-pyodide/bin/activate pip install "setuptools>=70.0.0" PyYAML click packaging pytest - pip install --no-build-isolation -e . + python -m pip install --no-build-isolation -e . - name: Test stopit run: | python tests.py From 49377478347ba035ae27b69f091a18e0d3132091 Mon Sep 17 00:00:00 2001 From: mmatera Date: Sun, 5 Jan 2025 00:15:31 -0300 Subject: [PATCH 16/16] rename workflows --- .github/workflows/macos.yml | 2 +- .github/workflows/pyodide.yml | 3 ++- .github/workflows/ubuntu.yml | 2 +- .github/workflows/windows.yml | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index f07496c..d98e87b 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -1,4 +1,4 @@ -name: Mathics3 (macOS) +name: Stopit (macOS) on: push: diff --git a/.github/workflows/pyodide.yml b/.github/workflows/pyodide.yml index c7fc574..46f6ea5 100644 --- a/.github/workflows/pyodide.yml +++ b/.github/workflows/pyodide.yml @@ -1,6 +1,6 @@ # Copied from SymPy https://github.com/sympy/sympy/pull/27183 -name: Mathics3 (Pyodide) +name: Stopit (Pyodide) on: push: @@ -56,4 +56,5 @@ jobs: python -m pip install --no-build-isolation -e . - name: Test stopit run: | + python -c "import sys; print(sys.path); import your_package_name" python tests.py diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 41f5418..4ae30e2 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -1,4 +1,4 @@ -name: Mathics3 (ubuntu) +name: Stopit (ubuntu) on: push: diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 511d7ff..b6538cc 100755 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -1,4 +1,4 @@ -name: Mathics3 (Windows) +name: Stopit (Windows) on: push: