Merge pull request #130 from njsmith/restrict-ki-to-checkpoints · python-trio/trio@8fee2bc (original) (raw)
`@@ -1040,7 +1040,8 @@ def current_instruments(self):
`
1040
1040
`# run
`
1041
1041
`################################################################
`
1042
1042
``
1043
``
`-
def run(async_fn, *args, clock=None, instruments=[]):
`
``
1043
`+
def run(async_fn, *args, clock=None, instruments=[],
`
``
1044
`+
restrict_keyboard_interrupt_to_checkpoints=False):
`
1044
1045
`"""Run a trio-flavored async function, and return the result.
`
1045
1046
``
1046
1047
` Calling::
`
`@@ -1059,23 +1060,51 @@ def run(async_fn, *args, clock=None, instruments=[]):
`
1059
1060
``
1060
1061
` Args:
`
1061
1062
` async_fn: An async function.
`
``
1063
+
1062
1064
` args: Positional arguments to be passed to async_fn. If you need to
`
1063
1065
`` pass keyword arguments, then use :func:functools.partial
.
``
``
1066
+
1064
1067
``` clock: None
to use the default system-specific monotonic clock;
`1065`
`1068`
`` otherwise, an object implementing the :class:`trio.abc.Clock`
``
`1066`
`1069`
`` interface, like (for example) a :class:`trio.testing.MockClock`
``
`1067`
`1070`
` instance.
`
``
`1071`
`+`
`1068`
`1072`
`` instruments (list of :class:`trio.abc.Instrument` objects): Any
``
`1069`
`1073`
` instrumentation you want to apply to this run. This can also be
`
`1070`
`1074`
`` modified during the run; see :ref:`instrumentation`.
``
`1071`
`1075`
``
``
`1076`
`+
restrict_keyboard_interrupt_to_checkpoints (bool): What happens if the
`
``
`1077`
`` +
user hits control-C while :func:`run` is running? If this argument
``
``
`1078`
`+
is False (the default), then you get the standard Python behavior: a
`
``
`1079`
`` +
:exc:`KeyboardInterrupt` exception will immediately interrupt
``
``
`1080`
`+
whatever task is running (or if no task is running, then trio will
`
``
`1081`
`+
wake up a task to be interrupted). Alternatively, if you set this
`
``
`1082`
`` +
argument to True, then :exc:`KeyboardInterrupt` delivery will be
``
``
`1083`
`` +
delayed: it will be *only* be raised at :ref:`checkpoints
``
``
`1084`
`` +
<checkpoints>`, like a :exc:`Cancelled` exception.
``
``
`1085`
`+`
``
`1086`
`+
The default behavior is nice because it means that even if you
`
``
`1087`
`+
accidentally write an infinite loop that never executes any
`
``
`1088`
`+
checkpoints, then you can still break out of it using control-C. The
`
``
`1089`
`+
the alternative behavior is nice if you're paranoid about a
`
``
`1090`
`` +
:exc:`KeyboardInterrupt` at just the wrong place leaving your
``
``
`1091`
`+
program in an inconsistent state, because it means that you only
`
``
`1092`
`` +
have to worry about :exc:`KeyboardInterrupt` at the exact same
``
``
`1093`
`` +
places where you already have to worry about :exc:`Cancelled`.
``
``
`1094`
`+`
``
`1095`
`+
This setting has no effect if your program has registered a custom
`
``
`1096`
`` +
SIGINT handler, or if :func:`run` is called from anywhere but the
``
``
`1097`
`+
main thread (this is a Python limitation), or if you use
`
``
`1098`
`` +
:func:`catch_signals` to catch SIGINT.
``
``
`1099`
`+`
`1072`
`1100`
` Returns:
`
`1073`
`1101`
``` Whatever ``async_fn`` returns.
1074
1102
``
1075
1103
` Raises:
`
1076
1104
` TrioInternalError: if an unexpected error is encountered inside trio's
`
1077
1105
`` internal machinery. This is a bug and you should `let us know
``
1078
1106
`` https://github.com/python-trio/trio/issues`__.
``
``
1107
+
1079
1108
``` Anything else: if async_fn
raises an exception, then :func:run
```
1080
1109
` propagates it.
`
1081
1110
``
`@@ -1114,7 +1143,8 @@ def run(async_fn, *args, clock=None, instruments=[]):
`
1114
1143
`# where KeyboardInterrupt would be allowed and converted into an
`
1115
1144
`# TrioInternalError:
`
1116
1145
`try:
`
1117
``
`-
with ki_manager(runner.deliver_ki):
`
``
1146
`+
with ki_manager(
`
``
1147
`+
runner.deliver_ki, restrict_keyboard_interrupt_to_checkpoints):
`
1118
1148
`try:
`
1119
1149
`with closing(runner):
`
1120
1150
`# The main reason this is split off into its own function
`