• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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