MCPcopy Index your code
hub / github.com/matplotlib/matplotlib / _allow_interrupt

Function _allow_interrupt

lib/matplotlib/backend_bases.py:1650–1706  ·  view source on GitHub ↗

A context manager that allows terminating a plot by sending a SIGINT. It is necessary because the running backend prevents the Python interpreter from running and processing signals (i.e., to raise a KeyboardInterrupt). To solve this, one needs to somehow wake up the interpreter an

(prepare_notifier, handle_sigint)

Source from the content-addressed store, hash-verified

1648
1649@contextmanager
1650def _allow_interrupt(prepare_notifier, handle_sigint):
1651 """
1652 A context manager that allows terminating a plot by sending a SIGINT. It
1653 is necessary because the running backend prevents the Python interpreter
1654 from running and processing signals (i.e., to raise a KeyboardInterrupt).
1655 To solve this, one needs to somehow wake up the interpreter and make it
1656 close the plot window. We do this by using the signal.set_wakeup_fd()
1657 function which organizes a write of the signal number into a socketpair.
1658 A backend-specific function, *prepare_notifier*, arranges to listen to
1659 the pair's read socket while the event loop is running. (If it returns a
1660 notifier object, that object is kept alive while the context manager runs.)
1661
1662 If SIGINT was indeed caught, after exiting the on_signal() function the
1663 interpreter reacts to the signal according to the handler function which
1664 had been set up by a signal.signal() call; here, we arrange to call the
1665 backend-specific *handle_sigint* function, passing the notifier object
1666 as returned by prepare_notifier(). Finally, we call the old SIGINT
1667 handler with the same arguments that were given to our custom handler.
1668
1669 We do this only if the old handler for SIGINT was not None, which means
1670 that a non-python handler was installed, i.e. in Julia, and not SIG_IGN
1671 which means we should ignore the interrupts.
1672
1673 Parameters
1674 ----------
1675 prepare_notifier : Callable[[socket.socket], object]
1676 handle_sigint : Callable[[object], object]
1677 """
1678
1679 old_sigint_handler = signal.getsignal(signal.SIGINT)
1680 if old_sigint_handler in (None, signal.SIG_IGN, signal.SIG_DFL):
1681 yield
1682 return
1683
1684 handler_args = None
1685 wsock, rsock = socket.socketpair()
1686 wsock.setblocking(False)
1687 rsock.setblocking(False)
1688 old_wakeup_fd = signal.set_wakeup_fd(wsock.fileno())
1689 notifier = prepare_notifier(rsock)
1690
1691 def save_args_and_handle_sigint(*args):
1692 nonlocal handler_args, notifier
1693 handler_args = args
1694 handle_sigint(notifier)
1695 notifier = None
1696
1697 signal.signal(signal.SIGINT, save_args_and_handle_sigint)
1698 try:
1699 yield
1700 finally:
1701 wsock.close()
1702 rsock.close()
1703 signal.set_wakeup_fd(old_wakeup_fd)
1704 signal.signal(signal.SIGINT, old_sigint_handler)
1705 if handler_args is not None:
1706 old_sigint_handler(*handler_args)
1707

Callers 2

_allow_interrupt_macosFunction · 0.90
_allow_interrupt_qtFunction · 0.90

Calls 2

prepare_notifierFunction · 0.85
closeMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…