bpo-31370: Remove support for threads-less builds (#3385)

* Remove Setup.config
* Always define WITH_THREAD for compatibility.
This commit is contained in:
Antoine Pitrou 2017-09-07 18:56:24 +02:00 committed by Victor Stinner
parent 1f06a680de
commit a6a4dc816d
135 changed files with 2472 additions and 4377 deletions

View File

@ -344,6 +344,9 @@ Build and C API Changes
download a copy of 32-bit Python for this purpose. (Contributed by Zachary download a copy of 32-bit Python for this purpose. (Contributed by Zachary
Ware in :issue:`30450`.) Ware in :issue:`30450`.)
* Support for building ``--without-threads`` is removed.
(Contributed by Antoine Pitrou in :issue:`31370`.).
Deprecated Deprecated
========== ==========

View File

@ -18,7 +18,7 @@
#error "Python's source code assumes C's unsigned char is an 8-bit type." #error "Python's source code assumes C's unsigned char is an 8-bit type."
#endif #endif
#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE) #if defined(__sgi) && !defined(_SGI_MP_SOURCE)
#define _SGI_MP_SOURCE #define _SGI_MP_SOURCE
#endif #endif

View File

@ -183,8 +183,6 @@ PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(struct _frame *f, int exc);
PyAPI_FUNC(PyThreadState *) PyEval_SaveThread(void); PyAPI_FUNC(PyThreadState *) PyEval_SaveThread(void);
PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *); PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *);
#ifdef WITH_THREAD
PyAPI_FUNC(int) PyEval_ThreadsInitialized(void); PyAPI_FUNC(int) PyEval_ThreadsInitialized(void);
PyAPI_FUNC(void) PyEval_InitThreads(void); PyAPI_FUNC(void) PyEval_InitThreads(void);
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
@ -213,15 +211,6 @@ PyAPI_FUNC(Py_ssize_t) _PyEval_RequestCodeExtraIndex(freefunc);
#define Py_END_ALLOW_THREADS PyEval_RestoreThread(_save); \ #define Py_END_ALLOW_THREADS PyEval_RestoreThread(_save); \
} }
#else /* !WITH_THREAD */
#define Py_BEGIN_ALLOW_THREADS {
#define Py_BLOCK_THREADS
#define Py_UNBLOCK_THREADS
#define Py_END_ALLOW_THREADS }
#endif /* !WITH_THREAD */
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *); PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *);
PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *); PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *);

View File

@ -100,13 +100,8 @@ PyAPI_FUNC(int) PyImport_ImportFrozenModule(
); );
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
#ifdef WITH_THREAD
PyAPI_FUNC(void) _PyImport_AcquireLock(void); PyAPI_FUNC(void) _PyImport_AcquireLock(void);
PyAPI_FUNC(int) _PyImport_ReleaseLock(void); PyAPI_FUNC(int) _PyImport_ReleaseLock(void);
#else
#define _PyImport_AcquireLock()
#define _PyImport_ReleaseLock() 1
#endif
PyAPI_FUNC(void) _PyImport_ReInitLock(void); PyAPI_FUNC(void) _PyImport_ReInitLock(void);

View File

@ -797,4 +797,12 @@ extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler;
#include <android/api-level.h> #include <android/api-level.h>
#endif #endif
/* This macro used to tell whether Python was built with multithreading
* enabled. Now multithreading is always enabled, but keep the macro
* for compatibility.
*/
#ifndef WITH_THREAD
#define WITH_THREAD
#endif
#endif /* Py_PYPORT_H */ #endif /* Py_PYPORT_H */

View File

