Skip to content

Commit 69601a1

Browse files
authored
Upgrade threading to 3.13.11; sys.setprofile & impl more threading (#6691)
* Upgrade threading,test_threading from 3.13.11 * increase ci limit to 45mins * impl more threading * no static for asyncgen
1 parent 00bfea8 commit 69601a1

File tree

18 files changed

+2366
-757
lines changed

18 files changed

+2366
-757
lines changed

.github/workflows/ci.yaml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,14 @@ env:
106106
test_weakref
107107
test_yield_from
108108
ENV_POLLUTING_TESTS_COMMON: >-
109-
test_threading
110109
ENV_POLLUTING_TESTS_LINUX: >-
111-
test.test_concurrent_futures.test_thread_pool
112110
test.test_multiprocessing_fork.test_processes
113111
test.test_multiprocessing_fork.test_threads
114112
test.test_multiprocessing_forkserver.test_processes
115113
test.test_multiprocessing_forkserver.test_threads
116114
test.test_multiprocessing_spawn.test_processes
117115
test.test_multiprocessing_spawn.test_threads
118116
ENV_POLLUTING_TESTS_MACOS: >-
119-
test.test_concurrent_futures.test_thread_pool
120117
test.test_multiprocessing_forkserver.test_processes
121118
test.test_multiprocessing_forkserver.test_threads
122119
test.test_multiprocessing_spawn.test_processes
@@ -297,21 +294,21 @@ jobs:
297294
env:
298295
RUSTPYTHON_SKIP_ENV_POLLUTERS: true
299296
run: target/release/rustpython -m test -j 1 -u all --slowest --fail-env-changed --timeout 600 -v ${{ env.PLATFORM_INDEPENDENT_TESTS }}
300-
timeout-minutes: 35
297+
timeout-minutes: 45
301298

302299
- if: runner.os == 'Linux'
303300
name: run cpython platform-dependent tests (Linux)
304301
env:
305302
RUSTPYTHON_SKIP_ENV_POLLUTERS: true
306303
run: target/release/rustpython -m test -j 1 -u all --slowest --fail-env-changed --timeout 600 -v -x ${{ env.PLATFORM_INDEPENDENT_TESTS }}
307-
timeout-minutes: 35
304+
timeout-minutes: 45
308305

309306
- if: runner.os == 'macOS'
310307
name: run cpython platform-dependent tests (MacOS)
311308
env:
312309
RUSTPYTHON_SKIP_ENV_POLLUTERS: true
313310
run: target/release/rustpython -m test -j 1 --slowest --fail-env-changed --timeout 600 -v -x ${{ env.PLATFORM_INDEPENDENT_TESTS }}
314-
timeout-minutes: 35
311+
timeout-minutes: 45
315312

316313
- if: runner.os == 'Windows'
317314
name: run cpython platform-dependent tests (windows partial - fixme)

Lib/_dummy_thread.py

Lines changed: 142 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,43 @@
1111
import _dummy_thread as _thread
1212
1313
"""
14+
1415
# Exports only things specified by thread documentation;
1516
# skipping obsolete synonyms allocate(), start_new(), exit_thread().
16-
__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock',
17-
'interrupt_main', 'LockType', 'RLock',
18-
'_count']
17+
__all__ = [
18+
"error",
19+
"start_new_thread",
20+
"exit",
21+
"get_ident",
22+
"allocate_lock",
23+
"interrupt_main",
24+
"LockType",
25+
"RLock",
26+
"_count",
27+
"start_joinable_thread",
28+
"daemon_threads_allowed",
29+
"_shutdown",
30+
"_make_thread_handle",
31+
"_ThreadHandle",
32+
"_get_main_thread_ident",
33+
"_is_main_interpreter",
34+
"_local",
35+
]
1936

2037
# A dummy value
2138
TIMEOUT_MAX = 2**31
2239

40+
# Main thread ident for dummy implementation
41+
_MAIN_THREAD_IDENT = -1
42+
2343
# NOTE: this module can be imported early in the extension building process,
2444
# and so top level imports of other modules should be avoided. Instead, all
2545
# imports are done when needed on a function-by-function basis. Since threads
2646
# are disabled, the import lock should not be an issue anyway (??).
2747

2848
error = RuntimeError
2949

50+
3051
def start_new_thread(function, args, kwargs={}):
3152
"""Dummy implementation of _thread.start_new_thread().
3253
@@ -52,44 +73,98 @@ def start_new_thread(function, args, kwargs={}):
5273
pass
5374
except:
5475
import traceback
76+
5577
traceback.print_exc()
5678
_main = True
5779
global _interrupt
5880
if _interrupt:
5981
_interrupt = False
6082
raise KeyboardInterrupt
6183

84+
85+
def start_joinable_thread(function, handle=None, daemon=True):
86+
"""Dummy implementation of _thread.start_joinable_thread().
87+
88+
In dummy thread, we just run the function synchronously.
89+
"""
90+
if handle is None:
91+
handle = _ThreadHandle()
92+
try:
93+
function()
94+
except SystemExit:
95+
pass
96+
except:
97+
import traceback
98+
99+
traceback.print_exc()
100+
handle._set_done()
101+
return handle
102+
103+
104+
def daemon_threads_allowed():
105+
"""Dummy implementation of _thread.daemon_threads_allowed()."""
106+
return True
107+
108+
109+
def _shutdown():
110+
"""Dummy implementation of _thread._shutdown()."""
111+
pass
112+
113+
114+
def _make_thread_handle(ident):
115+
"""Dummy implementation of _thread._make_thread_handle()."""
116+
handle = _ThreadHandle()
117+
handle._ident = ident
118+
return handle
119+
120+
121+
def _get_main_thread_ident():
122+
"""Dummy implementation of _thread._get_main_thread_ident()."""
123+
return _MAIN_THREAD_IDENT
124+
125+
126+
def _is_main_interpreter():
127+
"""Dummy implementation of _thread._is_main_interpreter()."""
128+
return True
129+
130+
62131
def exit():
63132
"""Dummy implementation of _thread.exit()."""
64133
raise SystemExit
65134

135+
66136
def get_ident():
67137
"""Dummy implementation of _thread.get_ident().
68138
69139
Since this module should only be used when _threadmodule is not
70140
available, it is safe to assume that the current process is the
71141
only thread. Thus a constant can be safely returned.
72142
"""
73-
return -1
143+
return _MAIN_THREAD_IDENT
144+
74145

75146
def allocate_lock():
76147
"""Dummy implementation of _thread.allocate_lock()."""
77148
return LockType()
78149

150+
79151
def stack_size(size=None):
80152
"""Dummy implementation of _thread.stack_size()."""
81153
if size is not None:
82154
raise error("setting thread stack size not supported")
83155
return 0
84156

157+
85158
def _set_sentinel():
86159
"""Dummy implementation of _thread._set_sentinel()."""
87160
return LockType()
88161

162+
89163
def _count():
90164
"""Dummy implementation of _thread._count()."""
91165
return 0
92166

167+
93168
class LockType(object):
94169
"""Class implementing dummy implementation of _thread.LockType.
95170
@@ -125,6 +200,7 @@ def acquire(self, waitflag=None, timeout=-1):
125200
else:
126201
if timeout > 0:
127202
import time
203+
128204
time.sleep(timeout)
129205
return False
130206

@@ -153,14 +229,41 @@ def __repr__(self):
153229
"locked" if self.locked_status else "unlocked",
154230
self.__class__.__module__,
155231
self.__class__.__qualname__,
156-
hex(id(self))
232+
hex(id(self)),
157233
)
158234

235+
236+
class _ThreadHandle:
237+
"""Dummy implementation of _thread._ThreadHandle."""
238+
239+
def __init__(self):
240+
self._ident = _MAIN_THREAD_IDENT
241+
self._done = False
242+
243+
@property
244+
def ident(self):
245+
return self._ident
246+
247+
def _set_done(self):
248+
self._done = True
249+
250+
def is_done(self):
251+
return self._done
252+
253+
def join(self, timeout=None):
254+
# In dummy thread, thread is always done
255+
return
256+
257+
def __repr__(self):
258+
return f"<_ThreadHandle ident={self._ident}>"
259+
260+
159261
# Used to signal that interrupt_main was called in a "thread"
160262
_interrupt = False
161263
# True when not executing in a "thread"
162264
_main = True
163265

266+
164267
def interrupt_main():
165268
"""Set _interrupt flag to True to have start_new_thread raise
166269
KeyboardInterrupt upon exiting."""
@@ -170,6 +273,7 @@ def interrupt_main():
170273
global _interrupt
171274
_interrupt = True
172275

276+
173277
class RLock:
174278
def __init__(self):
175279
self.locked_count = 0
@@ -190,7 +294,7 @@ def release(self):
190294
return True
191295

192296
def locked(self):
193-
return self.locked_status != 0
297+
return self.locked_count != 0
194298

195299
def __repr__(self):
196300
return "<%s %s.%s object owner=%s count=%s at %s>" % (
@@ -199,5 +303,36 @@ def __repr__(self):
199303
self.__class__.__qualname__,
200304
get_ident() if self.locked_count else 0,
201305
self.locked_count,
202-
hex(id(self))
306+
hex(id(self)),
203307
)
308+
309+
310+
class _local:
311+
"""Dummy implementation of _thread._local (thread-local storage)."""
312+
313+
def __init__(self):
314+
object.__setattr__(self, "_local__impl", {})
315+
316+
def __getattribute__(self, name):
317+
if name.startswith("_local__"):
318+
return object.__getattribute__(self, name)
319+
impl = object.__getattribute__(self, "_local__impl")
320+
try:
321+
return impl[name]
322+
except KeyError:
323+
raise AttributeError(name)
324+
325+
def __setattr__(self, name, value):
326+
if name.startswith("_local__"):
327+
return object.__setattr__(self, name, value)
328+
impl = object.__getattribute__(self, "_local__impl")
329+
impl[name] = value
330+
331+
def __delattr__(self, name):
332+
if name.startswith("_local__"):
333+
return object.__delattr__(self, name)
334+
impl = object.__getattribute__(self, "_local__impl")
335+
try:
336+
del impl[name]
337+
except KeyError:
338+
raise AttributeError(name)

Lib/dummy_threading.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
regardless of whether ``_thread`` was available which is not desired.
77
88
"""
9+
910
from sys import modules as sys_modules
1011

1112
import _dummy_thread
@@ -19,59 +20,62 @@
1920
# Could have checked if ``_thread`` was not in sys.modules and gone
2021
# a different route, but decided to mirror technique used with
2122
# ``threading`` below.
22-
if '_thread' in sys_modules:
23-
held_thread = sys_modules['_thread']
23+
if "_thread" in sys_modules:
24+
held_thread = sys_modules["_thread"]
2425
holding_thread = True
2526
# Must have some module named ``_thread`` that implements its API
2627
# in order to initially import ``threading``.
27-
sys_modules['_thread'] = sys_modules['_dummy_thread']
28+
sys_modules["_thread"] = sys_modules["_dummy_thread"]
2829

29-
if 'threading' in sys_modules:
30+
if "threading" in sys_modules:
3031
# If ``threading`` is already imported, might as well prevent
3132
# trying to import it more than needed by saving it if it is
3233
# already imported before deleting it.
33-
held_threading = sys_modules['threading']
34+
held_threading = sys_modules["threading"]
3435
holding_threading = True
35-
del sys_modules['threading']
36+
del sys_modules["threading"]
3637

37-
if '_threading_local' in sys_modules:
38+
if "_threading_local" in sys_modules:
3839
# If ``_threading_local`` is already imported, might as well prevent
3940
# trying to import it more than needed by saving it if it is
4041
# already imported before deleting it.
41-
held__threading_local = sys_modules['_threading_local']
42+
held__threading_local = sys_modules["_threading_local"]
4243
holding__threading_local = True
43-
del sys_modules['_threading_local']
44+
del sys_modules["_threading_local"]
4445

4546
import threading
47+
4648
# Need a copy of the code kept somewhere...
47-
sys_modules['_dummy_threading'] = sys_modules['threading']
48-
del sys_modules['threading']
49-
sys_modules['_dummy__threading_local'] = sys_modules['_threading_local']
50-
del sys_modules['_threading_local']
49+
sys_modules["_dummy_threading"] = sys_modules["threading"]
50+
del sys_modules["threading"]
51+
# _threading_local may not be imported if _thread._local is available
52+
if "_threading_local" in sys_modules:
53+
sys_modules["_dummy__threading_local"] = sys_modules["_threading_local"]
54+
del sys_modules["_threading_local"]
5155
from _dummy_threading import *
5256
from _dummy_threading import __all__
5357

5458
finally:
5559
# Put back ``threading`` if we overwrote earlier
5660

5761
if holding_threading:
58-
sys_modules['threading'] = held_threading
62+
sys_modules["threading"] = held_threading
5963
del held_threading
6064
del holding_threading
6165

6266
# Put back ``_threading_local`` if we overwrote earlier
6367

6468
if holding__threading_local:
65-
sys_modules['_threading_local'] = held__threading_local
69+
sys_modules["_threading_local"] = held__threading_local
6670
del held__threading_local
6771
del holding__threading_local
6872

6973
# Put back ``thread`` if we overwrote, else del the entry we made
7074
if holding_thread:
71-
sys_modules['_thread'] = held_thread
75+
sys_modules["_thread"] = held_thread
7276
del held_thread
7377
else:
74-
del sys_modules['_thread']
78+
del sys_modules["_thread"]
7579
del holding_thread
7680

7781
del _dummy_thread

0 commit comments

Comments
 (0)