1import _signal 2from _signal import * 3from enum import IntEnum as _IntEnum 4 5_globals = globals() 6 7_IntEnum._convert_( 8 'Signals', __name__, 9 lambda name: 10 name.isupper() 11 and (name.startswith('SIG') and not name.startswith('SIG_')) 12 or name.startswith('CTRL_')) 13 14_IntEnum._convert_( 15 'Handlers', __name__, 16 lambda name: name in ('SIG_DFL', 'SIG_IGN')) 17 18if 'pthread_sigmask' in _globals: 19 _IntEnum._convert_( 20 'Sigmasks', __name__, 21 lambda name: name in ('SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK')) 22 23 24def _int_to_enum(value, enum_klass): 25 """Convert a possible numeric value to an IntEnum member. 26 If it's not a known member, return the value itself. 27 """ 28 if not isinstance(value, int): 29 return value 30 try: 31 return enum_klass(value) 32 except ValueError: 33 return value 34 35 36def _enum_to_int(value): 37 """Convert an IntEnum member to a numeric value. 38 If it's not an IntEnum member return the value itself. 39 """ 40 try: 41 return int(value) 42 except (ValueError, TypeError): 43 return value 44 45 46# Similar to functools.wraps(), but only assign __doc__. 47# __module__ should be preserved, 48# __name__ and __qualname__ are already fine, 49# __annotations__ is not set. 50def _wraps(wrapped): 51 def decorator(wrapper): 52 wrapper.__doc__ = wrapped.__doc__ 53 return wrapper 54 return decorator 55 56@_wraps(_signal.signal) 57def signal(signalnum, handler): 58 handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler)) 59 return _int_to_enum(handler, Handlers) 60 61 62@_wraps(_signal.getsignal) 63def getsignal(signalnum): 64 handler = _signal.getsignal(signalnum) 65 return _int_to_enum(handler, Handlers) 66 67 68if 'pthread_sigmask' in _globals: 69 @_wraps(_signal.pthread_sigmask) 70 def pthread_sigmask(how, mask): 71 sigs_set = _signal.pthread_sigmask(how, mask) 72 return set(_int_to_enum(x, Signals) for x in sigs_set) 73 74 75if 'sigpending' in _globals: 76 @_wraps(_signal.sigpending) 77 def sigpending(): 78 return {_int_to_enum(x, Signals) for x in _signal.sigpending()} 79 80 81if 'sigwait' in _globals: 82 @_wraps(_signal.sigwait) 83 def sigwait(sigset): 84 retsig = _signal.sigwait(sigset) 85 return _int_to_enum(retsig, Signals) 86 87 88if 'valid_signals' in _globals: 89 @_wraps(_signal.valid_signals) 90 def valid_signals(): 91 return {_int_to_enum(x, Signals) for x in _signal.valid_signals()} 92 93 94del _globals, _wraps 95