@ -218,12 +218,10 @@ PyAPI_FUNC(void) PyThreadState_Delete(PyThreadState *);
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate); PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
#endif /* !Py_LIMITED_API */ #endif /* !Py_LIMITED_API */
#ifdef WITH_THREAD
PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void); PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void);
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
PyAPI_FUNC(void) _PyGILState_Reinit(void); PyAPI_FUNC(void) _PyGILState_Reinit(void);
#endif /* !Py_LIMITED_API */ #endif /* !Py_LIMITED_API */
#endif
/* Return the current thread state. The global interpreter lock must be held. /* Return the current thread state. The global interpreter lock must be held.
* When the current thread state is NULL, this issues a fatal error (so that * When the current thread state is NULL, this issues a fatal error (so that
@ -257,7 +255,6 @@ typedef
enum {PyGILState_LOCKED, PyGILState_UNLOCKED} enum {PyGILState_LOCKED, PyGILState_UNLOCKED}
PyGILState_STATE; PyGILState_STATE;
#ifdef WITH_THREAD
/* Ensure that the current thread is ready to call the Python /* Ensure that the current thread is ready to call the Python
C API, regardless of the current state of Python, or of its C API, regardless of the current state of Python, or of its
@ -319,7 +316,6 @@ PyAPI_FUNC(int) PyGILState_Check(void);
PyAPI_FUNC(PyInterpreterState *) _PyGILState_GetInterpreterStateUnsafe(void); PyAPI_FUNC(PyInterpreterState *) _PyGILState_GetInterpreterStateUnsafe(void);
#endif #endif
#endif /* #ifdef WITH_THREAD */
/* The implementation of sys._current_frames() Returns a dict mapping /* The implementation of sys._current_frames() Returns a dict mapping
thread id to that thread's current frame. thread id to that thread's current frame.

View File

@ -1,163 +0,0 @@
"""Drop-in replacement for the thread module.
Meant to be used as a brain-dead substitute so that threaded code does
not need to be rewritten for when the thread module is not present.
Suggested usage is::
try:
import _thread
except ImportError:
import _dummy_thread as _thread
"""
# Exports only things specified by thread documentation;
# skipping obsolete synonyms allocate(), start_new(), exit_thread().
__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock',
'interrupt_main', 'LockType']
# A dummy value
TIMEOUT_MAX = 2**31
# NOTE: this module can be imported early in the extension building process,
# and so top level imports of other modules should be avoided. Instead, all
# imports are done when needed on a function-by-function basis. Since threads
# are disabled, the import lock should not be an issue anyway (??).
error = RuntimeError
def start_new_thread(function, args, kwargs={}):
"""Dummy implementation of _thread.start_new_thread().
Compatibility is maintained by making sure that ``args`` is a
tuple and ``kwargs`` is a dictionary. If an exception is raised
and it is SystemExit (which can be done by _thread.exit()) it is
caught and nothing is done; all other exceptions are printed out
by using traceback.print_exc().
If the executed function calls interrupt_main the KeyboardInterrupt will be
raised when the function returns.
"""
if type(args) != type(tuple()):
raise TypeError("2nd arg must be a tuple")
if type(kwargs) != type(dict()):
raise TypeError("3rd arg must be a dict")
global _main
_main = False
try:
function(*args, **kwargs)
except SystemExit:
pass
except:
import traceback
traceback.print_exc()
_main = True
global _interrupt
if _interrupt:
_interrupt = False
raise KeyboardInterrupt
def exit():
"""Dummy implementation of _thread.exit()."""
raise SystemExit
def get_ident():
"""Dummy implementation of _thread.get_ident().
Since this module should only be used when _threadmodule is not
available, it is safe to assume that the current process is the
only thread. Thus a constant can be safely returned.
"""
return 1
def allocate_lock():
"""Dummy implementation of _thread.allocate_lock()."""
return LockType()
def stack_size(size=None):
"""Dummy implementation of _thread.stack_size()."""
if size is not None:
raise error("setting thread stack size not supported")
return 0
def _set_sentinel():
"""Dummy implementation of _thread._set_sentinel()."""
return LockType()
class LockType(object):
"""Class implementing dummy implementation of _thread.LockType.
Compatibility is maintained by maintaining self.locked_status
which is a boolean that stores the state of the lock. Pickling of
the lock, though, should not be done since if the _thread module is
then used with an unpickled ``lock()`` from here problems could
occur from this class not having atomic methods.
"""
def __init__(self):
self.locked_status = False
def acquire(self, waitflag=None, timeout=-1):
"""Dummy implementation of acquire().
For blocking calls, self.locked_status is automatically set to
True and returned appropriately based on value of
``waitflag``. If it is non-blocking, then the value is
actually checked and not set if it is already acquired. This
is all done so that threading.Condition's assert statements
aren't triggered and throw a little fit.
"""
if waitflag is None or waitflag:
self.locked_status = True
return True
else:
if not self.locked_status:
self.locked_status = True
return True
else:
if timeout > 0:
import time
time.sleep(timeout)
return False
__enter__ = acquire
def __exit__(self, typ, val, tb):
self.release()
def release(self):
"""Release the dummy lock."""
# XXX Perhaps shouldn't actually bother to test? Could lead
# to problems for complex, threaded code.
if not self.locked_status:
raise error
self.locked_status = False
return True
def locked(self):
return self.locked_status
def __repr__(self):
return "<%s %s.%s object at %s>" % (
"locked" if self.locked_status else "unlocked",
self.__class__.__module__,
self.__class__.__qualname__,
hex(id(self))
)
# Used to signal that interrupt_main was called in a "thread"
_interrupt = False
# True when not executing in a "thread"
_main = True
def interrupt_main():
"""Set _interrupt flag to True to have start_new_thread raise
KeyboardInterrupt upon exiting."""
if _main:
raise KeyboardInterrupt
else:
global _interrupt
_interrupt = True

View File

@ -436,75 +436,34 @@ _rounding_modes = (ROUND_DOWN, ROUND_HALF_UP, ROUND_HALF_EVEN, ROUND_CEILING,
# work for older Pythons. If threads are not part of the build, create a # work for older Pythons. If threads are not part of the build, create a
# mock threading object with threading.local() returning the module namespace. # mock threading object with threading.local() returning the module namespace.
try: import threading
import threading
except ImportError:
# Python was compiled without threads; create a mock object instead
class MockThreading(object):
def local(self, sys=sys):
return sys.modules[__xname__]
threading = MockThreading()
del MockThreading
try: local = threading.local()
threading.local if hasattr(local, '__decimal_context__'):
del local.__decimal_context__
except AttributeError: def getcontext(_local=local):
"""Returns this thread's context.
# To fix reloading, force it to create a new context If this thread does not yet have a context, returns
# Old contexts have different exceptions in their dicts, making problems. a new context and sets this thread's context.
if hasattr(threading.current_thread(), '__decimal_context__'): New contexts are copies of DefaultContext.
del threading.current_thread().__decimal_context__ """
try:
def setcontext(context): return _local.__decimal_context__
"""Set this thread's context to context.""" except AttributeError:
if context in (DefaultContext, BasicContext, ExtendedContext): context = Context()
context = context.copy()
context.clear_flags()
threading.current_thread().__decimal_context__ = context
def getcontext():
"""Returns this thread's context.
If this thread does not yet have a context, returns
a new context and sets this thread's context.
New contexts are copies of DefaultContext.
"""
try:
return threading.current_thread().__decimal_context__
except AttributeError:
context = Context()
threading.current_thread().__decimal_context__ = context
return context
else:
local = threading.local()
if hasattr(local, '__decimal_context__'):
del local.__decimal_context__
def getcontext(_local=local):
"""Returns this thread's context.
If this thread does not yet have a context, returns
a new context and sets this thread's context.
New contexts are copies of DefaultContext.
"""
try:
return _local.__decimal_context__
except AttributeError:
context = Context()
_local.__decimal_context__ = context
return context
def setcontext(context, _local=local):
"""Set this thread's context to context."""
if context in (DefaultContext, BasicContext, ExtendedContext):
context = context.copy()
context.clear_flags()
_local.__decimal_context__ = context _local.__decimal_context__ = context
return context
del threading, local # Don't contaminate the namespace def setcontext(context, _local=local):
"""Set this thread's context to context."""
if context in (DefaultContext, BasicContext, ExtendedContext):
context = context.copy()
context.clear_flags()
_local.__decimal_context__ = context
del threading, local # Don't contaminate the namespace
def localcontext(ctx=None): def localcontext(ctx=None):
"""Return a context manager for a copy of the supplied context """Return a context manager for a copy of the supplied context

View File

@ -9,10 +9,7 @@ import errno
import stat import stat
import sys import sys
# Import _thread instead of threading to reduce startup cost # Import _thread instead of threading to reduce startup cost
try: from _thread import allocate_lock as Lock
from _thread import allocate_lock as Lock
except ImportError:
from _dummy_thread import allocate_lock as Lock
if sys.platform in {'win32', 'cygwin'}: if sys.platform in {'win32', 'cygwin'}:
from msvcrt import setmode as _setmode from msvcrt import setmode as _setmode
else: else:

View File

@ -19,10 +19,7 @@ from re import escape as re_escape
from datetime import (date as datetime_date, from datetime import (date as datetime_date,
timedelta as datetime_timedelta, timedelta as datetime_timedelta,
timezone as datetime_timezone) timezone as datetime_timezone)
try: from _thread import allocate_lock as _thread_allocate_lock
from _thread import allocate_lock as _thread_allocate_lock
except ImportError:
from _dummy_thread import allocate_lock as _thread_allocate_lock
__all__ = [] __all__ = []

View File

@ -14,11 +14,7 @@ import io
import os import os
import warnings import warnings
import _compression import _compression
from threading import RLock
try:
from threading import RLock
except ImportError:
from dummy_threading import RLock
from _bz2 import BZ2Compressor, BZ2Decompressor from _bz2 import BZ2Compressor, BZ2Decompressor

View File

@ -1,10 +1,8 @@
import unittest, os, errno import unittest, os, errno
import threading
from ctypes import * from ctypes import *
from ctypes.util import find_library from ctypes.util import find_library
try:
import threading
except ImportError:
threading = None
class Test(unittest.TestCase): class Test(unittest.TestCase):
def test_open(self): def test_open(self):
@ -25,26 +23,25 @@ class Test(unittest.TestCase):
self.assertEqual(set_errno(32), errno.ENOENT) self.assertEqual(set_errno(32), errno.ENOENT)
self.assertEqual(get_errno(), 32) self.assertEqual(get_errno(), 32)
if threading: def _worker():
def _worker():
set_errno(0)
libc = CDLL(libc_name, use_errno=False)
if os.name == "nt":
libc_open = libc._open
else:
libc_open = libc.open
libc_open.argtypes = c_char_p, c_int
self.assertEqual(libc_open(b"", 0), -1)
self.assertEqual(get_errno(), 0)
t = threading.Thread(target=_worker)
t.start()
t.join()
self.assertEqual(get_errno(), 32)
set_errno(0) set_errno(0)
libc = CDLL(libc_name, use_errno=False)
if os.name == "nt":
libc_open = libc._open
else:
libc_open = libc.open
libc_open.argtypes = c_char_p, c_int
self.assertEqual(libc_open(b"", 0), -1)
self.assertEqual(get_errno(), 0)
t = threading.Thread(target=_worker)
t.start()
t.join()
self.assertEqual(get_errno(), 32)
set_errno(0)
@unittest.skipUnless(os.name == "nt", 'Test specific to Windows') @unittest.skipUnless(os.name == "nt", 'Test specific to Windows')
def test_GetLastError(self): def test_GetLastError(self):
dll = WinDLL("kernel32", use_last_error=True) dll = WinDLL("kernel32", use_last_error=True)

View File

@ -1,78 +0,0 @@
"""Faux ``threading`` version using ``dummy_thread`` instead of ``thread``.
The module ``_dummy_threading`` is added to ``sys.modules`` in order
to not have ``threading`` considered imported. Had ``threading`` been
directly imported it would have made all subsequent imports succeed
regardless of whether ``_thread`` was available which is not desired.
"""
from sys import modules as sys_modules
import _dummy_thread
# Declaring now so as to not have to nest ``try``s to get proper clean-up.
holding_thread = False
holding_threading = False
holding__threading_local = False
try:
# Could have checked if ``_thread`` was not in sys.modules and gone
# a different route, but decided to mirror technique used with
# ``threading`` below.
if '_thread' in sys_modules:
held_thread = sys_modules['_thread']
holding_thread = True
# Must have some module named ``_thread`` that implements its API
# in order to initially import ``threading``.
sys_modules['_thread'] = sys_modules['_dummy_thread']
if 'threading' in sys_modules:
# If ``threading`` is already imported, might as well prevent
# trying to import it more than needed by saving it if it is
# already imported before deleting it.
held_threading = sys_modules['threading']
holding_threading = True
del sys_modules['threading']
if '_threading_local' in sys_modules:
# If ``_threading_local`` is already imported, might as well prevent
# trying to import it more than needed by saving it if it is
# already imported before deleting it.
held__threading_local = sys_modules['_threading_local']
holding__threading_local = True
del sys_modules['_threading_local']
import threading
# Need a copy of the code kept somewhere...
sys_modules['_dummy_threading'] = sys_modules['threading']
del sys_modules['threading']
sys_modules['_dummy__threading_local'] = sys_modules['_threading_local']
del sys_modules['_threading_local']
from _dummy_threading import *
from _dummy_threading import __all__
finally:
# Put back ``threading`` if we overwrote earlier
if holding_threading:
sys_modules['threading'] = held_threading
del held_threading
del holding_threading
# Put back ``_threading_local`` if we overwrote earlier
if holding__threading_local:
sys_modules['_threading_local'] = held__threading_local
del held__threading_local
del holding__threading_local
# Put back ``thread`` if we overwrote, else del the entry we made
if holding_thread:
sys_modules['_thread'] = held_thread
del held_thread
else:
del sys_modules['_thread']
del holding_thread
del _dummy_thread
del sys_modules

View File

@ -22,13 +22,7 @@ from collections import namedtuple
from types import MappingProxyType from types import MappingProxyType
from weakref import WeakKeyDictionary from weakref import WeakKeyDictionary
from reprlib import recursive_repr from reprlib import recursive_repr
try: from _thread import RLock
from _thread import RLock
except ImportError:
class RLock:
'Dummy reentrant lock for builds without threads'
def __enter__(self): pass
def __exit__(self, exctype, excinst, exctb): pass
################################################################################ ################################################################################

View File

@ -33,10 +33,7 @@ import datetime
import re import re
import time import time
import urllib.parse, urllib.request import urllib.parse, urllib.request
try: import threading as _threading
import threading as _threading
except ImportError:
import dummy_threading as _threading
import http.client # only for the default HTTP port import http.client # only for the default HTTP port
from calendar import timegm from calendar import timegm

View File

@ -37,10 +37,7 @@ __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
'warn', 'warning', 'getLogRecordFactory', 'setLogRecordFactory', 'warn', 'warning', 'getLogRecordFactory', 'setLogRecordFactory',
'lastResort', 'raiseExceptions'] 'lastResort', 'raiseExceptions']
try: import threading
import threading
except ImportError: #pragma: no cover
threading = None
__author__ = "Vinay Sajip <vinay_sajip@red-dove.com>" __author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
__status__ = "production" __status__ = "production"
@ -210,11 +207,7 @@ def _checkLevel(level):
#the lock would already have been acquired - so we need an RLock. #the lock would already have been acquired - so we need an RLock.
#The same argument applies to Loggers and Manager.loggerDict. #The same argument applies to Loggers and Manager.loggerDict.
# #
if threading: _lock = threading.RLock()
_lock = threading.RLock()
else: #pragma: no cover
_lock = None
def _acquireLock(): def _acquireLock():
""" """
@ -295,7 +288,7 @@ class LogRecord(object):
self.created = ct self.created = ct
self.msecs = (ct - int(ct)) * 1000 self.msecs = (ct - int(ct)) * 1000
self.relativeCreated = (self.created - _startTime) * 1000 self.relativeCreated = (self.created - _startTime) * 1000
if logThreads and threading: if logThreads:
self.thread = threading.get_ident() self.thread = threading.get_ident()
self.threadName = threading.current_thread().name self.threadName = threading.current_thread().name
else: # pragma: no cover else: # pragma: no cover
@ -799,10 +792,7 @@ class Handler(Filterer):
""" """
Acquire a thread lock for serializing access to the underlying I/O. Acquire a thread lock for serializing access to the underlying I/O.
""" """
if threading: self.lock = threading.RLock()
self.lock = threading.RLock()
else: #pragma: no cover
self.lock = None
def acquire(self): def acquire(self):
""" """

View File

@ -31,14 +31,9 @@ import logging.handlers
import re import re
import struct import struct
import sys import sys
import threading
import traceback import traceback
try:
import _thread as thread
import threading
except ImportError: #pragma: no cover
thread = None
from socketserver import ThreadingTCPServer, StreamRequestHandler from socketserver import ThreadingTCPServer, StreamRequestHandler
@ -816,8 +811,6 @@ def listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None):
normal. Note that you can return transformed bytes, e.g. by decrypting normal. Note that you can return transformed bytes, e.g. by decrypting
the bytes passed in. the bytes passed in.
""" """
if not thread: #pragma: no cover
raise NotImplementedError("listen() needs threading to work")
class ConfigStreamHandler(StreamRequestHandler): class ConfigStreamHandler(StreamRequestHandler):
""" """

View File

@ -26,10 +26,7 @@ To use, simply 'import logging.handlers' and log away!
import logging, socket, os, pickle, struct, time, re import logging, socket, os, pickle, struct, time, re
from stat import ST_DEV, ST_INO, ST_MTIME from stat import ST_DEV, ST_INO, ST_MTIME
import queue import queue
try: import threading
import threading
except ImportError: #pragma: no cover
threading = None
# #
# Some constants... # Some constants...
@ -1395,110 +1392,110 @@ class QueueHandler(logging.Handler):
except Exception: except Exception:
self.handleError(record) self.handleError(record)
if threading:
class QueueListener(object): class QueueListener(object):
"""
This class implements an internal threaded listener which watches for
LogRecords being added to a queue, removes them and passes them to a
list of handlers for processing.
"""
_sentinel = None
def __init__(self, queue, *handlers, respect_handler_level=False):
""" """
This class implements an internal threaded listener which watches for Initialise an instance with the specified queue and
LogRecords being added to a queue, removes them and passes them to a handlers.
list of handlers for processing.
""" """
_sentinel = None self.queue = queue
self.handlers = handlers
self._thread = None
self.respect_handler_level = respect_handler_level
def __init__(self, queue, *handlers, respect_handler_level=False): def dequeue(self, block):
""" """
Initialise an instance with the specified queue and Dequeue a record and return it, optionally blocking.
handlers.
"""
self.queue = queue
self.handlers = handlers
self._thread = None
self.respect_handler_level = respect_handler_level
def dequeue(self, block): The base implementation uses get. You may want to override this method
""" if you want to use timeouts or work with custom queue implementations.
Dequeue a record and return it, optionally blocking. """
return self.queue.get(block)
The base implementation uses get. You may want to override this method def start(self):
if you want to use timeouts or work with custom queue implementations. """
""" Start the listener.
return self.queue.get(block)
def start(self): This starts up a background thread to monitor the queue for
""" LogRecords to process.
Start the listener. """
self._thread = t = threading.Thread(target=self._monitor)
t.daemon = True
t.start()
This starts up a background thread to monitor the queue for def prepare(self , record):
LogRecords to process. """
""" Prepare a record for handling.
self._thread = t = threading.Thread(target=self._monitor)
t.daemon = True
t.start()
def prepare(self , record): This method just returns the passed-in record. You may want to
""" override this method if you need to do any custom marshalling or
Prepare a record for handling. manipulation of the record before passing it to the handlers.
"""
return record
This method just returns the passed-in record. You may want to def handle(self, record):
override this method if you need to do any custom marshalling or """
manipulation of the record before passing it to the handlers. Handle a record.
"""
return record
def handle(self, record): This just loops through the handlers offering them the record
""" to handle.
Handle a record. """
record = self.prepare(record)
for handler in self.handlers:
if not self.respect_handler_level:
process = True
else:
process = record.levelno >= handler.level
if process:
handler.handle(record)
This just loops through the handlers offering them the record def _monitor(self):
to handle. """
""" Monitor the queue for records, and ask the handler
record = self.prepare(record) to deal with them.
for handler in self.handlers:
if not self.respect_handler_level:
process = True
else:
process = record.levelno >= handler.level
if process:
handler.handle(record)
def _monitor(self): This method runs on a separate, internal thread.
""" The thread will terminate if it sees a sentinel object in the queue.
Monitor the queue for records, and ask the handler """
to deal with them. q = self.queue
has_task_done = hasattr(q, 'task_done')
This method runs on a separate, internal thread. while True:
The thread will terminate if it sees a sentinel object in the queue. try:
""" record = self.dequeue(True)
q = self.queue if record is self._sentinel:
has_task_done = hasattr(q, 'task_done')
while True:
try:
record = self.dequeue(True)
if record is self._sentinel:
break
self.handle(record)
if has_task_done:
q.task_done()
except queue.Empty:
break break
self.handle(record)
if has_task_done:
q.task_done()
except queue.Empty:
break
def enqueue_sentinel(self): def enqueue_sentinel(self):
""" """
This is used to enqueue the sentinel record. This is used to enqueue the sentinel record.
The base implementation uses put_nowait. You may want to override this The base implementation uses put_nowait. You may want to override this
method if you want to use timeouts or work with custom queue method if you want to use timeouts or work with custom queue
implementations. implementations.
""" """
self.queue.put_nowait(self._sentinel) self.queue.put_nowait(self._sentinel)
def stop(self): def stop(self):
""" """
Stop the listener. Stop the listener.
This asks the thread to terminate, and then waits for it to do so. This asks the thread to terminate, and then waits for it to do so.
Note that if you don't call this before your application exits, there Note that if you don't call this before your application exits, there
may be some records still left on the queue, which won't be processed. may be some records still left on the queue, which won't be processed.
""" """
self.enqueue_sentinel() self.enqueue_sentinel()
self._thread.join() self._thread.join()
self._thread = None self._thread = None

View File

@ -1,9 +1,6 @@
'''A multi-producer, multi-consumer queue.''' '''A multi-producer, multi-consumer queue.'''
try: import threading
import threading
except ImportError:
import dummy_threading as threading
from collections import deque from collections import deque
from heapq import heappush, heappop from heapq import heappush, heappop
from time import monotonic as time from time import monotonic as time

View File

@ -4,10 +4,7 @@ __all__ = ["Repr", "repr", "recursive_repr"]
import builtins import builtins
from itertools import islice from itertools import islice
try: from _thread import get_ident
from _thread import get_ident
except ImportError:
from _dummy_thread import get_ident
def recursive_repr(fillvalue='...'): def recursive_repr(fillvalue='...'):
'Decorator to make a repr function return fillvalue for a recursive call' 'Decorator to make a repr function return fillvalue for a recursive call'

View File

@ -26,10 +26,7 @@ has another way to reference private data (besides global variables).
import time import time
import heapq import heapq
from collections import namedtuple from collections import namedtuple
try: import threading
import threading
except ImportError:
import dummy_threading as threading
from time import monotonic as _time from time import monotonic as _time
__all__ = ["scheduler"] __all__ = ["scheduler"]

View File

@ -127,10 +127,7 @@ import socket
import selectors import selectors
import os import os
import sys import sys
try: import threading
import threading
except ImportError:
import dummy_threading as threading
from io import BufferedIOBase from io import BufferedIOBase
from time import monotonic as time from time import monotonic as time

View File

@ -21,12 +21,9 @@
# misrepresented as being the original software. # misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution. # 3. This notice may not be removed or altered from any source distribution.
import threading
import unittest import unittest
import sqlite3 as sqlite import sqlite3 as sqlite
try:
import threading
except ImportError:
threading = None
from test.support import TESTFN, unlink from test.support import TESTFN, unlink
@ -503,7 +500,6 @@ class CursorTests(unittest.TestCase):
self.assertEqual(results, expected) self.assertEqual(results, expected)
@unittest.skipUnless(threading, 'This test requires threading.')
class ThreadTests(unittest.TestCase): class ThreadTests(unittest.TestCase):
def setUp(self): def setUp(self):
self.con = sqlite.connect(":memory:") self.con = sqlite.connect(":memory:")

View File

@ -138,10 +138,7 @@ else:
import _posixsubprocess import _posixsubprocess
import select import select
import selectors import selectors
try: import threading
import threading
except ImportError:
import dummy_threading as threading
# When select or poll has indicated that the file is writable, # When select or poll has indicated that the file is writable,
# we can write up to _PIPE_BUF bytes without risk of blocking. # we can write up to _PIPE_BUF bytes without risk of blocking.

View File

@ -44,11 +44,7 @@ import shutil as _shutil
import errno as _errno import errno as _errno
from random import Random as _Random from random import Random as _Random
import weakref as _weakref import weakref as _weakref
import _thread
try:
import _thread
except ImportError:
import _dummy_thread as _thread
_allocate_lock = _thread.allocate_lock _allocate_lock = _thread.allocate_lock
_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL _text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL

View File

@ -10,9 +10,9 @@ active threads survive in the child after a fork(); this is an error.
""" """
import os, sys, time, unittest import os, sys, time, unittest
import threading
import test.support as support import test.support as support
threading = support.import_module('threading')
LONGSLEEP = 2 LONGSLEEP = 2
SHORTSLEEP = 0.5 SHORTSLEEP = 0.5

View File

@ -3,15 +3,11 @@ import json
import os import os
import queue import queue
import sys import sys
import threading
import time import time
import traceback import traceback
import types import types
from test import support from test import support
try:
import threading
except ImportError:
print("Multiprocess option requires thread support")
sys.exit(2)
from test.libregrtest.runtest import ( from test.libregrtest.runtest import (
runtest, INTERRUPTED, CHILD_ERROR, PROGRESS_MIN_TIME, runtest, INTERRUPTED, CHILD_ERROR, PROGRESS_MIN_TIME,

View File

@ -5,12 +5,9 @@ import os
import shutil import shutil
import sys import sys
import sysconfig import sysconfig
import threading
import warnings import warnings
from test import support from test import support
try:
import threading
except ImportError:
threading = None
try: try:
import _multiprocessing, multiprocessing.process import _multiprocessing, multiprocessing.process
except ImportError: except ImportError:
@ -181,13 +178,9 @@ class saved_test_environment:
# Controlling dangling references to Thread objects can make it easier # Controlling dangling references to Thread objects can make it easier
# to track reference leaks. # to track reference leaks.
def get_threading__dangling(self): def get_threading__dangling(self):
if not threading:
return None
# This copies the weakrefs without making any strong reference # This copies the weakrefs without making any strong reference
return threading._dangling.copy() return threading._dangling.copy()
def restore_threading__dangling(self, saved): def restore_threading__dangling(self, saved):
if not threading:
return
threading._dangling.clear() threading._dangling.clear()
threading._dangling.update(saved) threading._dangling.update(saved)

View File

@ -25,17 +25,14 @@ import subprocess
import sys import sys
import sysconfig import sysconfig
import tempfile import tempfile
import _thread
import threading
import time import time
import types import types
import unittest import unittest
import urllib.error import urllib.error
import warnings import warnings
try:
import _thread, threading
except ImportError:
_thread = None
threading = None
try: try:
import multiprocessing.process import multiprocessing.process
except ImportError: except ImportError:
@ -2028,16 +2025,11 @@ environment_altered = False
# at the end of a test run. # at the end of a test run.
def threading_setup(): def threading_setup():
if _thread: return _thread._count(), threading._dangling.copy()
return _thread._count(), threading._dangling.copy()
else:
return 1, ()
def threading_cleanup(*original_values): def threading_cleanup(*original_values):
global environment_altered global environment_altered
if not _thread:
return
_MAX_COUNT = 100 _MAX_COUNT = 100
t0 = time.monotonic() t0 = time.monotonic()
for count in range(_MAX_COUNT): for count in range(_MAX_COUNT):
@ -2061,9 +2053,6 @@ def reap_threads(func):
ensure that the threads are cleaned up even when the test fails. ensure that the threads are cleaned up even when the test fails.
If threading is unavailable this function does nothing. If threading is unavailable this function does nothing.
""" """
if not _thread:
return func
@functools.wraps(func) @functools.wraps(func)
def decorator(*args): def decorator(*args):
key = threading_setup() key = threading_setup()

View File

@ -2,110 +2,104 @@
from test import support from test import support
# If this fails, the test will be skipped.
thread = support.import_module('_thread')
import asynchat import asynchat
import asyncore import asyncore
import errno import errno
import socket import socket
import sys import sys
import _thread as thread
import threading
import time import time
import unittest import unittest
import unittest.mock import unittest.mock
try:
import threading
except ImportError:
threading = None
HOST = support.HOST HOST = support.HOST
SERVER_QUIT = b'QUIT\n' SERVER_QUIT = b'QUIT\n'
TIMEOUT = 3.0 TIMEOUT = 3.0
if threading:
class echo_server(threading.Thread):
# parameter to determine the number of bytes passed back to the
# client each send
chunk_size = 1
def __init__(self, event): class echo_server(threading.Thread):
threading.Thread.__init__(self) # parameter to determine the number of bytes passed back to the
self.event = event # client each send
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) chunk_size = 1
self.port = support.bind_port(self.sock)
# This will be set if the client wants us to wait before echoing
# data back.
self.start_resend_event = None
def run(self): def __init__(self, event):
self.sock.listen() threading.Thread.__init__(self)
self.event.set() self.event = event
conn, client = self.sock.accept() self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.buffer = b"" self.port = support.bind_port(self.sock)
# collect data until quit message is seen # This will be set if the client wants us to wait before echoing
while SERVER_QUIT not in self.buffer: # data back.
data = conn.recv(1) self.start_resend_event = None
if not data:
break
self.buffer = self.buffer + data
# remove the SERVER_QUIT message def run(self):
self.buffer = self.buffer.replace(SERVER_QUIT, b'') self.sock.listen()
self.event.set()
conn, client = self.sock.accept()
self.buffer = b""
# collect data until quit message is seen
while SERVER_QUIT not in self.buffer:
data = conn.recv(1)
if not data:
break
self.buffer = self.buffer + data
if self.start_resend_event: # remove the SERVER_QUIT message
self.start_resend_event.wait() self.buffer = self.buffer.replace(SERVER_QUIT, b'')
# re-send entire set of collected data if self.start_resend_event:
try: self.start_resend_event.wait()
# this may fail on some tests, such as test_close_when_done,
# since the client closes the channel when it's done sending # re-send entire set of collected data
while self.buffer: try:
n = conn.send(self.buffer[:self.chunk_size]) # this may fail on some tests, such as test_close_when_done,
time.sleep(0.001) # since the client closes the channel when it's done sending
self.buffer = self.buffer[n:] while self.buffer:
except: n = conn.send(self.buffer[:self.chunk_size])
time.sleep(0.001)
self.buffer = self.buffer[n:]
except:
pass
conn.close()
self.sock.close()
class echo_client(asynchat.async_chat):
def __init__(self, terminator, server_port):
asynchat.async_chat.__init__(self)
self.contents = []
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((HOST, server_port))
self.set_terminator(terminator)
self.buffer = b""
def handle_connect(self):
pass
if sys.platform == 'darwin':
# select.poll returns a select.POLLHUP at the end of the tests
# on darwin, so just ignore it
def handle_expt(self):
pass pass
conn.close() def collect_incoming_data(self, data):
self.sock.close() self.buffer += data
class echo_client(asynchat.async_chat): def found_terminator(self):
self.contents.append(self.buffer)
self.buffer = b""
def __init__(self, terminator, server_port): def start_echo_server():
asynchat.async_chat.__init__(self) event = threading.Event()
self.contents = [] s = echo_server(event)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM) s.start()
self.connect((HOST, server_port)) event.wait()
self.set_terminator(terminator) event.clear()
self.buffer = b"" time.sleep(0.01) # Give server time to start accepting.
return s, event
def handle_connect(self):
pass
if sys.platform == 'darwin':
# select.poll returns a select.POLLHUP at the end of the tests
# on darwin, so just ignore it
def handle_expt(self):
pass
def collect_incoming_data(self, data):
self.buffer += data
def found_terminator(self):
self.contents.append(self.buffer)
self.buffer = b""
def start_echo_server():
event = threading.Event()
s = echo_server(event)
s.start()
event.wait()
event.clear()
time.sleep(0.01) # Give server time to start accepting.
return s, event
@unittest.skipUnless(threading, 'Threading required for this test.')
class TestAsynchat(unittest.TestCase): class TestAsynchat(unittest.TestCase):
usepoll = False usepoll = False

View File

@ -1,8 +1,6 @@
import os import os
from test.support import load_package_tests, import_module from test.support import load_package_tests, import_module
# Skip tests if we don't have threading.
import_module('threading')
# Skip tests if we don't have concurrent.futures. # Skip tests if we don't have concurrent.futures.
import_module('concurrent.futures') import_module('concurrent.futures')

View File

@ -7,6 +7,7 @@ import sys
import time import time
import errno import errno
import struct import struct
import threading
from test import support from test import support
from io import BytesIO from io import BytesIO
@ -14,10 +15,6 @@ from io import BytesIO
if support.PGO: if support.PGO:
raise unittest.SkipTest("test is not helpful for PGO") raise unittest.SkipTest("test is not helpful for PGO")
try:
import threading
except ImportError:
threading = None
TIMEOUT = 3 TIMEOUT = 3
HAS_UNIX_SOCKETS = hasattr(socket, 'AF_UNIX') HAS_UNIX_SOCKETS = hasattr(socket, 'AF_UNIX')
@ -326,7 +323,6 @@ class DispatcherWithSendTests(unittest.TestCase):
def tearDown(self): def tearDown(self):
asyncore.close_all() asyncore.close_all()
@unittest.skipUnless(threading, 'Threading required for this test.')
@support.reap_threads @support.reap_threads
def test_send(self): def test_send(self):
evt = threading.Event() evt = threading.Event()
@ -776,7 +772,6 @@ class BaseTestAPI:
self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET, self.assertTrue(s.socket.getsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR)) socket.SO_REUSEADDR))
@unittest.skipUnless(threading, 'Threading required for this test.')
@support.reap_threads @support.reap_threads
def test_quick_connect(self): def test_quick_connect(self):
# see: http://bugs.python.org/issue10340 # see: http://bugs.python.org/issue10340

View File

@ -10,13 +10,10 @@ import pathlib
import random import random
import shutil import shutil
import subprocess import subprocess
import threading
from test.support import unlink from test.support import unlink
import _compression import _compression
try:
import threading
except ImportError:
threading = None
# Skip tests if the bz2 module doesn't exist. # Skip tests if the bz2 module doesn't exist.
bz2 = support.import_module('bz2') bz2 = support.import_module('bz2')
@ -491,7 +488,6 @@ class BZ2FileTest(BaseTest):
else: else:
self.fail("1/0 didn't raise an exception") self.fail("1/0 didn't raise an exception")
@unittest.skipUnless(threading, 'Threading required for this test.')
def testThreading(self): def testThreading(self):
# Issue #7205: Using a BZ2File from several threads shouldn't deadlock. # Issue #7205: Using a BZ2File from several threads shouldn't deadlock.
data = b"1" * 2**20 data = b"1" * 2**20
@ -504,13 +500,6 @@ class BZ2FileTest(BaseTest):
with support.start_threads(threads): with support.start_threads(threads):
pass pass
def testWithoutThreading(self):
module = support.import_fresh_module("bz2", blocked=("threading",))
with module.BZ2File(self.filename, "wb") as f:
f.write(b"abc")
with module.BZ2File(self.filename, "rb") as f:
self.assertEqual(f.read(), b"abc")
def testMixedIterationAndReads(self): def testMixedIterationAndReads(self):
self.createTempFile() self.createTempFile()
linelen = len(self.TEXT_LINES[0]) linelen = len(self.TEXT_LINES[0])

View File

@ -11,6 +11,7 @@ import subprocess
import sys import sys
import sysconfig import sysconfig
import textwrap import textwrap
import threading
import time import time
import unittest import unittest
from test import support from test import support
@ -20,10 +21,7 @@ try:
import _posixsubprocess import _posixsubprocess
except ImportError: except ImportError:
_posixsubprocess = None _posixsubprocess = None
try:
import threading
except ImportError:
threading = None
# Skip this test if the _testcapi module isn't available. # Skip this test if the _testcapi module isn't available.
_testcapi = support.import_module('_testcapi') _testcapi = support.import_module('_testcapi')
@ -52,7 +50,6 @@ class CAPITest(unittest.TestCase):
self.assertEqual(testfunction.attribute, "test") self.assertEqual(testfunction.attribute, "test")
self.assertRaises(AttributeError, setattr, inst.testfunction, "attribute", "test") self.assertRaises(AttributeError, setattr, inst.testfunction, "attribute", "test")
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_no_FatalError_infinite_loop(self): def test_no_FatalError_infinite_loop(self):
with support.SuppressCrashReport(): with support.SuppressCrashReport():
p = subprocess.Popen([sys.executable, "-c", p = subprocess.Popen([sys.executable, "-c",
@ -276,7 +273,6 @@ class CAPITest(unittest.TestCase):
self.assertIn(b'MemoryError 3 30', out) self.assertIn(b'MemoryError 3 30', out)
@unittest.skipUnless(threading, 'Threading required for this test.')
class TestPendingCalls(unittest.TestCase): class TestPendingCalls(unittest.TestCase):
def pendingcalls_submit(self, l, n): def pendingcalls_submit(self, l, n):
@ -685,7 +681,6 @@ class SkipitemTest(unittest.TestCase):
parse((1,), {}, 'O|OO', ['', 'a', '']) parse((1,), {}, 'O|OO', ['', 'a', ''])
@unittest.skipUnless(threading, 'Threading required for this test.')
class TestThreadState(unittest.TestCase): class TestThreadState(unittest.TestCase):
@support.reap_threads @support.reap_threads
@ -762,7 +757,6 @@ class PyMemDebugTests(unittest.TestCase):
regex = regex.format(ptr=self.PTR_REGEX) regex = regex.format(ptr=self.PTR_REGEX)
self.assertRegex(out, regex) self.assertRegex(out, regex)
@unittest.skipUnless(threading, 'Test requires a GIL (multithreading)')
def check_malloc_without_gil(self, code): def check_malloc_without_gil(self, code):
out = self.check(code) out = self.check(code)
expected = ('Fatal Python error: Python memory allocator called ' expected = ('Fatal Python error: Python memory allocator called '

View File

@ -4,10 +4,6 @@ import test.support
test.support.import_module('_multiprocessing') test.support.import_module('_multiprocessing')
# Skip tests if sem_open implementation is broken. # Skip tests if sem_open implementation is broken.
test.support.import_module('multiprocessing.synchronize') test.support.import_module('multiprocessing.synchronize')
# import threading after _multiprocessing to raise a more relevant error
# message: "No module named _multiprocessing". _multiprocessing is not compiled
# without thread support.
test.support.import_module('threading')
from test.support.script_helper import assert_python_ok from test.support.script_helper import assert_python_ok

View File

@ -3,13 +3,10 @@
import io import io
import sys import sys
import tempfile import tempfile
import threading
import unittest import unittest
from contextlib import * # Tests __all__ from contextlib import * # Tests __all__
from test import support from test import support
try:
import threading
except ImportError:
threading = None
class TestAbstractContextManager(unittest.TestCase): class TestAbstractContextManager(unittest.TestCase):
@ -275,7 +272,6 @@ class FileContextTestCase(unittest.TestCase):
finally: finally:
support.unlink(tfn) support.unlink(tfn)
@unittest.skipUnless(threading, 'Threading required for this test.')
class LockContextTestCase(unittest.TestCase): class LockContextTestCase(unittest.TestCase):
def boilerPlate(self, lock, locked): def boilerPlate(self, lock, locked):

View File

@ -38,10 +38,7 @@ from test.support import (import_fresh_module, TestFailed,
run_with_locale, cpython_only) run_with_locale, cpython_only)
import random import random
import inspect import inspect
try: import threading
import threading
except ImportError:
threading = None
C = import_fresh_module('decimal', fresh=['_decimal']) C = import_fresh_module('decimal', fresh=['_decimal'])
@ -1625,10 +1622,10 @@ class ThreadingTest(unittest.TestCase):
DefaultContext.Emax = save_emax DefaultContext.Emax = save_emax
DefaultContext.Emin = save_emin DefaultContext.Emin = save_emin
@unittest.skipUnless(threading, 'threading required')
class CThreadingTest(ThreadingTest): class CThreadingTest(ThreadingTest):
decimal = C decimal = C
@unittest.skipUnless(threading, 'threading required')
class PyThreadingTest(ThreadingTest): class PyThreadingTest(ThreadingTest):
decimal = P decimal = P

View File

@ -1,8 +1,8 @@
from xmlrpc.server import DocXMLRPCServer from xmlrpc.server import DocXMLRPCServer
import http.client import http.client
import sys import sys
import threading
from test import support from test import support
threading = support.import_module('threading')
import unittest import unittest
def make_request_and_skipIf(condition, reason): def make_request_and_skipIf(condition, reason):

View File

@ -1,255 +0,0 @@
import _dummy_thread as _thread
import time
import queue
import random
import unittest
from test import support
from unittest import mock
DELAY = 0
class LockTests(unittest.TestCase):
"""Test lock objects."""
def setUp(self):
# Create a lock
self.lock = _thread.allocate_lock()
def test_initlock(self):
#Make sure locks start locked
self.assertFalse(self.lock.locked(),
"Lock object is not initialized unlocked.")
def test_release(self):
# Test self.lock.release()
self.lock.acquire()
self.lock.release()
self.assertFalse(self.lock.locked(),
"Lock object did not release properly.")
def test_LockType_context_manager(self):
with _thread.LockType():
pass
self.assertFalse(self.lock.locked(),
"Acquired Lock was not released")
def test_improper_release(self):
#Make sure release of an unlocked thread raises RuntimeError
self.assertRaises(RuntimeError, self.lock.release)
def test_cond_acquire_success(self):
#Make sure the conditional acquiring of the lock works.
self.assertTrue(self.lock.acquire(0),
"Conditional acquiring of the lock failed.")
def test_cond_acquire_fail(self):
#Test acquiring locked lock returns False
self.lock.acquire(0)
self.assertFalse(self.lock.acquire(0),
"Conditional acquiring of a locked lock incorrectly "
"succeeded.")
def test_uncond_acquire_success(self):
#Make sure unconditional acquiring of a lock works.
self.lock.acquire()
self.assertTrue(self.lock.locked(),
"Uncondional locking failed.")
def test_uncond_acquire_return_val(self):
#Make sure that an unconditional locking returns True.
self.assertIs(self.lock.acquire(1), True,
"Unconditional locking did not return True.")
self.assertIs(self.lock.acquire(), True)
def test_uncond_acquire_blocking(self):
#Make sure that unconditional acquiring of a locked lock blocks.
def delay_unlock(to_unlock, delay):
"""Hold on to lock for a set amount of time before unlocking."""
time.sleep(delay)
to_unlock.release()
self.lock.acquire()
start_time = int(time.time())
_thread.start_new_thread(delay_unlock,(self.lock, DELAY))
if support.verbose:
print()
print("*** Waiting for thread to release the lock "\
"(approx. %s sec.) ***" % DELAY)
self.lock.acquire()
end_time = int(time.time())
if support.verbose:
print("done")
self.assertGreaterEqual(end_time - start_time, DELAY,
"Blocking by unconditional acquiring failed.")
@mock.patch('time.sleep')
def test_acquire_timeout(self, mock_sleep):
"""Test invoking acquire() with a positive timeout when the lock is
already acquired. Ensure that time.sleep() is invoked with the given
timeout and that False is returned."""
self.lock.acquire()
retval = self.lock.acquire(waitflag=0, timeout=1)
self.assertTrue(mock_sleep.called)
mock_sleep.assert_called_once_with(1)
self.assertEqual(retval, False)
def test_lock_representation(self):
self.lock.acquire()
self.assertIn("locked", repr(self.lock))
self.lock.release()
self.assertIn("unlocked", repr(self.lock))
class MiscTests(unittest.TestCase):
"""Miscellaneous tests."""
def test_exit(self):
self.assertRaises(SystemExit, _thread.exit)
def test_ident(self):
self.assertIsInstance(_thread.get_ident(), int,
"_thread.get_ident() returned a non-integer")
self.assertGreater(_thread.get_ident(), 0)
def test_LockType(self):
self.assertIsInstance(_thread.allocate_lock(), _thread.LockType,
"_thread.LockType is not an instance of what "
"is returned by _thread.allocate_lock()")
def test_set_sentinel(self):
self.assertIsInstance(_thread._set_sentinel(), _thread.LockType,
"_thread._set_sentinel() did not return a "
"LockType instance.")
def test_interrupt_main(self):
#Calling start_new_thread with a function that executes interrupt_main
# should raise KeyboardInterrupt upon completion.
def call_interrupt():
_thread.interrupt_main()
self.assertRaises(KeyboardInterrupt,
_thread.start_new_thread,
call_interrupt,
tuple())
def test_interrupt_in_main(self):
self.assertRaises(KeyboardInterrupt, _thread.interrupt_main)
def test_stack_size_None(self):
retval = _thread.stack_size(None)
self.assertEqual(retval, 0)
def test_stack_size_not_None(self):
with self.assertRaises(_thread.error) as cm:
_thread.stack_size("")
self.assertEqual(cm.exception.args[0],
"setting thread stack size not supported")
class ThreadTests(unittest.TestCase):
"""Test thread creation."""
def test_arg_passing(self):
#Make sure that parameter passing works.
def arg_tester(queue, arg1=False, arg2=False):
"""Use to test _thread.start_new_thread() passes args properly."""
queue.put((arg1, arg2))
testing_queue = queue.Queue(1)
_thread.start_new_thread(arg_tester, (testing_queue, True, True))
result = testing_queue.get()
self.assertTrue(result[0] and result[1],
"Argument passing for thread creation "
"using tuple failed")
_thread.start_new_thread(
arg_tester,
tuple(),
{'queue':testing_queue, 'arg1':True, 'arg2':True})
result = testing_queue.get()
self.assertTrue(result[0] and result[1],
"Argument passing for thread creation "
"using kwargs failed")
_thread.start_new_thread(
arg_tester,
(testing_queue, True),
{'arg2':True})
result = testing_queue.get()
self.assertTrue(result[0] and result[1],
"Argument passing for thread creation using both tuple"
" and kwargs failed")
def test_multi_thread_creation(self):
def queue_mark(queue, delay):
time.sleep(delay)
queue.put(_thread.get_ident())
thread_count = 5
testing_queue = queue.Queue(thread_count)
if support.verbose:
print()
print("*** Testing multiple thread creation "
"(will take approx. %s to %s sec.) ***" % (
DELAY, thread_count))
for count in range(thread_count):
if DELAY:
local_delay = round(random.random(), 1)
else:
local_delay = 0
_thread.start_new_thread(queue_mark,
(testing_queue, local_delay))
time.sleep(DELAY)
if support.verbose:
print('done')
self.assertEqual(testing_queue.qsize(), thread_count,
"Not all %s threads executed properly "
"after %s sec." % (thread_count, DELAY))
def test_args_not_tuple(self):
"""
Test invoking start_new_thread() with a non-tuple value for "args".
Expect TypeError with a meaningful error message to be raised.
"""
with self.assertRaises(TypeError) as cm:
_thread.start_new_thread(mock.Mock(), [])
self.assertEqual(cm.exception.args[0], "2nd arg must be a tuple")
def test_kwargs_not_dict(self):
"""
Test invoking start_new_thread() with a non-dict value for "kwargs".
Expect TypeError with a meaningful error message to be raised.
"""
with self.assertRaises(TypeError) as cm:
_thread.start_new_thread(mock.Mock(), tuple(), kwargs=[])
self.assertEqual(cm.exception.args[0], "3rd arg must be a dict")
def test_SystemExit(self):
"""
Test invoking start_new_thread() with a function that raises
SystemExit.
The exception should be discarded.
"""
func = mock.Mock(side_effect=SystemExit())
try:
_thread.start_new_thread(func, tuple())
except SystemExit:
self.fail("start_new_thread raised SystemExit.")
@mock.patch('traceback.print_exc')
def test_RaiseException(self, mock_print_exc):
"""
Test invoking start_new_thread() with a function that raises exception.
The exception should be discarded and the traceback should be printed
via traceback.print_exc()
"""
func = mock.Mock(side_effect=Exception)
_thread.start_new_thread(func, tuple())
self.assertTrue(mock_print_exc.called)

View File

@ -1,60 +0,0 @@
from test import support
import unittest
import dummy_threading as _threading
import time
class DummyThreadingTestCase(unittest.TestCase):
class TestThread(_threading.Thread):
def run(self):
global running
global sema
global mutex
# Uncomment if testing another module, such as the real 'threading'
# module.
#delay = random.random() * 2
delay = 0
if support.verbose:
print('task', self.name, 'will run for', delay, 'sec')
sema.acquire()
mutex.acquire()
running += 1
if support.verbose:
print(running, 'tasks are running')
mutex.release()
time.sleep(delay)
if support.verbose:
print('task', self.name, 'done')
mutex.acquire()
running -= 1
if support.verbose:
print(self.name, 'is finished.', running, 'tasks are running')
mutex.release()
sema.release()
def setUp(self):
self.numtasks = 10
global sema
sema = _threading.BoundedSemaphore(value=3)
global mutex
mutex = _threading.RLock()
global running
running = 0
self.threads = []
def test_tasks(self):
for i in range(self.numtasks):
t = self.TestThread(name="<thread %d>"%i)
self.threads.append(t)
t.start()
if support.verbose:
print('waiting for all tasks to complete')
for t in self.threads:
t.join()
if support.verbose:
print('all tasks done')
if __name__ == '__main__':
unittest.main()

View File

@ -12,10 +12,7 @@ from io import StringIO, BytesIO
from itertools import chain from itertools import chain
from random import choice from random import choice
from socket import getfqdn from socket import getfqdn
try: from threading import Thread
from threading import Thread
except ImportError:
from dummy_threading import Thread
import email import email
import email.policy import email.policy

View File

@ -2,15 +2,12 @@ import enum
import inspect import inspect
import pydoc import pydoc
import unittest import unittest
import threading
from collections import OrderedDict from collections import OrderedDict
from enum import Enum, IntEnum, EnumMeta, Flag, IntFlag, unique, auto from enum import Enum, IntEnum, EnumMeta, Flag, IntFlag, unique, auto
from io import StringIO from io import StringIO
from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
from test import support from test import support
try:
import threading
except ImportError:
threading = None
# for pickle tests # for pickle tests
@ -1988,7 +1985,6 @@ class TestFlag(unittest.TestCase):
d = 6 d = 6
self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>') self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
@unittest.skipUnless(threading, 'Threading required for this test.')
@support.reap_threads @support.reap_threads
def test_unique_composite(self): def test_unique_composite(self):
# override __eq__ to be identity only # override __eq__ to be identity only
@ -2339,7 +2335,6 @@ class TestIntFlag(unittest.TestCase):
for f in Open: for f in Open:
self.assertEqual(bool(f.value), bool(f)) self.assertEqual(bool(f.value), bool(f))
@unittest.skipUnless(threading, 'Threading required for this test.')
@support.reap_threads @support.reap_threads
def test_unique_composite(self): def test_unique_composite(self):
# override __eq__ to be identity only # override __eq__ to be identity only

View File

@ -8,14 +8,10 @@ import sys
from test import support from test import support
from test.support import script_helper, is_android, requires_android_level from test.support import script_helper, is_android, requires_android_level
import tempfile import tempfile
import threading
import unittest import unittest
from textwrap import dedent from textwrap import dedent
try:
import threading
HAVE_THREADS = True
except ImportError:
HAVE_THREADS = False
try: try:
import _testcapi import _testcapi
except ImportError: except ImportError:
@ -154,7 +150,6 @@ class FaultHandlerTests(unittest.TestCase):
3, 3,
'Segmentation fault') 'Segmentation fault')
@unittest.skipIf(not HAVE_THREADS, 'need threads')
def test_fatal_error_c_thread(self): def test_fatal_error_c_thread(self):
self.check_fatal_error(""" self.check_fatal_error("""
import faulthandler import faulthandler
@ -231,7 +226,7 @@ class FaultHandlerTests(unittest.TestCase):
2, 2,
'xyz') 'xyz')
@unittest.skipIf(sys.platform.startswith('openbsd') and HAVE_THREADS, @unittest.skipIf(sys.platform.startswith('openbsd'),
"Issue #12868: sigaltstack() doesn't work on " "Issue #12868: sigaltstack() doesn't work on "
"OpenBSD if Python is compiled with pthread") "OpenBSD if Python is compiled with pthread")
@unittest.skipIf(not hasattr(faulthandler, '_stack_overflow'), @unittest.skipIf(not hasattr(faulthandler, '_stack_overflow'),
@ -456,7 +451,6 @@ class FaultHandlerTests(unittest.TestCase):
self.assertEqual(trace, expected) self.assertEqual(trace, expected)
self.assertEqual(exitcode, 0) self.assertEqual(exitcode, 0)
@unittest.skipIf(not HAVE_THREADS, 'need threads')
def check_dump_traceback_threads(self, filename): def check_dump_traceback_threads(self, filename):
""" """
Call explicitly dump_traceback(all_threads=True) and check the output. Call explicitly dump_traceback(all_threads=True) and check the output.

View File

@ -5,6 +5,7 @@ import _imp as imp
import os import os
import signal import signal
import sys import sys
import threading
import time import time
import unittest import unittest
@ -12,7 +13,6 @@ from test.fork_wait import ForkWait
from test.support import (reap_children, get_attribute, from test.support import (reap_children, get_attribute,
import_module, verbose) import_module, verbose)
threading = import_module('threading')
# Skip test if fork does not exist. # Skip test if fork does not exist.
get_attribute(os, 'fork') get_attribute(os, 'fork')

View File

@ -10,6 +10,7 @@ import socket
import io import io
import errno import errno
import os import os
import threading
import time import time
try: try:
import ssl import ssl
@ -19,7 +20,6 @@ except ImportError:
from unittest import TestCase, skipUnless from unittest import TestCase, skipUnless
from test import support from test import support
from test.support import HOST, HOSTv6 from test.support import HOST, HOSTv6
threading = support.import_module('threading')
TIMEOUT = 3 TIMEOUT = 3
# the dummy data returned by server over the data channel when # the dummy data returned by server over the data channel when

View File

@ -8,15 +8,12 @@ import pickle
from random import choice from random import choice
import sys import sys
from test import support from test import support
import threading
import time import time
import unittest import unittest
import unittest.mock import unittest.mock
from weakref import proxy from weakref import proxy
import contextlib import contextlib
try:
import threading
except ImportError:
threading = None
import functools import functools
@ -1406,7 +1403,6 @@ class TestLRU:
for attr in self.module.WRAPPER_ASSIGNMENTS: for attr in self.module.WRAPPER_ASSIGNMENTS:
self.assertEqual(getattr(g, attr), getattr(f, attr)) self.assertEqual(getattr(g, attr), getattr(f, attr))
@unittest.skipUnless(threading, 'This test requires threading.')
def test_lru_cache_threaded(self): def test_lru_cache_threaded(self):
n, m = 5, 11 n, m = 5, 11
def orig(x, y): def orig(x, y):
@ -1455,7 +1451,6 @@ class TestLRU:
finally: finally:
sys.setswitchinterval(orig_si) sys.setswitchinterval(orig_si)
@unittest.skipUnless(threading, 'This test requires threading.')
def test_lru_cache_threaded2(self): def test_lru_cache_threaded2(self):
# Simultaneous call with the same arguments # Simultaneous call with the same arguments
n, m = 5, 7 n, m = 5, 7
@ -1483,7 +1478,6 @@ class TestLRU:
pause.reset() pause.reset()
self.assertEqual(f.cache_info(), (0, (i+1)*n, m*n, i+1)) self.assertEqual(f.cache_info(), (0, (i+1)*n, m*n, i+1))
@unittest.skipUnless(threading, 'This test requires threading.')
def test_lru_cache_threaded3(self): def test_lru_cache_threaded3(self):
@self.module.lru_cache(maxsize=2) @self.module.lru_cache(maxsize=2)
def f(x): def f(x):

View File

@ -8,11 +8,7 @@ import sys
import time import time
import gc import gc
import weakref import weakref
import threading
try:
import threading
except ImportError:
threading = None
try: try:
from _testcapi import with_tp_del from _testcapi import with_tp_del
@ -352,7 +348,6 @@ class GCTests(unittest.TestCase):
v = {1: v, 2: Ouch()} v = {1: v, 2: Ouch()}
gc.disable() gc.disable()
@unittest.skipUnless(threading, "test meaningless on builds without threads")
def test_trashcan_threads(self): def test_trashcan_threads(self):
# Issue #13992: trashcan mechanism should be thread-safe # Issue #13992: trashcan mechanism should be thread-safe
NESTING = 60 NESTING = 60

View File

@ -12,12 +12,6 @@ import sysconfig
import textwrap import textwrap
import unittest import unittest
# Is this Python configured to support threads?
try:
import _thread
except ImportError:
_thread = None
from test import support from test import support
from test.support import run_unittest, findfile, python_is_optimized from test.support import run_unittest, findfile, python_is_optimized
@ -755,8 +749,6 @@ Traceback \(most recent call first\):
foo\(1, 2, 3\) foo\(1, 2, 3\)
''') ''')
@unittest.skipUnless(_thread,
"Python was compiled without thread support")
def test_threads(self): def test_threads(self):
'Verify that "py-bt" indicates threads that are waiting for the GIL' 'Verify that "py-bt" indicates threads that are waiting for the GIL'
cmd = ''' cmd = '''
@ -794,8 +786,6 @@ id(42)
# Some older versions of gdb will fail with # Some older versions of gdb will fail with
# "Cannot find new threads: generic error" # "Cannot find new threads: generic error"
# unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround # unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround
@unittest.skipUnless(_thread,
"Python was compiled without thread support")
def test_gc(self): def test_gc(self):
'Verify that "py-bt" indicates if a thread is garbage-collecting' 'Verify that "py-bt" indicates if a thread is garbage-collecting'
cmd = ('from gc import collect\n' cmd = ('from gc import collect\n'
@ -822,8 +812,6 @@ id(42)
# Some older versions of gdb will fail with # Some older versions of gdb will fail with
# "Cannot find new threads: generic error" # "Cannot find new threads: generic error"
# unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround # unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround
@unittest.skipUnless(_thread,
"Python was compiled without thread support")
def test_pycfunction(self): def test_pycfunction(self):
'Verify that "py-bt" displays invocations of PyCFunction instances' 'Verify that "py-bt" displays invocations of PyCFunction instances'
# Tested function must not be defined with METH_NOARGS or METH_O, # Tested function must not be defined with METH_NOARGS or METH_O,

View File

@ -12,10 +12,7 @@ import hashlib
import itertools import itertools
import os import os
import sys import sys
try: import threading
import threading
except ImportError:
threading = None
import unittest import unittest
import warnings import warnings
from test import support from test import support
@ -738,7 +735,6 @@ class HashLibTestCase(unittest.TestCase):
m = hashlib.md5(b'x' * gil_minsize) m = hashlib.md5(b'x' * gil_minsize)
self.assertEqual(m.hexdigest(), 'cfb767f225d58469c5de3632a8803958') self.assertEqual(m.hexdigest(), 'cfb767f225d58469c5de3632a8803958')
@unittest.skipUnless(threading, 'Threading required for this test.')
@support.reap_threads @support.reap_threads
def test_threaded_hashing(self): def test_threaded_hashing(self):
# Updating the same hash object from several threads at once # Updating the same hash object from several threads at once

View File

@ -22,12 +22,13 @@ import urllib.parse
import tempfile import tempfile
import time import time
import datetime import datetime
import threading
from unittest import mock from unittest import mock
from io import BytesIO from io import BytesIO
import unittest import unittest
from test import support from test import support
threading = support.import_module('threading')
class NoLogRequestHandler: class NoLogRequestHandler:
def log_message(self, *args): def log_message(self, *args):

View File

@ -3,7 +3,6 @@ from test.support import import_module
# Skip test if _thread or _tkinter wasn't built, if idlelib is missing, # Skip test if _thread or _tkinter wasn't built, if idlelib is missing,
# or if tcl/tk is not the 8.5+ needed for ttk widgets. # or if tcl/tk is not the 8.5+ needed for ttk widgets.
import_module('threading') # imported by PyShell, imports _thread
tk = import_module('tkinter') # imports _tkinter tk = import_module('tkinter') # imports _tkinter
if tk.TkVersion < 8.5: if tk.TkVersion < 8.5:
raise unittest.SkipTest("IDLE requires tk 8.5 or later.") raise unittest.SkipTest("IDLE requires tk 8.5 or later.")

View File

@ -1,8 +1,4 @@
from test import support from test import support
# If we end up with a significant number of tests that don't require
# threading, this test module should be split. Right now we skip
# them all if we don't have threading.
threading = support.import_module('threading')
from contextlib import contextmanager from contextlib import contextmanager
import imaplib import imaplib
@ -10,6 +6,7 @@ import os.path
import socketserver import socketserver
import time import time
import calendar import calendar
import threading
from test.support import (reap_threads, verbose, transient_internet, from test.support import (reap_threads, verbose, transient_internet,
run_with_tz, run_with_locale, cpython_only) run_with_tz, run_with_locale, cpython_only)

View File

@ -1,7 +1,3 @@
try:
import _thread
except ImportError:
_thread = None
import importlib import importlib
import importlib.util import importlib.util
import os import os
@ -23,7 +19,6 @@ def requires_load_dynamic(meth):
'imp.load_dynamic() required')(meth) 'imp.load_dynamic() required')(meth)
@unittest.skipIf(_thread is None, '_thread module is required')
class LockTests(unittest.TestCase): class LockTests(unittest.TestCase):
"""Very basic test of import lock functions.""" """Very basic test of import lock functions."""

View File

@ -3,134 +3,112 @@ from . import util as test_util
init = test_util.import_importlib('importlib') init = test_util.import_importlib('importlib')
import sys import sys
import threading
import unittest import unittest
import weakref import weakref
from test import support from test import support
from test import lock_tests
try:
import threading
except ImportError:
threading = None
else:
from test import lock_tests
if threading is not None:
class ModuleLockAsRLockTests:
locktype = classmethod(lambda cls: cls.LockType("some_lock"))
# _is_owned() unsupported
test__is_owned = None
# acquire(blocking=False) unsupported
test_try_acquire = None
test_try_acquire_contended = None
# `with` unsupported
test_with = None
# acquire(timeout=...) unsupported
test_timeout = None
# _release_save() unsupported
test_release_save_unacquired = None
# lock status in repr unsupported
test_repr = None
test_locked_repr = None
LOCK_TYPES = {kind: splitinit._bootstrap._ModuleLock
for kind, splitinit in init.items()}
(Frozen_ModuleLockAsRLockTests,
Source_ModuleLockAsRLockTests
) = test_util.test_both(ModuleLockAsRLockTests, lock_tests.RLockTests,
LockType=LOCK_TYPES)
else:
LOCK_TYPES = {}
class Frozen_ModuleLockAsRLockTests(unittest.TestCase):
pass
class Source_ModuleLockAsRLockTests(unittest.TestCase):
pass
if threading is not None: class ModuleLockAsRLockTests:
class DeadlockAvoidanceTests: locktype = classmethod(lambda cls: cls.LockType("some_lock"))
def setUp(self): # _is_owned() unsupported
test__is_owned = None
# acquire(blocking=False) unsupported
test_try_acquire = None
test_try_acquire_contended = None
# `with` unsupported
test_with = None
# acquire(timeout=...) unsupported
test_timeout = None
# _release_save() unsupported
test_release_save_unacquired = None
# lock status in repr unsupported
test_repr = None
test_locked_repr = None
LOCK_TYPES = {kind: splitinit._bootstrap._ModuleLock
for kind, splitinit in init.items()}
(Frozen_ModuleLockAsRLockTests,
Source_ModuleLockAsRLockTests
) = test_util.test_both(ModuleLockAsRLockTests, lock_tests.RLockTests,
LockType=LOCK_TYPES)
class DeadlockAvoidanceTests:
def setUp(self):
try:
self.old_switchinterval = sys.getswitchinterval()
support.setswitchinterval(0.000001)
except AttributeError:
self.old_switchinterval = None
def tearDown(self):
if self.old_switchinterval is not None:
sys.setswitchinterval(self.old_switchinterval)
def run_deadlock_avoidance_test(self, create_deadlock):
NLOCKS = 10
locks = [self.LockType(str(i)) for i in range(NLOCKS)]
pairs = [(locks[i], locks[(i+1)%NLOCKS]) for i in range(NLOCKS)]
if create_deadlock:
NTHREADS = NLOCKS
else:
NTHREADS = NLOCKS - 1
barrier = threading.Barrier(NTHREADS)
results = []
def _acquire(lock):
"""Try to acquire the lock. Return True on success,
False on deadlock."""
try: try:
self.old_switchinterval = sys.getswitchinterval() lock.acquire()
support.setswitchinterval(0.000001) except self.DeadlockError:
except AttributeError: return False
self.old_switchinterval = None
def tearDown(self):
if self.old_switchinterval is not None:
sys.setswitchinterval(self.old_switchinterval)
def run_deadlock_avoidance_test(self, create_deadlock):
NLOCKS = 10
locks = [self.LockType(str(i)) for i in range(NLOCKS)]
pairs = [(locks[i], locks[(i+1)%NLOCKS]) for i in range(NLOCKS)]
if create_deadlock:
NTHREADS = NLOCKS
else: else:
NTHREADS = NLOCKS - 1 return True
barrier = threading.Barrier(NTHREADS)
results = []
def _acquire(lock): def f():
"""Try to acquire the lock. Return True on success, a, b = pairs.pop()
False on deadlock.""" ra = _acquire(a)
try: barrier.wait()
lock.acquire() rb = _acquire(b)
except self.DeadlockError: results.append((ra, rb))
return False if rb:
else: b.release()
return True if ra:
a.release()
lock_tests.Bunch(f, NTHREADS).wait_for_finished()
self.assertEqual(len(results), NTHREADS)
return results
def f(): def test_deadlock(self):
a, b = pairs.pop() results = self.run_deadlock_avoidance_test(True)
ra = _acquire(a) # At least one of the threads detected a potential deadlock on its
barrier.wait() # second acquire() call. It may be several of them, because the
rb = _acquire(b) # deadlock avoidance mechanism is conservative.
results.append((ra, rb)) nb_deadlocks = results.count((True, False))
if rb: self.assertGreaterEqual(nb_deadlocks, 1)
b.release() self.assertEqual(results.count((True, True)), len(results) - nb_deadlocks)
if ra:
a.release()
lock_tests.Bunch(f, NTHREADS).wait_for_finished()
self.assertEqual(len(results), NTHREADS)
return results
def test_deadlock(self): def test_no_deadlock(self):
results = self.run_deadlock_avoidance_test(True) results = self.run_deadlock_avoidance_test(False)
# At least one of the threads detected a potential deadlock on its self.assertEqual(results.count((True, False)), 0)
# second acquire() call. It may be several of them, because the self.assertEqual(results.count((True, True)), len(results))
# deadlock avoidance mechanism is conservative.
nb_deadlocks = results.count((True, False))
self.assertGreaterEqual(nb_deadlocks, 1)
self.assertEqual(results.count((True, True)), len(results) - nb_deadlocks)
def test_no_deadlock(self):
results = self.run_deadlock_avoidance_test(False)
self.assertEqual(results.count((True, False)), 0)
self.assertEqual(results.count((True, True)), len(results))
DEADLOCK_ERRORS = {kind: splitinit._bootstrap._DeadlockError DEADLOCK_ERRORS = {kind: splitinit._bootstrap._DeadlockError
for kind, splitinit in init.items()} for kind, splitinit in init.items()}
(Frozen_DeadlockAvoidanceTests, (Frozen_DeadlockAvoidanceTests,
Source_DeadlockAvoidanceTests Source_DeadlockAvoidanceTests
) = test_util.test_both(DeadlockAvoidanceTests, ) = test_util.test_both(DeadlockAvoidanceTests,
LockType=LOCK_TYPES, LockType=LOCK_TYPES,
DeadlockError=DEADLOCK_ERRORS) DeadlockError=DEADLOCK_ERRORS)
else:
DEADLOCK_ERRORS = {}
class Frozen_DeadlockAvoidanceTests(unittest.TestCase):
pass
class Source_DeadlockAvoidanceTests(unittest.TestCase):
pass
class LifetimeTests: class LifetimeTests:

View File

@ -28,6 +28,7 @@ import pickle
import random import random
import signal import signal
import sys import sys
import threading
import time import time
import unittest import unittest
import warnings import warnings
@ -40,10 +41,6 @@ from test.support.script_helper import assert_python_ok, run_python_until_end
import codecs import codecs
import io # C implementation of io import io # C implementation of io
import _pyio as pyio # Python implementation of io import _pyio as pyio # Python implementation of io
try:
import threading
except ImportError:
threading = None
try: try:
import ctypes import ctypes
@ -443,8 +440,6 @@ class IOTest(unittest.TestCase):
(self.BytesIO, "rws"), (self.StringIO, "rws"), (self.BytesIO, "rws"), (self.StringIO, "rws"),
) )
for [test, abilities] in tests: for [test, abilities] in tests:
if test is pipe_writer and not threading:
continue # Skip subtest that uses a background thread
with self.subTest(test), test() as obj: with self.subTest(test), test() as obj:
readable = "r" in abilities readable = "r" in abilities
self.assertEqual(obj.readable(), readable) self.assertEqual(obj.readable(), readable)
@ -1337,7 +1332,6 @@ class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
self.assertEqual(b"abcdefg", bufio.read()) self.assertEqual(b"abcdefg", bufio.read())
@unittest.skipUnless(threading, 'Threading required for this test.')
@support.requires_resource('cpu') @support.requires_resource('cpu')
def test_threads(self): def test_threads(self):
try: try:
@ -1664,7 +1658,6 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests):
with self.open(support.TESTFN, "rb", buffering=0) as f: with self.open(support.TESTFN, "rb", buffering=0) as f:
self.assertEqual(f.read(), b"abc") self.assertEqual(f.read(), b"abc")
@unittest.skipUnless(threading, 'Threading required for this test.')
@support.requires_resource('cpu') @support.requires_resource('cpu')
def test_threads(self): def test_threads(self):
try: try:
@ -3053,7 +3046,6 @@ class TextIOWrapperTest(unittest.TestCase):
self.assertEqual(f.errors, "replace") self.assertEqual(f.errors, "replace")
@support.no_tracing @support.no_tracing
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_threads_write(self): def test_threads_write(self):
# Issue6750: concurrent writes could duplicate data # Issue6750: concurrent writes could duplicate data
event = threading.Event() event = threading.Event()
@ -3804,7 +3796,6 @@ class CMiscIOTest(MiscIOTest):
b = bytearray(2) b = bytearray(2)
self.assertRaises(ValueError, bufio.readinto, b) self.assertRaises(ValueError, bufio.readinto, b)
@unittest.skipUnless(threading, 'Threading required for this test.')
def check_daemon_threads_shutdown_deadlock(self, stream_name): def check_daemon_threads_shutdown_deadlock(self, stream_name):
# Issue #23309: deadlocks at shutdown should be avoided when a # Issue #23309: deadlocks at shutdown should be avoided when a
# daemon thread and the main thread both write to a file. # daemon thread and the main thread both write to a file.
@ -3868,7 +3859,6 @@ class SignalsTest(unittest.TestCase):
def alarm_interrupt(self, sig, frame): def alarm_interrupt(self, sig, frame):
1/0 1/0
@unittest.skipUnless(threading, 'Threading required for this test.')
def check_interrupted_write(self, item, bytes, **fdopen_kwargs): def check_interrupted_write(self, item, bytes, **fdopen_kwargs):
"""Check that a partial write, when it gets interrupted, properly """Check that a partial write, when it gets interrupted, properly
invokes the signal handler, and bubbles up the exception raised invokes the signal handler, and bubbles up the exception raised
@ -3990,7 +3980,6 @@ class SignalsTest(unittest.TestCase):
self.check_interrupted_read_retry(lambda x: x, self.check_interrupted_read_retry(lambda x: x,
mode="r") mode="r")
@unittest.skipUnless(threading, 'Threading required for this test.')
def check_interrupted_write_retry(self, item, **fdopen_kwargs): def check_interrupted_write_retry(self, item, **fdopen_kwargs):
"""Check that a buffered write, when it gets interrupted (either """Check that a buffered write, when it gets interrupted (either
returning a partial result or EINTR), properly invokes the signal returning a partial result or EINTR), properly invokes the signal

View File

@ -42,22 +42,19 @@ import tempfile
from test.support.script_helper import assert_python_ok from test.support.script_helper import assert_python_ok
from test import support from test import support
import textwrap import textwrap
import threading
import time import time
import unittest import unittest
import warnings import warnings
import weakref import weakref
try:
import threading import asyncore
# The following imports are needed only for tests which from http.server import HTTPServer, BaseHTTPRequestHandler
# require threading import smtpd
import asyncore from urllib.parse import urlparse, parse_qs
from http.server import HTTPServer, BaseHTTPRequestHandler from socketserver import (ThreadingUDPServer, DatagramRequestHandler,
import smtpd ThreadingTCPServer, StreamRequestHandler)
from urllib.parse import urlparse, parse_qs
from socketserver import (ThreadingUDPServer, DatagramRequestHandler,
ThreadingTCPServer, StreamRequestHandler)
except ImportError:
threading = None
try: try:
import win32evtlog, win32evtlogutil, pywintypes import win32evtlog, win32evtlogutil, pywintypes
except ImportError: except ImportError:
@ -625,7 +622,6 @@ class HandlerTest(BaseTest):
os.unlink(fn) os.unlink(fn)
@unittest.skipIf(os.name == 'nt', 'WatchedFileHandler not appropriate for Windows.') @unittest.skipIf(os.name == 'nt', 'WatchedFileHandler not appropriate for Windows.')
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_race(self): def test_race(self):
# Issue #14632 refers. # Issue #14632 refers.
def remove_loop(fname, tries): def remove_loop(fname, tries):
@ -719,276 +715,274 @@ class StreamHandlerTest(BaseTest):
# -- The following section could be moved into a server_helper.py module # -- The following section could be moved into a server_helper.py module
# -- if it proves to be of wider utility than just test_logging # -- if it proves to be of wider utility than just test_logging
if threading: class TestSMTPServer(smtpd.SMTPServer):
class TestSMTPServer(smtpd.SMTPServer): """
""" This class implements a test SMTP server.
This class implements a test SMTP server.
:param addr: A (host, port) tuple which the server listens on. :param addr: A (host, port) tuple which the server listens on.
You can specify a port value of zero: the server's You can specify a port value of zero: the server's
*port* attribute will hold the actual port number *port* attribute will hold the actual port number
used, which can be used in client connections. used, which can be used in client connections.
:param handler: A callable which will be called to process :param handler: A callable which will be called to process
incoming messages. The handler will be passed incoming messages. The handler will be passed
the client address tuple, who the message is from, the client address tuple, who the message is from,
a list of recipients and the message data. a list of recipients and the message data.
:param poll_interval: The interval, in seconds, used in the underlying
:func:`select` or :func:`poll` call by
:func:`asyncore.loop`.
:param sockmap: A dictionary which will be used to hold
:class:`asyncore.dispatcher` instances used by
:func:`asyncore.loop`. This avoids changing the
:mod:`asyncore` module's global state.
"""
def __init__(self, addr, handler, poll_interval, sockmap):
smtpd.SMTPServer.__init__(self, addr, None, map=sockmap,
decode_data=True)
self.port = self.socket.getsockname()[1]
self._handler = handler
self._thread = None
self.poll_interval = poll_interval
def process_message(self, peer, mailfrom, rcpttos, data):
"""
Delegates to the handler passed in to the server's constructor.
Typically, this will be a test case method.
:param peer: The client (host, port) tuple.
:param mailfrom: The address of the sender.
:param rcpttos: The addresses of the recipients.
:param data: The message.
"""
self._handler(peer, mailfrom, rcpttos, data)
def start(self):
"""
Start the server running on a separate daemon thread.
"""
self._thread = t = threading.Thread(target=self.serve_forever,
args=(self.poll_interval,))
t.setDaemon(True)
t.start()
def serve_forever(self, poll_interval):
"""
Run the :mod:`asyncore` loop until normal termination
conditions arise.
:param poll_interval: The interval, in seconds, used in the underlying :param poll_interval: The interval, in seconds, used in the underlying
:func:`select` or :func:`poll` call by :func:`select` or :func:`poll` call by
:func:`asyncore.loop`. :func:`asyncore.loop`.
:param sockmap: A dictionary which will be used to hold
:class:`asyncore.dispatcher` instances used by
:func:`asyncore.loop`. This avoids changing the
:mod:`asyncore` module's global state.
""" """
try:
asyncore.loop(poll_interval, map=self._map)
except OSError:
# On FreeBSD 8, closing the server repeatably
# raises this error. We swallow it if the
# server has been closed.
if self.connected or self.accepting:
raise
def __init__(self, addr, handler, poll_interval, sockmap): def stop(self, timeout=None):
smtpd.SMTPServer.__init__(self, addr, None, map=sockmap, """
decode_data=True) Stop the thread by closing the server instance.
self.port = self.socket.getsockname()[1] Wait for the server thread to terminate.
self._handler = handler
self._thread = None
self.poll_interval = poll_interval
def process_message(self, peer, mailfrom, rcpttos, data): :param timeout: How long to wait for the server thread
""" to terminate.
Delegates to the handler passed in to the server's constructor. """
self.close()
self._thread.join(timeout)
asyncore.close_all(map=self._map, ignore_all=True)
Typically, this will be a test case method. alive = self._thread.is_alive()
:param peer: The client (host, port) tuple. self._thread = None
:param mailfrom: The address of the sender. if alive:
:param rcpttos: The addresses of the recipients. self.fail("join() timed out")
:param data: The message.
"""
self._handler(peer, mailfrom, rcpttos, data)
def start(self): class ControlMixin(object):
""" """
Start the server running on a separate daemon thread. This mixin is used to start a server on a separate thread, and
""" shut it down programmatically. Request handling is simplified - instead
self._thread = t = threading.Thread(target=self.serve_forever, of needing to derive a suitable RequestHandler subclass, you just
args=(self.poll_interval,)) provide a callable which will be passed each received request to be
t.setDaemon(True) processed.
t.start()
def serve_forever(self, poll_interval): :param handler: A handler callable which will be called with a
""" single parameter - the request - in order to
Run the :mod:`asyncore` loop until normal termination process the request. This handler is called on the
conditions arise. server thread, effectively meaning that requests are
:param poll_interval: The interval, in seconds, used in the underlying processed serially. While not quite Web scale ;-),
:func:`select` or :func:`poll` call by this should be fine for testing applications.
:func:`asyncore.loop`. :param poll_interval: The polling interval in seconds.
""" """
try: def __init__(self, handler, poll_interval):
asyncore.loop(poll_interval, map=self._map) self._thread = None
except OSError: self.poll_interval = poll_interval
# On FreeBSD 8, closing the server repeatably self._handler = handler
# raises this error. We swallow it if the self.ready = threading.Event()
# server has been closed.
if self.connected or self.accepting:
raise
def stop(self, timeout=None): def start(self):
""" """
Stop the thread by closing the server instance. Create a daemon thread to run the server, and start it.
Wait for the server thread to terminate. """
self._thread = t = threading.Thread(target=self.serve_forever,
args=(self.poll_interval,))
t.setDaemon(True)
t.start()
:param timeout: How long to wait for the server thread def serve_forever(self, poll_interval):
to terminate. """
""" Run the server. Set the ready flag before entering the
self.close() service loop.
"""
self.ready.set()
super(ControlMixin, self).serve_forever(poll_interval)
def stop(self, timeout=None):
"""
Tell the server thread to stop, and wait for it to do so.
:param timeout: How long to wait for the server thread
to terminate.
"""
self.shutdown()
if self._thread is not None:
self._thread.join(timeout) self._thread.join(timeout)
asyncore.close_all(map=self._map, ignore_all=True)
alive = self._thread.is_alive() alive = self._thread.is_alive()
self._thread = None self._thread = None
if alive: if alive:
self.fail("join() timed out") self.fail("join() timed out")
self.server_close()
self.ready.clear()
class ControlMixin(object): class TestHTTPServer(ControlMixin, HTTPServer):
""" """
This mixin is used to start a server on a separate thread, and An HTTP server which is controllable using :class:`ControlMixin`.
shut it down programmatically. Request handling is simplified - instead
of needing to derive a suitable RequestHandler subclass, you just
provide a callable which will be passed each received request to be
processed.
:param handler: A handler callable which will be called with a :param addr: A tuple with the IP address and port to listen on.
single parameter - the request - in order to :param handler: A handler callable which will be called with a
process the request. This handler is called on the single parameter - the request - in order to
server thread, effectively meaning that requests are process the request.
processed serially. While not quite Web scale ;-), :param poll_interval: The polling interval in seconds.
this should be fine for testing applications. :param log: Pass ``True`` to enable log messages.
:param poll_interval: The polling interval in seconds. """
""" def __init__(self, addr, handler, poll_interval=0.5,
def __init__(self, handler, poll_interval): log=False, sslctx=None):
self._thread = None class DelegatingHTTPRequestHandler(BaseHTTPRequestHandler):
self.poll_interval = poll_interval def __getattr__(self, name, default=None):
self._handler = handler if name.startswith('do_'):
self.ready = threading.Event() return self.process_request
raise AttributeError(name)
def start(self): def process_request(self):
""" self.server._handler(self)
Create a daemon thread to run the server, and start it.
"""
self._thread = t = threading.Thread(target=self.serve_forever,
args=(self.poll_interval,))
t.setDaemon(True)
t.start()
def serve_forever(self, poll_interval): def log_message(self, format, *args):
""" if log:
Run the server. Set the ready flag before entering the super(DelegatingHTTPRequestHandler,
service loop. self).log_message(format, *args)
""" HTTPServer.__init__(self, addr, DelegatingHTTPRequestHandler)
self.ready.set() ControlMixin.__init__(self, handler, poll_interval)
super(ControlMixin, self).serve_forever(poll_interval) self.sslctx = sslctx
def stop(self, timeout=None): def get_request(self):
""" try:
Tell the server thread to stop, and wait for it to do so. sock, addr = self.socket.accept()
if self.sslctx:
sock = self.sslctx.wrap_socket(sock, server_side=True)
except OSError as e:
# socket errors are silenced by the caller, print them here
sys.stderr.write("Got an error:\n%s\n" % e)
raise
return sock, addr
:param timeout: How long to wait for the server thread class TestTCPServer(ControlMixin, ThreadingTCPServer):
to terminate. """
""" A TCP server which is controllable using :class:`ControlMixin`.
self.shutdown()
if self._thread is not None:
self._thread.join(timeout)
alive = self._thread.is_alive()
self._thread = None
if alive:
self.fail("join() timed out")
self.server_close()
self.ready.clear()
class TestHTTPServer(ControlMixin, HTTPServer): :param addr: A tuple with the IP address and port to listen on.
""" :param handler: A handler callable which will be called with a single
An HTTP server which is controllable using :class:`ControlMixin`. parameter - the request - in order to process the request.
:param poll_interval: The polling interval in seconds.
:bind_and_activate: If True (the default), binds the server and starts it
listening. If False, you need to call
:meth:`server_bind` and :meth:`server_activate` at
some later time before calling :meth:`start`, so that
the server will set up the socket and listen on it.
"""
:param addr: A tuple with the IP address and port to listen on. allow_reuse_address = True
:param handler: A handler callable which will be called with a
single parameter - the request - in order to
process the request.
:param poll_interval: The polling interval in seconds.
:param log: Pass ``True`` to enable log messages.
"""
def __init__(self, addr, handler, poll_interval=0.5,
log=False, sslctx=None):
class DelegatingHTTPRequestHandler(BaseHTTPRequestHandler):
def __getattr__(self, name, default=None):
if name.startswith('do_'):
return self.process_request
raise AttributeError(name)
def process_request(self): def __init__(self, addr, handler, poll_interval=0.5,
self.server._handler(self) bind_and_activate=True):
class DelegatingTCPRequestHandler(StreamRequestHandler):
def log_message(self, format, *args): def handle(self):
if log: self.server._handler(self)
super(DelegatingHTTPRequestHandler, ThreadingTCPServer.__init__(self, addr, DelegatingTCPRequestHandler,
self).log_message(format, *args) bind_and_activate)
HTTPServer.__init__(self, addr, DelegatingHTTPRequestHandler) ControlMixin.__init__(self, handler, poll_interval)
ControlMixin.__init__(self, handler, poll_interval)
self.sslctx = sslctx
def get_request(self): def server_bind(self):
try: super(TestTCPServer, self).server_bind()
sock, addr = self.socket.accept() self.port = self.socket.getsockname()[1]
if self.sslctx:
sock = self.sslctx.wrap_socket(sock, server_side=True)
except OSError as e:
# socket errors are silenced by the caller, print them here
sys.stderr.write("Got an error:\n%s\n" % e)
raise
return sock, addr
class TestTCPServer(ControlMixin, ThreadingTCPServer): class TestUDPServer(ControlMixin, ThreadingUDPServer):
""" """
A TCP server which is controllable using :class:`ControlMixin`. A UDP server which is controllable using :class:`ControlMixin`.
:param addr: A tuple with the IP address and port to listen on. :param addr: A tuple with the IP address and port to listen on.
:param handler: A handler callable which will be called with a single :param handler: A handler callable which will be called with a
parameter - the request - in order to process the request. single parameter - the request - in order to
:param poll_interval: The polling interval in seconds. process the request.
:bind_and_activate: If True (the default), binds the server and starts it :param poll_interval: The polling interval for shutdown requests,
listening. If False, you need to call in seconds.
:meth:`server_bind` and :meth:`server_activate` at :bind_and_activate: If True (the default), binds the server and
some later time before calling :meth:`start`, so that starts it listening. If False, you need to
the server will set up the socket and listen on it. call :meth:`server_bind` and
""" :meth:`server_activate` at some later time
before calling :meth:`start`, so that the server will
set up the socket and listen on it.
"""
def __init__(self, addr, handler, poll_interval=0.5,
bind_and_activate=True):
class DelegatingUDPRequestHandler(DatagramRequestHandler):
allow_reuse_address = True def handle(self):
self.server._handler(self)
def __init__(self, addr, handler, poll_interval=0.5, def finish(self):
bind_and_activate=True): data = self.wfile.getvalue()
class DelegatingTCPRequestHandler(StreamRequestHandler): if data:
try:
super(DelegatingUDPRequestHandler, self).finish()
except OSError:
if not self.server._closed:
raise
def handle(self): ThreadingUDPServer.__init__(self, addr,
self.server._handler(self) DelegatingUDPRequestHandler,
ThreadingTCPServer.__init__(self, addr, DelegatingTCPRequestHandler, bind_and_activate)
bind_and_activate) ControlMixin.__init__(self, handler, poll_interval)
ControlMixin.__init__(self, handler, poll_interval) self._closed = False
def server_bind(self): def server_bind(self):
super(TestTCPServer, self).server_bind() super(TestUDPServer, self).server_bind()
self.port = self.socket.getsockname()[1] self.port = self.socket.getsockname()[1]
class TestUDPServer(ControlMixin, ThreadingUDPServer): def server_close(self):
""" super(TestUDPServer, self).server_close()
A UDP server which is controllable using :class:`ControlMixin`. self._closed = True
:param addr: A tuple with the IP address and port to listen on. if hasattr(socket, "AF_UNIX"):
:param handler: A handler callable which will be called with a class TestUnixStreamServer(TestTCPServer):
single parameter - the request - in order to address_family = socket.AF_UNIX
process the request.
:param poll_interval: The polling interval for shutdown requests,
in seconds.
:bind_and_activate: If True (the default), binds the server and
starts it listening. If False, you need to
call :meth:`server_bind` and
:meth:`server_activate` at some later time
before calling :meth:`start`, so that the server will
set up the socket and listen on it.
"""
def __init__(self, addr, handler, poll_interval=0.5,
bind_and_activate=True):
class DelegatingUDPRequestHandler(DatagramRequestHandler):
def handle(self): class TestUnixDatagramServer(TestUDPServer):
self.server._handler(self) address_family = socket.AF_UNIX
def finish(self):
data = self.wfile.getvalue()
if data:
try:
super(DelegatingUDPRequestHandler, self).finish()
except OSError:
if not self.server._closed:
raise
ThreadingUDPServer.__init__(self, addr,
DelegatingUDPRequestHandler,
bind_and_activate)
ControlMixin.__init__(self, handler, poll_interval)
self._closed = False
def server_bind(self):
super(TestUDPServer, self).server_bind()
self.port = self.socket.getsockname()[1]
def server_close(self):
super(TestUDPServer, self).server_close()
self._closed = True
if hasattr(socket, "AF_UNIX"):
class TestUnixStreamServer(TestTCPServer):
address_family = socket.AF_UNIX
class TestUnixDatagramServer(TestUDPServer):
address_family = socket.AF_UNIX
# - end of server_helper section # - end of server_helper section
@unittest.skipUnless(threading, 'Threading required for this test.')
class SMTPHandlerTest(BaseTest): class SMTPHandlerTest(BaseTest):
TIMEOUT = 8.0 TIMEOUT = 8.0
@ -1472,14 +1466,12 @@ class ConfigFileTest(BaseTest):
@unittest.skipIf(True, "FIXME: bpo-30830") @unittest.skipIf(True, "FIXME: bpo-30830")
@unittest.skipUnless(threading, 'Threading required for this test.')
class SocketHandlerTest(BaseTest): class SocketHandlerTest(BaseTest):
"""Test for SocketHandler objects.""" """Test for SocketHandler objects."""
if threading: server_class = TestTCPServer
server_class = TestTCPServer address = ('localhost', 0)
address = ('localhost', 0)
def setUp(self): def setUp(self):
"""Set up a TCP server to receive log messages, and a SocketHandler """Set up a TCP server to receive log messages, and a SocketHandler
@ -1573,12 +1565,11 @@ def _get_temp_domain_socket():
@unittest.skipIf(True, "FIXME: bpo-30830") @unittest.skipIf(True, "FIXME: bpo-30830")
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
@unittest.skipUnless(threading, 'Threading required for this test.')
class UnixSocketHandlerTest(SocketHandlerTest): class UnixSocketHandlerTest(SocketHandlerTest):
"""Test for SocketHandler with unix sockets.""" """Test for SocketHandler with unix sockets."""
if threading and hasattr(socket, "AF_UNIX"): if hasattr(socket, "AF_UNIX"):
server_class = TestUnixStreamServer server_class = TestUnixStreamServer
def setUp(self): def setUp(self):
@ -1591,14 +1582,12 @@ class UnixSocketHandlerTest(SocketHandlerTest):
support.unlink(self.address) support.unlink(self.address)
@unittest.skipIf(True, "FIXME: bpo-30830") @unittest.skipIf(True, "FIXME: bpo-30830")
@unittest.skipUnless(threading, 'Threading required for this test.')
class DatagramHandlerTest(BaseTest): class DatagramHandlerTest(BaseTest):
"""Test for DatagramHandler.""" """Test for DatagramHandler."""
if threading: server_class = TestUDPServer
server_class = TestUDPServer address = ('localhost', 0)
address = ('localhost', 0)
def setUp(self): def setUp(self):
"""Set up a UDP server to receive log messages, and a DatagramHandler """Set up a UDP server to receive log messages, and a DatagramHandler
@ -1659,12 +1648,11 @@ class DatagramHandlerTest(BaseTest):
@unittest.skipIf(True, "FIXME: bpo-30830") @unittest.skipIf(True, "FIXME: bpo-30830")
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
@unittest.skipUnless(threading, 'Threading required for this test.')
class UnixDatagramHandlerTest(DatagramHandlerTest): class UnixDatagramHandlerTest(DatagramHandlerTest):
"""Test for DatagramHandler using Unix sockets.""" """Test for DatagramHandler using Unix sockets."""
if threading and hasattr(socket, "AF_UNIX"): if hasattr(socket, "AF_UNIX"):
server_class = TestUnixDatagramServer server_class = TestUnixDatagramServer
def setUp(self): def setUp(self):
@ -1676,14 +1664,12 @@ class UnixDatagramHandlerTest(DatagramHandlerTest):
DatagramHandlerTest.tearDown(self) DatagramHandlerTest.tearDown(self)
support.unlink(self.address) support.unlink(self.address)
@unittest.skipUnless(threading, 'Threading required for this test.')
class SysLogHandlerTest(BaseTest): class SysLogHandlerTest(BaseTest):
"""Test for SysLogHandler using UDP.""" """Test for SysLogHandler using UDP."""
if threading: server_class = TestUDPServer
server_class = TestUDPServer address = ('localhost', 0)
address = ('localhost', 0)
def setUp(self): def setUp(self):
"""Set up a UDP server to receive log messages, and a SysLogHandler """Set up a UDP server to receive log messages, and a SysLogHandler
@ -1747,12 +1733,11 @@ class SysLogHandlerTest(BaseTest):
@unittest.skipIf(True, "FIXME: bpo-30830") @unittest.skipIf(True, "FIXME: bpo-30830")
@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
@unittest.skipUnless(threading, 'Threading required for this test.')
class UnixSysLogHandlerTest(SysLogHandlerTest): class UnixSysLogHandlerTest(SysLogHandlerTest):
"""Test for SysLogHandler with Unix sockets.""" """Test for SysLogHandler with Unix sockets."""
if threading and hasattr(socket, "AF_UNIX"): if hasattr(socket, "AF_UNIX"):
server_class = TestUnixDatagramServer server_class = TestUnixDatagramServer
def setUp(self): def setUp(self):
@ -1767,7 +1752,6 @@ class UnixSysLogHandlerTest(SysLogHandlerTest):
@unittest.skipIf(True, "FIXME: bpo-30830") @unittest.skipIf(True, "FIXME: bpo-30830")
@unittest.skipUnless(support.IPV6_ENABLED, @unittest.skipUnless(support.IPV6_ENABLED,
'IPv6 support required for this test.') 'IPv6 support required for this test.')
@unittest.skipUnless(threading, 'Threading required for this test.')
class IPv6SysLogHandlerTest(SysLogHandlerTest): class IPv6SysLogHandlerTest(SysLogHandlerTest):
"""Test for SysLogHandler with IPv6 host.""" """Test for SysLogHandler with IPv6 host."""
@ -1783,7 +1767,6 @@ class IPv6SysLogHandlerTest(SysLogHandlerTest):
self.server_class.address_family = socket.AF_INET self.server_class.address_family = socket.AF_INET
super(IPv6SysLogHandlerTest, self).tearDown() super(IPv6SysLogHandlerTest, self).tearDown()
@unittest.skipUnless(threading, 'Threading required for this test.')
class HTTPHandlerTest(BaseTest): class HTTPHandlerTest(BaseTest):
"""Test for HTTPHandler.""" """Test for HTTPHandler."""
@ -2892,7 +2875,6 @@ class ConfigDictTest(BaseTest):
# listen() uses ConfigSocketReceiver which is based # listen() uses ConfigSocketReceiver which is based
# on socketserver.ThreadingTCPServer # on socketserver.ThreadingTCPServer
@unittest.skipIf(True, "FIXME: bpo-30830") @unittest.skipIf(True, "FIXME: bpo-30830")
@unittest.skipUnless(threading, 'listen() needs threading to work')
def setup_via_listener(self, text, verify=None): def setup_via_listener(self, text, verify=None):
text = text.encode("utf-8") text = text.encode("utf-8")
# Ask for a randomly assigned port (by using port 0) # Ask for a randomly assigned port (by using port 0)
@ -2923,7 +2905,6 @@ class ConfigDictTest(BaseTest):
if t.is_alive(): if t.is_alive():
self.fail("join() timed out") self.fail("join() timed out")
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_listen_config_10_ok(self): def test_listen_config_10_ok(self):
with support.captured_stdout() as output: with support.captured_stdout() as output:
self.setup_via_listener(json.dumps(self.config10)) self.setup_via_listener(json.dumps(self.config10))
@ -2943,7 +2924,6 @@ class ConfigDictTest(BaseTest):
('ERROR', '4'), ('ERROR', '4'),
], stream=output) ], stream=output)
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_listen_config_1_ok(self): def test_listen_config_1_ok(self):
with support.captured_stdout() as output: with support.captured_stdout() as output:
self.setup_via_listener(textwrap.dedent(ConfigFileTest.config1)) self.setup_via_listener(textwrap.dedent(ConfigFileTest.config1))
@ -2958,7 +2938,6 @@ class ConfigDictTest(BaseTest):
# Original logger output is empty. # Original logger output is empty.
self.assert_log_lines([]) self.assert_log_lines([])
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_listen_verify(self): def test_listen_verify(self):
def verify_fail(stuff): def verify_fail(stuff):
@ -3713,9 +3692,8 @@ class LogRecordTest(BaseTest):
def test_optional(self): def test_optional(self):
r = logging.makeLogRecord({}) r = logging.makeLogRecord({})
NOT_NONE = self.assertIsNotNone NOT_NONE = self.assertIsNotNone
if threading: NOT_NONE(r.thread)
NOT_NONE(r.thread) NOT_NONE(r.threadName)
NOT_NONE(r.threadName)
NOT_NONE(r.process) NOT_NONE(r.process)
NOT_NONE(r.processName) NOT_NONE(r.processName)
log_threads = logging.logThreads log_threads = logging.logThreads

View File

@ -6,6 +6,8 @@ import unittest
import functools import functools
import contextlib import contextlib
import os.path import os.path
import threading
from test import support from test import support
from nntplib import NNTP, GroupInfo from nntplib import NNTP, GroupInfo
import nntplib import nntplib
@ -14,10 +16,7 @@ try:
import ssl import ssl
except ImportError: except ImportError:
ssl = None ssl = None
try:
import threading
except ImportError:
threading = None
TIMEOUT = 30 TIMEOUT = 30
certfile = os.path.join(os.path.dirname(__file__), 'keycert3.pem') certfile = os.path.join(os.path.dirname(__file__), 'keycert3.pem')
@ -1520,7 +1519,7 @@ class MockSslTests(MockSocketTests):
def nntp_class(*pos, **kw): def nntp_class(*pos, **kw):
return nntplib.NNTP_SSL(*pos, ssl_context=bypass_context, **kw) return nntplib.NNTP_SSL(*pos, ssl_context=bypass_context, **kw)
@unittest.skipUnless(threading, 'requires multithreading')
class LocalServerTests(unittest.TestCase): class LocalServerTests(unittest.TestCase):
def setUp(self): def setUp(self):
sock = socket.socket() sock = socket.socket()

View File

@ -22,15 +22,13 @@ import stat
import subprocess import subprocess
import sys import sys
import sysconfig import sysconfig
import threading
import time import time
import unittest import unittest
import uuid import uuid
import warnings import warnings
from test import support from test import support
try:
import threading
except ImportError:
threading = None
try: try:
import resource import resource
except ImportError: except ImportError:
@ -2516,92 +2514,90 @@ class ProgramPriorityTests(unittest.TestCase):
raise raise
if threading is not None: class SendfileTestServer(asyncore.dispatcher, threading.Thread):
class SendfileTestServer(asyncore.dispatcher, threading.Thread):
class Handler(asynchat.async_chat): class Handler(asynchat.async_chat):
def __init__(self, conn): def __init__(self, conn):
asynchat.async_chat.__init__(self, conn) asynchat.async_chat.__init__(self, conn)
self.in_buffer = [] self.in_buffer = []
self.closed = False self.closed = False
self.push(b"220 ready\r\n") self.push(b"220 ready\r\n")
def handle_read(self): def handle_read(self):
data = self.recv(4096) data = self.recv(4096)
self.in_buffer.append(data) self.in_buffer.append(data)
def get_data(self): def get_data(self):
return b''.join(self.in_buffer) return b''.join(self.in_buffer)
def handle_close(self): def handle_close(self):
self.close()
self.closed = True
def handle_error(self):
raise
def __init__(self, address):
threading.Thread.__init__(self)
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.bind(address)
self.listen(5)
self.host, self.port = self.socket.getsockname()[:2]
self.handler_instance = None
self._active = False
self._active_lock = threading.Lock()
# --- public API
@property
def running(self):
return self._active
def start(self):
assert not self.running
self.__flag = threading.Event()
threading.Thread.start(self)
self.__flag.wait()
def stop(self):
assert self.running
self._active = False
self.join()
def wait(self):
# wait for handler connection to be closed, then stop the server
while not getattr(self.handler_instance, "closed", False):
time.sleep(0.001)
self.stop()
# --- internals
def run(self):
self._active = True
self.__flag.set()
while self._active and asyncore.socket_map:
self._active_lock.acquire()
asyncore.loop(timeout=0.001, count=1)
self._active_lock.release()
asyncore.close_all()
def handle_accept(self):
conn, addr = self.accept()
self.handler_instance = self.Handler(conn)
def handle_connect(self):
self.close() self.close()
handle_read = handle_connect self.closed = True
def writable(self):
return 0
def handle_error(self): def handle_error(self):
raise raise
def __init__(self, address):
threading.Thread.__init__(self)
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.bind(address)
self.listen(5)
self.host, self.port = self.socket.getsockname()[:2]
self.handler_instance = None
self._active = False
self._active_lock = threading.Lock()
# --- public API
@property
def running(self):
return self._active
def start(self):
assert not self.running
self.__flag = threading.Event()
threading.Thread.start(self)
self.__flag.wait()
def stop(self):
assert self.running
self._active = False
self.join()
def wait(self):
# wait for handler connection to be closed, then stop the server
while not getattr(self.handler_instance, "closed", False):
time.sleep(0.001)
self.stop()
# --- internals
def run(self):
self._active = True
self.__flag.set()
while self._active and asyncore.socket_map:
self._active_lock.acquire()
asyncore.loop(timeout=0.001, count=1)
self._active_lock.release()
asyncore.close_all()
def handle_accept(self):
conn, addr = self.accept()
self.handler_instance = self.Handler(conn)
def handle_connect(self):
self.close()
handle_read = handle_connect
def writable(self):
return 0
def handle_error(self):
raise
@unittest.skipUnless(threading is not None, "test needs threading module")
@unittest.skipUnless(hasattr(os, 'sendfile'), "test needs os.sendfile()") @unittest.skipUnless(hasattr(os, 'sendfile'), "test needs os.sendfile()")
class TestSendfile(unittest.TestCase): class TestSendfile(unittest.TestCase):

View File

@ -1040,9 +1040,6 @@ class PdbTestCase(unittest.TestCase):
# invoking "continue" on a non-main thread triggered an exception # invoking "continue" on a non-main thread triggered an exception
# inside signal.signal # inside signal.signal
# raises SkipTest if python was built without threads
support.import_module('threading')
with open(support.TESTFN, 'wb') as f: with open(support.TESTFN, 'wb') as f:
f.write(textwrap.dedent(""" f.write(textwrap.dedent("""
import threading import threading

View File

@ -4,10 +4,7 @@ import os
import subprocess import subprocess
import random import random
import select import select
try: import threading
import threading
except ImportError:
threading = None
import time import time
import unittest import unittest
from test.support import TESTFN, run_unittest, reap_threads, cpython_only from test.support import TESTFN, run_unittest, reap_threads, cpython_only
@ -179,7 +176,6 @@ class PollTests(unittest.TestCase):
self.assertRaises(OverflowError, pollster.poll, INT_MAX + 1) self.assertRaises(OverflowError, pollster.poll, INT_MAX + 1)
self.assertRaises(OverflowError, pollster.poll, UINT_MAX + 1) self.assertRaises(OverflowError, pollster.poll, UINT_MAX + 1)
@unittest.skipUnless(threading, 'Threading required for this test.')
@reap_threads @reap_threads
def test_threaded_poll(self): def test_threaded_poll(self):
r, w = os.pipe() r, w = os.pipe()

View File

@ -9,10 +9,10 @@ import asynchat
import socket import socket
import os import os
import errno import errno
import threading
from unittest import TestCase, skipUnless from unittest import TestCase, skipUnless
from test import support as test_support from test import support as test_support
threading = test_support.import_module('threading')
HOST = test_support.HOST HOST = test_support.HOST
PORT = 0 PORT = 0

View File

@ -20,6 +20,7 @@ import urllib.parse
import xml.etree import xml.etree
import xml.etree.ElementTree import xml.etree.ElementTree
import textwrap import textwrap
import threading
from io import StringIO from io import StringIO
from collections import namedtuple from collections import namedtuple
from test.support.script_helper import assert_python_ok from test.support.script_helper import assert_python_ok
@ -30,10 +31,6 @@ from test.support import (
) )
from test import pydoc_mod from test import pydoc_mod
try:
import threading
except ImportError:
threading = None
class nonascii: class nonascii:
'Це не латиниця' 'Це не латиниця'
@ -902,7 +899,6 @@ class TestDescriptions(unittest.TestCase):
"stat(path, *, dir_fd=None, follow_symlinks=True)") "stat(path, *, dir_fd=None, follow_symlinks=True)")
@unittest.skipUnless(threading, 'Threading required for this test.')
class PydocServerTest(unittest.TestCase): class PydocServerTest(unittest.TestCase):
"""Tests for pydoc._start_server""" """Tests for pydoc._start_server"""

View File

@ -1,10 +1,11 @@
# Some simple queue module tests, plus some failure conditions # Some simple queue module tests, plus some failure conditions
# to ensure the Queue locks remain stable. # to ensure the Queue locks remain stable.
import queue import queue
import threading
import time import time
import unittest import unittest
from test import support from test import support
threading = support.import_module('threading')
QUEUE_SIZE = 5 QUEUE_SIZE = 5

View File

@ -15,6 +15,7 @@ import sys
import sysconfig import sysconfig
import tempfile import tempfile
import textwrap import textwrap
import threading
import unittest import unittest
from test import libregrtest from test import libregrtest
from test import support from test import support
@ -741,12 +742,7 @@ class ArgsTestCase(BaseTestCase):
code = TEST_INTERRUPTED code = TEST_INTERRUPTED
test = self.create_test("sigint", code=code) test = self.create_test("sigint", code=code)
try: for multiprocessing in (False, True):
import threading
tests = (False, True)
except ImportError:
tests = (False,)
for multiprocessing in tests:
if multiprocessing: if multiprocessing:
args = ("--slowest", "-j2", test) args = ("--slowest", "-j2", test)
else: else:

View File

@ -1,14 +1,11 @@
import io import io
import os import os
import threading
import unittest import unittest
import urllib.robotparser import urllib.robotparser
from collections import namedtuple from collections import namedtuple
from test import support from test import support
from http.server import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
try:
import threading
except ImportError:
threading = None
class BaseRobotTest: class BaseRobotTest:
@ -255,7 +252,6 @@ class RobotHandler(BaseHTTPRequestHandler):
pass pass
@unittest.skipUnless(threading, 'threading required for this test')
class PasswordProtectedSiteTestCase(unittest.TestCase): class PasswordProtectedSiteTestCase(unittest.TestCase):
def setUp(self): def setUp(self):

View File

@ -1,11 +1,9 @@
import queue import queue
import sched import sched
import threading
import time import time
import unittest import unittest
try:
import threading
except ImportError:
threading = None
TIMEOUT = 10 TIMEOUT = 10
@ -58,7 +56,6 @@ class TestCase(unittest.TestCase):
scheduler.run() scheduler.run()
self.assertEqual(l, [0.01, 0.02, 0.03, 0.04, 0.05]) self.assertEqual(l, [0.01, 0.02, 0.03, 0.04, 0.05])
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_enter_concurrent(self): def test_enter_concurrent(self):
q = queue.Queue() q = queue.Queue()
fun = q.put fun = q.put
@ -113,7 +110,6 @@ class TestCase(unittest.TestCase):
scheduler.run() scheduler.run()
self.assertEqual(l, [0.02, 0.03, 0.04]) self.assertEqual(l, [0.02, 0.03, 0.04])
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_cancel_concurrent(self): def test_cancel_concurrent(self):
q = queue.Queue() q = queue.Queue()
fun = q.put fun = q.put

View File

@ -5,14 +5,11 @@ import socket
import statistics import statistics
import subprocess import subprocess
import sys import sys
import threading
import time import time
import unittest import unittest
from test import support from test import support
from test.support.script_helper import assert_python_ok, spawn_python from test.support.script_helper import assert_python_ok, spawn_python
try:
import threading
except ImportError:
threading = None
try: try:
import _testcapi import _testcapi
except ImportError: except ImportError:
@ -21,7 +18,6 @@ except ImportError:
class GenericTests(unittest.TestCase): class GenericTests(unittest.TestCase):
@unittest.skipIf(threading is None, "test needs threading module")
def test_enums(self): def test_enums(self):
for name in dir(signal): for name in dir(signal):
sig = getattr(signal, name) sig = getattr(signal, name)
@ -807,7 +803,6 @@ class PendingSignalsTests(unittest.TestCase):
'need signal.sigwait()') 'need signal.sigwait()')
@unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
'need signal.pthread_sigmask()') 'need signal.pthread_sigmask()')
@unittest.skipIf(threading is None, "test needs threading module")
def test_sigwait_thread(self): def test_sigwait_thread(self):
# Check that calling sigwait() from a thread doesn't suspend the whole # Check that calling sigwait() from a thread doesn't suspend the whole
# process. A new interpreter is spawned to avoid problems when mixing # process. A new interpreter is spawned to avoid problems when mixing

View File

@ -15,14 +15,11 @@ import time
import select import select
import errno import errno
import textwrap import textwrap
import threading
import unittest import unittest
from test import support, mock_socket from test import support, mock_socket
try:
import threading
except ImportError:
threading = None
HOST = support.HOST HOST = support.HOST
@ -191,7 +188,6 @@ MSG_END = '------------ END MESSAGE ------------\n'
# test server times out, causing the test to fail. # test server times out, causing the test to fail.
# Test behavior of smtpd.DebuggingServer # Test behavior of smtpd.DebuggingServer
@unittest.skipUnless(threading, 'Threading required for this test.')
class DebuggingServerTests(unittest.TestCase): class DebuggingServerTests(unittest.TestCase):
maxDiff = None maxDiff = None
@ -570,7 +566,6 @@ class NonConnectingTests(unittest.TestCase):
# test response of client to a non-successful HELO message # test response of client to a non-successful HELO message
@unittest.skipUnless(threading, 'Threading required for this test.')
class BadHELOServerTests(unittest.TestCase): class BadHELOServerTests(unittest.TestCase):
def setUp(self): def setUp(self):
@ -590,7 +585,6 @@ class BadHELOServerTests(unittest.TestCase):
HOST, self.port, 'localhost', 3) HOST, self.port, 'localhost', 3)
@unittest.skipUnless(threading, 'Threading required for this test.')
class TooLongLineTests(unittest.TestCase): class TooLongLineTests(unittest.TestCase):
respdata = b'250 OK' + (b'.' * smtplib._MAXLINE * 2) + b'\n' respdata = b'250 OK' + (b'.' * smtplib._MAXLINE * 2) + b'\n'
@ -835,7 +829,6 @@ class SimSMTPServer(smtpd.SMTPServer):
# Test various SMTP & ESMTP commands/behaviors that require a simulated server # Test various SMTP & ESMTP commands/behaviors that require a simulated server
# (i.e., something with more features than DebuggingServer) # (i.e., something with more features than DebuggingServer)
@unittest.skipUnless(threading, 'Threading required for this test.')
class SMTPSimTests(unittest.TestCase): class SMTPSimTests(unittest.TestCase):
def setUp(self): def setUp(self):
@ -1091,7 +1084,6 @@ class SimSMTPUTF8Server(SimSMTPServer):
self.last_rcpt_options = rcpt_options self.last_rcpt_options = rcpt_options
@unittest.skipUnless(threading, 'Threading required for this test.')
class SMTPUTF8SimTests(unittest.TestCase): class SMTPUTF8SimTests(unittest.TestCase):
maxDiff = None maxDiff = None
@ -1227,7 +1219,6 @@ class SimSMTPAUTHInitialResponseServer(SimSMTPServer):
channel_class = SimSMTPAUTHInitialResponseChannel channel_class = SimSMTPAUTHInitialResponseChannel
@unittest.skipUnless(threading, 'Threading required for this test.')
class SMTPAUTHInitialResponseSimTests(unittest.TestCase): class SMTPAUTHInitialResponseSimTests(unittest.TestCase):
def setUp(self): def setUp(self):
self.real_getfqdn = socket.getfqdn self.real_getfqdn = socket.getfqdn

View File

@ -21,6 +21,8 @@ import pickle
import struct import struct
import random import random
import string import string
import _thread as thread
import threading
try: try:
import multiprocessing import multiprocessing
except ImportError: except ImportError:
@ -35,12 +37,6 @@ MSG = 'Michael Gilfix was here\u1234\r\n'.encode('utf-8') ## test unicode string
VSOCKPORT = 1234 VSOCKPORT = 1234
try:
import _thread as thread
import threading
except ImportError:
thread = None
threading = None
try: try:
import _socket import _socket
except ImportError: except ImportError:
@ -143,18 +139,17 @@ class ThreadSafeCleanupTestCase(unittest.TestCase):
with a recursive lock. with a recursive lock.
""" """
if threading: def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)
super().__init__(*args, **kwargs) self._cleanup_lock = threading.RLock()
self._cleanup_lock = threading.RLock()
def addCleanup(self, *args, **kwargs): def addCleanup(self, *args, **kwargs):
with self._cleanup_lock: with self._cleanup_lock:
return super().addCleanup(*args, **kwargs) return super().addCleanup(*args, **kwargs)
def doCleanups(self, *args, **kwargs): def doCleanups(self, *args, **kwargs):
with self._cleanup_lock: with self._cleanup_lock:
return super().doCleanups(*args, **kwargs) return super().doCleanups(*args, **kwargs)
class SocketCANTest(unittest.TestCase): class SocketCANTest(unittest.TestCase):
@ -407,7 +402,6 @@ class ThreadedRDSSocketTest(SocketRDSTest, ThreadableTest):
ThreadableTest.clientTearDown(self) ThreadableTest.clientTearDown(self)
@unittest.skipIf(fcntl is None, "need fcntl") @unittest.skipIf(fcntl is None, "need fcntl")
@unittest.skipUnless(thread, 'Threading required for this test.')
@unittest.skipUnless(HAVE_SOCKET_VSOCK, @unittest.skipUnless(HAVE_SOCKET_VSOCK,
'VSOCK sockets required for this test.') 'VSOCK sockets required for this test.')
@unittest.skipUnless(get_cid() != 2, @unittest.skipUnless(get_cid() != 2,
@ -1684,7 +1678,6 @@ class BasicCANTest(unittest.TestCase):
@unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.') @unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.')
@unittest.skipUnless(thread, 'Threading required for this test.')
class CANTest(ThreadedCANSocketTest): class CANTest(ThreadedCANSocketTest):
def __init__(self, methodName='runTest'): def __init__(self, methodName='runTest'):
@ -1838,7 +1831,6 @@ class BasicRDSTest(unittest.TestCase):
@unittest.skipUnless(HAVE_SOCKET_RDS, 'RDS sockets required for this test.') @unittest.skipUnless(HAVE_SOCKET_RDS, 'RDS sockets required for this test.')
@unittest.skipUnless(thread, 'Threading required for this test.')
class RDSTest(ThreadedRDSSocketTest): class RDSTest(ThreadedRDSSocketTest):
def __init__(self, methodName='runTest'): def __init__(self, methodName='runTest'):
@ -1977,7 +1969,7 @@ class BasicVSOCKTest(unittest.TestCase):
s.getsockopt(socket.AF_VSOCK, s.getsockopt(socket.AF_VSOCK,
socket.SO_VM_SOCKETS_BUFFER_MIN_SIZE)) socket.SO_VM_SOCKETS_BUFFER_MIN_SIZE))
@unittest.skipUnless(thread, 'Threading required for this test.')
class BasicTCPTest(SocketConnectedTest): class BasicTCPTest(SocketConnectedTest):
def __init__(self, methodName='runTest'): def __init__(self, methodName='runTest'):
@ -2100,7 +2092,7 @@ class BasicTCPTest(SocketConnectedTest):
def _testDetach(self): def _testDetach(self):
self.serv_conn.send(MSG) self.serv_conn.send(MSG)
@unittest.skipUnless(thread, 'Threading required for this test.')
class BasicUDPTest(ThreadedUDPSocketTest): class BasicUDPTest(ThreadedUDPSocketTest):
def __init__(self, methodName='runTest'): def __init__(self, methodName='runTest'):
@ -3697,17 +3689,14 @@ class SendrecvmsgUDPTestBase(SendrecvmsgDgramFlagsBase,
pass pass
@requireAttrs(socket.socket, "sendmsg") @requireAttrs(socket.socket, "sendmsg")
@unittest.skipUnless(thread, 'Threading required for this test.')
class SendmsgUDPTest(SendmsgConnectionlessTests, SendrecvmsgUDPTestBase): class SendmsgUDPTest(SendmsgConnectionlessTests, SendrecvmsgUDPTestBase):
pass pass
@requireAttrs(socket.socket, "recvmsg") @requireAttrs(socket.socket, "recvmsg")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgUDPTest(RecvmsgTests, SendrecvmsgUDPTestBase): class RecvmsgUDPTest(RecvmsgTests, SendrecvmsgUDPTestBase):
pass pass
@requireAttrs(socket.socket, "recvmsg_into") @requireAttrs(socket.socket, "recvmsg_into")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgIntoUDPTest(RecvmsgIntoTests, SendrecvmsgUDPTestBase): class RecvmsgIntoUDPTest(RecvmsgIntoTests, SendrecvmsgUDPTestBase):
pass pass
@ -3724,21 +3713,18 @@ class SendrecvmsgUDP6TestBase(SendrecvmsgDgramFlagsBase,
@requireAttrs(socket.socket, "sendmsg") @requireAttrs(socket.socket, "sendmsg")
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
@requireSocket("AF_INET6", "SOCK_DGRAM") @requireSocket("AF_INET6", "SOCK_DGRAM")
@unittest.skipUnless(thread, 'Threading required for this test.')
class SendmsgUDP6Test(SendmsgConnectionlessTests, SendrecvmsgUDP6TestBase): class SendmsgUDP6Test(SendmsgConnectionlessTests, SendrecvmsgUDP6TestBase):
pass pass
@requireAttrs(socket.socket, "recvmsg") @requireAttrs(socket.socket, "recvmsg")
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
@requireSocket("AF_INET6", "SOCK_DGRAM") @requireSocket("AF_INET6", "SOCK_DGRAM")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgUDP6Test(RecvmsgTests, SendrecvmsgUDP6TestBase): class RecvmsgUDP6Test(RecvmsgTests, SendrecvmsgUDP6TestBase):
pass pass
@requireAttrs(socket.socket, "recvmsg_into") @requireAttrs(socket.socket, "recvmsg_into")
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
@requireSocket("AF_INET6", "SOCK_DGRAM") @requireSocket("AF_INET6", "SOCK_DGRAM")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgIntoUDP6Test(RecvmsgIntoTests, SendrecvmsgUDP6TestBase): class RecvmsgIntoUDP6Test(RecvmsgIntoTests, SendrecvmsgUDP6TestBase):
pass pass
@ -3746,7 +3732,6 @@ class RecvmsgIntoUDP6Test(RecvmsgIntoTests, SendrecvmsgUDP6TestBase):
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
@requireAttrs(socket, "IPPROTO_IPV6") @requireAttrs(socket, "IPPROTO_IPV6")
@requireSocket("AF_INET6", "SOCK_DGRAM") @requireSocket("AF_INET6", "SOCK_DGRAM")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgRFC3542AncillaryUDP6Test(RFC3542AncillaryTest, class RecvmsgRFC3542AncillaryUDP6Test(RFC3542AncillaryTest,
SendrecvmsgUDP6TestBase): SendrecvmsgUDP6TestBase):
pass pass
@ -3755,7 +3740,6 @@ class RecvmsgRFC3542AncillaryUDP6Test(RFC3542AncillaryTest,
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
@requireAttrs(socket, "IPPROTO_IPV6") @requireAttrs(socket, "IPPROTO_IPV6")
@requireSocket("AF_INET6", "SOCK_DGRAM") @requireSocket("AF_INET6", "SOCK_DGRAM")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgIntoRFC3542AncillaryUDP6Test(RecvmsgIntoMixin, class RecvmsgIntoRFC3542AncillaryUDP6Test(RecvmsgIntoMixin,
RFC3542AncillaryTest, RFC3542AncillaryTest,
SendrecvmsgUDP6TestBase): SendrecvmsgUDP6TestBase):
@ -3767,18 +3751,15 @@ class SendrecvmsgTCPTestBase(SendrecvmsgConnectedBase,
pass pass
@requireAttrs(socket.socket, "sendmsg") @requireAttrs(socket.socket, "sendmsg")
@unittest.skipUnless(thread, 'Threading required for this test.')
class SendmsgTCPTest(SendmsgStreamTests, SendrecvmsgTCPTestBase): class SendmsgTCPTest(SendmsgStreamTests, SendrecvmsgTCPTestBase):
pass pass
@requireAttrs(socket.socket, "recvmsg") @requireAttrs(socket.socket, "recvmsg")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgTCPTest(RecvmsgTests, RecvmsgGenericStreamTests, class RecvmsgTCPTest(RecvmsgTests, RecvmsgGenericStreamTests,
SendrecvmsgTCPTestBase): SendrecvmsgTCPTestBase):
pass pass
@requireAttrs(socket.socket, "recvmsg_into") @requireAttrs(socket.socket, "recvmsg_into")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgIntoTCPTest(RecvmsgIntoTests, RecvmsgGenericStreamTests, class RecvmsgIntoTCPTest(RecvmsgIntoTests, RecvmsgGenericStreamTests,
SendrecvmsgTCPTestBase): SendrecvmsgTCPTestBase):
pass pass
@ -3791,13 +3772,11 @@ class SendrecvmsgSCTPStreamTestBase(SendrecvmsgSCTPFlagsBase,
@requireAttrs(socket.socket, "sendmsg") @requireAttrs(socket.socket, "sendmsg")
@requireSocket("AF_INET", "SOCK_STREAM", "IPPROTO_SCTP") @requireSocket("AF_INET", "SOCK_STREAM", "IPPROTO_SCTP")
@unittest.skipUnless(thread, 'Threading required for this test.')
class SendmsgSCTPStreamTest(SendmsgStreamTests, SendrecvmsgSCTPStreamTestBase): class SendmsgSCTPStreamTest(SendmsgStreamTests, SendrecvmsgSCTPStreamTestBase):
pass pass
@requireAttrs(socket.socket, "recvmsg") @requireAttrs(socket.socket, "recvmsg")
@requireSocket("AF_INET", "SOCK_STREAM", "IPPROTO_SCTP") @requireSocket("AF_INET", "SOCK_STREAM", "IPPROTO_SCTP")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgSCTPStreamTest(RecvmsgTests, RecvmsgGenericStreamTests, class RecvmsgSCTPStreamTest(RecvmsgTests, RecvmsgGenericStreamTests,
SendrecvmsgSCTPStreamTestBase): SendrecvmsgSCTPStreamTestBase):
@ -3811,7 +3790,6 @@ class RecvmsgSCTPStreamTest(RecvmsgTests, RecvmsgGenericStreamTests,
@requireAttrs(socket.socket, "recvmsg_into") @requireAttrs(socket.socket, "recvmsg_into")
@requireSocket("AF_INET", "SOCK_STREAM", "IPPROTO_SCTP") @requireSocket("AF_INET", "SOCK_STREAM", "IPPROTO_SCTP")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgIntoSCTPStreamTest(RecvmsgIntoTests, RecvmsgGenericStreamTests, class RecvmsgIntoSCTPStreamTest(RecvmsgIntoTests, RecvmsgGenericStreamTests,
SendrecvmsgSCTPStreamTestBase): SendrecvmsgSCTPStreamTestBase):
@ -3830,33 +3808,28 @@ class SendrecvmsgUnixStreamTestBase(SendrecvmsgConnectedBase,
@requireAttrs(socket.socket, "sendmsg") @requireAttrs(socket.socket, "sendmsg")
@requireAttrs(socket, "AF_UNIX") @requireAttrs(socket, "AF_UNIX")
@unittest.skipUnless(thread, 'Threading required for this test.')
class SendmsgUnixStreamTest(SendmsgStreamTests, SendrecvmsgUnixStreamTestBase): class SendmsgUnixStreamTest(SendmsgStreamTests, SendrecvmsgUnixStreamTestBase):
pass pass
@requireAttrs(socket.socket, "recvmsg") @requireAttrs(socket.socket, "recvmsg")
@requireAttrs(socket, "AF_UNIX") @requireAttrs(socket, "AF_UNIX")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgUnixStreamTest(RecvmsgTests, RecvmsgGenericStreamTests, class RecvmsgUnixStreamTest(RecvmsgTests, RecvmsgGenericStreamTests,
SendrecvmsgUnixStreamTestBase): SendrecvmsgUnixStreamTestBase):
pass pass
@requireAttrs(socket.socket, "recvmsg_into") @requireAttrs(socket.socket, "recvmsg_into")
@requireAttrs(socket, "AF_UNIX") @requireAttrs(socket, "AF_UNIX")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgIntoUnixStreamTest(RecvmsgIntoTests, RecvmsgGenericStreamTests, class RecvmsgIntoUnixStreamTest(RecvmsgIntoTests, RecvmsgGenericStreamTests,
SendrecvmsgUnixStreamTestBase): SendrecvmsgUnixStreamTestBase):
pass pass
@requireAttrs(socket.socket, "sendmsg", "recvmsg") @requireAttrs(socket.socket, "sendmsg", "recvmsg")
@requireAttrs(socket, "AF_UNIX", "SOL_SOCKET", "SCM_RIGHTS") @requireAttrs(socket, "AF_UNIX", "SOL_SOCKET", "SCM_RIGHTS")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgSCMRightsStreamTest(SCMRightsTest, SendrecvmsgUnixStreamTestBase): class RecvmsgSCMRightsStreamTest(SCMRightsTest, SendrecvmsgUnixStreamTestBase):
pass pass
@requireAttrs(socket.socket, "sendmsg", "recvmsg_into") @requireAttrs(socket.socket, "sendmsg", "recvmsg_into")
@requireAttrs(socket, "AF_UNIX", "SOL_SOCKET", "SCM_RIGHTS") @requireAttrs(socket, "AF_UNIX", "SOL_SOCKET", "SCM_RIGHTS")
@unittest.skipUnless(thread, 'Threading required for this test.')
class RecvmsgIntoSCMRightsStreamTest(RecvmsgIntoMixin, SCMRightsTest, class RecvmsgIntoSCMRightsStreamTest(RecvmsgIntoMixin, SCMRightsTest,
SendrecvmsgUnixStreamTestBase): SendrecvmsgUnixStreamTestBase):
pass pass
@ -3944,7 +3917,6 @@ class InterruptedRecvTimeoutTest(InterruptedTimeoutBase, UDPTestBase):
@requireAttrs(signal, "siginterrupt") @requireAttrs(signal, "siginterrupt")
@unittest.skipUnless(hasattr(signal, "alarm") or hasattr(signal, "setitimer"), @unittest.skipUnless(hasattr(signal, "alarm") or hasattr(signal, "setitimer"),
"Don't have signal.alarm or signal.setitimer") "Don't have signal.alarm or signal.setitimer")
@unittest.skipUnless(thread, 'Threading required for this test.')
class InterruptedSendTimeoutTest(InterruptedTimeoutBase, class InterruptedSendTimeoutTest(InterruptedTimeoutBase,
ThreadSafeCleanupTestCase, ThreadSafeCleanupTestCase,
SocketListeningTestMixin, TCPTestBase): SocketListeningTestMixin, TCPTestBase):
@ -3997,7 +3969,6 @@ class InterruptedSendTimeoutTest(InterruptedTimeoutBase,
self.checkInterruptedSend(self.serv_conn.sendmsg, [b"a"*512]) self.checkInterruptedSend(self.serv_conn.sendmsg, [b"a"*512])
@unittest.skipUnless(thread, 'Threading required for this test.')
class TCPCloserTest(ThreadedTCPSocketTest): class TCPCloserTest(ThreadedTCPSocketTest):
def testClose(self): def testClose(self):
@ -4017,7 +3988,7 @@ class TCPCloserTest(ThreadedTCPSocketTest):
self.cli.connect((HOST, self.port)) self.cli.connect((HOST, self.port))
time.sleep(1.0) time.sleep(1.0)
@unittest.skipUnless(thread, 'Threading required for this test.')
class BasicSocketPairTest(SocketPairTest): class BasicSocketPairTest(SocketPairTest):
def __init__(self, methodName='runTest'): def __init__(self, methodName='runTest'):
@ -4052,7 +4023,7 @@ class BasicSocketPairTest(SocketPairTest):
msg = self.cli.recv(1024) msg = self.cli.recv(1024)
self.assertEqual(msg, MSG) self.assertEqual(msg, MSG)
@unittest.skipUnless(thread, 'Threading required for this test.')
class NonBlockingTCPTests(ThreadedTCPSocketTest): class NonBlockingTCPTests(ThreadedTCPSocketTest):
def __init__(self, methodName='runTest'): def __init__(self, methodName='runTest'):
@ -4180,7 +4151,7 @@ class NonBlockingTCPTests(ThreadedTCPSocketTest):
time.sleep(0.1) time.sleep(0.1)
self.cli.send(MSG) self.cli.send(MSG)
@unittest.skipUnless(thread, 'Threading required for this test.')
class FileObjectClassTestCase(SocketConnectedTest): class FileObjectClassTestCase(SocketConnectedTest):
"""Unit tests for the object returned by socket.makefile() """Unit tests for the object returned by socket.makefile()
@ -4564,7 +4535,6 @@ class NetworkConnectionNoServer(unittest.TestCase):
socket.create_connection((HOST, 1234)) socket.create_connection((HOST, 1234))
@unittest.skipUnless(thread, 'Threading required for this test.')
class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest): class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest):
def __init__(self, methodName='runTest'): def __init__(self, methodName='runTest'):
@ -4633,7 +4603,7 @@ class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest):
self.addCleanup(self.cli.close) self.addCleanup(self.cli.close)
self.assertEqual(self.cli.gettimeout(), 30) self.assertEqual(self.cli.gettimeout(), 30)
@unittest.skipUnless(thread, 'Threading required for this test.')
class NetworkConnectionBehaviourTest(SocketTCPTest, ThreadableTest): class NetworkConnectionBehaviourTest(SocketTCPTest, ThreadableTest):
def __init__(self, methodName='runTest'): def __init__(self, methodName='runTest'):
@ -4877,7 +4847,7 @@ class TestUnixDomain(unittest.TestCase):
self.addCleanup(support.unlink, path) self.addCleanup(support.unlink, path)
self.assertEqual(self.sock.getsockname(), path) self.assertEqual(self.sock.getsockname(), path)
@unittest.skipUnless(thread, 'Threading required for this test.')
class BufferIOTest(SocketConnectedTest): class BufferIOTest(SocketConnectedTest):
""" """
Test the buffer versions of socket.recv() and socket.send(). Test the buffer versions of socket.recv() and socket.send().
@ -5050,7 +5020,6 @@ class TIPCThreadableTest(unittest.TestCase, ThreadableTest):
self.cli.close() self.cli.close()
@unittest.skipUnless(thread, 'Threading required for this test.')
class ContextManagersTest(ThreadedTCPSocketTest): class ContextManagersTest(ThreadedTCPSocketTest):
def _testSocketClass(self): def _testSocketClass(self):
@ -5312,7 +5281,6 @@ class TestSocketSharing(SocketTCPTest):
source.close() source.close()
@unittest.skipUnless(thread, 'Threading required for this test.')
class SendfileUsingSendTest(ThreadedTCPSocketTest): class SendfileUsingSendTest(ThreadedTCPSocketTest):
""" """
Test the send() implementation of socket.sendfile(). Test the send() implementation of socket.sendfile().
@ -5570,7 +5538,6 @@ class SendfileUsingSendTest(ThreadedTCPSocketTest):
meth, file, count=-1) meth, file, count=-1)
@unittest.skipUnless(thread, 'Threading required for this test.')
@unittest.skipUnless(hasattr(os, "sendfile"), @unittest.skipUnless(hasattr(os, "sendfile"),
'os.sendfile() required for this test.') 'os.sendfile() required for this test.')
class SendfileUsingSendfileTest(SendfileUsingSendTest): class SendfileUsingSendfileTest(SendfileUsingSendTest):

View File

@ -9,15 +9,13 @@ import select
import signal import signal
import socket import socket
import tempfile import tempfile
import threading
import unittest import unittest
import socketserver import socketserver
import test.support import test.support
from test.support import reap_children, reap_threads, verbose from test.support import reap_children, reap_threads, verbose
try:
import threading
except ImportError:
threading = None
test.support.requires("network") test.support.requires("network")
@ -68,7 +66,6 @@ def simple_subprocess(testcase):
testcase.assertEqual(72 << 8, status) testcase.assertEqual(72 << 8, status)
@unittest.skipUnless(threading, 'Threading required for this test.')
class SocketServerTest(unittest.TestCase): class SocketServerTest(unittest.TestCase):
"""Test all socket servers.""" """Test all socket servers."""
@ -306,12 +303,10 @@ class ErrorHandlerTest(unittest.TestCase):
BaseErrorTestServer(SystemExit) BaseErrorTestServer(SystemExit)
self.check_result(handled=False) self.check_result(handled=False)
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_threading_handled(self): def test_threading_handled(self):
ThreadingErrorTestServer(ValueError) ThreadingErrorTestServer(ValueError)
self.check_result(handled=True) self.check_result(handled=True)
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_threading_not_handled(self): def test_threading_not_handled(self):
ThreadingErrorTestServer(SystemExit) ThreadingErrorTestServer(SystemExit)
self.check_result(handled=False) self.check_result(handled=False)
@ -396,7 +391,6 @@ class SocketWriterTest(unittest.TestCase):
self.assertIsInstance(server.wfile, io.BufferedIOBase) self.assertIsInstance(server.wfile, io.BufferedIOBase)
self.assertEqual(server.wfile_fileno, server.request_fileno) self.assertEqual(server.wfile_fileno, server.request_fileno)
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_write(self): def test_write(self):
# Test that wfile.write() sends data immediately, and that it does # Test that wfile.write() sends data immediately, and that it does
# not truncate sends when interrupted by a Unix signal # not truncate sends when interrupted by a Unix signal

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@ import selectors
import sysconfig import sysconfig
import select import select
import shutil import shutil
import threading
import gc import gc
import textwrap import textwrap
@ -24,11 +25,6 @@ except ImportError:
else: else:
import ctypes.util import ctypes.util
try:
import threading
except ImportError:
threading = None
try: try:
import _testcapi import _testcapi
except ImportError: except ImportError:
@ -1196,7 +1192,6 @@ class ProcessTestCase(BaseTestCase):
self.assertEqual(stderr, "") self.assertEqual(stderr, "")
self.assertEqual(proc.returncode, 0) self.assertEqual(proc.returncode, 0)
@unittest.skipIf(threading is None, "threading required")
def test_double_close_on_error(self): def test_double_close_on_error(self):
# Issue #18851 # Issue #18851
fds = [] fds = []
@ -1226,7 +1221,6 @@ class ProcessTestCase(BaseTestCase):
if exc is not None: if exc is not None:
raise exc raise exc
@unittest.skipIf(threading is None, "threading required")
def test_threadsafe_wait(self): def test_threadsafe_wait(self):
"""Issue21291: Popen.wait() needs to be threadsafe for returncode.""" """Issue21291: Popen.wait() needs to be threadsafe for returncode."""
proc = subprocess.Popen([sys.executable, '-c', proc = subprocess.Popen([sys.executable, '-c',

View File

@ -10,15 +10,12 @@ import codecs
import gc import gc
import sysconfig import sysconfig
import locale import locale
import threading
# count the number of test runs, used to create unique # count the number of test runs, used to create unique
# strings to intern in test_intern() # strings to intern in test_intern()
numruns = 0 numruns = 0
try:
import threading
except ImportError:
threading = None
class SysModuleTest(unittest.TestCase): class SysModuleTest(unittest.TestCase):
@ -172,7 +169,6 @@ class SysModuleTest(unittest.TestCase):
sys.setcheckinterval(n) sys.setcheckinterval(n)
self.assertEqual(sys.getcheckinterval(), n) self.assertEqual(sys.getcheckinterval(), n)
@unittest.skipUnless(threading, 'Threading required for this test.')
def test_switchinterval(self): def test_switchinterval(self):
self.assertRaises(TypeError, sys.setswitchinterval) self.assertRaises(TypeError, sys.setswitchinterval)
self.assertRaises(TypeError, sys.setswitchinterval, "a") self.assertRaises(TypeError, sys.setswitchinterval, "a")
@ -348,21 +344,8 @@ class SysModuleTest(unittest.TestCase):
) )
# sys._current_frames() is a CPython-only gimmick. # sys._current_frames() is a CPython-only gimmick.
def test_current_frames(self):
have_threads = True
try:
import _thread
except ImportError:
have_threads = False
if have_threads:
self.current_frames_with_threads()
else:
self.current_frames_without_threads()
# Test sys._current_frames() in a WITH_THREADS build.
@test.support.reap_threads @test.support.reap_threads
def current_frames_with_threads(self): def test_current_frames(self):
import threading import threading
import traceback import traceback
@ -426,15 +409,6 @@ class SysModuleTest(unittest.TestCase):
leave_g.set() leave_g.set()
t.join() t.join()
# Test sys._current_frames() when thread support doesn't exist.
def current_frames_without_threads(self):
# Not much happens here: there is only one thread, with artificial
# "thread id" 0.
d = sys._current_frames()
self.assertEqual(len(d), 1)
self.assertIn(0, d)
self.assertTrue(d[0] is sys._getframe())
def test_attributes(self): def test_attributes(self):
self.assertIsInstance(sys.api_version, int) self.assertIsInstance(sys.api_version, int)
self.assertIsInstance(sys.argv, list) self.assertIsInstance(sys.argv, list)
@ -516,8 +490,6 @@ class SysModuleTest(unittest.TestCase):
if not sys.platform.startswith('win'): if not sys.platform.startswith('win'):
self.assertIsInstance(sys.abiflags, str) self.assertIsInstance(sys.abiflags, str)
@unittest.skipUnless(hasattr(sys, 'thread_info'),
'Threading required for this test.')
def test_thread_info(self): def test_thread_info(self):
info = sys.thread_info info = sys.thread_info
self.assertEqual(len(info), 3) self.assertEqual(len(info), 3)

View File

@ -1,11 +1,11 @@
import socket import socket
import selectors import selectors
import telnetlib import telnetlib
import threading
import contextlib import contextlib
from test import support from test import support
import unittest import unittest
threading = support.import_module('threading')
HOST = support.HOST HOST = support.HOST

View File

@ -11,12 +11,12 @@ import importlib
import sys import sys
import time import time
import shutil import shutil
import threading
import unittest import unittest
from unittest import mock from unittest import mock
from test.support import ( from test.support import (
verbose, import_module, run_unittest, TESTFN, reap_threads, verbose, import_module, run_unittest, TESTFN, reap_threads,
forget, unlink, rmtree, start_threads) forget, unlink, rmtree, start_threads)
threading = import_module('threading')
def task(N, done, done_tasks, errors): def task(N, done, done_tasks, errors):
try: try:

View File

@ -19,9 +19,9 @@ FILES_PER_THREAD = 50
import tempfile import tempfile
from test.support import start_threads, import_module from test.support import start_threads, import_module
threading = import_module('threading')
import unittest import unittest
import io import io
import threading
from traceback import print_exc from traceback import print_exc
startEvent = threading.Event() startEvent = threading.Event()

View File

@ -9,8 +9,8 @@ from test.support.script_helper import assert_python_ok, assert_python_failure
import random import random
import sys import sys
_thread = import_module('_thread') import _thread
threading = import_module('threading') import threading
import time import time
import unittest import unittest
import weakref import weakref

View File

@ -5,8 +5,8 @@ import weakref
import gc import gc
# Modules under test # Modules under test
_thread = support.import_module('_thread') import _thread
threading = support.import_module('threading') import threading
import _threading_local import _threading_local

View File

@ -8,10 +8,6 @@ import sys
import sysconfig import sysconfig
import time import time
import unittest import unittest
try:
import threading
except ImportError:
threading = None
try: try:
import _testcapi import _testcapi
except ImportError: except ImportError:

View File

@ -7,10 +7,7 @@ from unittest.mock import patch
from test.support.script_helper import (assert_python_ok, assert_python_failure, from test.support.script_helper import (assert_python_ok, assert_python_failure,
interpreter_requires_environment) interpreter_requires_environment)
from test import support from test import support
try:
import threading
except ImportError:
threading = None
try: try:
import _testcapi import _testcapi
except ImportError: except ImportError:

View File

@ -4,13 +4,12 @@ import email
import urllib.parse import urllib.parse
import urllib.request import urllib.request
import http.server import http.server
import threading
import unittest import unittest
import hashlib import hashlib
from test import support from test import support
threading = support.import_module('threading')
try: try:
import ssl import ssl
except ImportError: except ImportError:
@ -276,7 +275,6 @@ class FakeProxyHandler(http.server.BaseHTTPRequestHandler):
# Test cases # Test cases
@unittest.skipUnless(threading, "Threading required for this test.")
class BasicAuthTests(unittest.TestCase): class BasicAuthTests(unittest.TestCase):
USER = "testUser" USER = "testUser"
PASSWD = "testPass" PASSWD = "testPass"
@ -317,7 +315,6 @@ class BasicAuthTests(unittest.TestCase):
self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, self.server_url) self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, self.server_url)
@unittest.skipUnless(threading, "Threading required for this test.")
class ProxyAuthTests(unittest.TestCase): class ProxyAuthTests(unittest.TestCase):
URL = "http://localhost" URL = "http://localhost"
@ -439,7 +436,6 @@ def GetRequestHandler(responses):
return FakeHTTPRequestHandler return FakeHTTPRequestHandler
@unittest.skipUnless(threading, "Threading required for this test.")
class TestUrlopen(unittest.TestCase): class TestUrlopen(unittest.TestCase):
"""Tests urllib.request.urlopen using the network. """Tests urllib.request.urlopen using the network.

View File

@ -15,15 +15,10 @@ import sys
import tempfile import tempfile
from test.support import (captured_stdout, captured_stderr, from test.support import (captured_stdout, captured_stderr,
can_symlink, EnvironmentVarGuard, rmtree) can_symlink, EnvironmentVarGuard, rmtree)
import threading
import unittest import unittest
import venv import venv
try:
import threading
except ImportError:
threading = None
try: try:
import ctypes import ctypes
except ImportError: except ImportError:
@ -420,8 +415,6 @@ class EnsurePipTest(BaseTest):
if not system_site_packages: if not system_site_packages:
self.assert_pip_not_installed() self.assert_pip_not_installed()
@unittest.skipUnless(threading, 'some dependencies of pip import threading'
' module unconditionally')
# Issue #26610: pip/pep425tags.py requires ctypes # Issue #26610: pip/pep425tags.py requires ctypes
@unittest.skipUnless(ctypes, 'pip requires ctypes') @unittest.skipUnless(ctypes, 'pip requires ctypes')
def test_with_pip(self): def test_with_pip(self):

View File

@ -6,6 +6,7 @@ import weakref
import operator import operator
import contextlib import contextlib
import copy import copy
import threading
import time import time
from test import support from test import support
@ -78,7 +79,6 @@ def collect_in_thread(period=0.0001):
""" """
Ensure GC collections happen in a different thread, at a high frequency. Ensure GC collections happen in a different thread, at a high frequency.
""" """
threading = support.import_module('threading')
please_stop = False please_stop = False
def collect(): def collect():

View File

@ -10,6 +10,7 @@ import xmlrpc.server
import http.client import http.client
import http, http.server import http, http.server
import socket import socket
import threading
import re import re
import io import io
import contextlib import contextlib
@ -19,10 +20,6 @@ try:
import gzip import gzip
except ImportError: except ImportError:
gzip = None gzip = None
try:
import threading
except ImportError:
threading = None
alist = [{'astring': 'foo@bar.baz.spam', alist = [{'astring': 'foo@bar.baz.spam',
'afloat': 7283.43, 'afloat': 7283.43,
@ -307,7 +304,6 @@ class XMLRPCTestCase(unittest.TestCase):
except OSError: except OSError:
self.assertTrue(has_ssl) self.assertTrue(has_ssl)
@unittest.skipUnless(threading, "Threading required for this test.")
def test_keepalive_disconnect(self): def test_keepalive_disconnect(self):
class RequestHandler(http.server.BaseHTTPRequestHandler): class RequestHandler(http.server.BaseHTTPRequestHandler):
protocol_version = "HTTP/1.1" protocol_version = "HTTP/1.1"
@ -747,7 +743,6 @@ def make_request_and_skipIf(condition, reason):
return make_request_and_skip return make_request_and_skip
return decorator return decorator
@unittest.skipUnless(threading, 'Threading required for this test.')
class BaseServerTestCase(unittest.TestCase): class BaseServerTestCase(unittest.TestCase):
requestHandler = None requestHandler = None
request_count = 1 request_count = 1
@ -1206,7 +1201,6 @@ class FailingMessageClass(http.client.HTTPMessage):
return super().get(key, failobj) return super().get(key, failobj)
@unittest.skipUnless(threading, 'Threading required for this test.')
class FailingServerTestCase(unittest.TestCase): class FailingServerTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
self.evt = threading.Event() self.evt = threading.Event()

View File

@ -990,38 +990,12 @@ class Thread:
def _delete(self): def _delete(self):
"Remove current thread from the dict of currently running threads." "Remove current thread from the dict of currently running threads."
with _active_limbo_lock:
# Notes about running with _dummy_thread: del _active[get_ident()]
# # There must not be any python code between the previous line
# Must take care to not raise an exception if _dummy_thread is being # and after the lock is released. Otherwise a tracing function
# used (and thus this module is being used as an instance of # could try to acquire the lock again in the same thread, (in
# dummy_threading). _dummy_thread.get_ident() always returns 1 since # current_thread()), and would block.
# there is only one thread if _dummy_thread is being used. Thus
# len(_active) is always <= 1 here, and any Thread instance created
# overwrites the (if any) thread currently registered in _active.
#
# An instance of _MainThread is always created by 'threading'. This
# gets overwritten the instant an instance of Thread is created; both
# threads return 1 from _dummy_thread.get_ident() and thus have the
# same key in the dict. So when the _MainThread instance created by
# 'threading' tries to clean itself up when atexit calls this method
# it gets a KeyError if another Thread instance was created.
#
# This all means that KeyError from trying to delete something from
# _active if dummy_threading is being used is a red herring. But
# since it isn't if dummy_threading is *not* being used then don't
# hide the exception.
try:
with _active_limbo_lock:
del _active[get_ident()]
# There must not be any python code between the previous line
# and after the lock is released. Otherwise a tracing function
# could try to acquire the lock again in the same thread, (in
# current_thread()), and would block.
except KeyError:
if 'dummy_threading' not in _sys.modules:
raise
def join(self, timeout=None): def join(self, timeout=None):
"""Wait until the thread terminates. """Wait until the thread terminates.

View File

@ -61,21 +61,15 @@ import dis
import pickle import pickle
from time import monotonic as _time from time import monotonic as _time
try: import threading
import threading
except ImportError:
_settrace = sys.settrace
def _unsettrace(): def _settrace(func):
sys.settrace(None) threading.settrace(func)
else: sys.settrace(func)
def _settrace(func):
threading.settrace(func)
sys.settrace(func)
def _unsettrace(): def _unsettrace():
sys.settrace(None) sys.settrace(None)
threading.settrace(None) threading.settrace(None)
PRAGMA_NOCOVER = "#pragma NO COVER" PRAGMA_NOCOVER = "#pragma NO COVER"

View File

@ -12,11 +12,7 @@ import stat
import shutil import shutil
import struct import struct
import binascii import binascii
import threading
try:
import threading
except ImportError:
import dummy_threading as threading
try: try:
import zlib # We may need its compression method import zlib # We may need its compression method

View File

@ -220,7 +220,6 @@ LIBC= @LIBC@
SYSLIBS= $(LIBM) $(LIBC) SYSLIBS= $(LIBM) $(LIBC)
SHLIBS= @SHLIBS@ SHLIBS= @SHLIBS@
THREADOBJ= @THREADOBJ@
DLINCLDIR= @DLINCLDIR@ DLINCLDIR= @DLINCLDIR@
DYNLOADFILE= @DYNLOADFILE@ DYNLOADFILE= @DYNLOADFILE@
MACHDEP_OBJS= @MACHDEP_OBJS@ MACHDEP_OBJS= @MACHDEP_OBJS@
@ -354,6 +353,7 @@ PYTHON_OBJS= \
Python/structmember.o \ Python/structmember.o \
Python/symtable.o \ Python/symtable.o \
Python/sysmodule.o \ Python/sysmodule.o \
Python/thread.o \
Python/traceback.o \ Python/traceback.o \
Python/getopt.o \ Python/getopt.o \
Python/pystrcmp.o \ Python/pystrcmp.o \
@ -365,7 +365,6 @@ PYTHON_OBJS= \
Python/$(DYNLOADFILE) \ Python/$(DYNLOADFILE) \
$(LIBOBJS) \ $(LIBOBJS) \
$(MACHDEP_OBJS) \ $(MACHDEP_OBJS) \
$(THREADOBJ) \
$(DTRACE_OBJS) $(DTRACE_OBJS)
@ -655,12 +654,10 @@ oldsharedmods: $(SHAREDMODS)
Makefile Modules/config.c: Makefile.pre \ Makefile Modules/config.c: Makefile.pre \
$(srcdir)/Modules/config.c.in \ $(srcdir)/Modules/config.c.in \
$(MAKESETUP) \ $(MAKESETUP) \
Modules/Setup.config \
Modules/Setup \ Modules/Setup \
Modules/Setup.local Modules/Setup.local
$(SHELL) $(MAKESETUP) -c $(srcdir)/Modules/config.c.in \ $(SHELL) $(MAKESETUP) -c $(srcdir)/Modules/config.c.in \
-s Modules \ -s Modules \
Modules/Setup.config \
Modules/Setup.local \ Modules/Setup.local \
Modules/Setup Modules/Setup
@mv config.c Modules @mv config.c Modules
@ -1421,7 +1418,6 @@ libainstall: @DEF_MAKE_RULE@ python-config
$(INSTALL_DATA) Makefile $(DESTDIR)$(LIBPL)/Makefile $(INSTALL_DATA) Makefile $(DESTDIR)$(LIBPL)/Makefile
$(INSTALL_DATA) Modules/Setup $(DESTDIR)$(LIBPL)/Setup $(INSTALL_DATA) Modules/Setup $(DESTDIR)$(LIBPL)/Setup
$(INSTALL_DATA) Modules/Setup.local $(DESTDIR)$(LIBPL)/Setup.local $(INSTALL_DATA) Modules/Setup.local $(DESTDIR)$(LIBPL)/Setup.local
$(INSTALL_DATA) Modules/Setup.config $(DESTDIR)$(LIBPL)/Setup.config
$(INSTALL_DATA) Misc/python.pc $(DESTDIR)$(LIBPC)/python-$(VERSION).pc $(INSTALL_DATA) Misc/python.pc $(DESTDIR)$(LIBPC)/python-$(VERSION).pc
$(INSTALL_SCRIPT) $(srcdir)/Modules/makesetup $(DESTDIR)$(LIBPL)/makesetup $(INSTALL_SCRIPT) $(srcdir)/Modules/makesetup $(DESTDIR)$(LIBPL)/makesetup
$(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh $(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh
@ -1642,7 +1638,7 @@ distclean: clobber
if test "$$file" != "$(srcdir)/Lib/test/data/README"; then rm "$$file"; fi; \ if test "$$file" != "$(srcdir)/Lib/test/data/README"; then rm "$$file"; fi; \
done done
-rm -f core Makefile Makefile.pre config.status \ -rm -f core Makefile Makefile.pre config.status \
Modules/Setup Modules/Setup.local Modules/Setup.config \ Modules/Setup Modules/Setup.local \
Modules/ld_so_aix Modules/python.exp Misc/python.pc \ Modules/ld_so_aix Modules/python.exp Misc/python.pc \
Misc/python-config.sh Misc/python-config.sh
-rm -f python*-gdb.py -rm -f python*-gdb.py

View File

@ -0,0 +1,5 @@
Remove support for building --without-threads.
This option is not really useful anymore in the 21st century. Removing lots
of conditional paths allows us to simplify the code base, including in
difficult to maintain low-level internal code.

View File

@ -1,10 +0,0 @@
# This file is transmogrified into Setup.config by config.status.
# The purpose of this file is to conditionally enable certain modules
# based on configure-time options.
# Threading
@USE_THREAD_MODULE@_thread _threadmodule.c
# The rest of the modules previously listed in this file are built
# by the setup.py script in Python 2.1 and later.

View File

@ -123,6 +123,7 @@ atexit atexitmodule.c # Register functions to be run at interpreter-shutdow
_signal signalmodule.c _signal signalmodule.c
_stat _stat.c # stat.h interface _stat _stat.c # stat.h interface
time timemodule.c # -lm # time operations and variables time timemodule.c # -lm # time operations and variables
_thread _threadmodule.c # low-level threading interface
# access to ISO C locale support # access to ISO C locale support
_locale _localemodule.c # -lintl _locale _localemodule.c # -lintl
@ -216,8 +217,6 @@ _symtable symtablemodule.c
# The crypt module is now disabled by default because it breaks builds # The crypt module is now disabled by default because it breaks builds
# on many systems (where -lcrypt is needed), e.g. Linux (I believe). # on many systems (where -lcrypt is needed), e.g. Linux (I believe).
#
# First, look at Setup.config; configure may have set this for you.
#_crypt _cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems #_crypt _cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems
@ -308,8 +307,6 @@ _symtable symtablemodule.c
# Curses support, requiring the System V version of curses, often # Curses support, requiring the System V version of curses, often
# provided by the ncurses library. e.g. on Linux, link with -lncurses # provided by the ncurses library. e.g. on Linux, link with -lncurses
# instead of -lcurses). # instead of -lcurses).
#
# First, look at Setup.config; configure may have set this for you.
#_curses _cursesmodule.c -lcurses -ltermcap #_curses _cursesmodule.c -lcurses -ltermcap
# Wrapper for the panel library that's part of ncurses and SYSV curses. # Wrapper for the panel library that's part of ncurses and SYSV curses.
@ -323,18 +320,9 @@ _symtable symtablemodule.c
# implementation independent wrapper for these; dbm/dumb.py provides # implementation independent wrapper for these; dbm/dumb.py provides
# similar functionality (but slower of course) implemented in Python. # similar functionality (but slower of course) implemented in Python.
# The standard Unix dbm module has been moved to Setup.config so that
# it will be compiled as a shared library by default. Compiling it as
# a built-in module causes conflicts with the pybsddb3 module since it
# creates a static dependency on an out-of-date version of db.so.
#
# First, look at Setup.config; configure may have set this for you.
#_dbm _dbmmodule.c # dbm(3) may require -lndbm or similar #_dbm _dbmmodule.c # dbm(3) may require -lndbm or similar
# Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm:
#
# First, look at Setup.config; configure may have set this for you.
#_gdbm _gdbmmodule.c -I/usr/local/include -L/usr/local/lib -lgdbm #_gdbm _gdbmmodule.c -I/usr/local/include -L/usr/local/lib -lgdbm

View File

@ -15,9 +15,7 @@
#include "Python.h" #include "Python.h"
#include "pystrhex.h" #include "pystrhex.h"
#ifdef WITH_THREAD
#include "pythread.h" #include "pythread.h"
#endif
#include "../hashlib.h" #include "../hashlib.h"
#include "blake2ns.h" #include "blake2ns.h"
@ -41,9 +39,7 @@ typedef struct {
PyObject_HEAD PyObject_HEAD
blake2b_param param; blake2b_param param;
blake2b_state state; blake2b_state state;
#ifdef WITH_THREAD
PyThread_type_lock lock; PyThread_type_lock lock;
#endif
} BLAKE2bObject; } BLAKE2bObject;
#include "clinic/blake2b_impl.c.h" #include "clinic/blake2b_impl.c.h"
@ -60,11 +56,9 @@ new_BLAKE2bObject(PyTypeObject *type)
{ {
BLAKE2bObject *self; BLAKE2bObject *self;
self = (BLAKE2bObject *)type->tp_alloc(type, 0); self = (BLAKE2bObject *)type->tp_alloc(type, 0);
#ifdef WITH_THREAD
if (self != NULL) { if (self != NULL) {
self->lock = NULL; self->lock = NULL;
} }
#endif
return self; return self;
} }
@ -292,7 +286,6 @@ _blake2b_blake2b_update(BLAKE2bObject *self, PyObject *obj)
GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
#ifdef WITH_THREAD
if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
self->lock = PyThread_allocate_lock(); self->lock = PyThread_allocate_lock();
@ -305,9 +298,6 @@ _blake2b_blake2b_update(BLAKE2bObject *self, PyObject *obj)
} else { } else {
blake2b_update(&self->state, buf.buf, buf.len); blake2b_update(&self->state, buf.buf, buf.len);
} }
#else
blake2b_update(&self->state, buf.buf, buf.len);
#endif /* !WITH_THREAD */
PyBuffer_Release(&buf); PyBuffer_Release(&buf);
Py_RETURN_NONE; Py_RETURN_NONE;
@ -407,12 +397,10 @@ py_blake2b_dealloc(PyObject *self)
/* Try not to leave state in memory. */ /* Try not to leave state in memory. */
secure_zero_memory(&obj->param, sizeof(obj->param)); secure_zero_memory(&obj->param, sizeof(obj->param));
secure_zero_memory(&obj->state, sizeof(obj->state)); secure_zero_memory(&obj->state, sizeof(obj->state));
#ifdef WITH_THREAD
if (obj->lock) { if (obj->lock) {
PyThread_free_lock(obj->lock); PyThread_free_lock(obj->lock);
obj->lock = NULL; obj->lock = NULL;
} }
#endif
PyObject_Del(self); PyObject_Del(self);
} }

