blob: dedbca99384c795e052673299649d67ef9bd8688 [file] [log] [blame]
Yury Selivanovf23746a2018-01-22 19:11:18 -05001#include "Python.h"
2
Victor Stinner27e2d1f2018-11-01 00:52:28 +01003#include "pycore_context.h"
Victor Stinnere5014be2020-04-14 17:52:15 +02004#include "pycore_gc.h" // _PyObject_GC_MAY_BE_TRACKED()
Victor Stinner27e2d1f2018-11-01 00:52:28 +01005#include "pycore_hamt.h"
Victor Stinnerbcda8f12018-11-21 22:27:47 +01006#include "pycore_object.h"
Victor Stinner7e433732019-11-08 10:05:17 +01007#include "pycore_pyerrors.h"
Victor Stinnere5014be2020-04-14 17:52:15 +02008#include "pycore_pystate.h" // _PyThreadState_GET()
Victor Stinner4a21e572020-04-15 02:35:41 +02009#include "structmember.h" // PyMemberDef
Yury Selivanovf23746a2018-01-22 19:11:18 -050010
11
12#define CONTEXT_FREELIST_MAXLEN 255
Yury Selivanovf23746a2018-01-22 19:11:18 -050013
14
15#include "clinic/context.c.h"
16/*[clinic input]
17module _contextvars
18[clinic start generated code]*/
19/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a0955718c8b8cea6]*/
20
21
Yury Selivanov2ec872b2018-09-21 15:33:56 -040022#define ENSURE_Context(o, err_ret) \
23 if (!PyContext_CheckExact(o)) { \
24 PyErr_SetString(PyExc_TypeError, \
25 "an instance of Context was expected"); \
26 return err_ret; \
27 }
28
29#define ENSURE_ContextVar(o, err_ret) \
30 if (!PyContextVar_CheckExact(o)) { \
31 PyErr_SetString(PyExc_TypeError, \
32 "an instance of ContextVar was expected"); \
33 return err_ret; \
34 }
35
36#define ENSURE_ContextToken(o, err_ret) \
37 if (!PyContextToken_CheckExact(o)) { \
38 PyErr_SetString(PyExc_TypeError, \
39 "an instance of Token was expected"); \
40 return err_ret; \
41 }
42
43
Yury Selivanovf23746a2018-01-22 19:11:18 -050044/////////////////////////// Context API
45
46
47static PyContext *
48context_new_empty(void);
49
50static PyContext *
51context_new_from_vars(PyHamtObject *vars);
52
53static inline PyContext *
54context_get(void);
55
56static PyContextToken *
57token_new(PyContext *ctx, PyContextVar *var, PyObject *val);
58
59static PyContextVar *
60contextvar_new(PyObject *name, PyObject *def);
61
62static int
63contextvar_set(PyContextVar *var, PyObject *val);
64
65static int
66contextvar_del(PyContextVar *var);
67
68
69PyObject *
70_PyContext_NewHamtForTests(void)
71{
72 return (PyObject *)_PyHamt_New();
73}
74
75
Yury Selivanov2ec872b2018-09-21 15:33:56 -040076PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -050077PyContext_New(void)
78{
Yury Selivanov2ec872b2018-09-21 15:33:56 -040079 return (PyObject *)context_new_empty();
Yury Selivanovf23746a2018-01-22 19:11:18 -050080}
81
82
Yury Selivanov2ec872b2018-09-21 15:33:56 -040083PyObject *
84PyContext_Copy(PyObject * octx)
Yury Selivanovf23746a2018-01-22 19:11:18 -050085{
Yury Selivanov2ec872b2018-09-21 15:33:56 -040086 ENSURE_Context(octx, NULL)
87 PyContext *ctx = (PyContext *)octx;
88 return (PyObject *)context_new_from_vars(ctx->ctx_vars);
Yury Selivanovf23746a2018-01-22 19:11:18 -050089}
90
91
Yury Selivanov2ec872b2018-09-21 15:33:56 -040092PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -050093PyContext_CopyCurrent(void)
94{
95 PyContext *ctx = context_get();
96 if (ctx == NULL) {
97 return NULL;
98 }
99
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400100 return (PyObject *)context_new_from_vars(ctx->ctx_vars);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500101}
102
103
Victor Stinner7e433732019-11-08 10:05:17 +0100104static int
105_PyContext_Enter(PyThreadState *ts, PyObject *octx)
Yury Selivanovf23746a2018-01-22 19:11:18 -0500106{
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400107 ENSURE_Context(octx, -1)
108 PyContext *ctx = (PyContext *)octx;
109
Yury Selivanovf23746a2018-01-22 19:11:18 -0500110 if (ctx->ctx_entered) {
Victor Stinner7e433732019-11-08 10:05:17 +0100111 _PyErr_Format(ts, PyExc_RuntimeError,
112 "cannot enter context: %R is already entered", ctx);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500113 return -1;
114 }
115
Yury Selivanovf23746a2018-01-22 19:11:18 -0500116 ctx->ctx_prev = (PyContext *)ts->context; /* borrow */
117 ctx->ctx_entered = 1;
118
119 Py_INCREF(ctx);
120 ts->context = (PyObject *)ctx;
121 ts->context_ver++;
122
123 return 0;
124}
125
126
127int
Victor Stinner7e433732019-11-08 10:05:17 +0100128PyContext_Enter(PyObject *octx)
129{
130 PyThreadState *ts = _PyThreadState_GET();
131 assert(ts != NULL);
132 return _PyContext_Enter(ts, octx);
133}
134
135
136static int
137_PyContext_Exit(PyThreadState *ts, PyObject *octx)
Yury Selivanovf23746a2018-01-22 19:11:18 -0500138{
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400139 ENSURE_Context(octx, -1)
140 PyContext *ctx = (PyContext *)octx;
141
Yury Selivanovf23746a2018-01-22 19:11:18 -0500142 if (!ctx->ctx_entered) {
143 PyErr_Format(PyExc_RuntimeError,
144 "cannot exit context: %R has not been entered", ctx);
145 return -1;
146 }
147
Yury Selivanovf23746a2018-01-22 19:11:18 -0500148 if (ts->context != (PyObject *)ctx) {
149 /* Can only happen if someone misuses the C API */
150 PyErr_SetString(PyExc_RuntimeError,
151 "cannot exit context: thread state references "
152 "a different context object");
153 return -1;
154 }
155
156 Py_SETREF(ts->context, (PyObject *)ctx->ctx_prev);
157 ts->context_ver++;
158
159 ctx->ctx_prev = NULL;
160 ctx->ctx_entered = 0;
161
162 return 0;
163}
164
Victor Stinner7e433732019-11-08 10:05:17 +0100165int
166PyContext_Exit(PyObject *octx)
167{
168 PyThreadState *ts = _PyThreadState_GET();
169 assert(ts != NULL);
170 return _PyContext_Exit(ts, octx);
171}
172
Yury Selivanovf23746a2018-01-22 19:11:18 -0500173
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400174PyObject *
Yury Selivanovf23746a2018-01-22 19:11:18 -0500175PyContextVar_New(const char *name, PyObject *def)
176{
177 PyObject *pyname = PyUnicode_FromString(name);
178 if (pyname == NULL) {
179 return NULL;
180 }
Yury Selivanov6ab62922018-01-25 14:18:55 -0500181 PyContextVar *var = contextvar_new(pyname, def);
182 Py_DECREF(pyname);
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400183 return (PyObject *)var;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500184}
185
186
187int
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400188PyContextVar_Get(PyObject *ovar, PyObject *def, PyObject **val)
Yury Selivanovf23746a2018-01-22 19:11:18 -0500189{
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400190 ENSURE_ContextVar(ovar, -1)
191 PyContextVar *var = (PyContextVar *)ovar;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500192
Victor Stinner50b48572018-11-01 01:51:40 +0100193 PyThreadState *ts = _PyThreadState_GET();
Yury Selivanov226e5002018-01-26 17:24:52 -0500194 assert(ts != NULL);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500195 if (ts->context == NULL) {
196 goto not_found;
197 }
198
199 if (var->var_cached != NULL &&
200 var->var_cached_tsid == ts->id &&
201 var->var_cached_tsver == ts->context_ver)
202 {
203 *val = var->var_cached;
204 goto found;
205 }
206
207 assert(PyContext_CheckExact(ts->context));
208 PyHamtObject *vars = ((PyContext *)ts->context)->ctx_vars;
209
210 PyObject *found = NULL;
211 int res = _PyHamt_Find(vars, (PyObject*)var, &found);
212 if (res < 0) {
213 goto error;
214 }
215 if (res == 1) {
216 assert(found != NULL);
217 var->var_cached = found; /* borrow */
218 var->var_cached_tsid = ts->id;
219 var->var_cached_tsver = ts->context_ver;
220
221 *val = found;
222 goto found;
223 }
224
225not_found:
226 if (def == NULL) {
227 if (var->var_default != NULL) {
228 *val = var->var_default;
229 goto found;
230 }
231
232 *val = NULL;
233 goto found;
234 }
235 else {
236 *val = def;
237 goto found;
238 }
239
240found:
241 Py_XINCREF(*val);
242 return 0;
243
244error:
245 *val = NULL;
246 return -1;
247}
248
249
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400250PyObject *
251PyContextVar_Set(PyObject *ovar, PyObject *val)
Yury Selivanovf23746a2018-01-22 19:11:18 -0500252{
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400253 ENSURE_ContextVar(ovar, NULL)
254 PyContextVar *var = (PyContextVar *)ovar;
255
Yury Selivanovf23746a2018-01-22 19:11:18 -0500256 if (!PyContextVar_CheckExact(var)) {
257 PyErr_SetString(
258 PyExc_TypeError, "an instance of ContextVar was expected");
259 return NULL;
260 }
261
262 PyContext *ctx = context_get();
263 if (ctx == NULL) {
264 return NULL;
265 }
266
267 PyObject *old_val = NULL;
268 int found = _PyHamt_Find(ctx->ctx_vars, (PyObject *)var, &old_val);
269 if (found < 0) {
270 return NULL;
271 }
272
273 Py_XINCREF(old_val);
274 PyContextToken *tok = token_new(ctx, var, old_val);
275 Py_XDECREF(old_val);
276
277 if (contextvar_set(var, val)) {
278 Py_DECREF(tok);
279 return NULL;
280 }
281
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400282 return (PyObject *)tok;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500283}
284
285
286int
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400287PyContextVar_Reset(PyObject *ovar, PyObject *otok)
Yury Selivanovf23746a2018-01-22 19:11:18 -0500288{
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400289 ENSURE_ContextVar(ovar, -1)
290 ENSURE_ContextToken(otok, -1)
291 PyContextVar *var = (PyContextVar *)ovar;
292 PyContextToken *tok = (PyContextToken *)otok;
293
Yury Selivanovf23746a2018-01-22 19:11:18 -0500294 if (tok->tok_used) {
295 PyErr_Format(PyExc_RuntimeError,
296 "%R has already been used once", tok);
297 return -1;
298 }
299
300 if (var != tok->tok_var) {
301 PyErr_Format(PyExc_ValueError,
302 "%R was created by a different ContextVar", tok);
303 return -1;
304 }
305
306 PyContext *ctx = context_get();
307 if (ctx != tok->tok_ctx) {
308 PyErr_Format(PyExc_ValueError,
309 "%R was created in a different Context", tok);
310 return -1;
311 }
312
313 tok->tok_used = 1;
314
315 if (tok->tok_oldval == NULL) {
316 return contextvar_del(var);
317 }
318 else {
319 return contextvar_set(var, tok->tok_oldval);
320 }
321}
322
323
324/////////////////////////// PyContext
325
326/*[clinic input]
327class _contextvars.Context "PyContext *" "&PyContext_Type"
328[clinic start generated code]*/
329/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bdf87f8e0cb580e8]*/
330
331
332static inline PyContext *
333_context_alloc(void)
334{
Victor Stinnere005ead2020-06-05 02:56:37 +0200335 PyInterpreterState *interp = _PyInterpreterState_GET();
336 struct _Py_context_state *state = &interp->context;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500337 PyContext *ctx;
Victor Stinnerbcb19832020-06-08 02:14:47 +0200338#ifdef Py_DEBUG
339 // _context_alloc() must not be called after _PyContext_Fini()
340 assert(state->numfree != -1);
341#endif
Victor Stinnere005ead2020-06-05 02:56:37 +0200342 if (state->numfree) {
343 state->numfree--;
344 ctx = state->freelist;
345 state->freelist = (PyContext *)ctx->ctx_weakreflist;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500346 ctx->ctx_weakreflist = NULL;
347 _Py_NewReference((PyObject *)ctx);
348 }
349 else {
350 ctx = PyObject_GC_New(PyContext, &PyContext_Type);
351 if (ctx == NULL) {
352 return NULL;
353 }
354 }
355
356 ctx->ctx_vars = NULL;
357 ctx->ctx_prev = NULL;
358 ctx->ctx_entered = 0;
359 ctx->ctx_weakreflist = NULL;
360
361 return ctx;
362}
363
364
365static PyContext *
366context_new_empty(void)
367{
368 PyContext *ctx = _context_alloc();
369 if (ctx == NULL) {
370 return NULL;
371 }
372
373 ctx->ctx_vars = _PyHamt_New();
374 if (ctx->ctx_vars == NULL) {
375 Py_DECREF(ctx);
376 return NULL;
377 }
378
379 _PyObject_GC_TRACK(ctx);
380 return ctx;
381}
382
383
384static PyContext *
385context_new_from_vars(PyHamtObject *vars)
386{
387 PyContext *ctx = _context_alloc();
388 if (ctx == NULL) {
389 return NULL;
390 }
391
392 Py_INCREF(vars);
393 ctx->ctx_vars = vars;
394
395 _PyObject_GC_TRACK(ctx);
396 return ctx;
397}
398
399
400static inline PyContext *
401context_get(void)
402{
Victor Stinner50b48572018-11-01 01:51:40 +0100403 PyThreadState *ts = _PyThreadState_GET();
Yury Selivanovbc4123b2018-01-27 13:24:20 -0500404 assert(ts != NULL);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500405 PyContext *current_ctx = (PyContext *)ts->context;
406 if (current_ctx == NULL) {
407 current_ctx = context_new_empty();
408 if (current_ctx == NULL) {
409 return NULL;
410 }
411 ts->context = (PyObject *)current_ctx;
412 }
413 return current_ctx;
414}
415
416static int
417context_check_key_type(PyObject *key)
418{
419 if (!PyContextVar_CheckExact(key)) {
420 // abort();
421 PyErr_Format(PyExc_TypeError,
422 "a ContextVar key was expected, got %R", key);
423 return -1;
424 }
425 return 0;
426}
427
428static PyObject *
429context_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
430{
431 if (PyTuple_Size(args) || (kwds != NULL && PyDict_Size(kwds))) {
432 PyErr_SetString(
433 PyExc_TypeError, "Context() does not accept any arguments");
434 return NULL;
435 }
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400436 return PyContext_New();
Yury Selivanovf23746a2018-01-22 19:11:18 -0500437}
438
439static int
440context_tp_clear(PyContext *self)
441{
442 Py_CLEAR(self->ctx_prev);
443 Py_CLEAR(self->ctx_vars);
444 return 0;
445}
446
447static int
448context_tp_traverse(PyContext *self, visitproc visit, void *arg)
449{
450 Py_VISIT(self->ctx_prev);
451 Py_VISIT(self->ctx_vars);
452 return 0;
453}
454
455static void
456context_tp_dealloc(PyContext *self)
457{
458 _PyObject_GC_UNTRACK(self);
459
460 if (self->ctx_weakreflist != NULL) {
461 PyObject_ClearWeakRefs((PyObject*)self);
462 }
463 (void)context_tp_clear(self);
464
Victor Stinnere005ead2020-06-05 02:56:37 +0200465 PyInterpreterState *interp = _PyInterpreterState_GET();
466 struct _Py_context_state *state = &interp->context;
Victor Stinnerbcb19832020-06-08 02:14:47 +0200467#ifdef Py_DEBUG
468 // _context_alloc() must not be called after _PyContext_Fini()
469 assert(state->numfree != -1);
470#endif
Victor Stinnere005ead2020-06-05 02:56:37 +0200471 if (state->numfree < CONTEXT_FREELIST_MAXLEN) {
472 state->numfree++;
473 self->ctx_weakreflist = (PyObject *)state->freelist;
474 state->freelist = self;
Yury Selivanovf23746a2018-01-22 19:11:18 -0500475 }
476 else {
477 Py_TYPE(self)->tp_free(self);
478 }
479}
480
481static PyObject *
482context_tp_iter(PyContext *self)
483{
484 return _PyHamt_NewIterKeys(self->ctx_vars);
485}
486
487static PyObject *
488context_tp_richcompare(PyObject *v, PyObject *w, int op)
489{
490 if (!PyContext_CheckExact(v) || !PyContext_CheckExact(w) ||
491 (op != Py_EQ && op != Py_NE))
492 {
493 Py_RETURN_NOTIMPLEMENTED;
494 }
495
496 int res = _PyHamt_Eq(
497 ((PyContext *)v)->ctx_vars, ((PyContext *)w)->ctx_vars);
498 if (res < 0) {
499 return NULL;
500 }
501
502 if (op == Py_NE) {
503 res = !res;
504 }
505
506 if (res) {
507 Py_RETURN_TRUE;
508 }
509 else {
510 Py_RETURN_FALSE;
511 }
512}
513
514static Py_ssize_t
515context_tp_len(PyContext *self)
516{
517 return _PyHamt_Len(self->ctx_vars);
518}
519
520static PyObject *
521context_tp_subscript(PyContext *self, PyObject *key)
522{
523 if (context_check_key_type(key)) {
524 return NULL;
525 }
526 PyObject *val = NULL;
527 int found = _PyHamt_Find(self->ctx_vars, key, &val);
528 if (found < 0) {
529 return NULL;
530 }
531 if (found == 0) {
532 PyErr_SetObject(PyExc_KeyError, key);
533 return NULL;
534 }
535 Py_INCREF(val);
536 return val;
537}
538
539static int
540context_tp_contains(PyContext *self, PyObject *key)
541{
542 if (context_check_key_type(key)) {
543 return -1;
544 }
545 PyObject *val = NULL;
546 return _PyHamt_Find(self->ctx_vars, key, &val);
547}
548
549
550/*[clinic input]
551_contextvars.Context.get
552 key: object
553 default: object = None
554 /
Peter Lamut20678fd2018-07-30 16:15:44 +0100555
556Return the value for `key` if `key` has the value in the context object.
557
558If `key` does not exist, return `default`. If `default` is not given,
559return None.
Yury Selivanovf23746a2018-01-22 19:11:18 -0500560[clinic start generated code]*/
561
562static PyObject *
563_contextvars_Context_get_impl(PyContext *self, PyObject *key,
564 PyObject *default_value)
Peter Lamut20678fd2018-07-30 16:15:44 +0100565/*[clinic end generated code: output=0c54aa7664268189 input=c8eeb81505023995]*/
Yury Selivanovf23746a2018-01-22 19:11:18 -0500566{
567 if (context_check_key_type(key)) {
568 return NULL;
569 }
570
571 PyObject *val = NULL;
572 int found = _PyHamt_Find(self->ctx_vars, key, &val);
573 if (found < 0) {
574 return NULL;
575 }
576 if (found == 0) {
577 Py_INCREF(default_value);
578 return default_value;
579 }
580 Py_INCREF(val);
581 return val;
582}
583
584
585/*[clinic input]
586_contextvars.Context.items
Peter Lamut20678fd2018-07-30 16:15:44 +0100587
588Return all variables and their values in the context object.
589
590The result is returned as a list of 2-tuples (variable, value).
Yury Selivanovf23746a2018-01-22 19:11:18 -0500591[clinic start generated code]*/
592
593static PyObject *
594_contextvars_Context_items_impl(PyContext *self)
Peter Lamut20678fd2018-07-30 16:15:44 +0100595/*[clinic end generated code: output=fa1655c8a08502af input=00db64ae379f9f42]*/
Yury Selivanovf23746a2018-01-22 19:11:18 -0500596{
597 return _PyHamt_NewIterItems(self->ctx_vars);
598}
599
600
601/*[clinic input]
602_contextvars.Context.keys
Peter Lamut20678fd2018-07-30 16:15:44 +0100603
604Return a list of all variables in the context object.
Yury Selivanovf23746a2018-01-22 19:11:18 -0500605[clinic start generated code]*/
606
607static PyObject *
608_contextvars_Context_keys_impl(PyContext *self)
Peter Lamut20678fd2018-07-30 16:15:44 +0100609/*[clinic end generated code: output=177227c6b63ec0e2 input=114b53aebca3449c]*/
Yury Selivanovf23746a2018-01-22 19:11:18 -0500610{
611 return _PyHamt_NewIterKeys(self->ctx_vars);
612}
613
614
615/*[clinic input]
616_contextvars.Context.values
Peter Lamut20678fd2018-07-30 16:15:44 +0100617
animalize463572c2019-02-25 07:18:48 +0800618Return a list of all variables' values in the context object.
Yury Selivanovf23746a2018-01-22 19:11:18 -0500619[clinic start generated code]*/
620
621static PyObject *
622_contextvars_Context_values_impl(PyContext *self)
animalize463572c2019-02-25 07:18:48 +0800623/*[clinic end generated code: output=d286dabfc8db6dde input=ce8075d04a6ea526]*/
Yury Selivanovf23746a2018-01-22 19:11:18 -0500624{
625 return _PyHamt_NewIterValues(self->ctx_vars);
626}
627
628
629/*[clinic input]
630_contextvars.Context.copy
Peter Lamut20678fd2018-07-30 16:15:44 +0100631
632Return a shallow copy of the context object.
Yury Selivanovf23746a2018-01-22 19:11:18 -0500633[clinic start generated code]*/
634
635static PyObject *
636_contextvars_Context_copy_impl(PyContext *self)
Peter Lamut20678fd2018-07-30 16:15:44 +0100637/*[clinic end generated code: output=30ba8896c4707a15 input=ebafdbdd9c72d592]*/
Yury Selivanovf23746a2018-01-22 19:11:18 -0500638{
639 return (PyObject *)context_new_from_vars(self->ctx_vars);
640}
641
642
643static PyObject *
644context_run(PyContext *self, PyObject *const *args,
645 Py_ssize_t nargs, PyObject *kwnames)
646{
Victor Stinner7e433732019-11-08 10:05:17 +0100647 PyThreadState *ts = _PyThreadState_GET();
648
Yury Selivanovf23746a2018-01-22 19:11:18 -0500649 if (nargs < 1) {
Victor Stinner7e433732019-11-08 10:05:17 +0100650 _PyErr_SetString(ts, PyExc_TypeError,
651 "run() missing 1 required positional argument");
Yury Selivanovf23746a2018-01-22 19:11:18 -0500652 return NULL;
653 }
654
Victor Stinner7e433732019-11-08 10:05:17 +0100655 if (_PyContext_Enter(ts, (PyObject *)self)) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500656 return NULL;
657 }
658
Victor Stinner7e433732019-11-08 10:05:17 +0100659 PyObject *call_result = _PyObject_VectorcallTstate(
660 ts, args[0], args + 1, nargs - 1, kwnames);
Yury Selivanovf23746a2018-01-22 19:11:18 -0500661
Victor Stinner7e433732019-11-08 10:05:17 +0100662 if (_PyContext_Exit(ts, (PyObject *)self)) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500663 return NULL;
664 }
665
666 return call_result;
667}
668
669
670static PyMethodDef PyContext_methods[] = {
671 _CONTEXTVARS_CONTEXT_GET_METHODDEF
672 _CONTEXTVARS_CONTEXT_ITEMS_METHODDEF
673 _CONTEXTVARS_CONTEXT_KEYS_METHODDEF
674 _CONTEXTVARS_CONTEXT_VALUES_METHODDEF
675 _CONTEXTVARS_CONTEXT_COPY_METHODDEF
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200676 {"run", (PyCFunction)(void(*)(void))context_run, METH_FASTCALL | METH_KEYWORDS, NULL},
Yury Selivanovf23746a2018-01-22 19:11:18 -0500677 {NULL, NULL}
678};
679
680static PySequenceMethods PyContext_as_sequence = {
681 0, /* sq_length */
682 0, /* sq_concat */
683 0, /* sq_repeat */
684 0, /* sq_item */
685 0, /* sq_slice */
686 0, /* sq_ass_item */
687 0, /* sq_ass_slice */
688 (objobjproc)context_tp_contains, /* sq_contains */
689 0, /* sq_inplace_concat */
690 0, /* sq_inplace_repeat */
691};
692
693static PyMappingMethods PyContext_as_mapping = {
694 (lenfunc)context_tp_len, /* mp_length */
695 (binaryfunc)context_tp_subscript, /* mp_subscript */
696};
697
698PyTypeObject PyContext_Type = {
699 PyVarObject_HEAD_INIT(&PyType_Type, 0)
700 "Context",
701 sizeof(PyContext),
702 .tp_methods = PyContext_methods,
703 .tp_as_mapping = &PyContext_as_mapping,
704 .tp_as_sequence = &PyContext_as_sequence,
705 .tp_iter = (getiterfunc)context_tp_iter,
706 .tp_dealloc = (destructor)context_tp_dealloc,
707 .tp_getattro = PyObject_GenericGetAttr,
708 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
709 .tp_richcompare = context_tp_richcompare,
710 .tp_traverse = (traverseproc)context_tp_traverse,
711 .tp_clear = (inquiry)context_tp_clear,
712 .tp_new = context_tp_new,
713 .tp_weaklistoffset = offsetof(PyContext, ctx_weakreflist),
714 .tp_hash = PyObject_HashNotImplemented,
715};
716
717
718/////////////////////////// ContextVar
719
720
721static int
722contextvar_set(PyContextVar *var, PyObject *val)
723{
724 var->var_cached = NULL;
725 PyThreadState *ts = PyThreadState_Get();
726
727 PyContext *ctx = context_get();
728 if (ctx == NULL) {
729 return -1;
730 }
731
732 PyHamtObject *new_vars = _PyHamt_Assoc(
733 ctx->ctx_vars, (PyObject *)var, val);
734 if (new_vars == NULL) {
735 return -1;
736 }
737
738 Py_SETREF(ctx->ctx_vars, new_vars);
739
740 var->var_cached = val; /* borrow */
741 var->var_cached_tsid = ts->id;
742 var->var_cached_tsver = ts->context_ver;
743 return 0;
744}
745
746static int
747contextvar_del(PyContextVar *var)
748{
749 var->var_cached = NULL;
750
751 PyContext *ctx = context_get();
752 if (ctx == NULL) {
753 return -1;
754 }
755
756 PyHamtObject *vars = ctx->ctx_vars;
757 PyHamtObject *new_vars = _PyHamt_Without(vars, (PyObject *)var);
758 if (new_vars == NULL) {
759 return -1;
760 }
761
762 if (vars == new_vars) {
763 Py_DECREF(new_vars);
764 PyErr_SetObject(PyExc_LookupError, (PyObject *)var);
765 return -1;
766 }
767
768 Py_SETREF(ctx->ctx_vars, new_vars);
769 return 0;
770}
771
772static Py_hash_t
773contextvar_generate_hash(void *addr, PyObject *name)
774{
775 /* Take hash of `name` and XOR it with the object's addr.
776
777 The structure of the tree is encoded in objects' hashes, which
778 means that sufficiently similar hashes would result in tall trees
779 with many Collision nodes. Which would, in turn, result in slower
780 get and set operations.
781
782 The XORing helps to ensure that:
783
784 (1) sequentially allocated ContextVar objects have
785 different hashes;
786
787 (2) context variables with equal names have
788 different hashes.
789 */
790
791 Py_hash_t name_hash = PyObject_Hash(name);
792 if (name_hash == -1) {
793 return -1;
794 }
795
796 Py_hash_t res = _Py_HashPointer(addr) ^ name_hash;
797 return res == -1 ? -2 : res;
798}
799
800static PyContextVar *
801contextvar_new(PyObject *name, PyObject *def)
802{
803 if (!PyUnicode_Check(name)) {
804 PyErr_SetString(PyExc_TypeError,
805 "context variable name must be a str");
806 return NULL;
807 }
808
809 PyContextVar *var = PyObject_GC_New(PyContextVar, &PyContextVar_Type);
810 if (var == NULL) {
811 return NULL;
812 }
813
814 var->var_hash = contextvar_generate_hash(var, name);
815 if (var->var_hash == -1) {
816 Py_DECREF(var);
817 return NULL;
818 }
819
820 Py_INCREF(name);
821 var->var_name = name;
822
823 Py_XINCREF(def);
824 var->var_default = def;
825
826 var->var_cached = NULL;
827 var->var_cached_tsid = 0;
828 var->var_cached_tsver = 0;
829
Yury Selivanov6ab62922018-01-25 14:18:55 -0500830 if (_PyObject_GC_MAY_BE_TRACKED(name) ||
831 (def != NULL && _PyObject_GC_MAY_BE_TRACKED(def)))
Yury Selivanovf23746a2018-01-22 19:11:18 -0500832 {
833 PyObject_GC_Track(var);
834 }
835 return var;
836}
837
838
839/*[clinic input]
840class _contextvars.ContextVar "PyContextVar *" "&PyContextVar_Type"
841[clinic start generated code]*/
842/*[clinic end generated code: output=da39a3ee5e6b4b0d input=445da935fa8883c3]*/
843
844
845static PyObject *
846contextvar_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
847{
848 static char *kwlist[] = {"", "default", NULL};
849 PyObject *name;
850 PyObject *def = NULL;
851
852 if (!PyArg_ParseTupleAndKeywords(
853 args, kwds, "O|$O:ContextVar", kwlist, &name, &def))
854 {
855 return NULL;
856 }
857
858 return (PyObject *)contextvar_new(name, def);
859}
860
861static int
862contextvar_tp_clear(PyContextVar *self)
863{
864 Py_CLEAR(self->var_name);
865 Py_CLEAR(self->var_default);
866 self->var_cached = NULL;
867 self->var_cached_tsid = 0;
868 self->var_cached_tsver = 0;
869 return 0;
870}
871
872static int
873contextvar_tp_traverse(PyContextVar *self, visitproc visit, void *arg)
874{
875 Py_VISIT(self->var_name);
876 Py_VISIT(self->var_default);
877 return 0;
878}
879
880static void
881contextvar_tp_dealloc(PyContextVar *self)
882{
883 PyObject_GC_UnTrack(self);
884 (void)contextvar_tp_clear(self);
885 Py_TYPE(self)->tp_free(self);
886}
887
888static Py_hash_t
889contextvar_tp_hash(PyContextVar *self)
890{
891 return self->var_hash;
892}
893
894static PyObject *
895contextvar_tp_repr(PyContextVar *self)
896{
897 _PyUnicodeWriter writer;
898
899 _PyUnicodeWriter_Init(&writer);
900
901 if (_PyUnicodeWriter_WriteASCIIString(
902 &writer, "<ContextVar name=", 17) < 0)
903 {
904 goto error;
905 }
906
907 PyObject *name = PyObject_Repr(self->var_name);
908 if (name == NULL) {
909 goto error;
910 }
911 if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) {
912 Py_DECREF(name);
913 goto error;
914 }
915 Py_DECREF(name);
916
917 if (self->var_default != NULL) {
918 if (_PyUnicodeWriter_WriteASCIIString(&writer, " default=", 9) < 0) {
919 goto error;
920 }
921
922 PyObject *def = PyObject_Repr(self->var_default);
923 if (def == NULL) {
924 goto error;
925 }
926 if (_PyUnicodeWriter_WriteStr(&writer, def) < 0) {
927 Py_DECREF(def);
928 goto error;
929 }
930 Py_DECREF(def);
931 }
932
933 PyObject *addr = PyUnicode_FromFormat(" at %p>", self);
934 if (addr == NULL) {
935 goto error;
936 }
937 if (_PyUnicodeWriter_WriteStr(&writer, addr) < 0) {
938 Py_DECREF(addr);
939 goto error;
940 }
941 Py_DECREF(addr);
942
943 return _PyUnicodeWriter_Finish(&writer);
944
945error:
946 _PyUnicodeWriter_Dealloc(&writer);
947 return NULL;
948}
949
950
951/*[clinic input]
952_contextvars.ContextVar.get
953 default: object = NULL
954 /
Peter Lamut20678fd2018-07-30 16:15:44 +0100955
956Return a value for the context variable for the current context.
957
958If there is no value for the variable in the current context, the method will:
959 * return the value of the default argument of the method, if provided; or
960 * return the default value for the context variable, if it was created
961 with one; or
962 * raise a LookupError.
Yury Selivanovf23746a2018-01-22 19:11:18 -0500963[clinic start generated code]*/
964
965static PyObject *
966_contextvars_ContextVar_get_impl(PyContextVar *self, PyObject *default_value)
Peter Lamut20678fd2018-07-30 16:15:44 +0100967/*[clinic end generated code: output=0746bd0aa2ced7bf input=30aa2ab9e433e401]*/
Yury Selivanovf23746a2018-01-22 19:11:18 -0500968{
969 if (!PyContextVar_CheckExact(self)) {
970 PyErr_SetString(
971 PyExc_TypeError, "an instance of ContextVar was expected");
972 return NULL;
973 }
974
975 PyObject *val;
Yury Selivanov2ec872b2018-09-21 15:33:56 -0400976 if (PyContextVar_Get((PyObject *)self, default_value, &val) < 0) {
Yury Selivanovf23746a2018-01-22 19:11:18 -0500977 return NULL;
978 }
979
980 if (val == NULL) {
981 PyErr_SetObject(PyExc_LookupError, (PyObject *)self);
982 return NULL;
983 }
984
985 return val;
986}
987
988/*[clinic input]
989_contextvars.ContextVar.set
990 value: object
991 /
Peter Lamut20678fd2018-07-30 16:15:44 +0100992
993Call to set a new value for the context variable in the current context.
994
995The required value argument is the new value for the context variable.
996
997Returns a Token object that can be used to restore the variable to its previous
998value via the `ContextVar.reset()` method.
Yury Selivanovf23746a2018-01-22 19:11:18 -0500999[clinic start generated code]*/
1000
1001static PyObject *
1002_contextvars_ContextVar_set(PyContextVar *self, PyObject *value)
Peter Lamut20678fd2018-07-30 16:15:44 +01001003/*[clinic end generated code: output=446ed5e820d6d60b input=c0a6887154227453]*/
Yury Selivanovf23746a2018-01-22 19:11:18 -05001004{
Yury Selivanov2ec872b2018-09-21 15:33:56 -04001005 return PyContextVar_Set((PyObject *)self, value);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001006}
1007
1008/*[clinic input]
1009_contextvars.ContextVar.reset
1010 token: object
1011 /
Peter Lamut20678fd2018-07-30 16:15:44 +01001012
1013Reset the context variable.
1014
1015The variable is reset to the value it had before the `ContextVar.set()` that
1016created the token was used.
Yury Selivanovf23746a2018-01-22 19:11:18 -05001017[clinic start generated code]*/
1018
1019static PyObject *
1020_contextvars_ContextVar_reset(PyContextVar *self, PyObject *token)
Peter Lamut20678fd2018-07-30 16:15:44 +01001021/*[clinic end generated code: output=d4ee34d0742d62ee input=ebe2881e5af4ffda]*/
Yury Selivanovf23746a2018-01-22 19:11:18 -05001022{
1023 if (!PyContextToken_CheckExact(token)) {
1024 PyErr_Format(PyExc_TypeError,
1025 "expected an instance of Token, got %R", token);
1026 return NULL;
1027 }
1028
Yury Selivanov2ec872b2018-09-21 15:33:56 -04001029 if (PyContextVar_Reset((PyObject *)self, token)) {
Yury Selivanovf23746a2018-01-22 19:11:18 -05001030 return NULL;
1031 }
1032
1033 Py_RETURN_NONE;
1034}
1035
1036
Yury Selivanov41cb0ba2018-06-28 13:20:29 -04001037static PyMemberDef PyContextVar_members[] = {
1038 {"name", T_OBJECT, offsetof(PyContextVar, var_name), READONLY},
1039 {NULL}
1040};
Yury Selivanovf23746a2018-01-22 19:11:18 -05001041
1042static PyMethodDef PyContextVar_methods[] = {
1043 _CONTEXTVARS_CONTEXTVAR_GET_METHODDEF
1044 _CONTEXTVARS_CONTEXTVAR_SET_METHODDEF
1045 _CONTEXTVARS_CONTEXTVAR_RESET_METHODDEF
Ethan Smithd01628e2020-04-14 16:14:15 -07001046 {"__class_getitem__", (PyCFunction)Py_GenericAlias,
1047 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
Yury Selivanovf23746a2018-01-22 19:11:18 -05001048 {NULL, NULL}
1049};
1050
1051PyTypeObject PyContextVar_Type = {
1052 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1053 "ContextVar",
1054 sizeof(PyContextVar),
1055 .tp_methods = PyContextVar_methods,
Yury Selivanov41cb0ba2018-06-28 13:20:29 -04001056 .tp_members = PyContextVar_members,
Yury Selivanovf23746a2018-01-22 19:11:18 -05001057 .tp_dealloc = (destructor)contextvar_tp_dealloc,
1058 .tp_getattro = PyObject_GenericGetAttr,
1059 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1060 .tp_traverse = (traverseproc)contextvar_tp_traverse,
1061 .tp_clear = (inquiry)contextvar_tp_clear,
1062 .tp_new = contextvar_tp_new,
1063 .tp_free = PyObject_GC_Del,
1064 .tp_hash = (hashfunc)contextvar_tp_hash,
1065 .tp_repr = (reprfunc)contextvar_tp_repr,
1066};
1067
1068
1069/////////////////////////// Token
1070
1071static PyObject * get_token_missing(void);
1072
1073
1074/*[clinic input]
1075class _contextvars.Token "PyContextToken *" "&PyContextToken_Type"
1076[clinic start generated code]*/
1077/*[clinic end generated code: output=da39a3ee5e6b4b0d input=338a5e2db13d3f5b]*/
1078
1079
1080static PyObject *
1081token_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1082{
1083 PyErr_SetString(PyExc_RuntimeError,
1084 "Tokens can only be created by ContextVars");
1085 return NULL;
1086}
1087
1088static int
1089token_tp_clear(PyContextToken *self)
1090{
1091 Py_CLEAR(self->tok_ctx);
1092 Py_CLEAR(self->tok_var);
1093 Py_CLEAR(self->tok_oldval);
1094 return 0;
1095}
1096
1097static int
1098token_tp_traverse(PyContextToken *self, visitproc visit, void *arg)
1099{
1100 Py_VISIT(self->tok_ctx);
1101 Py_VISIT(self->tok_var);
1102 Py_VISIT(self->tok_oldval);
1103 return 0;
1104}
1105
1106static void
1107token_tp_dealloc(PyContextToken *self)
1108{
1109 PyObject_GC_UnTrack(self);
1110 (void)token_tp_clear(self);
1111 Py_TYPE(self)->tp_free(self);
1112}
1113
1114static PyObject *
1115token_tp_repr(PyContextToken *self)
1116{
1117 _PyUnicodeWriter writer;
1118
1119 _PyUnicodeWriter_Init(&writer);
1120
1121 if (_PyUnicodeWriter_WriteASCIIString(&writer, "<Token", 6) < 0) {
1122 goto error;
1123 }
1124
1125 if (self->tok_used) {
1126 if (_PyUnicodeWriter_WriteASCIIString(&writer, " used", 5) < 0) {
1127 goto error;
1128 }
1129 }
1130
1131 if (_PyUnicodeWriter_WriteASCIIString(&writer, " var=", 5) < 0) {
1132 goto error;
1133 }
1134
1135 PyObject *var = PyObject_Repr((PyObject *)self->tok_var);
1136 if (var == NULL) {
1137 goto error;
1138 }
1139 if (_PyUnicodeWriter_WriteStr(&writer, var) < 0) {
1140 Py_DECREF(var);
1141 goto error;
1142 }
1143 Py_DECREF(var);
1144
1145 PyObject *addr = PyUnicode_FromFormat(" at %p>", self);
1146 if (addr == NULL) {
1147 goto error;
1148 }
1149 if (_PyUnicodeWriter_WriteStr(&writer, addr) < 0) {
1150 Py_DECREF(addr);
1151 goto error;
1152 }
1153 Py_DECREF(addr);
1154
1155 return _PyUnicodeWriter_Finish(&writer);
1156
1157error:
1158 _PyUnicodeWriter_Dealloc(&writer);
1159 return NULL;
1160}
1161
1162static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001163token_get_var(PyContextToken *self, void *Py_UNUSED(ignored))
Yury Selivanovf23746a2018-01-22 19:11:18 -05001164{
1165 Py_INCREF(self->tok_var);
1166 return (PyObject *)self->tok_var;
1167}
1168
1169static PyObject *
Serhiy Storchakad4f9cf52018-11-27 19:34:35 +02001170token_get_old_value(PyContextToken *self, void *Py_UNUSED(ignored))
Yury Selivanovf23746a2018-01-22 19:11:18 -05001171{
1172 if (self->tok_oldval == NULL) {
1173 return get_token_missing();
1174 }
1175
1176 Py_INCREF(self->tok_oldval);
1177 return self->tok_oldval;
1178}
1179
1180static PyGetSetDef PyContextTokenType_getsetlist[] = {
1181 {"var", (getter)token_get_var, NULL, NULL},
1182 {"old_value", (getter)token_get_old_value, NULL, NULL},
1183 {NULL}
1184};
1185
Ethan Smithd01628e2020-04-14 16:14:15 -07001186static PyMethodDef PyContextTokenType_methods[] = {
1187 {"__class_getitem__", (PyCFunction)Py_GenericAlias,
1188 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
1189 {NULL}
1190};
1191
Yury Selivanovf23746a2018-01-22 19:11:18 -05001192PyTypeObject PyContextToken_Type = {
1193 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1194 "Token",
1195 sizeof(PyContextToken),
Ethan Smithd01628e2020-04-14 16:14:15 -07001196 .tp_methods = PyContextTokenType_methods,
Yury Selivanovf23746a2018-01-22 19:11:18 -05001197 .tp_getset = PyContextTokenType_getsetlist,
1198 .tp_dealloc = (destructor)token_tp_dealloc,
1199 .tp_getattro = PyObject_GenericGetAttr,
1200 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1201 .tp_traverse = (traverseproc)token_tp_traverse,
1202 .tp_clear = (inquiry)token_tp_clear,
1203 .tp_new = token_tp_new,
1204 .tp_free = PyObject_GC_Del,
1205 .tp_hash = PyObject_HashNotImplemented,
1206 .tp_repr = (reprfunc)token_tp_repr,
1207};
1208
1209static PyContextToken *
1210token_new(PyContext *ctx, PyContextVar *var, PyObject *val)
1211{
1212 PyContextToken *tok = PyObject_GC_New(PyContextToken, &PyContextToken_Type);
1213 if (tok == NULL) {
1214 return NULL;
1215 }
1216
1217 Py_INCREF(ctx);
1218 tok->tok_ctx = ctx;
1219
1220 Py_INCREF(var);
1221 tok->tok_var = var;
1222
1223 Py_XINCREF(val);
1224 tok->tok_oldval = val;
1225
1226 tok->tok_used = 0;
1227
1228 PyObject_GC_Track(tok);
1229 return tok;
1230}
1231
1232
1233/////////////////////////// Token.MISSING
1234
1235
1236static PyObject *_token_missing;
1237
1238
1239typedef struct {
1240 PyObject_HEAD
1241} PyContextTokenMissing;
1242
1243
1244static PyObject *
1245context_token_missing_tp_repr(PyObject *self)
1246{
1247 return PyUnicode_FromString("<Token.MISSING>");
1248}
1249
1250
1251PyTypeObject PyContextTokenMissing_Type = {
1252 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1253 "Token.MISSING",
1254 sizeof(PyContextTokenMissing),
1255 .tp_getattro = PyObject_GenericGetAttr,
1256 .tp_flags = Py_TPFLAGS_DEFAULT,
1257 .tp_repr = context_token_missing_tp_repr,
1258};
1259
1260
1261static PyObject *
1262get_token_missing(void)
1263{
1264 if (_token_missing != NULL) {
1265 Py_INCREF(_token_missing);
1266 return _token_missing;
1267 }
1268
1269 _token_missing = (PyObject *)PyObject_New(
1270 PyContextTokenMissing, &PyContextTokenMissing_Type);
1271 if (_token_missing == NULL) {
1272 return NULL;
1273 }
1274
1275 Py_INCREF(_token_missing);
1276 return _token_missing;
1277}
1278
1279
1280///////////////////////////
1281
1282
Victor Stinnerae00a5a2020-04-29 02:29:20 +02001283void
Victor Stinnere005ead2020-06-05 02:56:37 +02001284_PyContext_ClearFreeList(PyThreadState *tstate)
Yury Selivanovf23746a2018-01-22 19:11:18 -05001285{
Victor Stinnere005ead2020-06-05 02:56:37 +02001286 struct _Py_context_state *state = &tstate->interp->context;
1287 for (; state->numfree; state->numfree--) {
1288 PyContext *ctx = state->freelist;
1289 state->freelist = (PyContext *)ctx->ctx_weakreflist;
Yury Selivanovf23746a2018-01-22 19:11:18 -05001290 ctx->ctx_weakreflist = NULL;
1291 PyObject_GC_Del(ctx);
Yury Selivanovf23746a2018-01-22 19:11:18 -05001292 }
Yury Selivanovf23746a2018-01-22 19:11:18 -05001293}
1294
1295
1296void
Victor Stinnere005ead2020-06-05 02:56:37 +02001297_PyContext_Fini(PyThreadState *tstate)
Yury Selivanovf23746a2018-01-22 19:11:18 -05001298{
1299 Py_CLEAR(_token_missing);
Victor Stinnere005ead2020-06-05 02:56:37 +02001300 _PyContext_ClearFreeList(tstate);
Victor Stinnerbcb19832020-06-08 02:14:47 +02001301#ifdef Py_DEBUG
1302 struct _Py_context_state *state = &tstate->interp->context;
1303 state->numfree = -1;
1304#endif
Victor Stinnerae00a5a2020-04-29 02:29:20 +02001305 _PyHamt_Fini();
Yury Selivanovf23746a2018-01-22 19:11:18 -05001306}
1307
1308
1309int
1310_PyContext_Init(void)
1311{
1312 if (!_PyHamt_Init()) {
1313 return 0;
1314 }
1315
1316 if ((PyType_Ready(&PyContext_Type) < 0) ||
1317 (PyType_Ready(&PyContextVar_Type) < 0) ||
1318 (PyType_Ready(&PyContextToken_Type) < 0) ||
1319 (PyType_Ready(&PyContextTokenMissing_Type) < 0))
1320 {
1321 return 0;
1322 }
1323
1324 PyObject *missing = get_token_missing();
1325 if (PyDict_SetItemString(
1326 PyContextToken_Type.tp_dict, "MISSING", missing))
1327 {
1328 Py_DECREF(missing);
1329 return 0;
1330 }
1331 Py_DECREF(missing);
1332
1333 return 1;
1334}