1import _signal
2from _signal import *
3from functools import wraps as _wraps
4from enum import IntEnum as _IntEnum
5
6_globals = globals()
7
8_IntEnum._convert(
9        'Signals', __name__,
10        lambda name:
11            name.isupper()
12            and (name.startswith('SIG') and not name.startswith('SIG_'))
13            or name.startswith('CTRL_'))
14
15_IntEnum._convert(
16        'Handlers', __name__,
17        lambda name: name in ('SIG_DFL', 'SIG_IGN'))
18
19if 'pthread_sigmask' in _globals:
20    _IntEnum._convert(
21            'Sigmasks', __name__,
22            lambda name: name in ('SIG_BLOCK', 'SIG_UNBLOCK', 'SIG_SETMASK'))
23
24
25def _int_to_enum(value, enum_klass):
26    """Convert a numeric value to an IntEnum member.
27    If it's not a known member, return the numeric value itself.
28    """
29    try:
30        return enum_klass(value)
31    except ValueError:
32        return value
33
34
35def _enum_to_int(value):
36    """Convert an IntEnum member to a numeric value.
37    If it's not an IntEnum member return the value itself.
38    """
39    try:
40        return int(value)
41    except (ValueError, TypeError):
42        return value
43
44
45@_wraps(_signal.signal)
46def signal(signalnum, handler):
47    handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
48    return _int_to_enum(handler, Handlers)
49
50
51@_wraps(_signal.getsignal)
52def getsignal(signalnum):
53    handler = _signal.getsignal(signalnum)
54    return _int_to_enum(handler, Handlers)
55
56
57if 'pthread_sigmask' in _globals:
58    @_wraps(_signal.pthread_sigmask)
59    def pthread_sigmask(how, mask):
60        sigs_set = _signal.pthread_sigmask(how, mask)
61        return set(_int_to_enum(x, Signals) for x in sigs_set)
62    pthread_sigmask.__doc__ = _signal.pthread_sigmask.__doc__
63
64
65if 'sigpending' in _globals:
66    @_wraps(_signal.sigpending)
67    def sigpending():
68        sigs = _signal.sigpending()
69        return set(_int_to_enum(x, Signals) for x in sigs)
70
71
72if 'sigwait' in _globals:
73    @_wraps(_signal.sigwait)
74    def sigwait(sigset):
75        retsig = _signal.sigwait(sigset)
76        return _int_to_enum(retsig, Signals)
77    sigwait.__doc__ = _signal.sigwait
78
79del _globals, _wraps
80