View File

@ -15,9 +15,7 @@
#include "Python.h" #include "Python.h"
#include "pystrhex.h" #include "pystrhex.h"
#ifdef WITH_THREAD
#include "pythread.h" #include "pythread.h"
#endif
#include "../hashlib.h" #include "../hashlib.h"
#include "blake2ns.h" #include "blake2ns.h"
@ -41,9 +39,7 @@ typedef struct {
PyObject_HEAD PyObject_HEAD
blake2s_param param; blake2s_param param;
blake2s_state state; blake2s_state state;
#ifdef WITH_THREAD
PyThread_type_lock lock; PyThread_type_lock lock;
#endif
} BLAKE2sObject; } BLAKE2sObject;
#include "clinic/blake2s_impl.c.h" #include "clinic/blake2s_impl.c.h"
@ -60,11 +56,9 @@ new_BLAKE2sObject(PyTypeObject *type)
{ {
BLAKE2sObject *self; BLAKE2sObject *self;
self = (BLAKE2sObject *)type->tp_alloc(type, 0); self = (BLAKE2sObject *)type->tp_alloc(type, 0);
#ifdef WITH_THREAD
if (self != NULL) { if (self != NULL) {
self->lock = NULL; self->lock = NULL;
} }
#endif
return self; return self;
} }
@ -292,7 +286,6 @@ _blake2s_blake2s_update(BLAKE2sObject *self, PyObject *obj)
GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
#ifdef WITH_THREAD
if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
self->lock = PyThread_allocate_lock(); self->lock = PyThread_allocate_lock();
@ -305,9 +298,6 @@ _blake2s_blake2s_update(BLAKE2sObject *self, PyObject *obj)
} else { } else {
blake2s_update(&self->state, buf.buf, buf.len); blake2s_update(&self->state, buf.buf, buf.len);
} }
#else
blake2s_update(&self->state, buf.buf, buf.len);
#endif /* !WITH_THREAD */
PyBuffer_Release(&buf); PyBuffer_Release(&buf);
Py_RETURN_NONE; Py_RETURN_NONE;
@ -407,12 +397,10 @@ py_blake2s_dealloc(PyObject *self)
/* Try not to leave state in memory. */ /* Try not to leave state in memory. */
secure_zero_memory(&obj->param, sizeof(obj->param)); secure_zero_memory(&obj->param, sizeof(obj->param));
secure_zero_memory(&obj->state, sizeof(obj->state)); secure_zero_memory(&obj->state, sizeof(obj->state));
#ifdef WITH_THREAD
if (obj->lock) { if (obj->lock) {
PyThread_free_lock(obj->lock); PyThread_free_lock(obj->lock);
obj->lock = NULL; obj->lock = NULL;
} }
#endif
PyObject_Del(self); PyObject_Del(self);
} }

