https://github.com/python/cpython/commit/3cfab449ab1e3c1472d2a33dc3fae3dc06c39f7b
commit: 3cfab449ab1e3c1472d2a33dc3fae3dc06c39f7b
branch: main
author: mpage <mp...@meta.com>
committer: mpage <mp...@cs.stanford.edu>
date: 2025-04-21T16:07:54-07:00
summary:

gh-132578: Rename the `threading.Thread._handle` field (#132696)

Commit `0e9c364f` introduced the `_handle` field on instances of
`threading.Thread`. Unfortunately it's fairly common for subclasses
of `threading.Thread` to define a `_handle()` method, which is shadowed
by the new field.

files:
A Misc/NEWS.d/next/Library/2025-04-18-10-00-09.gh-issue-132578.ruNvF-.rst
M Lib/threading.py

diff --git a/Lib/threading.py b/Lib/threading.py
index c4cc4dd2b00aa8..39a1a7f4cdfda0 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -935,7 +935,7 @@ class is implemented.
         self._ident = None
         if _HAVE_THREAD_NATIVE_ID:
             self._native_id = None
-        self._handle = _ThreadHandle()
+        self._os_thread_handle = _ThreadHandle()
         self._started = Event()
         self._initialized = True
         # Copy of sys.stderr used by self._invoke_excepthook()
@@ -950,7 +950,7 @@ def _after_fork(self, new_ident=None):
         if new_ident is not None:
             # This thread is alive.
             self._ident = new_ident
-            assert self._handle.ident == new_ident
+            assert self._os_thread_handle.ident == new_ident
         else:
             # Otherwise, the thread is dead, Jim.  _PyThread_AfterFork()
             # already marked our handle done.
@@ -961,7 +961,7 @@ def __repr__(self):
         status = "initial"
         if self._started.is_set():
             status = "started"
-        if self._handle.is_done():
+        if self._os_thread_handle.is_done():
             status = "stopped"
         if self._daemonic:
             status += " daemon"
@@ -999,7 +999,7 @@ def start(self):
 
         try:
             # Start joinable thread
-            _start_joinable_thread(self._bootstrap, handle=self._handle,
+            _start_joinable_thread(self._bootstrap, 
handle=self._os_thread_handle,
                                    daemon=self.daemon)
         except Exception:
             with _active_limbo_lock:
@@ -1127,7 +1127,7 @@ def join(self, timeout=None):
         if timeout is not None:
             timeout = max(timeout, 0)
 
-        self._handle.join(timeout)
+        self._os_thread_handle.join(timeout)
 
     @property
     def name(self):
@@ -1180,7 +1180,7 @@ def is_alive(self):
 
         """
         assert self._initialized, "Thread.__init__() not called"
-        return self._started.is_set() and not self._handle.is_done()
+        return self._started.is_set() and not self._os_thread_handle.is_done()
 
     @property
     def daemon(self):
@@ -1391,7 +1391,7 @@ def __init__(self):
         Thread.__init__(self, name="MainThread", daemon=False)
         self._started.set()
         self._ident = _get_main_thread_ident()
-        self._handle = _make_thread_handle(self._ident)
+        self._os_thread_handle = _make_thread_handle(self._ident)
         if _HAVE_THREAD_NATIVE_ID:
             self._set_native_id()
         with _active_limbo_lock:
@@ -1439,7 +1439,7 @@ def __init__(self):
                         daemon=_daemon_threads_allowed())
         self._started.set()
         self._set_ident()
-        self._handle = _make_thread_handle(self._ident)
+        self._os_thread_handle = _make_thread_handle(self._ident)
         if _HAVE_THREAD_NATIVE_ID:
             self._set_native_id()
         with _active_limbo_lock:
@@ -1447,7 +1447,7 @@ def __init__(self):
         _DeleteDummyThreadOnDel(self)
 
     def is_alive(self):
-        if not self._handle.is_done() and self._started.is_set():
+        if not self._os_thread_handle.is_done() and self._started.is_set():
             return True
         raise RuntimeError("thread is not alive")
 
@@ -1561,7 +1561,7 @@ def _shutdown():
     # dubious, but some code does it. We can't wait for it to be marked as done
     # normally - that won't happen until the interpreter is nearly dead. So
     # mark it done here.
-    if _main_thread._handle.is_done() and _is_main_interpreter():
+    if _main_thread._os_thread_handle.is_done() and _is_main_interpreter():
         # _shutdown() was already called
         return
 
@@ -1574,7 +1574,7 @@ def _shutdown():
         atexit_call()
 
     if _is_main_interpreter():
-        _main_thread._handle._set_done()
+        _main_thread._os_thread_handle._set_done()
 
     # Wait for all non-daemon threads to exit.
     _thread_shutdown()
diff --git 
a/Misc/NEWS.d/next/Library/2025-04-18-10-00-09.gh-issue-132578.ruNvF-.rst 
b/Misc/NEWS.d/next/Library/2025-04-18-10-00-09.gh-issue-132578.ruNvF-.rst
new file mode 100644
index 00000000000000..56faa5d1235e32
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-04-18-10-00-09.gh-issue-132578.ruNvF-.rst
@@ -0,0 +1,2 @@
+Rename the ``threading.Thread._handle`` field to avoid shadowing methods
+defined on subclasses of ``threading.Thread``.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to