Skip to content

Commit 7088e50

Browse files
authored
Merge pull request #3 from Mathics3/fixing_nested_Timeout_contexts_using_signal-rocky
Bump version
2 parents aca930e + aa24620 commit 7088e50

File tree

6 files changed

+47
-21
lines changed

6 files changed

+47
-21
lines changed

.github/workflows/pyodide.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,14 @@ jobs:
5050
pyodide venv .venv-pyodide
5151
5252
# Activate the virtual environment
53-
source .venv-pyodide/bin/activate
54-
53+
. .venv-pyodide/bin/activate
5554
pip install "setuptools>=70.0.0" PyYAML click packaging pytest
5655
5756
pip install --no-build-isolation -v -v -v -e .
5857
- name: Test stopit
5958
run: |
60-
python -c "import sys; print(sys.path); import stopit"
61-
python tests.py
59+
# Activate the virtual environment
60+
. .venv-pyodide/bin/activate
61+
echo $PATH
62+
python -c "import sys; print(sys.path); import stopit"
63+
# python tests.py

.gitignore

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
.DS_Store
2-
build/
3-
dist/
1+
*.egg-info
42
*.pyc
53
*.pyo
6-
*.egg-info
4+
.DS_Store
5+
/.pyodide-xbuildenv*
6+
/.python-version
77
__pycache__/
8+
build/
9+
dist/

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import os
1212
from setuptools import setup, find_packages
1313

14-
version = '1.2dev0'
14+
version = '1.1.3.dev0'
1515

1616
this_directory = os.path.abspath(os.path.dirname(__file__))
1717

src/stopit/signalstop.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@
1616
ALARMS = []
1717

1818

19-
2019
def handle_alarms(signum, frame):
2120
global ALARMS
22-
new_alarms = [(ctx, max(0, remaining-1),) for ctx, remaining in ALARMS]
23-
expired = [ctx for ctx, remaining in new_alarms if remaining==0]
24-
ALARMS = [(ctx, remaining,) for ctx, remaining in new_alarms if remaining>0]
21+
new_alarms = [(ctx, max(0, remaining-1),) for ctx, remaining in ALARMS]
22+
expired = [ctx for ctx, remaining in new_alarms if remaining == 0]
23+
ALARMS = [
24+
(
25+
ctx,
26+
remaining,
27+
) for ctx, remaining in new_alarms
28+
if remaining > 0]
2529
if ALARMS:
2630
signal.alarm(1)
2731
for task in expired:
@@ -37,7 +41,11 @@ class SignalTimeout(BaseTimeout):
3741
"""
3842

3943
def __init__(self, seconds, swallow_exc=True):
40-
seconds = int(seconds) # alarm delay for signal MUST be int
44+
45+
# The alarm delay for a SIGALARM MUST be an integer
46+
# greater than 1. Round up non-integer values.
47+
seconds = max(1, int(seconds + 0.99))
48+
4149
super(SignalTimeout, self).__init__(seconds, swallow_exc)
4250

4351
def stop(self):
@@ -49,23 +57,31 @@ def stop(self):
4957
# Required overrides
5058
def setup_interrupt(self):
5159
global ALARMS
52-
for ctx, remaining in ALARMS:
53-
if ctx is self:
54-
return
55-
if len(ALARMS)==0:
60+
61+
# If we have already registered ourself, do nothing and
62+
# return.
63+
if any(ctx is self for ctx, _ in ALARMS):
64+
return
65+
66+
# If no ALARMS have been set up before, register
67+
# signal.SIGALRM.
68+
if len(ALARMS) == 0:
5669
signal.signal(signal.SIGALRM, handle_alarms)
5770
signal.alarm(1)
71+
72+
# Register our self.seconds value in the global
73+
# ALARMS registry.
5874
ALARMS.append((self, int(self.seconds),))
5975

6076
def suppress_interrupt(self):
6177
global ALARMS
6278
ALARMS = [(ctx, remaining) for ctx, remaining in ALARMS if ctx is not self]
63-
if len(ALARMS)==0:
79+
if len(ALARMS) == 0:
6480
signal.alarm(0)
6581
signal.signal(signal.SIGALRM, signal.SIG_DFL)
6682

6783

68-
class signal_timeoutable(base_timeoutable): #noqa
84+
class signal_timeoutable(base_timeoutable): # noqa
6985
"""A function or method decorator that raises a ``TimeoutException`` to
7086
decorated functions that should not last a certain amount of time.
7187
this one uses ``SignalTimeout`` context manager.

src/stopit/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ class base_timeoutable(object): # noqa
135135
.. note::
136136
137137
This is a base class that must be subclassed. subclasses must override
138-
thz ``to_ctx_mgr`` with a timeout context manager class which in turn
138+
the ``to_ctx_mgr`` with a timeout context manager class which in turn
139139
must subclasses of above ``BaseTimeout`` class.
140140
"""
141141
to_ctx_mgr = None

tests.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ def test_nested_long_outer(self):
8484
self.assertEqual(self.check_nest(10.0, 1.0, 5.0, handler), "inner")
8585
self.assertEqual(self.check_nest_swallow(10.0, 1.0, 5.0, handler), "inner")
8686

87+
if os.name == "posix": # Other OS have no support for signal.SIGALRM
88+
def test_signal_handler(self):
89+
for settime, expect_time in ((-1.5, 1), (0, 1), (0.5, 1), (3, 3),
90+
(3.2, 4)):
91+
self.assertEqual(SignalTimeout(settime).seconds, expect_time)
92+
8793

8894
def suite(): # Func for setuptools.setup(test_suite=xxx)
8995
test_suite = unittest.TestSuite()

0 commit comments

Comments
 (0)