View File

@ -5,9 +5,7 @@
#include "Python.h" #include "Python.h"
#include "structmember.h" #include "structmember.h"
#ifdef WITH_THREAD
#include "pythread.h" #include "pythread.h"
#endif
#include <bzlib.h> #include <bzlib.h>
#include <stdio.h> #include <stdio.h>
@ -23,7 +21,6 @@
#endif /* ! BZ_CONFIG_ERROR */ #endif /* ! BZ_CONFIG_ERROR */
#ifdef WITH_THREAD
#define ACQUIRE_LOCK(obj) do { \ #define ACQUIRE_LOCK(obj) do { \
if (!PyThread_acquire_lock((obj)->lock, 0)) { \ if (!PyThread_acquire_lock((obj)->lock, 0)) { \
Py_BEGIN_ALLOW_THREADS \ Py_BEGIN_ALLOW_THREADS \
@ -31,19 +28,13 @@
Py_END_ALLOW_THREADS \ Py_END_ALLOW_THREADS \
} } while (0) } } while (0)
#define RELEASE_LOCK(obj) PyThread_release_lock((obj)->lock) #define RELEASE_LOCK(obj) PyThread_release_lock((obj)->lock)
#else
#define ACQUIRE_LOCK(obj)
#define RELEASE_LOCK(obj)
#endif
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
bz_stream bzs; bz_stream bzs;
int flushed; int flushed;
#ifdef WITH_THREAD
PyThread_type_lock lock; PyThread_type_lock lock;
#endif
} BZ2Compressor; } BZ2Compressor;
typedef struct { typedef struct {
@ -59,9 +50,7 @@ typedef struct {
separately. Conversion and looping is encapsulated in separately. Conversion and looping is encapsulated in
decompress_buf() */ decompress_buf() */
size_t bzs_avail_in_real; size_t bzs_avail_in_real;
#ifdef WITH_THREAD
PyThread_type_lock lock; PyThread_type_lock lock;
#endif
} BZ2Decompressor; } BZ2Decompressor;
static PyTypeObject BZ2Compressor_Type; static PyTypeObject BZ2Compressor_Type;
@ -325,13 +314,11 @@ _bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel)
return -1; return -1;
} }
#ifdef WITH_THREAD
self->lock = PyThread_allocate_lock(); self->lock = PyThread_allocate_lock();
if (self->lock == NULL) { if (self->lock == NULL) {
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock"); PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
return -1; return -1;
} }
#endif
self->bzs.opaque = NULL; self->bzs.opaque = NULL;
self->bzs.bzalloc = BZ2_Malloc; self->bzs.bzalloc = BZ2_Malloc;
@ -343,10 +330,8 @@ _bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel)
return 0; return 0;
error: error:
#ifdef WITH_THREAD
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
self->lock = NULL; self->lock = NULL;
#endif
return -1; return -1;
} }
@ -354,10 +339,8 @@ static void
BZ2Compressor_dealloc(BZ2Compressor *self) BZ2Compressor_dealloc(BZ2Compressor *self)
{ {
BZ2_bzCompressEnd(&self->bzs); BZ2_bzCompressEnd(&self->bzs);
#ifdef WITH_THREAD
if (self->lock != NULL) if (self->lock != NULL)
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
#endif
Py_TYPE(self)->tp_free((PyObject *)self); Py_TYPE(self)->tp_free((PyObject *)self);
} }
@ -651,13 +634,11 @@ _bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self)
{ {
int bzerror; int bzerror;
#ifdef WITH_THREAD
self->lock = PyThread_allocate_lock(); self->lock = PyThread_allocate_lock();
if (self->lock == NULL) { if (self->lock == NULL) {
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock"); PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
return -1; return -1;
} }
#endif
self->needs_input = 1; self->needs_input = 1;
self->bzs_avail_in_real = 0; self->bzs_avail_in_real = 0;
@ -675,10 +656,8 @@ _bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self)
error: error:
Py_CLEAR(self->unused_data); Py_CLEAR(self->unused_data);
#ifdef WITH_THREAD
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
self->lock = NULL; self->lock = NULL;
#endif
return -1; return -1;
} }
@ -689,10 +668,8 @@ BZ2Decompressor_dealloc(BZ2Decompressor *self)
PyMem_Free(self->input_buffer); PyMem_Free(self->input_buffer);
BZ2_bzDecompressEnd(&self->bzs); BZ2_bzDecompressEnd(&self->bzs);
Py_CLEAR(self->unused_data); Py_CLEAR(self->unused_data);
#ifdef WITH_THREAD
if (self->lock != NULL) if (self->lock != NULL)
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
#endif
Py_TYPE(self)->tp_free((PyObject *)self); Py_TYPE(self)->tp_free((PyObject *)self);
} }

