ยปCore Development>Code coverage>Modules/_asynciomodule.c

Python code coverage for Modules/_asynciomodule.c

#countcontent
1n/a#include "Python.h"
2n/a#include "structmember.h"
3n/a
4n/a
5n/a/*[clinic input]
6n/amodule _asyncio
7n/a[clinic start generated code]*/
8n/a/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fd17862aa989c69]*/
9n/a
10n/a
11n/a/* identifiers used from some functions */
12n/a_Py_IDENTIFIER(add_done_callback);
13n/a_Py_IDENTIFIER(call_soon);
14n/a_Py_IDENTIFIER(cancel);
15n/a_Py_IDENTIFIER(send);
16n/a_Py_IDENTIFIER(throw);
17n/a_Py_IDENTIFIER(_step);
18n/a_Py_IDENTIFIER(_schedule_callbacks);
19n/a_Py_IDENTIFIER(_wakeup);
20n/a
21n/a
22n/a/* State of the _asyncio module */
23n/astatic PyObject *all_tasks;
24n/astatic PyObject *current_tasks;
25n/astatic PyObject *traceback_extract_stack;
26n/astatic PyObject *asyncio_get_event_loop;
27n/astatic PyObject *asyncio_future_repr_info_func;
28n/astatic PyObject *asyncio_task_repr_info_func;
29n/astatic PyObject *asyncio_task_get_stack_func;
30n/astatic PyObject *asyncio_task_print_stack_func;
31n/astatic PyObject *asyncio_InvalidStateError;
32n/astatic PyObject *asyncio_CancelledError;
33n/astatic PyObject *inspect_isgenerator;
34n/a
35n/a
36n/atypedef enum {
37n/a STATE_PENDING,
38n/a STATE_CANCELLED,
39n/a STATE_FINISHED
40n/a} fut_state;
41n/a
42n/a#define FutureObj_HEAD(prefix) \
43n/a PyObject_HEAD \
44n/a PyObject *prefix##_loop; \
45n/a PyObject *prefix##_callbacks; \
46n/a PyObject *prefix##_exception; \
47n/a PyObject *prefix##_result; \
48n/a PyObject *prefix##_source_tb; \
49n/a fut_state prefix##_state; \
50n/a int prefix##_log_tb; \
51n/a int prefix##_blocking; \
52n/a PyObject *dict; \
53n/a PyObject *prefix##_weakreflist;
54n/a
55n/atypedef struct {
56n/a FutureObj_HEAD(fut)
57n/a} FutureObj;
58n/a
59n/atypedef struct {
60n/a FutureObj_HEAD(task)
61n/a PyObject *task_fut_waiter;
62n/a PyObject *task_coro;
63n/a int task_must_cancel;
64n/a int task_log_destroy_pending;
65n/a} TaskObj;
66n/a
67n/atypedef struct {
68n/a PyObject_HEAD
69n/a TaskObj *sw_task;
70n/a PyObject *sw_arg;
71n/a} TaskSendMethWrapper;
72n/a
73n/atypedef struct {
74n/a PyObject_HEAD
75n/a TaskObj *ww_task;
76n/a} TaskWakeupMethWrapper;
77n/a
78n/a
79n/a#include "clinic/_asynciomodule.c.h"
80n/a
81n/a
82n/a/*[clinic input]
83n/aclass _asyncio.Future "FutureObj *" "&Future_Type"
84n/a[clinic start generated code]*/
85n/a/*[clinic end generated code: output=da39a3ee5e6b4b0d input=00d3e4abca711e0f]*/
86n/a
87n/a/* Get FutureIter from Future */
88n/astatic PyObject* future_new_iter(PyObject *);
89n/astatic inline int future_call_schedule_callbacks(FutureObj *);
90n/a
91n/astatic int
92n/afuture_schedule_callbacks(FutureObj *fut)
93n/a{
94n/a Py_ssize_t len;
95n/a PyObject* iters;
96n/a int i;
97n/a
98n/a if (fut->fut_callbacks == NULL) {
99n/a PyErr_SetString(PyExc_RuntimeError, "NULL callbacks");
100n/a return -1;
101n/a }
102n/a
103n/a len = PyList_GET_SIZE(fut->fut_callbacks);
104n/a if (len == 0) {
105n/a return 0;
106n/a }
107n/a
108n/a iters = PyList_GetSlice(fut->fut_callbacks, 0, len);
109n/a if (iters == NULL) {
110n/a return -1;
111n/a }
112n/a if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) {
113n/a Py_DECREF(iters);
114n/a return -1;
115n/a }
116n/a
117n/a for (i = 0; i < len; i++) {
118n/a PyObject *handle = NULL;
119n/a PyObject *cb = PyList_GET_ITEM(iters, i);
120n/a
121n/a handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop, &PyId_call_soon,
122n/a cb, fut, NULL);
123n/a
124n/a if (handle == NULL) {
125n/a Py_DECREF(iters);
126n/a return -1;
127n/a }
128n/a else {
129n/a Py_DECREF(handle);
130n/a }
131n/a }
132n/a
133n/a Py_DECREF(iters);
134n/a return 0;
135n/a}
136n/a
137n/astatic int
138n/afuture_init(FutureObj *fut, PyObject *loop)
139n/a{
140n/a PyObject *res = NULL;
141n/a _Py_IDENTIFIER(get_debug);
142n/a
143n/a if (loop == NULL || loop == Py_None) {
144n/a loop = _PyObject_CallNoArg(asyncio_get_event_loop);
145n/a if (loop == NULL) {
146n/a return -1;
147n/a }
148n/a }
149n/a else {
150n/a Py_INCREF(loop);
151n/a }
152n/a Py_CLEAR(fut->fut_loop);
153n/a fut->fut_loop = loop;
154n/a
155n/a res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
156n/a if (res == NULL) {
157n/a return -1;
158n/a }
159n/a if (PyObject_IsTrue(res)) {
160n/a Py_CLEAR(res);
161n/a fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
162n/a if (fut->fut_source_tb == NULL) {
163n/a return -1;
164n/a }
165n/a }
166n/a else {
167n/a Py_CLEAR(res);
168n/a }
169n/a
170n/a fut->fut_callbacks = PyList_New(0);
171n/a if (fut->fut_callbacks == NULL) {
172n/a return -1;
173n/a }
174n/a
175n/a return 0;
176n/a}
177n/a
178n/astatic PyObject *
179n/afuture_set_result(FutureObj *fut, PyObject *res)
180n/a{
181n/a if (fut->fut_state != STATE_PENDING) {
182n/a PyErr_SetString(asyncio_InvalidStateError, "invalid state");
183n/a return NULL;
184n/a }
185n/a
186n/a Py_INCREF(res);
187n/a fut->fut_result = res;
188n/a fut->fut_state = STATE_FINISHED;
189n/a
190n/a if (future_call_schedule_callbacks(fut) == -1) {
191n/a return NULL;
192n/a }
193n/a Py_RETURN_NONE;
194n/a}
195n/a
196n/astatic PyObject *
197n/afuture_set_exception(FutureObj *fut, PyObject *exc)
198n/a{
199n/a PyObject *exc_val = NULL;
200n/a
201n/a if (fut->fut_state != STATE_PENDING) {
202n/a PyErr_SetString(asyncio_InvalidStateError, "invalid state");
203n/a return NULL;
204n/a }
205n/a
206n/a if (PyExceptionClass_Check(exc)) {
207n/a exc_val = _PyObject_CallNoArg(exc);
208n/a if (exc_val == NULL) {
209n/a return NULL;
210n/a }
211n/a }
212n/a else {
213n/a exc_val = exc;
214n/a Py_INCREF(exc_val);
215n/a }
216n/a if (!PyExceptionInstance_Check(exc_val)) {
217n/a Py_DECREF(exc_val);
218n/a PyErr_SetString(PyExc_TypeError, "invalid exception object");
219n/a return NULL;
220n/a }
221n/a if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
222n/a Py_DECREF(exc_val);
223n/a PyErr_SetString(PyExc_TypeError,
224n/a "StopIteration interacts badly with generators "
225n/a "and cannot be raised into a Future");
226n/a return NULL;
227n/a }
228n/a
229n/a fut->fut_exception = exc_val;
230n/a fut->fut_state = STATE_FINISHED;
231n/a
232n/a if (future_call_schedule_callbacks(fut) == -1) {
233n/a return NULL;
234n/a }
235n/a
236n/a fut->fut_log_tb = 1;
237n/a Py_RETURN_NONE;
238n/a}
239n/a
240n/astatic int
241n/afuture_get_result(FutureObj *fut, PyObject **result)
242n/a{
243n/a PyObject *exc;
244n/a
245n/a if (fut->fut_state == STATE_CANCELLED) {
246n/a exc = _PyObject_CallNoArg(asyncio_CancelledError);
247n/a if (exc == NULL) {
248n/a return -1;
249n/a }
250n/a *result = exc;
251n/a return 1;
252n/a }
253n/a
254n/a if (fut->fut_state != STATE_FINISHED) {
255n/a PyObject *msg = PyUnicode_FromString("Result is not ready.");
256n/a if (msg == NULL) {
257n/a return -1;
258n/a }
259n/a
260n/a exc = PyObject_CallFunctionObjArgs(asyncio_InvalidStateError, msg, NULL);
261n/a Py_DECREF(msg);
262n/a if (exc == NULL) {
263n/a return -1;
264n/a }
265n/a
266n/a *result = exc;
267n/a return 1;
268n/a }
269n/a
270n/a fut->fut_log_tb = 0;
271n/a if (fut->fut_exception != NULL) {
272n/a Py_INCREF(fut->fut_exception);
273n/a *result = fut->fut_exception;
274n/a return 1;
275n/a }
276n/a
277n/a Py_INCREF(fut->fut_result);
278n/a *result = fut->fut_result;
279n/a return 0;
280n/a}
281n/a
282n/astatic PyObject *
283n/afuture_add_done_callback(FutureObj *fut, PyObject *arg)
284n/a{
285n/a if (fut->fut_state != STATE_PENDING) {
286n/a PyObject *handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop,
287n/a &PyId_call_soon,
288n/a arg, fut, NULL);
289n/a
290n/a if (handle == NULL) {
291n/a return NULL;
292n/a }
293n/a else {
294n/a Py_DECREF(handle);
295n/a }
296n/a }
297n/a else {
298n/a int err = PyList_Append(fut->fut_callbacks, arg);
299n/a if (err != 0) {
300n/a return NULL;
301n/a }
302n/a }
303n/a Py_RETURN_NONE;
304n/a}
305n/a
306n/astatic PyObject *
307n/afuture_cancel(FutureObj *fut)
308n/a{
309n/a if (fut->fut_state != STATE_PENDING) {
310n/a Py_RETURN_FALSE;
311n/a }
312n/a fut->fut_state = STATE_CANCELLED;
313n/a
314n/a if (future_call_schedule_callbacks(fut) == -1) {
315n/a return NULL;
316n/a }
317n/a
318n/a Py_RETURN_TRUE;
319n/a}
320n/a
321n/a/*[clinic input]
322n/a_asyncio.Future.__init__
323n/a
324n/a *
325n/a loop: 'O' = NULL
326n/a
327n/aThis class is *almost* compatible with concurrent.futures.Future.
328n/a
329n/a Differences:
330n/a
331n/a - result() and exception() do not take a timeout argument and
332n/a raise an exception when the future isn't done yet.
333n/a
334n/a - Callbacks registered with add_done_callback() are always called
335n/a via the event loop's call_soon_threadsafe().
336n/a
337n/a - This class is not compatible with the wait() and as_completed()
338n/a methods in the concurrent.futures package.
339n/a[clinic start generated code]*/
340n/a
341n/astatic int
342n/a_asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
343n/a/*[clinic end generated code: output=9ed75799eaccb5d6 input=8e1681f23605be2d]*/
344n/a
345n/a{
346n/a return future_init(self, loop);
347n/a}
348n/a
349n/astatic int
350n/aFutureObj_clear(FutureObj *fut)
351n/a{
352n/a Py_CLEAR(fut->fut_loop);
353n/a Py_CLEAR(fut->fut_callbacks);
354n/a Py_CLEAR(fut->fut_result);
355n/a Py_CLEAR(fut->fut_exception);
356n/a Py_CLEAR(fut->fut_source_tb);
357n/a Py_CLEAR(fut->dict);
358n/a return 0;
359n/a}
360n/a
361n/astatic int
362n/aFutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
363n/a{
364n/a Py_VISIT(fut->fut_loop);
365n/a Py_VISIT(fut->fut_callbacks);
366n/a Py_VISIT(fut->fut_result);
367n/a Py_VISIT(fut->fut_exception);
368n/a Py_VISIT(fut->fut_source_tb);
369n/a Py_VISIT(fut->dict);
370n/a return 0;
371n/a}
372n/a
373n/a/*[clinic input]
374n/a_asyncio.Future.result
375n/a
376n/aReturn the result this future represents.
377n/a
378n/aIf the future has been cancelled, raises CancelledError. If the
379n/afuture's result isn't yet available, raises InvalidStateError. If
380n/athe future is done and has an exception set, this exception is raised.
381n/a[clinic start generated code]*/
382n/a
383n/astatic PyObject *
384n/a_asyncio_Future_result_impl(FutureObj *self)
385n/a/*[clinic end generated code: output=f35f940936a4b1e5 input=49ecf9cf5ec50dc5]*/
386n/a{
387n/a PyObject *result;
388n/a int res = future_get_result(self, &result);
389n/a
390n/a if (res == -1) {
391n/a return NULL;
392n/a }
393n/a
394n/a if (res == 0) {
395n/a return result;
396n/a }
397n/a
398n/a assert(res == 1);
399n/a
400n/a PyErr_SetObject(PyExceptionInstance_Class(result), result);
401n/a Py_DECREF(result);
402n/a return NULL;
403n/a}
404n/a
405n/a/*[clinic input]
406n/a_asyncio.Future.exception
407n/a
408n/aReturn the exception that was set on this future.
409n/a
410n/aThe exception (or None if no exception was set) is returned only if
411n/athe future is done. If the future has been cancelled, raises
412n/aCancelledError. If the future isn't done yet, raises
413n/aInvalidStateError.
414n/a[clinic start generated code]*/
415n/a
416n/astatic PyObject *
417n/a_asyncio_Future_exception_impl(FutureObj *self)
418n/a/*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
419n/a{
420n/a if (self->fut_state == STATE_CANCELLED) {
421n/a PyErr_SetString(asyncio_CancelledError, "");
422n/a return NULL;
423n/a }
424n/a
425n/a if (self->fut_state != STATE_FINISHED) {
426n/a PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");
427n/a return NULL;
428n/a }
429n/a
430n/a if (self->fut_exception != NULL) {
431n/a self->fut_log_tb = 0;
432n/a Py_INCREF(self->fut_exception);
433n/a return self->fut_exception;
434n/a }
435n/a
436n/a Py_RETURN_NONE;
437n/a}
438n/a
439n/a/*[clinic input]
440n/a_asyncio.Future.set_result
441n/a
442n/a res: 'O'
443n/a /
444n/a
445n/aMark the future done and set its result.
446n/a
447n/aIf the future is already done when this method is called, raises
448n/aInvalidStateError.
449n/a[clinic start generated code]*/
450n/a
451n/astatic PyObject *
452n/a_asyncio_Future_set_result(FutureObj *self, PyObject *res)
453n/a/*[clinic end generated code: output=a620abfc2796bfb6 input=8619565e0503357e]*/
454n/a{
455n/a return future_set_result(self, res);
456n/a}
457n/a
458n/a/*[clinic input]
459n/a_asyncio.Future.set_exception
460n/a
461n/a exception: 'O'
462n/a /
463n/a
464n/aMark the future done and set an exception.
465n/a
466n/aIf the future is already done when this method is called, raises
467n/aInvalidStateError.
468n/a[clinic start generated code]*/
469n/a
470n/astatic PyObject *
471n/a_asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
472n/a/*[clinic end generated code: output=f1c1b0cd321be360 input=1377dbe15e6ea186]*/
473n/a{
474n/a return future_set_exception(self, exception);
475n/a}
476n/a
477n/a/*[clinic input]
478n/a_asyncio.Future.add_done_callback
479n/a
480n/a fn: 'O'
481n/a /
482n/a
483n/aAdd a callback to be run when the future becomes done.
484n/a
485n/aThe callback is called with a single argument - the future object. If
486n/athe future is already done when this is called, the callback is
487n/ascheduled with call_soon.
488n/a[clinic start generated code]*/
489n/a
490n/astatic PyObject *
491n/a_asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
492n/a/*[clinic end generated code: output=819e09629b2ec2b5 input=8cce187e32cec6a8]*/
493n/a{
494n/a return future_add_done_callback(self, fn);
495n/a}
496n/a
497n/a/*[clinic input]
498n/a_asyncio.Future.remove_done_callback
499n/a
500n/a fn: 'O'
501n/a /
502n/a
503n/aRemove all instances of a callback from the "call when done" list.
504n/a
505n/aReturns the number of callbacks removed.
506n/a[clinic start generated code]*/
507n/a
508n/astatic PyObject *
509n/a_asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
510n/a/*[clinic end generated code: output=5ab1fb52b24ef31f input=3fedb73e1409c31c]*/
511n/a{
512n/a PyObject *newlist;
513n/a Py_ssize_t len, i, j=0;
514n/a
515n/a len = PyList_GET_SIZE(self->fut_callbacks);
516n/a if (len == 0) {
517n/a return PyLong_FromSsize_t(0);
518n/a }
519n/a
520n/a newlist = PyList_New(len);
521n/a if (newlist == NULL) {
522n/a return NULL;
523n/a }
524n/a
525n/a for (i = 0; i < len; i++) {
526n/a int ret;
527n/a PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
528n/a
529n/a if ((ret = PyObject_RichCompareBool(fn, item, Py_EQ)) < 0) {
530n/a goto fail;
531n/a }
532n/a if (ret == 0) {
533n/a Py_INCREF(item);
534n/a PyList_SET_ITEM(newlist, j, item);
535n/a j++;
536n/a }
537n/a }
538n/a
539n/a if (PyList_SetSlice(newlist, j, len, NULL) < 0) {
540n/a goto fail;
541n/a }
542n/a if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
543n/a goto fail;
544n/a }
545n/a Py_DECREF(newlist);
546n/a return PyLong_FromSsize_t(len - j);
547n/a
548n/afail:
549n/a Py_DECREF(newlist);
550n/a return NULL;
551n/a}
552n/a
553n/a/*[clinic input]
554n/a_asyncio.Future.cancel
555n/a
556n/aCancel the future and schedule callbacks.
557n/a
558n/aIf the future is already done or cancelled, return False. Otherwise,
559n/achange the future's state to cancelled, schedule the callbacks and
560n/areturn True.
561n/a[clinic start generated code]*/
562n/a
563n/astatic PyObject *
564n/a_asyncio_Future_cancel_impl(FutureObj *self)
565n/a/*[clinic end generated code: output=e45b932ba8bd68a1 input=515709a127995109]*/
566n/a{
567n/a return future_cancel(self);
568n/a}
569n/a
570n/a/*[clinic input]
571n/a_asyncio.Future.cancelled
572n/a
573n/aReturn True if the future was cancelled.
574n/a[clinic start generated code]*/
575n/a
576n/astatic PyObject *
577n/a_asyncio_Future_cancelled_impl(FutureObj *self)
578n/a/*[clinic end generated code: output=145197ced586357d input=943ab8b7b7b17e45]*/
579n/a{
580n/a if (self->fut_state == STATE_CANCELLED) {
581n/a Py_RETURN_TRUE;
582n/a }
583n/a else {
584n/a Py_RETURN_FALSE;
585n/a }
586n/a}
587n/a
588n/a/*[clinic input]
589n/a_asyncio.Future.done
590n/a
591n/aReturn True if the future is done.
592n/a
593n/aDone means either that a result / exception are available, or that the
594n/afuture was cancelled.
595n/a[clinic start generated code]*/
596n/a
597n/astatic PyObject *
598n/a_asyncio_Future_done_impl(FutureObj *self)
599n/a/*[clinic end generated code: output=244c5ac351145096 input=28d7b23fdb65d2ac]*/
600n/a{
601n/a if (self->fut_state == STATE_PENDING) {
602n/a Py_RETURN_FALSE;
603n/a }
604n/a else {
605n/a Py_RETURN_TRUE;
606n/a }
607n/a}
608n/a
609n/astatic PyObject *
610n/aFutureObj_get_blocking(FutureObj *fut)
611n/a{
612n/a if (fut->fut_blocking) {
613n/a Py_RETURN_TRUE;
614n/a }
615n/a else {
616n/a Py_RETURN_FALSE;
617n/a }
618n/a}
619n/a
620n/astatic int
621n/aFutureObj_set_blocking(FutureObj *fut, PyObject *val)
622n/a{
623n/a int is_true = PyObject_IsTrue(val);
624n/a if (is_true < 0) {
625n/a return -1;
626n/a }
627n/a fut->fut_blocking = is_true;
628n/a return 0;
629n/a}
630n/a
631n/astatic PyObject *
632n/aFutureObj_get_log_traceback(FutureObj *fut)
633n/a{
634n/a if (fut->fut_log_tb) {
635n/a Py_RETURN_TRUE;
636n/a }
637n/a else {
638n/a Py_RETURN_FALSE;
639n/a }
640n/a}
641n/a
642n/astatic PyObject *
643n/aFutureObj_get_loop(FutureObj *fut)
644n/a{
645n/a if (fut->fut_loop == NULL) {
646n/a Py_RETURN_NONE;
647n/a }
648n/a Py_INCREF(fut->fut_loop);
649n/a return fut->fut_loop;
650n/a}
651n/a
652n/astatic PyObject *
653n/aFutureObj_get_callbacks(FutureObj *fut)
654n/a{
655n/a if (fut->fut_callbacks == NULL) {
656n/a Py_RETURN_NONE;
657n/a }
658n/a Py_INCREF(fut->fut_callbacks);
659n/a return fut->fut_callbacks;
660n/a}
661n/a
662n/astatic PyObject *
663n/aFutureObj_get_result(FutureObj *fut)
664n/a{
665n/a if (fut->fut_result == NULL) {
666n/a Py_RETURN_NONE;
667n/a }
668n/a Py_INCREF(fut->fut_result);
669n/a return fut->fut_result;
670n/a}
671n/a
672n/astatic PyObject *
673n/aFutureObj_get_exception(FutureObj *fut)
674n/a{
675n/a if (fut->fut_exception == NULL) {
676n/a Py_RETURN_NONE;
677n/a }
678n/a Py_INCREF(fut->fut_exception);
679n/a return fut->fut_exception;
680n/a}
681n/a
682n/astatic PyObject *
683n/aFutureObj_get_source_traceback(FutureObj *fut)
684n/a{
685n/a if (fut->fut_source_tb == NULL) {
686n/a Py_RETURN_NONE;
687n/a }
688n/a Py_INCREF(fut->fut_source_tb);
689n/a return fut->fut_source_tb;
690n/a}
691n/a
692n/astatic PyObject *
693n/aFutureObj_get_state(FutureObj *fut)
694n/a{
695n/a _Py_IDENTIFIER(PENDING);
696n/a _Py_IDENTIFIER(CANCELLED);
697n/a _Py_IDENTIFIER(FINISHED);
698n/a PyObject *ret = NULL;
699n/a
700n/a switch (fut->fut_state) {
701n/a case STATE_PENDING:
702n/a ret = _PyUnicode_FromId(&PyId_PENDING);
703n/a break;
704n/a case STATE_CANCELLED:
705n/a ret = _PyUnicode_FromId(&PyId_CANCELLED);
706n/a break;
707n/a case STATE_FINISHED:
708n/a ret = _PyUnicode_FromId(&PyId_FINISHED);
709n/a break;
710n/a default:
711n/a assert (0);
712n/a }
713n/a Py_INCREF(ret);
714n/a return ret;
715n/a}
716n/a
717n/a/*[clinic input]
718n/a_asyncio.Future._repr_info
719n/a[clinic start generated code]*/
720n/a
721n/astatic PyObject *
722n/a_asyncio_Future__repr_info_impl(FutureObj *self)
723n/a/*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/
724n/a{
725n/a return PyObject_CallFunctionObjArgs(
726n/a asyncio_future_repr_info_func, self, NULL);
727n/a}
728n/a
729n/a/*[clinic input]
730n/a_asyncio.Future._schedule_callbacks
731n/a[clinic start generated code]*/
732n/a
733n/astatic PyObject *
734n/a_asyncio_Future__schedule_callbacks_impl(FutureObj *self)
735n/a/*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
736n/a{
737n/a int ret = future_schedule_callbacks(self);
738n/a if (ret == -1) {
739n/a return NULL;
740n/a }
741n/a Py_RETURN_NONE;
742n/a}
743n/a
744n/astatic PyObject *
745n/aFutureObj_repr(FutureObj *fut)
746n/a{
747n/a _Py_IDENTIFIER(_repr_info);
748n/a
749n/a PyObject *_repr_info = _PyUnicode_FromId(&PyId__repr_info); // borrowed
750n/a if (_repr_info == NULL) {
751n/a return NULL;
752n/a }
753n/a
754n/a PyObject *rinfo = PyObject_CallMethodObjArgs((PyObject*)fut, _repr_info,
755n/a NULL);
756n/a if (rinfo == NULL) {
757n/a return NULL;
758n/a }
759n/a
760n/a PyObject *sp = PyUnicode_FromString(" ");
761n/a if (sp == NULL) {
762n/a Py_DECREF(rinfo);
763n/a return NULL;
764n/a }
765n/a
766n/a PyObject *rinfo_s = PyUnicode_Join(sp, rinfo);
767n/a Py_DECREF(sp);
768n/a Py_DECREF(rinfo);
769n/a if (rinfo_s == NULL) {
770n/a return NULL;
771n/a }
772n/a
773n/a PyObject *rstr = NULL;
774n/a PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
775n/a "__name__");
776n/a if (type_name != NULL) {
777n/a rstr = PyUnicode_FromFormat("<%S %S>", type_name, rinfo_s);
778n/a Py_DECREF(type_name);
779n/a }
780n/a Py_DECREF(rinfo_s);
781n/a return rstr;
782n/a}
783n/a
784n/astatic void
785n/aFutureObj_finalize(FutureObj *fut)
786n/a{
787n/a _Py_IDENTIFIER(call_exception_handler);
788n/a _Py_IDENTIFIER(message);
789n/a _Py_IDENTIFIER(exception);
790n/a _Py_IDENTIFIER(future);
791n/a _Py_IDENTIFIER(source_traceback);
792n/a
793n/a if (!fut->fut_log_tb) {
794n/a return;
795n/a }
796n/a assert(fut->fut_exception != NULL);
797n/a fut->fut_log_tb = 0;;
798n/a
799n/a PyObject *error_type, *error_value, *error_traceback;
800n/a /* Save the current exception, if any. */
801n/a PyErr_Fetch(&error_type, &error_value, &error_traceback);
802n/a
803n/a PyObject *context = NULL;
804n/a PyObject *type_name = NULL;
805n/a PyObject *message = NULL;
806n/a PyObject *func = NULL;
807n/a PyObject *res = NULL;
808n/a
809n/a context = PyDict_New();
810n/a if (context == NULL) {
811n/a goto finally;
812n/a }
813n/a
814n/a type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
815n/a if (type_name == NULL) {
816n/a goto finally;
817n/a }
818n/a
819n/a message = PyUnicode_FromFormat(
820n/a "%S exception was never retrieved", type_name);
821n/a if (message == NULL) {
822n/a goto finally;
823n/a }
824n/a
825n/a if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
826n/a _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
827n/a _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
828n/a goto finally;
829n/a }
830n/a if (fut->fut_source_tb != NULL) {
831n/a if (_PyDict_SetItemId(context, &PyId_source_traceback,
832n/a fut->fut_source_tb) < 0) {
833n/a goto finally;
834n/a }
835n/a }
836n/a
837n/a func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
838n/a if (func != NULL) {
839n/a res = PyObject_CallFunctionObjArgs(func, context, NULL);
840n/a if (res == NULL) {
841n/a PyErr_WriteUnraisable(func);
842n/a }
843n/a }
844n/a
845n/afinally:
846n/a Py_CLEAR(context);
847n/a Py_CLEAR(type_name);
848n/a Py_CLEAR(message);
849n/a Py_CLEAR(func);
850n/a Py_CLEAR(res);
851n/a
852n/a /* Restore the saved exception. */
853n/a PyErr_Restore(error_type, error_value, error_traceback);
854n/a}
855n/a
856n/a
857n/astatic PyAsyncMethods FutureType_as_async = {
858n/a (unaryfunc)future_new_iter, /* am_await */
859n/a 0, /* am_aiter */
860n/a 0 /* am_anext */
861n/a};
862n/a
863n/astatic PyMethodDef FutureType_methods[] = {
864n/a _ASYNCIO_FUTURE_RESULT_METHODDEF
865n/a _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
866n/a _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
867n/a _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
868n/a _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
869n/a _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
870n/a _ASYNCIO_FUTURE_CANCEL_METHODDEF
871n/a _ASYNCIO_FUTURE_CANCELLED_METHODDEF
872n/a _ASYNCIO_FUTURE_DONE_METHODDEF
873n/a _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
874n/a _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
875n/a {NULL, NULL} /* Sentinel */
876n/a};
877n/a
878n/a#define FUTURE_COMMON_GETSETLIST \
879n/a {"_state", (getter)FutureObj_get_state, NULL, NULL}, \
880n/a {"_asyncio_future_blocking", (getter)FutureObj_get_blocking, \
881n/a (setter)FutureObj_set_blocking, NULL}, \
882n/a {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, \
883n/a {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL}, \
884n/a {"_result", (getter)FutureObj_get_result, NULL, NULL}, \
885n/a {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, \
886n/a {"_log_traceback", (getter)FutureObj_get_log_traceback, NULL, NULL}, \
887n/a {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
888n/a
889n/astatic PyGetSetDef FutureType_getsetlist[] = {
890n/a FUTURE_COMMON_GETSETLIST
891n/a {NULL} /* Sentinel */
892n/a};
893n/a
894n/astatic void FutureObj_dealloc(PyObject *self);
895n/a
896n/astatic PyTypeObject FutureType = {
897n/a PyVarObject_HEAD_INIT(NULL, 0)
898n/a "_asyncio.Future",
899n/a sizeof(FutureObj), /* tp_basicsize */
900n/a .tp_dealloc = FutureObj_dealloc,
901n/a .tp_as_async = &FutureType_as_async,
902n/a .tp_repr = (reprfunc)FutureObj_repr,
903n/a .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
904n/a | Py_TPFLAGS_HAVE_FINALIZE,
905n/a .tp_doc = _asyncio_Future___init____doc__,
906n/a .tp_traverse = (traverseproc)FutureObj_traverse,
907n/a .tp_clear = (inquiry)FutureObj_clear,
908n/a .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
909n/a .tp_iter = (getiterfunc)future_new_iter,
910n/a .tp_methods = FutureType_methods,
911n/a .tp_getset = FutureType_getsetlist,
912n/a .tp_dictoffset = offsetof(FutureObj, dict),
913n/a .tp_init = (initproc)_asyncio_Future___init__,
914n/a .tp_new = PyType_GenericNew,
915n/a .tp_finalize = (destructor)FutureObj_finalize,
916n/a};
917n/a
918n/a#define Future_CheckExact(obj) (Py_TYPE(obj) == &FutureType)
919n/a
920n/astatic inline int
921n/afuture_call_schedule_callbacks(FutureObj *fut)
922n/a{
923n/a if (Future_CheckExact(fut)) {
924n/a return future_schedule_callbacks(fut);
925n/a }
926n/a else {
927n/a /* `fut` is a subclass of Future */
928n/a PyObject *ret = _PyObject_CallMethodId(
929n/a (PyObject*)fut, &PyId__schedule_callbacks, NULL);
930n/a if (ret == NULL) {
931n/a return -1;
932n/a }
933n/a
934n/a Py_DECREF(ret);
935n/a return 0;
936n/a }
937n/a}
938n/a
939n/astatic void
940n/aFutureObj_dealloc(PyObject *self)
941n/a{
942n/a FutureObj *fut = (FutureObj *)self;
943n/a
944n/a if (Future_CheckExact(fut)) {
945n/a /* When fut is subclass of Future, finalizer is called from
946n/a * subtype_dealloc.
947n/a */
948n/a if (PyObject_CallFinalizerFromDealloc(self) < 0) {
949n/a // resurrected.
950n/a return;
951n/a }
952n/a }
953n/a
954n/a if (fut->fut_weakreflist != NULL) {
955n/a PyObject_ClearWeakRefs(self);
956n/a }
957n/a
958n/a (void)FutureObj_clear(fut);
959n/a Py_TYPE(fut)->tp_free(fut);
960n/a}
961n/a
962n/a
963n/a/*********************** Future Iterator **************************/
964n/a
965n/atypedef struct {
966n/a PyObject_HEAD
967n/a FutureObj *future;
968n/a} futureiterobject;
969n/a
970n/astatic void
971n/aFutureIter_dealloc(futureiterobject *it)
972n/a{
973n/a PyObject_GC_UnTrack(it);
974n/a Py_XDECREF(it->future);
975n/a PyObject_GC_Del(it);
976n/a}
977n/a
978n/astatic PyObject *
979n/aFutureIter_iternext(futureiterobject *it)
980n/a{
981n/a PyObject *res;
982n/a FutureObj *fut = it->future;
983n/a
984n/a if (fut == NULL) {
985n/a return NULL;
986n/a }
987n/a
988n/a if (fut->fut_state == STATE_PENDING) {
989n/a if (!fut->fut_blocking) {
990n/a fut->fut_blocking = 1;
991n/a Py_INCREF(fut);
992n/a return (PyObject *)fut;
993n/a }
994n/a PyErr_Format(PyExc_AssertionError,
995n/a "yield from wasn't used with future");
996n/a return NULL;
997n/a }
998n/a
999n/a res = _asyncio_Future_result_impl(fut);
1000n/a if (res != NULL) {
1001n/a /* The result of the Future is not an exception. */
1002n/a if (_PyGen_SetStopIterationValue(res) < 0) {
1003n/a Py_DECREF(res);
1004n/a return NULL;
1005n/a }
1006n/a Py_DECREF(res);
1007n/a }
1008n/a
1009n/a it->future = NULL;
1010n/a Py_DECREF(fut);
1011n/a return NULL;
1012n/a}
1013n/a
1014n/astatic PyObject *
1015n/aFutureIter_send(futureiterobject *self, PyObject *unused)
1016n/a{
1017n/a /* Future.__iter__ doesn't care about values that are pushed to the
1018n/a * generator, it just returns "self.result().
1019n/a */
1020n/a return FutureIter_iternext(self);
1021n/a}
1022n/a
1023n/astatic PyObject *
1024n/aFutureIter_throw(futureiterobject *self, PyObject *args)
1025n/a{
1026n/a PyObject *type=NULL, *val=NULL, *tb=NULL;
1027n/a if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
1028n/a return NULL;
1029n/a
1030n/a if (val == Py_None) {
1031n/a val = NULL;
1032n/a }
1033n/a if (tb == Py_None) {
1034n/a tb = NULL;
1035n/a } else if (tb != NULL && !PyTraceBack_Check(tb)) {
1036n/a PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback");
1037n/a return NULL;
1038n/a }
1039n/a
1040n/a Py_INCREF(type);
1041n/a Py_XINCREF(val);
1042n/a Py_XINCREF(tb);
1043n/a
1044n/a if (PyExceptionClass_Check(type)) {
1045n/a PyErr_NormalizeException(&type, &val, &tb);
1046n/a /* No need to call PyException_SetTraceback since we'll be calling
1047n/a PyErr_Restore for `type`, `val`, and `tb`. */
1048n/a } else if (PyExceptionInstance_Check(type)) {
1049n/a if (val) {
1050n/a PyErr_SetString(PyExc_TypeError,
1051n/a "instance exception may not have a separate value");
1052n/a goto fail;
1053n/a }
1054n/a val = type;
1055n/a type = PyExceptionInstance_Class(type);
1056n/a Py_INCREF(type);
1057n/a if (tb == NULL)
1058n/a tb = PyException_GetTraceback(val);
1059n/a } else {
1060n/a PyErr_SetString(PyExc_TypeError,
1061n/a "exceptions must be classes deriving BaseException or "
1062n/a "instances of such a class");
1063n/a goto fail;
1064n/a }
1065n/a
1066n/a Py_CLEAR(self->future);
1067n/a
1068n/a PyErr_Restore(type, val, tb);
1069n/a
1070n/a return FutureIter_iternext(self);
1071n/a
1072n/a fail:
1073n/a Py_DECREF(type);
1074n/a Py_XDECREF(val);
1075n/a Py_XDECREF(tb);
1076n/a return NULL;
1077n/a}
1078n/a
1079n/astatic PyObject *
1080n/aFutureIter_close(futureiterobject *self, PyObject *arg)
1081n/a{
1082n/a Py_CLEAR(self->future);
1083n/a Py_RETURN_NONE;
1084n/a}
1085n/a
1086n/astatic int
1087n/aFutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
1088n/a{
1089n/a Py_VISIT(it->future);
1090n/a return 0;
1091n/a}
1092n/a
1093n/astatic PyMethodDef FutureIter_methods[] = {
1094n/a {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
1095n/a {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
1096n/a {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
1097n/a {NULL, NULL} /* Sentinel */
1098n/a};
1099n/a
1100n/astatic PyTypeObject FutureIterType = {
1101n/a PyVarObject_HEAD_INIT(NULL, 0)
1102n/a "_asyncio.FutureIter",
1103n/a .tp_basicsize = sizeof(futureiterobject),
1104n/a .tp_itemsize = 0,
1105n/a .tp_dealloc = (destructor)FutureIter_dealloc,
1106n/a .tp_getattro = PyObject_GenericGetAttr,
1107n/a .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1108n/a .tp_traverse = (traverseproc)FutureIter_traverse,
1109n/a .tp_iter = PyObject_SelfIter,
1110n/a .tp_iternext = (iternextfunc)FutureIter_iternext,
1111n/a .tp_methods = FutureIter_methods,
1112n/a};
1113n/a
1114n/astatic PyObject *
1115n/afuture_new_iter(PyObject *fut)
1116n/a{
1117n/a futureiterobject *it;
1118n/a
1119n/a if (!PyObject_TypeCheck(fut, &FutureType)) {
1120n/a PyErr_BadInternalCall();
1121n/a return NULL;
1122n/a }
1123n/a it = PyObject_GC_New(futureiterobject, &FutureIterType);
1124n/a if (it == NULL) {
1125n/a return NULL;
1126n/a }
1127n/a Py_INCREF(fut);
1128n/a it->future = (FutureObj*)fut;
1129n/a PyObject_GC_Track(it);
1130n/a return (PyObject*)it;
1131n/a}
1132n/a
1133n/a
1134n/a/*********************** Task **************************/
1135n/a
1136n/a
1137n/a/*[clinic input]
1138n/aclass _asyncio.Task "TaskObj *" "&Task_Type"
1139n/a[clinic start generated code]*/
1140n/a/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
1141n/a
1142n/astatic int task_call_step_soon(TaskObj *, PyObject *);
1143n/astatic inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
1144n/astatic inline PyObject * task_call_step(TaskObj *, PyObject *);
1145n/astatic PyObject * task_wakeup(TaskObj *, PyObject *);
1146n/astatic PyObject * task_step(TaskObj *, PyObject *);
1147n/a
1148n/a/* ----- Task._step wrapper */
1149n/a
1150n/astatic int
1151n/aTaskSendMethWrapper_clear(TaskSendMethWrapper *o)
1152n/a{
1153n/a Py_CLEAR(o->sw_task);
1154n/a Py_CLEAR(o->sw_arg);
1155n/a return 0;
1156n/a}
1157n/a
1158n/astatic void
1159n/aTaskSendMethWrapper_dealloc(TaskSendMethWrapper *o)
1160n/a{
1161n/a PyObject_GC_UnTrack(o);
1162n/a (void)TaskSendMethWrapper_clear(o);
1163n/a Py_TYPE(o)->tp_free(o);
1164n/a}
1165n/a
1166n/astatic PyObject *
1167n/aTaskSendMethWrapper_call(TaskSendMethWrapper *o,
1168n/a PyObject *args, PyObject *kwds)
1169n/a{
1170n/a return task_call_step(o->sw_task, o->sw_arg);
1171n/a}
1172n/a
1173n/astatic int
1174n/aTaskSendMethWrapper_traverse(TaskSendMethWrapper *o,
1175n/a visitproc visit, void *arg)
1176n/a{
1177n/a Py_VISIT(o->sw_task);
1178n/a Py_VISIT(o->sw_arg);
1179n/a return 0;
1180n/a}
1181n/a
1182n/astatic PyObject *
1183n/aTaskSendMethWrapper_get___self__(TaskSendMethWrapper *o)
1184n/a{
1185n/a if (o->sw_task) {
1186n/a Py_INCREF(o->sw_task);
1187n/a return (PyObject*)o->sw_task;
1188n/a }
1189n/a Py_RETURN_NONE;
1190n/a}
1191n/a
1192n/astatic PyGetSetDef TaskSendMethWrapper_getsetlist[] = {
1193n/a {"__self__", (getter)TaskSendMethWrapper_get___self__, NULL, NULL},
1194n/a {NULL} /* Sentinel */
1195n/a};
1196n/a
1197n/aPyTypeObject TaskSendMethWrapper_Type = {
1198n/a PyVarObject_HEAD_INIT(NULL, 0)
1199n/a "TaskSendMethWrapper",
1200n/a .tp_basicsize = sizeof(TaskSendMethWrapper),
1201n/a .tp_itemsize = 0,
1202n/a .tp_getset = TaskSendMethWrapper_getsetlist,
1203n/a .tp_dealloc = (destructor)TaskSendMethWrapper_dealloc,
1204n/a .tp_call = (ternaryfunc)TaskSendMethWrapper_call,
1205n/a .tp_getattro = PyObject_GenericGetAttr,
1206n/a .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1207n/a .tp_traverse = (traverseproc)TaskSendMethWrapper_traverse,
1208n/a .tp_clear = (inquiry)TaskSendMethWrapper_clear,
1209n/a};
1210n/a
1211n/astatic PyObject *
1212n/aTaskSendMethWrapper_new(TaskObj *task, PyObject *arg)
1213n/a{
1214n/a TaskSendMethWrapper *o;
1215n/a o = PyObject_GC_New(TaskSendMethWrapper, &TaskSendMethWrapper_Type);
1216n/a if (o == NULL) {
1217n/a return NULL;
1218n/a }
1219n/a
1220n/a Py_INCREF(task);
1221n/a o->sw_task = task;
1222n/a
1223n/a Py_XINCREF(arg);
1224n/a o->sw_arg = arg;
1225n/a
1226n/a PyObject_GC_Track(o);
1227n/a return (PyObject*) o;
1228n/a}
1229n/a
1230n/a/* ----- Task._wakeup wrapper */
1231n/a
1232n/astatic PyObject *
1233n/aTaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
1234n/a PyObject *args, PyObject *kwds)
1235n/a{
1236n/a PyObject *fut;
1237n/a
1238n/a if (!PyArg_ParseTuple(args, "O|", &fut)) {
1239n/a return NULL;
1240n/a }
1241n/a
1242n/a return task_call_wakeup(o->ww_task, fut);
1243n/a}
1244n/a
1245n/astatic int
1246n/aTaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o)
1247n/a{
1248n/a Py_CLEAR(o->ww_task);
1249n/a return 0;
1250n/a}
1251n/a
1252n/astatic int
1253n/aTaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o,
1254n/a visitproc visit, void *arg)
1255n/a{
1256n/a Py_VISIT(o->ww_task);
1257n/a return 0;
1258n/a}
1259n/a
1260n/astatic void
1261n/aTaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o)
1262n/a{
1263n/a PyObject_GC_UnTrack(o);
1264n/a (void)TaskWakeupMethWrapper_clear(o);
1265n/a Py_TYPE(o)->tp_free(o);
1266n/a}
1267n/a
1268n/aPyTypeObject TaskWakeupMethWrapper_Type = {
1269n/a PyVarObject_HEAD_INIT(NULL, 0)
1270n/a "TaskWakeupMethWrapper",
1271n/a .tp_basicsize = sizeof(TaskWakeupMethWrapper),
1272n/a .tp_itemsize = 0,
1273n/a .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc,
1274n/a .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call,
1275n/a .tp_getattro = PyObject_GenericGetAttr,
1276n/a .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1277n/a .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse,
1278n/a .tp_clear = (inquiry)TaskWakeupMethWrapper_clear,
1279n/a};
1280n/a
1281n/astatic PyObject *
1282n/aTaskWakeupMethWrapper_new(TaskObj *task)
1283n/a{
1284n/a TaskWakeupMethWrapper *o;
1285n/a o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type);
1286n/a if (o == NULL) {
1287n/a return NULL;
1288n/a }
1289n/a
1290n/a Py_INCREF(task);
1291n/a o->ww_task = task;
1292n/a
1293n/a PyObject_GC_Track(o);
1294n/a return (PyObject*) o;
1295n/a}
1296n/a
1297n/a/* ----- Task */
1298n/a
1299n/a/*[clinic input]
1300n/a_asyncio.Task.__init__
1301n/a
1302n/a coro: 'O'
1303n/a *
1304n/a loop: 'O' = NULL
1305n/a
1306n/aA coroutine wrapped in a Future.
1307n/a[clinic start generated code]*/
1308n/a
1309n/astatic int
1310n/a_asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
1311n/a/*[clinic end generated code: output=9f24774c2287fc2f input=71d8d28c201a18cd]*/
1312n/a{
1313n/a PyObject *res;
1314n/a _Py_IDENTIFIER(add);
1315n/a
1316n/a if (future_init((FutureObj*)self, loop)) {
1317n/a return -1;
1318n/a }
1319n/a
1320n/a self->task_fut_waiter = NULL;
1321n/a self->task_must_cancel = 0;
1322n/a self->task_log_destroy_pending = 1;
1323n/a
1324n/a Py_INCREF(coro);
1325n/a self->task_coro = coro;
1326n/a
1327n/a if (task_call_step_soon(self, NULL)) {
1328n/a return -1;
1329n/a }
1330n/a
1331n/a res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_add, self, NULL);
1332n/a if (res == NULL) {
1333n/a return -1;
1334n/a }
1335n/a Py_DECREF(res);
1336n/a
1337n/a return 0;
1338n/a}
1339n/a
1340n/astatic int
1341n/aTaskObj_clear(TaskObj *task)
1342n/a{
1343n/a (void)FutureObj_clear((FutureObj*) task);
1344n/a Py_CLEAR(task->task_coro);
1345n/a Py_CLEAR(task->task_fut_waiter);
1346n/a return 0;
1347n/a}
1348n/a
1349n/astatic int
1350n/aTaskObj_traverse(TaskObj *task, visitproc visit, void *arg)
1351n/a{
1352n/a Py_VISIT(task->task_coro);
1353n/a Py_VISIT(task->task_fut_waiter);
1354n/a (void)FutureObj_traverse((FutureObj*) task, visit, arg);
1355n/a return 0;
1356n/a}
1357n/a
1358n/astatic PyObject *
1359n/aTaskObj_get_log_destroy_pending(TaskObj *task)
1360n/a{
1361n/a if (task->task_log_destroy_pending) {
1362n/a Py_RETURN_TRUE;
1363n/a }
1364n/a else {
1365n/a Py_RETURN_FALSE;
1366n/a }
1367n/a}
1368n/a
1369n/astatic int
1370n/aTaskObj_set_log_destroy_pending(TaskObj *task, PyObject *val)
1371n/a{
1372n/a int is_true = PyObject_IsTrue(val);
1373n/a if (is_true < 0) {
1374n/a return -1;
1375n/a }
1376n/a task->task_log_destroy_pending = is_true;
1377n/a return 0;
1378n/a}
1379n/a
1380n/astatic PyObject *
1381n/aTaskObj_get_must_cancel(TaskObj *task)
1382n/a{
1383n/a if (task->task_must_cancel) {
1384n/a Py_RETURN_TRUE;
1385n/a }
1386n/a else {
1387n/a Py_RETURN_FALSE;
1388n/a }
1389n/a}
1390n/a
1391n/astatic PyObject *
1392n/aTaskObj_get_coro(TaskObj *task)
1393n/a{
1394n/a if (task->task_coro) {
1395n/a Py_INCREF(task->task_coro);
1396n/a return task->task_coro;
1397n/a }
1398n/a
1399n/a Py_RETURN_NONE;
1400n/a}
1401n/a
1402n/astatic PyObject *
1403n/aTaskObj_get_fut_waiter(TaskObj *task)
1404n/a{
1405n/a if (task->task_fut_waiter) {
1406n/a Py_INCREF(task->task_fut_waiter);
1407n/a return task->task_fut_waiter;
1408n/a }
1409n/a
1410n/a Py_RETURN_NONE;
1411n/a}
1412n/a
1413n/a/*[clinic input]
1414n/a@classmethod
1415n/a_asyncio.Task.current_task
1416n/a
1417n/a loop: 'O' = NULL
1418n/a
1419n/aReturn the currently running task in an event loop or None.
1420n/a
1421n/aBy default the current task for the current event loop is returned.
1422n/a
1423n/aNone is returned when called not in the context of a Task.
1424n/a[clinic start generated code]*/
1425n/a
1426n/astatic PyObject *
1427n/a_asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
1428n/a/*[clinic end generated code: output=99fbe7332c516e03 input=cd784537f02cf833]*/
1429n/a{
1430n/a PyObject *res;
1431n/a
1432n/a if (loop == NULL) {
1433n/a loop = _PyObject_CallNoArg(asyncio_get_event_loop);
1434n/a if (loop == NULL) {
1435n/a return NULL;
1436n/a }
1437n/a
1438n/a res = PyDict_GetItem(current_tasks, loop);
1439n/a Py_DECREF(loop);
1440n/a }
1441n/a else {
1442n/a res = PyDict_GetItem(current_tasks, loop);
1443n/a }
1444n/a
1445n/a if (res == NULL) {
1446n/a Py_RETURN_NONE;
1447n/a }
1448n/a else {
1449n/a Py_INCREF(res);
1450n/a return res;
1451n/a }
1452n/a}
1453n/a
1454n/astatic PyObject *
1455n/atask_all_tasks(PyObject *loop)
1456n/a{
1457n/a PyObject *task;
1458n/a PyObject *task_loop;
1459n/a PyObject *set;
1460n/a PyObject *iter;
1461n/a
1462n/a assert(loop != NULL);
1463n/a
1464n/a set = PySet_New(NULL);
1465n/a if (set == NULL) {
1466n/a return NULL;
1467n/a }
1468n/a
1469n/a iter = PyObject_GetIter(all_tasks);
1470n/a if (iter == NULL) {
1471n/a goto fail;
1472n/a }
1473n/a
1474n/a while ((task = PyIter_Next(iter))) {
1475n/a task_loop = PyObject_GetAttrString(task, "_loop");
1476n/a if (task_loop == NULL) {
1477n/a Py_DECREF(task);
1478n/a goto fail;
1479n/a }
1480n/a if (task_loop == loop) {
1481n/a if (PySet_Add(set, task) == -1) {
1482n/a Py_DECREF(task_loop);
1483n/a Py_DECREF(task);
1484n/a goto fail;
1485n/a }
1486n/a }
1487n/a Py_DECREF(task_loop);
1488n/a Py_DECREF(task);
1489n/a }
1490n/a
1491n/a Py_DECREF(iter);
1492n/a return set;
1493n/a
1494n/afail:
1495n/a Py_XDECREF(set);
1496n/a Py_XDECREF(iter);
1497n/a return NULL;
1498n/a}
1499n/a
1500n/a/*[clinic input]
1501n/a@classmethod
1502n/a_asyncio.Task.all_tasks
1503n/a
1504n/a loop: 'O' = NULL
1505n/a
1506n/aReturn a set of all tasks for an event loop.
1507n/a
1508n/aBy default all tasks for the current event loop are returned.
1509n/a[clinic start generated code]*/
1510n/a
1511n/astatic PyObject *
1512n/a_asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
1513n/a/*[clinic end generated code: output=11f9b20749ccca5d input=cd64aa5f88bd5c49]*/
1514n/a{
1515n/a PyObject *res;
1516n/a
1517n/a if (loop == NULL) {
1518n/a loop = _PyObject_CallNoArg(asyncio_get_event_loop);
1519n/a if (loop == NULL) {
1520n/a return NULL;
1521n/a }
1522n/a
1523n/a res = task_all_tasks(loop);
1524n/a Py_DECREF(loop);
1525n/a }
1526n/a else {
1527n/a res = task_all_tasks(loop);
1528n/a }
1529n/a
1530n/a return res;
1531n/a}
1532n/a
1533n/a/*[clinic input]
1534n/a_asyncio.Task._repr_info
1535n/a[clinic start generated code]*/
1536n/a
1537n/astatic PyObject *
1538n/a_asyncio_Task__repr_info_impl(TaskObj *self)
1539n/a/*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/
1540n/a{
1541n/a return PyObject_CallFunctionObjArgs(
1542n/a asyncio_task_repr_info_func, self, NULL);
1543n/a}
1544n/a
1545n/a/*[clinic input]
1546n/a_asyncio.Task.cancel
1547n/a
1548n/aRequest that this task cancel itself.
1549n/a
1550n/aThis arranges for a CancelledError to be thrown into the
1551n/awrapped coroutine on the next cycle through the event loop.
1552n/aThe coroutine then has a chance to clean up or even deny
1553n/athe request using try/except/finally.
1554n/a
1555n/aUnlike Future.cancel, this does not guarantee that the
1556n/atask will be cancelled: the exception might be caught and
1557n/aacted upon, delaying cancellation of the task or preventing
1558n/acancellation completely. The task may also return a value or
1559n/araise a different exception.
1560n/a
1561n/aImmediately after this method is called, Task.cancelled() will
1562n/anot return True (unless the task was already cancelled). A
1563n/atask will be marked as cancelled when the wrapped coroutine
1564n/aterminates with a CancelledError exception (even if cancel()
1565n/awas not called).
1566n/a[clinic start generated code]*/
1567n/a
1568n/astatic PyObject *
1569n/a_asyncio_Task_cancel_impl(TaskObj *self)
1570n/a/*[clinic end generated code: output=6bfc0479da9d5757 input=13f9bf496695cb52]*/
1571n/a{
1572n/a if (self->task_state != STATE_PENDING) {
1573n/a Py_RETURN_FALSE;
1574n/a }
1575n/a
1576n/a if (self->task_fut_waiter) {
1577n/a PyObject *res;
1578n/a int is_true;
1579n/a
1580n/a res = _PyObject_CallMethodId(
1581n/a self->task_fut_waiter, &PyId_cancel, NULL);
1582n/a if (res == NULL) {
1583n/a return NULL;
1584n/a }
1585n/a
1586n/a is_true = PyObject_IsTrue(res);
1587n/a Py_DECREF(res);
1588n/a if (is_true < 0) {
1589n/a return NULL;
1590n/a }
1591n/a
1592n/a if (is_true) {
1593n/a Py_RETURN_TRUE;
1594n/a }
1595n/a }
1596n/a
1597n/a self->task_must_cancel = 1;
1598n/a Py_RETURN_TRUE;
1599n/a}
1600n/a
1601n/a/*[clinic input]
1602n/a_asyncio.Task.get_stack
1603n/a
1604n/a *
1605n/a limit: 'O' = None
1606n/a
1607n/aReturn the list of stack frames for this task's coroutine.
1608n/a
1609n/aIf the coroutine is not done, this returns the stack where it is
1610n/asuspended. If the coroutine has completed successfully or was
1611n/acancelled, this returns an empty list. If the coroutine was
1612n/aterminated by an exception, this returns the list of traceback
1613n/aframes.
1614n/a
1615n/aThe frames are always ordered from oldest to newest.
1616n/a
1617n/aThe optional limit gives the maximum number of frames to
1618n/areturn; by default all available frames are returned. Its
1619n/ameaning differs depending on whether a stack or a traceback is
1620n/areturned: the newest frames of a stack are returned, but the
1621n/aoldest frames of a traceback are returned. (This matches the
1622n/abehavior of the traceback module.)
1623n/a
1624n/aFor reasons beyond our control, only one stack frame is
1625n/areturned for a suspended coroutine.
1626n/a[clinic start generated code]*/
1627n/a
1628n/astatic PyObject *
1629n/a_asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
1630n/a/*[clinic end generated code: output=c9aeeeebd1e18118 input=b1920230a766d17a]*/
1631n/a{
1632n/a return PyObject_CallFunctionObjArgs(
1633n/a asyncio_task_get_stack_func, self, limit, NULL);
1634n/a}
1635n/a
1636n/a/*[clinic input]
1637n/a_asyncio.Task.print_stack
1638n/a
1639n/a *
1640n/a limit: 'O' = None
1641n/a file: 'O' = None
1642n/a
1643n/aPrint the stack or traceback for this task's coroutine.
1644n/a
1645n/aThis produces output similar to that of the traceback module,
1646n/afor the frames retrieved by get_stack(). The limit argument
1647n/ais passed to get_stack(). The file argument is an I/O stream
1648n/ato which the output is written; by default output is written
1649n/ato sys.stderr.
1650n/a[clinic start generated code]*/
1651n/a
1652n/astatic PyObject *
1653n/a_asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
1654n/a PyObject *file)
1655n/a/*[clinic end generated code: output=7339e10314cd3f4d input=19f1e99ab5400bc3]*/
1656n/a{
1657n/a return PyObject_CallFunctionObjArgs(
1658n/a asyncio_task_print_stack_func, self, limit, file, NULL);
1659n/a}
1660n/a
1661n/a/*[clinic input]
1662n/a_asyncio.Task._step
1663n/a
1664n/a exc: 'O' = NULL
1665n/a[clinic start generated code]*/
1666n/a
1667n/astatic PyObject *
1668n/a_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
1669n/a/*[clinic end generated code: output=7ed23f0cefd5ae42 input=ada4b2324e5370af]*/
1670n/a{
1671n/a return task_step(self, exc == Py_None ? NULL : exc);
1672n/a}
1673n/a
1674n/a/*[clinic input]
1675n/a_asyncio.Task._wakeup
1676n/a
1677n/a fut: 'O'
1678n/a[clinic start generated code]*/
1679n/a
1680n/astatic PyObject *
1681n/a_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
1682n/a/*[clinic end generated code: output=75cb341c760fd071 input=11ee4918a5bdbf21]*/
1683n/a{
1684n/a return task_wakeup(self, fut);
1685n/a}
1686n/a
1687n/astatic void
1688n/aTaskObj_finalize(TaskObj *task)
1689n/a{
1690n/a _Py_IDENTIFIER(call_exception_handler);
1691n/a _Py_IDENTIFIER(task);
1692n/a _Py_IDENTIFIER(message);
1693n/a _Py_IDENTIFIER(source_traceback);
1694n/a
1695n/a PyObject *message = NULL;
1696n/a PyObject *context = NULL;
1697n/a PyObject *func = NULL;
1698n/a PyObject *res = NULL;
1699n/a
1700n/a PyObject *error_type, *error_value, *error_traceback;
1701n/a
1702n/a if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
1703n/a goto done;
1704n/a }
1705n/a
1706n/a /* Save the current exception, if any. */
1707n/a PyErr_Fetch(&error_type, &error_value, &error_traceback);
1708n/a
1709n/a context = PyDict_New();
1710n/a if (context == NULL) {
1711n/a goto finally;
1712n/a }
1713n/a
1714n/a message = PyUnicode_FromString("Task was destroyed but it is pending!");
1715n/a if (message == NULL) {
1716n/a goto finally;
1717n/a }
1718n/a
1719n/a if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
1720n/a _PyDict_SetItemId(context, &PyId_task, (PyObject*)task) < 0)
1721n/a {
1722n/a goto finally;
1723n/a }
1724n/a
1725n/a if (task->task_source_tb != NULL) {
1726n/a if (_PyDict_SetItemId(context, &PyId_source_traceback,
1727n/a task->task_source_tb) < 0)
1728n/a {
1729n/a goto finally;
1730n/a }
1731n/a }
1732n/a
1733n/a func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
1734n/a if (func != NULL) {
1735n/a res = PyObject_CallFunctionObjArgs(func, context, NULL);
1736n/a if (res == NULL) {
1737n/a PyErr_WriteUnraisable(func);
1738n/a }
1739n/a }
1740n/a
1741n/afinally:
1742n/a Py_CLEAR(context);
1743n/a Py_CLEAR(message);
1744n/a Py_CLEAR(func);
1745n/a Py_CLEAR(res);
1746n/a
1747n/a /* Restore the saved exception. */
1748n/a PyErr_Restore(error_type, error_value, error_traceback);
1749n/a
1750n/adone:
1751n/a FutureObj_finalize((FutureObj*)task);
1752n/a}
1753n/a
1754n/astatic void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
1755n/a
1756n/astatic PyMethodDef TaskType_methods[] = {
1757n/a _ASYNCIO_FUTURE_RESULT_METHODDEF
1758n/a _ASYNCIO_FUTURE_EXCEPTION_METHODDEF
1759n/a _ASYNCIO_FUTURE_SET_RESULT_METHODDEF
1760n/a _ASYNCIO_FUTURE_SET_EXCEPTION_METHODDEF
1761n/a _ASYNCIO_FUTURE_ADD_DONE_CALLBACK_METHODDEF
1762n/a _ASYNCIO_FUTURE_REMOVE_DONE_CALLBACK_METHODDEF
1763n/a _ASYNCIO_FUTURE_CANCELLED_METHODDEF
1764n/a _ASYNCIO_FUTURE_DONE_METHODDEF
1765n/a _ASYNCIO_TASK_CURRENT_TASK_METHODDEF
1766n/a _ASYNCIO_TASK_ALL_TASKS_METHODDEF
1767n/a _ASYNCIO_TASK_CANCEL_METHODDEF
1768n/a _ASYNCIO_TASK_GET_STACK_METHODDEF
1769n/a _ASYNCIO_TASK_PRINT_STACK_METHODDEF
1770n/a _ASYNCIO_TASK__WAKEUP_METHODDEF
1771n/a _ASYNCIO_TASK__STEP_METHODDEF
1772n/a _ASYNCIO_TASK__REPR_INFO_METHODDEF
1773n/a {NULL, NULL} /* Sentinel */
1774n/a};
1775n/a
1776n/astatic PyGetSetDef TaskType_getsetlist[] = {
1777n/a FUTURE_COMMON_GETSETLIST
1778n/a {"_log_destroy_pending", (getter)TaskObj_get_log_destroy_pending,
1779n/a (setter)TaskObj_set_log_destroy_pending, NULL},
1780n/a {"_must_cancel", (getter)TaskObj_get_must_cancel, NULL, NULL},
1781n/a {"_coro", (getter)TaskObj_get_coro, NULL, NULL},
1782n/a {"_fut_waiter", (getter)TaskObj_get_fut_waiter, NULL, NULL},
1783n/a {NULL} /* Sentinel */
1784n/a};
1785n/a
1786n/astatic PyTypeObject TaskType = {
1787n/a PyVarObject_HEAD_INIT(NULL, 0)
1788n/a "_asyncio.Task",
1789n/a sizeof(TaskObj), /* tp_basicsize */
1790n/a .tp_base = &FutureType,
1791n/a .tp_dealloc = TaskObj_dealloc,
1792n/a .tp_as_async = &FutureType_as_async,
1793n/a .tp_repr = (reprfunc)FutureObj_repr,
1794n/a .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
1795n/a | Py_TPFLAGS_HAVE_FINALIZE,
1796n/a .tp_doc = _asyncio_Task___init____doc__,
1797n/a .tp_traverse = (traverseproc)TaskObj_traverse,
1798n/a .tp_clear = (inquiry)TaskObj_clear,
1799n/a .tp_weaklistoffset = offsetof(TaskObj, task_weakreflist),
1800n/a .tp_iter = (getiterfunc)future_new_iter,
1801n/a .tp_methods = TaskType_methods,
1802n/a .tp_getset = TaskType_getsetlist,
1803n/a .tp_dictoffset = offsetof(TaskObj, dict),
1804n/a .tp_init = (initproc)_asyncio_Task___init__,
1805n/a .tp_new = PyType_GenericNew,
1806n/a .tp_finalize = (destructor)TaskObj_finalize,
1807n/a};
1808n/a
1809n/a#define Task_CheckExact(obj) (Py_TYPE(obj) == &TaskType)
1810n/a
1811n/astatic void
1812n/aTaskObj_dealloc(PyObject *self)
1813n/a{
1814n/a TaskObj *task = (TaskObj *)self;
1815n/a
1816n/a if (Task_CheckExact(self)) {
1817n/a /* When fut is subclass of Task, finalizer is called from
1818n/a * subtype_dealloc.
1819n/a */
1820n/a if (PyObject_CallFinalizerFromDealloc(self) < 0) {
1821n/a // resurrected.
1822n/a return;
1823n/a }
1824n/a }
1825n/a
1826n/a if (task->task_weakreflist != NULL) {
1827n/a PyObject_ClearWeakRefs(self);
1828n/a }
1829n/a
1830n/a (void)TaskObj_clear(task);
1831n/a Py_TYPE(task)->tp_free(task);
1832n/a}
1833n/a
1834n/astatic inline PyObject *
1835n/atask_call_wakeup(TaskObj *task, PyObject *fut)
1836n/a{
1837n/a if (Task_CheckExact(task)) {
1838n/a return task_wakeup(task, fut);
1839n/a }
1840n/a else {
1841n/a /* `task` is a subclass of Task */
1842n/a return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
1843n/a fut, NULL);
1844n/a }
1845n/a}
1846n/a
1847n/astatic inline PyObject *
1848n/atask_call_step(TaskObj *task, PyObject *arg)
1849n/a{
1850n/a if (Task_CheckExact(task)) {
1851n/a return task_step(task, arg);
1852n/a }
1853n/a else {
1854n/a /* `task` is a subclass of Task */
1855n/a if (arg == NULL) {
1856n/a arg = Py_None;
1857n/a }
1858n/a return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
1859n/a arg, NULL);
1860n/a }
1861n/a}
1862n/a
1863n/astatic int
1864n/atask_call_step_soon(TaskObj *task, PyObject *arg)
1865n/a{
1866n/a PyObject *handle;
1867n/a
1868n/a PyObject *cb = TaskSendMethWrapper_new(task, arg);
1869n/a if (cb == NULL) {
1870n/a return -1;
1871n/a }
1872n/a
1873n/a handle = _PyObject_CallMethodIdObjArgs(task->task_loop, &PyId_call_soon,
1874n/a cb, NULL);
1875n/a Py_DECREF(cb);
1876n/a if (handle == NULL) {
1877n/a return -1;
1878n/a }
1879n/a
1880n/a Py_DECREF(handle);
1881n/a return 0;
1882n/a}
1883n/a
1884n/astatic PyObject *
1885n/atask_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...)
1886n/a{
1887n/a PyObject* msg;
1888n/a
1889n/a va_list vargs;
1890n/a#ifdef HAVE_STDARG_PROTOTYPES
1891n/a va_start(vargs, format);
1892n/a#else
1893n/a va_start(vargs);
1894n/a#endif
1895n/a msg = PyUnicode_FromFormatV(format, vargs);
1896n/a va_end(vargs);
1897n/a
1898n/a if (msg == NULL) {
1899n/a return NULL;
1900n/a }
1901n/a
1902n/a PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL);
1903n/a Py_DECREF(msg);
1904n/a if (e == NULL) {
1905n/a return NULL;
1906n/a }
1907n/a
1908n/a if (task_call_step_soon(task, e) == -1) {
1909n/a Py_DECREF(e);
1910n/a return NULL;
1911n/a }
1912n/a
1913n/a Py_DECREF(e);
1914n/a Py_RETURN_NONE;
1915n/a}
1916n/a
1917n/astatic PyObject *
1918n/atask_step_impl(TaskObj *task, PyObject *exc)
1919n/a{
1920n/a int res;
1921n/a int clear_exc = 0;
1922n/a PyObject *result = NULL;
1923n/a PyObject *coro = task->task_coro;
1924n/a PyObject *o;
1925n/a
1926n/a if (task->task_state != STATE_PENDING) {
1927n/a PyErr_Format(PyExc_AssertionError,
1928n/a "_step(): already done: %R %R",
1929n/a task,
1930n/a exc ? exc : Py_None);
1931n/a goto fail;
1932n/a }
1933n/a
1934n/a if (task->task_must_cancel) {
1935n/a assert(exc != Py_None);
1936n/a
1937n/a if (exc) {
1938n/a /* Check if exc is a CancelledError */
1939n/a res = PyObject_IsInstance(exc, asyncio_CancelledError);
1940n/a if (res == -1) {
1941n/a /* An error occurred, abort */
1942n/a goto fail;
1943n/a }
1944n/a if (res == 0) {
1945n/a /* exc is not CancelledError; reset it to NULL */
1946n/a exc = NULL;
1947n/a }
1948n/a }
1949n/a
1950n/a if (!exc) {
1951n/a /* exc was not a CancelledError */
1952n/a exc = _PyObject_CallNoArg(asyncio_CancelledError);
1953n/a if (!exc) {
1954n/a goto fail;
1955n/a }
1956n/a clear_exc = 1;
1957n/a }
1958n/a
1959n/a task->task_must_cancel = 0;
1960n/a }
1961n/a
1962n/a Py_CLEAR(task->task_fut_waiter);
1963n/a
1964n/a if (exc == NULL) {
1965n/a if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
1966n/a result = _PyGen_Send((PyGenObject*)coro, Py_None);
1967n/a }
1968n/a else {
1969n/a result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send,
1970n/a Py_None, NULL);
1971n/a }
1972n/a }
1973n/a else {
1974n/a result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw,
1975n/a exc, NULL);
1976n/a if (clear_exc) {
1977n/a /* We created 'exc' during this call */
1978n/a Py_CLEAR(exc);
1979n/a }
1980n/a }
1981n/a
1982n/a if (result == NULL) {
1983n/a PyObject *et, *ev, *tb;
1984n/a
1985n/a if (_PyGen_FetchStopIterationValue(&o) == 0) {
1986n/a /* The error is StopIteration and that means that
1987n/a the underlying coroutine has resolved */
1988n/a PyObject *res = future_set_result((FutureObj*)task, o);
1989n/a Py_DECREF(o);
1990n/a if (res == NULL) {
1991n/a return NULL;
1992n/a }
1993n/a Py_DECREF(res);
1994n/a Py_RETURN_NONE;
1995n/a }
1996n/a
1997n/a if (PyErr_ExceptionMatches(asyncio_CancelledError)) {
1998n/a /* CancelledError */
1999n/a PyErr_Clear();
2000n/a return future_cancel((FutureObj*)task);
2001n/a }
2002n/a
2003n/a /* Some other exception; pop it and call Task.set_exception() */
2004n/a PyErr_Fetch(&et, &ev, &tb);
2005n/a assert(et);
2006n/a if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2007n/a PyErr_NormalizeException(&et, &ev, &tb);
2008n/a }
2009n/a if (tb != NULL) {
2010n/a PyException_SetTraceback(ev, tb);
2011n/a }
2012n/a o = future_set_exception((FutureObj*)task, ev);
2013n/a if (!o) {
2014n/a /* An exception in Task.set_exception() */
2015n/a Py_XDECREF(et);
2016n/a Py_XDECREF(tb);
2017n/a Py_XDECREF(ev);
2018n/a goto fail;
2019n/a }
2020n/a assert(o == Py_None);
2021n/a Py_CLEAR(o);
2022n/a
2023n/a if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
2024n/a /* We've got a BaseException; re-raise it */
2025n/a PyErr_Restore(et, ev, tb);
2026n/a goto fail;
2027n/a }
2028n/a
2029n/a Py_XDECREF(et);
2030n/a Py_XDECREF(tb);
2031n/a Py_XDECREF(ev);
2032n/a
2033n/a Py_RETURN_NONE;
2034n/a }
2035n/a
2036n/a if (result == (PyObject*)task) {
2037n/a /* We have a task that wants to await on itself */
2038n/a goto self_await;
2039n/a }
2040n/a
2041n/a /* Check if `result` is FutureObj or TaskObj (and not a subclass) */
2042n/a if (Future_CheckExact(result) || Task_CheckExact(result)) {
2043n/a PyObject *wrapper;
2044n/a PyObject *res;
2045n/a FutureObj *fut = (FutureObj*)result;
2046n/a
2047n/a /* Check if `result` future is attached to a different loop */
2048n/a if (fut->fut_loop != task->task_loop) {
2049n/a goto different_loop;
2050n/a }
2051n/a
2052n/a if (fut->fut_blocking) {
2053n/a fut->fut_blocking = 0;
2054n/a
2055n/a /* result.add_done_callback(task._wakeup) */
2056n/a wrapper = TaskWakeupMethWrapper_new(task);
2057n/a if (wrapper == NULL) {
2058n/a goto fail;
2059n/a }
2060n/a res = future_add_done_callback((FutureObj*)result, wrapper);
2061n/a Py_DECREF(wrapper);
2062n/a if (res == NULL) {
2063n/a goto fail;
2064n/a }
2065n/a Py_DECREF(res);
2066n/a
2067n/a /* task._fut_waiter = result */
2068n/a task->task_fut_waiter = result; /* no incref is necessary */
2069n/a
2070n/a if (task->task_must_cancel) {
2071n/a PyObject *r;
2072n/a r = future_cancel(fut);
2073n/a if (r == NULL) {
2074n/a return NULL;
2075n/a }
2076n/a if (r == Py_True) {
2077n/a task->task_must_cancel = 0;
2078n/a }
2079n/a Py_DECREF(r);
2080n/a }
2081n/a
2082n/a Py_RETURN_NONE;
2083n/a }
2084n/a else {
2085n/a goto yield_insteadof_yf;
2086n/a }
2087n/a }
2088n/a
2089n/a /* Check if `result` is a Future-compatible object */
2090n/a o = PyObject_GetAttrString(result, "_asyncio_future_blocking");
2091n/a if (o == NULL) {
2092n/a if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2093n/a PyErr_Clear();
2094n/a }
2095n/a else {
2096n/a goto fail;
2097n/a }
2098n/a }
2099n/a else {
2100n/a if (o == Py_None) {
2101n/a Py_CLEAR(o);
2102n/a }
2103n/a else {
2104n/a /* `result` is a Future-compatible object */
2105n/a PyObject *wrapper;
2106n/a PyObject *res;
2107n/a
2108n/a int blocking = PyObject_IsTrue(o);
2109n/a Py_CLEAR(o);
2110n/a if (blocking < 0) {
2111n/a goto fail;
2112n/a }
2113n/a
2114n/a /* Check if `result` future is attached to a different loop */
2115n/a PyObject *oloop = PyObject_GetAttrString(result, "_loop");
2116n/a if (oloop == NULL) {
2117n/a goto fail;
2118n/a }
2119n/a if (oloop != task->task_loop) {
2120n/a Py_DECREF(oloop);
2121n/a goto different_loop;
2122n/a }
2123n/a else {
2124n/a Py_DECREF(oloop);
2125n/a }
2126n/a
2127n/a if (blocking) {
2128n/a /* result._asyncio_future_blocking = False */
2129n/a if (PyObject_SetAttrString(
2130n/a result, "_asyncio_future_blocking", Py_False) == -1) {
2131n/a goto fail;
2132n/a }
2133n/a
2134n/a /* result.add_done_callback(task._wakeup) */
2135n/a wrapper = TaskWakeupMethWrapper_new(task);
2136n/a if (wrapper == NULL) {
2137n/a goto fail;
2138n/a }
2139n/a res = _PyObject_CallMethodIdObjArgs(result,
2140n/a &PyId_add_done_callback,
2141n/a wrapper, NULL);
2142n/a Py_DECREF(wrapper);
2143n/a if (res == NULL) {
2144n/a goto fail;
2145n/a }
2146n/a Py_DECREF(res);
2147n/a
2148n/a /* task._fut_waiter = result */
2149n/a task->task_fut_waiter = result; /* no incref is necessary */
2150n/a
2151n/a if (task->task_must_cancel) {
2152n/a PyObject *r;
2153n/a int is_true;
2154n/a r = _PyObject_CallMethodId(result, &PyId_cancel, NULL);
2155n/a if (r == NULL) {
2156n/a return NULL;
2157n/a }
2158n/a is_true = PyObject_IsTrue(r);
2159n/a Py_DECREF(r);
2160n/a if (is_true < 0) {
2161n/a return NULL;
2162n/a }
2163n/a else if (is_true) {
2164n/a task->task_must_cancel = 0;
2165n/a }
2166n/a }
2167n/a
2168n/a Py_RETURN_NONE;
2169n/a }
2170n/a else {
2171n/a goto yield_insteadof_yf;
2172n/a }
2173n/a }
2174n/a }
2175n/a
2176n/a /* Check if `result` is None */
2177n/a if (result == Py_None) {
2178n/a /* Bare yield relinquishes control for one event loop iteration. */
2179n/a if (task_call_step_soon(task, NULL)) {
2180n/a goto fail;
2181n/a }
2182n/a return result;
2183n/a }
2184n/a
2185n/a /* Check if `result` is a generator */
2186n/a o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL);
2187n/a if (o == NULL) {
2188n/a /* An exception in inspect.isgenerator */
2189n/a goto fail;
2190n/a }
2191n/a res = PyObject_IsTrue(o);
2192n/a Py_CLEAR(o);
2193n/a if (res == -1) {
2194n/a /* An exception while checking if 'val' is True */
2195n/a goto fail;
2196n/a }
2197n/a if (res == 1) {
2198n/a /* `result` is a generator */
2199n/a PyObject *ret;
2200n/a ret = task_set_error_soon(
2201n/a task, PyExc_RuntimeError,
2202n/a "yield was used instead of yield from for "
2203n/a "generator in task %R with %S", task, result);
2204n/a Py_DECREF(result);
2205n/a return ret;
2206n/a }
2207n/a
2208n/a /* The `result` is none of the above */
2209n/a Py_DECREF(result);
2210n/a return task_set_error_soon(
2211n/a task, PyExc_RuntimeError, "Task got bad yield: %R", result);
2212n/a
2213n/aself_await:
2214n/a o = task_set_error_soon(
2215n/a task, PyExc_RuntimeError,
2216n/a "Task cannot await on itself: %R", task);
2217n/a Py_DECREF(result);
2218n/a return o;
2219n/a
2220n/ayield_insteadof_yf:
2221n/a o = task_set_error_soon(
2222n/a task, PyExc_RuntimeError,
2223n/a "yield was used instead of yield from "
2224n/a "in task %R with %R",
2225n/a task, result);
2226n/a Py_DECREF(result);
2227n/a return o;
2228n/a
2229n/adifferent_loop:
2230n/a o = task_set_error_soon(
2231n/a task, PyExc_RuntimeError,
2232n/a "Task %R got Future %R attached to a different loop",
2233n/a task, result);
2234n/a Py_DECREF(result);
2235n/a return o;
2236n/a
2237n/afail:
2238n/a Py_XDECREF(result);
2239n/a return NULL;
2240n/a}
2241n/a
2242n/astatic PyObject *
2243n/atask_step(TaskObj *task, PyObject *exc)
2244n/a{
2245n/a PyObject *res;
2246n/a PyObject *ot;
2247n/a
2248n/a if (PyDict_SetItem(current_tasks,
2249n/a task->task_loop, (PyObject*)task) == -1)
2250n/a {
2251n/a return NULL;
2252n/a }
2253n/a
2254n/a res = task_step_impl(task, exc);
2255n/a
2256n/a if (res == NULL) {
2257n/a PyObject *et, *ev, *tb;
2258n/a PyErr_Fetch(&et, &ev, &tb);
2259n/a ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2260n/a if (ot == NULL) {
2261n/a Py_XDECREF(et);
2262n/a Py_XDECREF(tb);
2263n/a Py_XDECREF(ev);
2264n/a return NULL;
2265n/a }
2266n/a Py_DECREF(ot);
2267n/a PyErr_Restore(et, ev, tb);
2268n/a return NULL;
2269n/a }
2270n/a else {
2271n/a ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
2272n/a if (ot == NULL) {
2273n/a Py_DECREF(res);
2274n/a return NULL;
2275n/a }
2276n/a else {
2277n/a Py_DECREF(ot);
2278n/a return res;
2279n/a }
2280n/a }
2281n/a}
2282n/a
2283n/astatic PyObject *
2284n/atask_wakeup(TaskObj *task, PyObject *o)
2285n/a{
2286n/a assert(o);
2287n/a
2288n/a if (Future_CheckExact(o) || Task_CheckExact(o)) {
2289n/a PyObject *fut_result = NULL;
2290n/a int res = future_get_result((FutureObj*)o, &fut_result);
2291n/a PyObject *result;
2292n/a
2293n/a switch(res) {
2294n/a case -1:
2295n/a assert(fut_result == NULL);
2296n/a return NULL;
2297n/a case 0:
2298n/a Py_DECREF(fut_result);
2299n/a return task_call_step(task, NULL);
2300n/a default:
2301n/a assert(res == 1);
2302n/a result = task_call_step(task, fut_result);
2303n/a Py_DECREF(fut_result);
2304n/a return result;
2305n/a }
2306n/a }
2307n/a
2308n/a PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
2309n/a if (fut_result == NULL) {
2310n/a PyObject *et, *ev, *tb;
2311n/a PyObject *res;
2312n/a
2313n/a PyErr_Fetch(&et, &ev, &tb);
2314n/a if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
2315n/a PyErr_NormalizeException(&et, &ev, &tb);
2316n/a }
2317n/a
2318n/a res = task_call_step(task, ev);
2319n/a
2320n/a Py_XDECREF(et);
2321n/a Py_XDECREF(tb);
2322n/a Py_XDECREF(ev);
2323n/a
2324n/a return res;
2325n/a }
2326n/a else {
2327n/a Py_DECREF(fut_result);
2328n/a return task_call_step(task, NULL);
2329n/a }
2330n/a}
2331n/a
2332n/a
2333n/a/*********************** Module **************************/
2334n/a
2335n/a
2336n/astatic void
2337n/amodule_free(void *m)
2338n/a{
2339n/a Py_CLEAR(current_tasks);
2340n/a Py_CLEAR(all_tasks);
2341n/a Py_CLEAR(traceback_extract_stack);
2342n/a Py_CLEAR(asyncio_get_event_loop);
2343n/a Py_CLEAR(asyncio_future_repr_info_func);
2344n/a Py_CLEAR(asyncio_task_repr_info_func);
2345n/a Py_CLEAR(asyncio_task_get_stack_func);
2346n/a Py_CLEAR(asyncio_task_print_stack_func);
2347n/a Py_CLEAR(asyncio_InvalidStateError);
2348n/a Py_CLEAR(asyncio_CancelledError);
2349n/a Py_CLEAR(inspect_isgenerator);
2350n/a}
2351n/a
2352n/astatic int
2353n/amodule_init(void)
2354n/a{
2355n/a PyObject *module = NULL;
2356n/a PyObject *cls;
2357n/a
2358n/a#define WITH_MOD(NAME) \
2359n/a Py_CLEAR(module); \
2360n/a module = PyImport_ImportModule(NAME); \
2361n/a if (module == NULL) { \
2362n/a return -1; \
2363n/a }
2364n/a
2365n/a#define GET_MOD_ATTR(VAR, NAME) \
2366n/a VAR = PyObject_GetAttrString(module, NAME); \
2367n/a if (VAR == NULL) { \
2368n/a goto fail; \
2369n/a }
2370n/a
2371n/a WITH_MOD("asyncio.events")
2372n/a GET_MOD_ATTR(asyncio_get_event_loop, "get_event_loop")
2373n/a
2374n/a WITH_MOD("asyncio.base_futures")
2375n/a GET_MOD_ATTR(asyncio_future_repr_info_func, "_future_repr_info")
2376n/a GET_MOD_ATTR(asyncio_InvalidStateError, "InvalidStateError")
2377n/a GET_MOD_ATTR(asyncio_CancelledError, "CancelledError")
2378n/a
2379n/a WITH_MOD("asyncio.base_tasks")
2380n/a GET_MOD_ATTR(asyncio_task_repr_info_func, "_task_repr_info")
2381n/a GET_MOD_ATTR(asyncio_task_get_stack_func, "_task_get_stack")
2382n/a GET_MOD_ATTR(asyncio_task_print_stack_func, "_task_print_stack")
2383n/a
2384n/a WITH_MOD("inspect")
2385n/a GET_MOD_ATTR(inspect_isgenerator, "isgenerator")
2386n/a
2387n/a WITH_MOD("traceback")
2388n/a GET_MOD_ATTR(traceback_extract_stack, "extract_stack")
2389n/a
2390n/a WITH_MOD("weakref")
2391n/a GET_MOD_ATTR(cls, "WeakSet")
2392n/a all_tasks = _PyObject_CallNoArg(cls);
2393n/a Py_CLEAR(cls);
2394n/a if (all_tasks == NULL) {
2395n/a goto fail;
2396n/a }
2397n/a
2398n/a current_tasks = PyDict_New();
2399n/a if (current_tasks == NULL) {
2400n/a goto fail;
2401n/a }
2402n/a
2403n/a Py_CLEAR(module);
2404n/a return 0;
2405n/a
2406n/afail:
2407n/a Py_CLEAR(module);
2408n/a module_free(NULL);
2409n/a return -1;
2410n/a
2411n/a#undef WITH_MOD
2412n/a#undef GET_MOD_ATTR
2413n/a}
2414n/a
2415n/aPyDoc_STRVAR(module_doc, "Accelerator module for asyncio");
2416n/a
2417n/astatic struct PyModuleDef _asynciomodule = {
2418n/a PyModuleDef_HEAD_INIT, /* m_base */
2419n/a "_asyncio", /* m_name */
2420n/a module_doc, /* m_doc */
2421n/a -1, /* m_size */
2422n/a NULL, /* m_methods */
2423n/a NULL, /* m_slots */
2424n/a NULL, /* m_traverse */
2425n/a NULL, /* m_clear */
2426n/a (freefunc)module_free /* m_free */
2427n/a};
2428n/a
2429n/a
2430n/aPyMODINIT_FUNC
2431n/aPyInit__asyncio(void)
2432n/a{
2433n/a if (module_init() < 0) {
2434n/a return NULL;
2435n/a }
2436n/a if (PyType_Ready(&FutureType) < 0) {
2437n/a return NULL;
2438n/a }
2439n/a if (PyType_Ready(&FutureIterType) < 0) {
2440n/a return NULL;
2441n/a }
2442n/a if (PyType_Ready(&TaskSendMethWrapper_Type) < 0) {
2443n/a return NULL;
2444n/a }
2445n/a if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
2446n/a return NULL;
2447n/a }
2448n/a if (PyType_Ready(&TaskType) < 0) {
2449n/a return NULL;
2450n/a }
2451n/a
2452n/a PyObject *m = PyModule_Create(&_asynciomodule);
2453n/a if (m == NULL) {
2454n/a return NULL;
2455n/a }
2456n/a
2457n/a Py_INCREF(&FutureType);
2458n/a if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
2459n/a Py_DECREF(&FutureType);
2460n/a return NULL;
2461n/a }
2462n/a
2463n/a Py_INCREF(&TaskType);
2464n/a if (PyModule_AddObject(m, "Task", (PyObject *)&TaskType) < 0) {
2465n/a Py_DECREF(&TaskType);
2466n/a return NULL;
2467n/a }
2468n/a
2469n/a return m;
2470n/a}