View File

@ -5410,9 +5410,7 @@ PyInit__ctypes(void)
ob_type is the metatype (the 'type'), defaults to PyType_Type, ob_type is the metatype (the 'type'), defaults to PyType_Type,
tp_base is the base type, defaults to 'object' aka PyBaseObject_Type. tp_base is the base type, defaults to 'object' aka PyBaseObject_Type.
*/ */
#ifdef WITH_THREAD
PyEval_InitThreads(); PyEval_InitThreads();
#endif
m = PyModule_Create(&_ctypesmodule); m = PyModule_Create(&_ctypesmodule);
if (!m) if (!m)
return NULL; return NULL;

View File

@ -137,9 +137,7 @@ static void _CallPythonObject(void *mem,
Py_ssize_t nArgs; Py_ssize_t nArgs;
PyObject *error_object = NULL; PyObject *error_object = NULL;
int *space; int *space;
#ifdef WITH_THREAD
PyGILState_STATE state = PyGILState_Ensure(); PyGILState_STATE state = PyGILState_Ensure();
#endif
nArgs = PySequence_Length(converters); nArgs = PySequence_Length(converters);
/* Hm. What to return in case of error? /* Hm. What to return in case of error?
@ -281,9 +279,7 @@ if (x == NULL) _PyTraceback_Add(what, "_ctypes/callbacks.c", __LINE__ - 1), PyEr
Py_XDECREF(result); Py_XDECREF(result);
Done: Done:
Py_XDECREF(arglist); Py_XDECREF(arglist);
#ifdef WITH_THREAD
PyGILState_Release(state); PyGILState_Release(state);
#endif
} }
static void closure_fcn(ffi_cif *cif, static void closure_fcn(ffi_cif *cif,
@ -347,7 +343,7 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
assert(CThunk_CheckExact((PyObject *)p)); assert(CThunk_CheckExact((PyObject *)p));
p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure), p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure),
&p->pcl_exec); &p->pcl_exec);
if (p->pcl_write == NULL) { if (p->pcl_write == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
goto error; goto error;
@ -397,8 +393,8 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p); result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
#else #else
result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn, result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
p, p,
p->pcl_exec); p->pcl_exec);
#endif #endif
if (result != FFI_OK) { if (result != FFI_OK) {
PyErr_Format(PyExc_RuntimeError, PyErr_Format(PyExc_RuntimeError,
@ -422,9 +418,7 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
static void LoadPython(void) static void LoadPython(void)
{ {
if (!Py_IsInitialized()) { if (!Py_IsInitialized()) {
#ifdef WITH_THREAD
PyEval_InitThreads(); PyEval_InitThreads();
#endif
Py_Initialize(); Py_Initialize();
} }
} }
@ -495,18 +489,12 @@ STDAPI DllGetClassObject(REFCLSID rclsid,
LPVOID *ppv) LPVOID *ppv)
{ {
long result; long result;
#ifdef WITH_THREAD
PyGILState_STATE state; PyGILState_STATE state;
#endif
LoadPython(); LoadPython();
#ifdef WITH_THREAD
state = PyGILState_Ensure(); state = PyGILState_Ensure();
#endif
result = Call_GetClassObject(rclsid, riid, ppv); result = Call_GetClassObject(rclsid, riid, ppv);
#ifdef WITH_THREAD
PyGILState_Release(state); PyGILState_Release(state);
#endif
return result; return result;
} }
@ -558,13 +546,9 @@ long Call_CanUnloadNow(void)
STDAPI DllCanUnloadNow(void) STDAPI DllCanUnloadNow(void)
{ {
long result; long result;
#ifdef WITH_THREAD
PyGILState_STATE state = PyGILState_Ensure(); PyGILState_STATE state = PyGILState_Ensure();
#endif
result = Call_CanUnloadNow(); result = Call_CanUnloadNow();
#ifdef WITH_THREAD
PyGILState_Release(state); PyGILState_Release(state);
#endif
return result; return result;
} }

View File

@ -745,9 +745,7 @@ static int _call_function_pointer(int flags,
void *resmem, void *resmem,
int argcount) int argcount)
{ {
#ifdef WITH_THREAD
PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */ PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */
#endif
PyObject *error_object = NULL; PyObject *error_object = NULL;
int *space; int *space;
ffi_cif cif; ffi_cif cif;
@ -786,10 +784,8 @@ static int _call_function_pointer(int flags,
if (error_object == NULL) if (error_object == NULL)
return -1; return -1;
} }
#ifdef WITH_THREAD
if ((flags & FUNCFLAG_PYTHONAPI) == 0) if ((flags & FUNCFLAG_PYTHONAPI) == 0)
Py_UNBLOCK_THREADS Py_UNBLOCK_THREADS
#endif
if (flags & FUNCFLAG_USE_ERRNO) { if (flags & FUNCFLAG_USE_ERRNO) {
int temp = space[0]; int temp = space[0];
space[0] = errno; space[0] = errno;
@ -826,10 +822,8 @@ static int _call_function_pointer(int flags,
space[0] = errno; space[0] = errno;
errno = temp; errno = temp;
} }
#ifdef WITH_THREAD
if ((flags & FUNCFLAG_PYTHONAPI) == 0) if ((flags & FUNCFLAG_PYTHONAPI) == 0)
Py_BLOCK_THREADS Py_BLOCK_THREADS
#endif
Py_XDECREF(error_object); Py_XDECREF(error_object);
#ifdef MS_WIN32 #ifdef MS_WIN32
#ifndef DONT_USE_SEH #ifndef DONT_USE_SEH
@ -982,9 +976,7 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
/* We absolutely have to release the GIL during COM method calls, /* We absolutely have to release the GIL during COM method calls,
otherwise we may get a deadlock! otherwise we may get a deadlock!
*/ */
#ifdef WITH_THREAD
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
#endif
hr = pIunk->lpVtbl->QueryInterface(pIunk, &IID_ISupportErrorInfo, (void **)&psei); hr = pIunk->lpVtbl->QueryInterface(pIunk, &IID_ISupportErrorInfo, (void **)&psei);
if (FAILED(hr)) if (FAILED(hr))
@ -1008,9 +1000,7 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
pei->lpVtbl->Release(pei); pei->lpVtbl->Release(pei);
failed: failed:
#ifdef WITH_THREAD
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
#endif
progid = NULL; progid = NULL;
ProgIDFromCLSID(&guid, &progid); ProgIDFromCLSID(&guid, &progid);

View File

@ -53,9 +53,7 @@ typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *name; /* name of this hash algorithm */ PyObject *name; /* name of this hash algorithm */
EVP_MD_CTX *ctx; /* OpenSSL message digest context */ EVP_MD_CTX *ctx; /* OpenSSL message digest context */
#ifdef WITH_THREAD
PyThread_type_lock lock; /* OpenSSL context lock */ PyThread_type_lock lock; /* OpenSSL context lock */
#endif
} EVPobject; } EVPobject;
@ -122,9 +120,7 @@ newEVPobject(PyObject *name)
/* save the name for .name to return */ /* save the name for .name to return */
Py_INCREF(name); Py_INCREF(name);
retval->name = name; retval->name = name;
#ifdef WITH_THREAD
retval->lock = NULL; retval->lock = NULL;
#endif
return retval; return retval;
} }
@ -153,10 +149,8 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
static void static void
EVP_dealloc(EVPobject *self) EVP_dealloc(EVPobject *self)
{ {
#ifdef WITH_THREAD
if (self->lock != NULL) if (self->lock != NULL)
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
#endif
EVP_MD_CTX_free(self->ctx); EVP_MD_CTX_free(self->ctx);
Py_XDECREF(self->name); Py_XDECREF(self->name);
PyObject_Del(self); PyObject_Del(self);
@ -267,7 +261,6 @@ EVP_update(EVPobject *self, PyObject *args)
GET_BUFFER_VIEW_OR_ERROUT(obj, &view); GET_BUFFER_VIEW_OR_ERROUT(obj, &view);
#ifdef WITH_THREAD
if (self->lock == NULL && view.len >= HASHLIB_GIL_MINSIZE) { if (self->lock == NULL && view.len >= HASHLIB_GIL_MINSIZE) {
self->lock = PyThread_allocate_lock(); self->lock = PyThread_allocate_lock();
/* fail? lock = NULL and we fail over to non-threaded code. */ /* fail? lock = NULL and we fail over to non-threaded code. */
@ -282,9 +275,6 @@ EVP_update(EVPobject *self, PyObject *args)
} else { } else {
EVP_hash(self, view.buf, view.len); EVP_hash(self, view.buf, view.len);
} }
#else
EVP_hash(self, view.buf, view.len);
#endif
PyBuffer_Release(&view); PyBuffer_Release(&view);
Py_RETURN_NONE; Py_RETURN_NONE;

View File

@ -230,10 +230,8 @@ typedef struct {
isn't ready for writing. */ isn't ready for writing. */
Py_off_t write_end; Py_off_t write_end;
#ifdef WITH_THREAD
PyThread_type_lock lock; PyThread_type_lock lock;
volatile unsigned long owner; volatile unsigned long owner;
#endif
Py_ssize_t buffer_size; Py_ssize_t buffer_size;
Py_ssize_t buffer_mask; Py_ssize_t buffer_mask;
@ -267,8 +265,6 @@ typedef struct {
/* These macros protect the buffered object against concurrent operations. */ /* These macros protect the buffered object against concurrent operations. */
#ifdef WITH_THREAD
static int static int
_enter_buffered_busy(buffered *self) _enter_buffered_busy(buffered *self)
{ {
@ -315,11 +311,6 @@ _enter_buffered_busy(buffered *self)
PyThread_release_lock(self->lock); \ PyThread_release_lock(self->lock); \
} while(0); } while(0);
#else
#define ENTER_BUFFERED(self) 1
#define LEAVE_BUFFERED(self)
#endif
#define CHECK_INITIALIZED(self) \ #define CHECK_INITIALIZED(self) \
if (self->ok <= 0) { \ if (self->ok <= 0) { \
if (self->detached) { \ if (self->detached) { \
@ -401,12 +392,10 @@ buffered_dealloc(buffered *self)
PyMem_Free(self->buffer); PyMem_Free(self->buffer);
self->buffer = NULL; self->buffer = NULL;
} }
#ifdef WITH_THREAD
if (self->lock) { if (self->lock) {
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
self->lock = NULL; self->lock = NULL;
} }
#endif
Py_CLEAR(self->dict); Py_CLEAR(self->dict);
Py_TYPE(self)->tp_free((PyObject *)self); Py_TYPE(self)->tp_free((PyObject *)self);
} }
@ -753,7 +742,6 @@ _buffered_init(buffered *self)
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
} }
#ifdef WITH_THREAD
if (self->lock) if (self->lock)
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
self->lock = PyThread_allocate_lock(); self->lock = PyThread_allocate_lock();
@ -762,7 +750,6 @@ _buffered_init(buffered *self)
return -1; return -1;
} }
self->owner = 0; self->owner = 0;
#endif
/* Find out whether buffer_size is a power of 2 */ /* Find out whether buffer_size is a power of 2 */
/* XXX is this optimization useful? */ /* XXX is this optimization useful? */
for (n = self->buffer_size - 1; n & 1; n >>= 1) for (n = self->buffer_size - 1; n & 1; n >>= 1)

View File

@ -9,16 +9,13 @@
#include "Python.h" #include "Python.h"
#include "structmember.h" #include "structmember.h"
#ifdef WITH_THREAD
#include "pythread.h" #include "pythread.h"
#endif
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <lzma.h> #include <lzma.h>
#ifdef WITH_THREAD
#define ACQUIRE_LOCK(obj) do { \ #define ACQUIRE_LOCK(obj) do { \
if (!PyThread_acquire_lock((obj)->lock, 0)) { \ if (!PyThread_acquire_lock((obj)->lock, 0)) { \
Py_BEGIN_ALLOW_THREADS \ Py_BEGIN_ALLOW_THREADS \
@ -26,10 +23,6 @@
Py_END_ALLOW_THREADS \ Py_END_ALLOW_THREADS \
} } while (0) } } while (0)
#define RELEASE_LOCK(obj) PyThread_release_lock((obj)->lock) #define RELEASE_LOCK(obj) PyThread_release_lock((obj)->lock)
#else
#define ACQUIRE_LOCK(obj)
#define RELEASE_LOCK(obj)
#endif
/* Container formats: */ /* Container formats: */
@ -48,9 +41,7 @@ typedef struct {
lzma_allocator alloc; lzma_allocator alloc;
lzma_stream lzs; lzma_stream lzs;
int flushed; int flushed;
#ifdef WITH_THREAD
PyThread_type_lock lock; PyThread_type_lock lock;
#endif
} Compressor; } Compressor;
typedef struct { typedef struct {
@ -63,9 +54,7 @@ typedef struct {
char needs_input; char needs_input;
uint8_t *input_buffer; uint8_t *input_buffer;
size_t input_buffer_size; size_t input_buffer_size;
#ifdef WITH_THREAD
PyThread_type_lock lock; PyThread_type_lock lock;
#endif
} Decompressor; } Decompressor;
/* LZMAError class object. */ /* LZMAError class object. */
@ -757,13 +746,11 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs)
self->alloc.free = PyLzma_Free; self->alloc.free = PyLzma_Free;
self->lzs.allocator = &self->alloc; self->lzs.allocator = &self->alloc;
#ifdef WITH_THREAD
self->lock = PyThread_allocate_lock(); self->lock = PyThread_allocate_lock();
if (self->lock == NULL) { if (self->lock == NULL) {
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock"); PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
return -1; return -1;
} }
#endif
self->flushed = 0; self->flushed = 0;
switch (format) { switch (format) {
@ -790,10 +777,8 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs)
break; break;
} }
#ifdef WITH_THREAD
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
self->lock = NULL; self->lock = NULL;
#endif
return -1; return -1;
} }
@ -801,10 +786,8 @@ static void
Compressor_dealloc(Compressor *self) Compressor_dealloc(Compressor *self)
{ {
lzma_end(&self->lzs); lzma_end(&self->lzs);
#ifdef WITH_THREAD
if (self->lock != NULL) if (self->lock != NULL)
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
#endif
Py_TYPE(self)->tp_free((PyObject *)self); Py_TYPE(self)->tp_free((PyObject *)self);
} }
@ -1180,13 +1163,11 @@ _lzma_LZMADecompressor___init___impl(Decompressor *self, int format,
self->lzs.allocator = &self->alloc; self->lzs.allocator = &self->alloc;
self->lzs.next_in = NULL; self->lzs.next_in = NULL;
#ifdef WITH_THREAD
self->lock = PyThread_allocate_lock(); self->lock = PyThread_allocate_lock();
if (self->lock == NULL) { if (self->lock == NULL) {
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock"); PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
return -1; return -1;
} }
#endif
self->check = LZMA_CHECK_UNKNOWN; self->check = LZMA_CHECK_UNKNOWN;
self->needs_input = 1; self->needs_input = 1;
@ -1230,10 +1211,8 @@ _lzma_LZMADecompressor___init___impl(Decompressor *self, int format,
error: error:
Py_CLEAR(self->unused_data); Py_CLEAR(self->unused_data);
#ifdef WITH_THREAD
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
self->lock = NULL; self->lock = NULL;
#endif
return -1; return -1;
} }
@ -1245,10 +1224,8 @@ Decompressor_dealloc(Decompressor *self)
lzma_end(&self->lzs); lzma_end(&self->lzs);
Py_CLEAR(self->unused_data); Py_CLEAR(self->unused_data);
#ifdef WITH_THREAD
if (self->lock != NULL) if (self->lock != NULL)
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
#endif
Py_TYPE(self)->tp_free((PyObject *)self); Py_TYPE(self)->tp_free((PyObject *)self);
} }

Some files were not shown because too many files have changed in this diff Show More