Coverage Report

Created: 2026-06-14 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Python-3.8.3/Modules/_abc.c
Line
Count
Source
1
/* ABCMeta implementation */
2
3
#include "Python.h"
4
#include "structmember.h"
5
#include "clinic/_abc.c.h"
6
7
/*[clinic input]
8
module _abc
9
[clinic start generated code]*/
10
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=964f5328e1aefcda]*/
11
12
PyDoc_STRVAR(_abc__doc__,
13
"Module contains faster C implementation of abc.ABCMeta");
14
15
_Py_IDENTIFIER(__abstractmethods__);
16
_Py_IDENTIFIER(__class__);
17
_Py_IDENTIFIER(__dict__);
18
_Py_IDENTIFIER(__bases__);
19
_Py_IDENTIFIER(_abc_impl);
20
_Py_IDENTIFIER(__subclasscheck__);
21
_Py_IDENTIFIER(__subclasshook__);
22
23
/* A global counter that is incremented each time a class is
24
   registered as a virtual subclass of anything.  It forces the
25
   negative cache to be cleared before its next use.
26
   Note: this counter is private. Use `abc.get_cache_token()` for
27
   external code. */
28
static unsigned long long abc_invalidation_counter = 0;
29
30
/* This object stores internal state for ABCs.
31
   Note that we can use normal sets for caches,
32
   since they are never iterated over. */
33
typedef struct {
34
    PyObject_HEAD
35
    PyObject *_abc_registry;
36
    PyObject *_abc_cache; /* Normal set of weak references. */
37
    PyObject *_abc_negative_cache; /* Normal set of weak references. */
38
    unsigned long long _abc_negative_cache_version;
39
} _abc_data;
40
41
static void
42
abc_data_dealloc(_abc_data *self)
43
0
{
44
0
    Py_XDECREF(self->_abc_registry);
45
0
    Py_XDECREF(self->_abc_cache);
46
0
    Py_XDECREF(self->_abc_negative_cache);
47
0
    Py_TYPE(self)->tp_free(self);
48
0
}
49
50
static PyObject *
51
abc_data_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
52
425
{
53
425
    _abc_data *self = (_abc_data *) type->tp_alloc(type, 0);
54
425
    if (self == NULL) {
55
0
        return NULL;
56
0
    }
57
58
425
    self->_abc_registry = NULL;
59
425
    self->_abc_cache = NULL;
60
425
    self->_abc_negative_cache = NULL;
61
425
    self->_abc_negative_cache_version = abc_invalidation_counter;
62
425
    return (PyObject *) self;
63
425
}
64
65
PyDoc_STRVAR(abc_data_doc,
66
"Internal state held by ABC machinery.");
67
68
static PyTypeObject _abc_data_type = {
69
    PyVarObject_HEAD_INIT(NULL, 0)
70
    "_abc_data",                        /*tp_name*/
71
    sizeof(_abc_data),                  /*tp_basicsize*/
72
    .tp_dealloc = (destructor)abc_data_dealloc,
73
    .tp_flags = Py_TPFLAGS_DEFAULT,
74
    .tp_alloc = PyType_GenericAlloc,
75
    .tp_new = abc_data_new,
76
};
77
78
static _abc_data *
79
_get_impl(PyObject *self)
80
829
{
81
829
    PyObject *impl = _PyObject_GetAttrId(self, &PyId__abc_impl);
82
829
    if (impl == NULL) {
83
0
        return NULL;
84
0
    }
85
829
    if (Py_TYPE(impl) != &_abc_data_type) {
86
0
        PyErr_SetString(PyExc_TypeError, "_abc_impl is set to a wrong type");
87
0
        Py_DECREF(impl);
88
0
        return NULL;
89
0
    }
90
829
    return (_abc_data *)impl;
91
829
}
92
93
static int
94
_in_weak_set(PyObject *set, PyObject *obj)
95
1.20k
{
96
1.20k
    if (set == NULL || PySet_GET_SIZE(set) == 0) {
97
902
        return 0;
98
902
    }
99
302
    PyObject *ref = PyWeakref_NewRef(obj, NULL);
100
302
    if (ref == NULL) {
101
0
        if (PyErr_ExceptionMatches(PyExc_TypeError)) {
102
0
            PyErr_Clear();
103
0
            return 0;
104
0
        }
105
0
        return -1;
106
0
    }
107
302
    int res = PySet_Contains(set, ref);
108
302
    Py_DECREF(ref);
109
302
    return res;
110
302
}
111
112
static PyObject *
113
_destroy(PyObject *setweakref, PyObject *objweakref)
114
0
{
115
0
    PyObject *set;
116
0
    set = PyWeakref_GET_OBJECT(setweakref);
117
0
    if (set == Py_None) {
118
0
        Py_RETURN_NONE;
119
0
    }
120
0
    Py_INCREF(set);
121
0
    if (PySet_Discard(set, objweakref) < 0) {
122
0
        Py_DECREF(set);
123
0
        return NULL;
124
0
    }
125
0
    Py_DECREF(set);
126
0
    Py_RETURN_NONE;
127
0
}
128
129
static PyMethodDef _destroy_def = {
130
    "_destroy", (PyCFunction) _destroy, METH_O
131
};
132
133
static int
134
_add_to_weak_set(PyObject **pset, PyObject *obj)
135
815
{
136
815
    if (*pset == NULL) {
137
395
        *pset = PySet_New(NULL);
138
395
        if (*pset == NULL) {
139
0
            return -1;
140
0
        }
141
395
    }
142
143
815
    PyObject *set = *pset;
144
815
    PyObject *ref, *wr;
145
815
    PyObject *destroy_cb;
146
815
    wr = PyWeakref_NewRef(set, NULL);
147
815
    if (wr == NULL) {
148
0
        return -1;
149
0
    }
150
815
    destroy_cb = PyCFunction_NewEx(&_destroy_def, wr, NULL);
151
815
    if (destroy_cb == NULL) {
152
0
        Py_DECREF(wr);
153
0
        return -1;
154
0
    }
155
815
    ref = PyWeakref_NewRef(obj, destroy_cb);
156
815
    Py_DECREF(destroy_cb);
157
815
    if (ref == NULL) {
158
0
        Py_DECREF(wr);
159
0
        return -1;
160
0
    }
161
815
    int ret = PySet_Add(set, ref);
162
815
    Py_DECREF(wr);
163
815
    Py_DECREF(ref);
164
815
    return ret;
165
815
}
166
167
/*[clinic input]
168
_abc._reset_registry
169
170
    self: object
171
    /
172
173
Internal ABC helper to reset registry of a given class.
174
175
Should be only used by refleak.py
176
[clinic start generated code]*/
177
178
static PyObject *
179
_abc__reset_registry(PyObject *module, PyObject *self)
180
/*[clinic end generated code: output=92d591a43566cc10 input=12a0b7eb339ac35c]*/
181
0
{
182
0
    _abc_data *impl = _get_impl(self);
183
0
    if (impl == NULL) {
184
0
        return NULL;
185
0
    }
186
0
    if (impl->_abc_registry != NULL && PySet_Clear(impl->_abc_registry) < 0) {
187
0
        Py_DECREF(impl);
188
0
        return NULL;
189
0
    }
190
0
    Py_DECREF(impl);
191
0
    Py_RETURN_NONE;
192
0
}
193
194
/*[clinic input]
195
_abc._reset_caches
196
197
    self: object
198
    /
199
200
Internal ABC helper to reset both caches of a given class.
201
202
Should be only used by refleak.py
203
[clinic start generated code]*/
204
205
static PyObject *
206
_abc__reset_caches(PyObject *module, PyObject *self)
207
/*[clinic end generated code: output=f296f0d5c513f80c input=c0ac616fd8acfb6f]*/
208
0
{
209
0
    _abc_data *impl = _get_impl(self);
210
0
    if (impl == NULL) {
211
0
        return NULL;
212
0
    }
213
0
    if (impl->_abc_cache != NULL && PySet_Clear(impl->_abc_cache) < 0) {
214
0
        Py_DECREF(impl);
215
0
        return NULL;
216
0
    }
217
    /* also the second cache */
218
0
    if (impl->_abc_negative_cache != NULL &&
219
0
            PySet_Clear(impl->_abc_negative_cache) < 0) {
220
0
        Py_DECREF(impl);
221
0
        return NULL;
222
0
    }
223
0
    Py_DECREF(impl);
224
0
    Py_RETURN_NONE;
225
0
}
226
227
/*[clinic input]
228
_abc._get_dump
229
230
    self: object
231
    /
232
233
Internal ABC helper for cache and registry debugging.
234
235
Return shallow copies of registry, of both caches, and
236
negative cache version. Don't call this function directly,
237
instead use ABC._dump_registry() for a nice repr.
238
[clinic start generated code]*/
239
240
static PyObject *
241
_abc__get_dump(PyObject *module, PyObject *self)
242
/*[clinic end generated code: output=9d9569a8e2c1c443 input=2c5deb1bfe9e3c79]*/
243
0
{
244
0
    _abc_data *impl = _get_impl(self);
245
0
    if (impl == NULL) {
246
0
        return NULL;
247
0
    }
248
0
    PyObject *res = Py_BuildValue("NNNK",
249
0
                                  PySet_New(impl->_abc_registry),
250
0
                                  PySet_New(impl->_abc_cache),
251
0
                                  PySet_New(impl->_abc_negative_cache),
252
0
                                  impl->_abc_negative_cache_version);
253
0
    Py_DECREF(impl);
254
0
    return res;
255
0
}
256
257
// Compute set of abstract method names.
258
static int
259
compute_abstract_methods(PyObject *self)
260
425
{
261
425
    int ret = -1;
262
425
    PyObject *abstracts = PyFrozenSet_New(NULL);
263
425
    if (abstracts == NULL) {
264
0
        return -1;
265
0
    }
266
267
425
    PyObject *ns = NULL, *items = NULL, *bases = NULL;  // Py_XDECREF()ed on error.
268
269
    /* Stage 1: direct abstract methods. */
270
425
    ns = _PyObject_GetAttrId(self, &PyId___dict__);
271
425
    if (!ns) {
272
0
        goto error;
273
0
    }
274
275
    // We can't use PyDict_Next(ns) even when ns is dict because
276
    // _PyObject_IsAbstract() can mutate ns.
277
425
    items = PyMapping_Items(ns);
278
425
    if (!items) {
279
0
        goto error;
280
0
    }
281
425
    assert(PyList_Check(items));
282
3.40k
    for (Py_ssize_t pos = 0; pos < PyList_GET_SIZE(items); pos++) {
283
2.98k
        PyObject *it = PySequence_Fast(
284
2.98k
                PyList_GET_ITEM(items, pos),
285
2.98k
                "items() returned non-iterable");
286
2.98k
        if (!it) {
287
0
            goto error;
288
0
        }
289
2.98k
        if (PySequence_Fast_GET_SIZE(it) != 2) {
290
0
            PyErr_SetString(PyExc_TypeError,
291
0
                            "items() returned item which size is not 2");
292
0
            Py_DECREF(it);
293
0
            goto error;
294
0
        }
295
296
        // borrowed
297
2.98k
        PyObject *key = PySequence_Fast_GET_ITEM(it, 0);
298
2.98k
        PyObject *value = PySequence_Fast_GET_ITEM(it, 1);
299
        // items or it may be cleared while accessing __abstractmethod__
300
        // So we need to keep strong reference for key
301
2.98k
        Py_INCREF(key);
302
2.98k
        int is_abstract = _PyObject_IsAbstract(value);
303
2.98k
        if (is_abstract < 0 ||
304
2.98k
                (is_abstract && PySet_Add(abstracts, key) < 0)) {
305
0
            Py_DECREF(it);
306
0
            Py_DECREF(key);
307
0
            goto error;
308
0
        }
309
2.98k
        Py_DECREF(key);
310
2.98k
        Py_DECREF(it);
311
2.98k
    }
312
313
    /* Stage 2: inherited abstract methods. */
314
425
    bases = _PyObject_GetAttrId(self, &PyId___bases__);
315
425
    if (!bases) {
316
0
        goto error;
317
0
    }
318
425
    if (!PyTuple_Check(bases)) {
319
0
        PyErr_SetString(PyExc_TypeError, "__bases__ is not tuple");
320
0
        goto error;
321
0
    }
322
323
967
    for (Py_ssize_t pos = 0; pos < PyTuple_GET_SIZE(bases); pos++) {
324
542
        PyObject *item = PyTuple_GET_ITEM(bases, pos);  // borrowed
325
542
        PyObject *base_abstracts, *iter;
326
327
542
        if (_PyObject_LookupAttrId(item, &PyId___abstractmethods__,
328
542
                                   &base_abstracts) < 0) {
329
0
            goto error;
330
0
        }
331
542
        if (base_abstracts == NULL) {
332
156
            continue;
333
156
        }
334
386
        if (!(iter = PyObject_GetIter(base_abstracts))) {
335
0
            Py_DECREF(base_abstracts);
336
0
            goto error;
337
0
        }
338
386
        Py_DECREF(base_abstracts);
339
386
        PyObject *key, *value;
340
998
        while ((key = PyIter_Next(iter))) {
341
612
            if (_PyObject_LookupAttr(self, key, &value) < 0) {
342
0
                Py_DECREF(key);
343
0
                Py_DECREF(iter);
344
0
                goto error;
345
0
            }
346
612
            if (value == NULL) {
347
0
                Py_DECREF(key);
348
0
                continue;
349
0
            }
350
351
612
            int is_abstract = _PyObject_IsAbstract(value);
352
612
            Py_DECREF(value);
353
612
            if (is_abstract < 0 ||
354
612
                    (is_abstract && PySet_Add(abstracts, key) < 0))
355
0
            {
356
0
                Py_DECREF(key);
357
0
                Py_DECREF(iter);
358
0
                goto error;
359
0
            }
360
612
            Py_DECREF(key);
361
612
        }
362
386
        Py_DECREF(iter);
363
386
        if (PyErr_Occurred()) {
364
0
            goto error;
365
0
        }
366
386
    }
367
368
425
    if (_PyObject_SetAttrId(self, &PyId___abstractmethods__, abstracts) < 0) {
369
0
        goto error;
370
0
    }
371
372
425
    ret = 0;
373
425
error:
374
425
    Py_DECREF(abstracts);
375
425
    Py_XDECREF(ns);
376
425
    Py_XDECREF(items);
377
425
    Py_XDECREF(bases);
378
425
    return ret;
379
425
}
380
381
/*[clinic input]
382
_abc._abc_init
383
384
    self: object
385
    /
386
387
Internal ABC helper for class set-up. Should be never used outside abc module.
388
[clinic start generated code]*/
389
390
static PyObject *
391
_abc__abc_init(PyObject *module, PyObject *self)
392
/*[clinic end generated code: output=594757375714cda1 input=8d7fe470ff77f029]*/
393
425
{
394
425
    PyObject *data;
395
425
    if (compute_abstract_methods(self) < 0) {
396
0
        return NULL;
397
0
    }
398
399
    /* Set up inheritance registry. */
400
425
    data = abc_data_new(&_abc_data_type, NULL, NULL);
401
425
    if (data == NULL) {
402
0
        return NULL;
403
0
    }
404
425
    if (_PyObject_SetAttrId(self, &PyId__abc_impl, data) < 0) {
405
0
        Py_DECREF(data);
406
0
        return NULL;
407
0
    }
408
425
    Py_DECREF(data);
409
425
    Py_RETURN_NONE;
410
425
}
411
412
/*[clinic input]
413
_abc._abc_register
414
415
    self: object
416
    subclass: object
417
    /
418
419
Internal ABC helper for subclasss registration. Should be never used outside abc module.
420
[clinic start generated code]*/
421
422
static PyObject *
423
_abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass)
424
/*[clinic end generated code: output=7851e7668c963524 input=ca589f8c3080e67f]*/
425
508
{
426
508
    if (!PyType_Check(subclass)) {
427
0
        PyErr_SetString(PyExc_TypeError, "Can only register classes");
428
0
        return NULL;
429
0
    }
430
508
    int result = PyObject_IsSubclass(subclass, self);
431
508
    if (result > 0) {
432
208
        Py_INCREF(subclass);
433
208
        return subclass;  /* Already a subclass. */
434
208
    }
435
300
    if (result < 0) {
436
0
        return NULL;
437
0
    }
438
    /* Subtle: test for cycles *after* testing for "already a subclass";
439
       this means we allow X.register(X) and interpret it as a no-op. */
440
300
    result = PyObject_IsSubclass(self, subclass);
441
300
    if (result > 0) {
442
        /* This would create a cycle, which is bad for the algorithm below. */
443
0
        PyErr_SetString(PyExc_RuntimeError, "Refusing to create an inheritance cycle");
444
0
        return NULL;
445
0
    }
446
300
    if (result < 0) {
447
0
        return NULL;
448
0
    }
449
300
    _abc_data *impl = _get_impl(self);
450
300
    if (impl == NULL) {
451
0
        return NULL;
452
0
    }
453
300
    if (_add_to_weak_set(&impl->_abc_registry, subclass) < 0) {
454
0
        Py_DECREF(impl);
455
0
        return NULL;
456
0
    }
457
300
    Py_DECREF(impl);
458
459
    /* Invalidate negative cache */
460
300
    abc_invalidation_counter++;
461
462
300
    Py_INCREF(subclass);
463
300
    return subclass;
464
300
}
465
466
467
/*[clinic input]
468
_abc._abc_instancecheck
469
470
    self: object
471
    instance: object
472
    /
473
474
Internal ABC helper for instance checks. Should be never used outside abc module.
475
[clinic start generated code]*/
476
477
static PyObject *
478
_abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
479
                             PyObject *instance)
480
/*[clinic end generated code: output=b8b5148f63b6b56f input=a4f4525679261084]*/
481
14
{
482
14
    PyObject *subtype, *result = NULL, *subclass = NULL;
483
14
    _abc_data *impl = _get_impl(self);
484
14
    if (impl == NULL) {
485
0
        return NULL;
486
0
    }
487
488
14
    subclass = _PyObject_GetAttrId(instance, &PyId___class__);
489
14
    if (subclass == NULL) {
490
0
        Py_DECREF(impl);
491
0
        return NULL;
492
0
    }
493
    /* Inline the cache checking. */
494
14
    int incache = _in_weak_set(impl->_abc_cache, subclass);
495
14
    if (incache < 0) {
496
0
        goto end;
497
0
    }
498
14
    if (incache > 0) {
499
0
        result = Py_True;
500
0
        Py_INCREF(result);
501
0
        goto end;
502
0
    }
503
14
    subtype = (PyObject *)Py_TYPE(instance);
504
14
    if (subtype == subclass) {
505
14
        if (impl->_abc_negative_cache_version == abc_invalidation_counter) {
506
13
            incache = _in_weak_set(impl->_abc_negative_cache, subclass);
507
13
            if (incache < 0) {
508
0
                goto end;
509
0
            }
510
13
            if (incache > 0) {
511
13
                result = Py_False;
512
13
                Py_INCREF(result);
513
13
                goto end;
514
13
            }
515
13
        }
516
        /* Fall back to the subclass check. */
517
1
        result = _PyObject_CallMethodIdObjArgs(self, &PyId___subclasscheck__,
518
1
                                               subclass, NULL);
519
1
        goto end;
520
14
    }
521
0
    result = _PyObject_CallMethodIdObjArgs(self, &PyId___subclasscheck__,
522
0
                                           subclass, NULL);
523
0
    if (result == NULL) {
524
0
        goto end;
525
0
    }
526
527
0
    switch (PyObject_IsTrue(result)) {
528
0
    case -1:
529
0
        Py_DECREF(result);
530
0
        result = NULL;
531
0
        break;
532
0
    case 0:
533
0
        Py_DECREF(result);
534
0
        result = _PyObject_CallMethodIdObjArgs(self, &PyId___subclasscheck__,
535
0
                                               subtype, NULL);
536
0
        break;
537
0
    case 1:  // Nothing to do.
538
0
        break;
539
0
    default:
540
0
        Py_UNREACHABLE();
541
0
    }
542
543
14
end:
544
14
    Py_XDECREF(impl);
545
14
    Py_XDECREF(subclass);
546
14
    return result;
547
0
}
548
549
550
// Return -1 when exception occurred.
551
// Return 1 when result is set.
552
// Return 0 otherwise.
553
static int subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
554
                                        PyObject **result);
555
556
/*[clinic input]
557
_abc._abc_subclasscheck
558
559
    self: object
560
    subclass: object
561
    /
562
563
Internal ABC helper for subclasss checks. Should be never used outside abc module.
564
[clinic start generated code]*/
565
566
static PyObject *
567
_abc__abc_subclasscheck_impl(PyObject *module, PyObject *self,
568
                             PyObject *subclass)
569
/*[clinic end generated code: output=b56c9e4a530e3894 input=1d947243409d10b8]*/
570
515
{
571
515
    if (!PyType_Check(subclass)) {
572
0
        PyErr_SetString(PyExc_TypeError, "issubclass() arg 1 must be a class");
573
0
        return NULL;
574
0
    }
575
576
515
    PyObject *ok, *subclasses = NULL, *result = NULL;
577
515
    Py_ssize_t pos;
578
515
    int incache;
579
515
    _abc_data *impl = _get_impl(self);
580
515
    if (impl == NULL) {
581
0
        return NULL;
582
0
    }
583
584
    /* 1. Check cache. */
585
515
    incache = _in_weak_set(impl->_abc_cache, subclass);
586
515
    if (incache < 0) {
587
0
        goto end;
588
0
    }
589
515
    if (incache > 0) {
590
0
        result = Py_True;
591
0
        goto end;
592
0
    }
593
594
    /* 2. Check negative cache; may have to invalidate. */
595
515
    if (impl->_abc_negative_cache_version < abc_invalidation_counter) {
596
        /* Invalidate the negative cache. */
597
160
        if (impl->_abc_negative_cache != NULL &&
598
133
                PySet_Clear(impl->_abc_negative_cache) < 0)
599
0
        {
600
0
            goto end;
601
0
        }
602
160
        impl->_abc_negative_cache_version = abc_invalidation_counter;
603
160
    }
604
355
    else {
605
355
        incache = _in_weak_set(impl->_abc_negative_cache, subclass);
606
355
        if (incache < 0) {
607
0
            goto end;
608
0
        }
609
355
        if (incache > 0) {
610
0
            result = Py_False;
611
0
            goto end;
612
0
        }
613
355
    }
614
615
    /* 3. Check the subclass hook. */
616
515
    ok = _PyObject_CallMethodIdObjArgs((PyObject *)self, &PyId___subclasshook__,
617
515
                                       subclass, NULL);
618
515
    if (ok == NULL) {
619
0
        goto end;
620
0
    }
621
515
    if (ok == Py_True) {
622
208
        Py_DECREF(ok);
623
208
        if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) {
624
0
            goto end;
625
0
        }
626
208
        result = Py_True;
627
208
        goto end;
628
208
    }
629
307
    if (ok == Py_False) {
630
0
        Py_DECREF(ok);
631
0
        if (_add_to_weak_set(&impl->_abc_negative_cache, subclass) < 0) {
632
0
            goto end;
633
0
        }
634
0
        result = Py_False;
635
0
        goto end;
636
0
    }
637
307
    if (ok != Py_NotImplemented) {
638
0
        Py_DECREF(ok);
639
0
        PyErr_SetString(PyExc_AssertionError, "__subclasshook__ must return either"
640
0
                                              " False, True, or NotImplemented");
641
0
        goto end;
642
0
    }
643
307
    Py_DECREF(ok);
644
645
    /* 4. Check if it's a direct subclass. */
646
307
    PyObject *mro = ((PyTypeObject *)subclass)->tp_mro;
647
307
    assert(PyTuple_Check(mro));
648
1.12k
    for (pos = 0; pos < PyTuple_GET_SIZE(mro); pos++) {
649
822
        PyObject *mro_item = PyTuple_GET_ITEM(mro, pos);
650
822
        assert(mro_item != NULL);
651
822
        if ((PyObject *)self == mro_item) {
652
0
            if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) {
653
0
                goto end;
654
0
            }
655
0
            result = Py_True;
656
0
            goto end;
657
0
        }
658
822
    }
659
660
    /* 5. Check if it's a subclass of a registered class (recursive). */
661
307
    if (subclasscheck_check_registry(impl, subclass, &result)) {
662
        // Exception occurred or result is set.
663
0
        goto end;
664
0
    }
665
666
    /* 6. Check if it's a subclass of a subclass (recursive). */
667
307
    subclasses = PyObject_CallMethod(self, "__subclasses__", NULL);
668
307
    if (subclasses == NULL) {
669
0
        goto end;
670
0
    }
671
307
    if (!PyList_Check(subclasses)) {
672
0
        PyErr_SetString(PyExc_TypeError, "__subclasses__() must return a list");
673
0
        goto end;
674
0
    }
675
313
    for (pos = 0; pos < PyList_GET_SIZE(subclasses); pos++) {
676
6
        PyObject *scls = PyList_GET_ITEM(subclasses, pos);
677
6
        Py_INCREF(scls);
678
6
        int r = PyObject_IsSubclass(subclass, scls);
679
6
        Py_DECREF(scls);
680
6
        if (r > 0) {
681
0
            if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) {
682
0
                goto end;
683
0
            }
684
0
            result = Py_True;
685
0
            goto end;
686
0
        }
687
6
        if (r < 0) {
688
0
            goto end;
689
0
        }
690
6
    }
691
692
    /* No dice; update negative cache. */
693
307
    if (_add_to_weak_set(&impl->_abc_negative_cache, subclass) < 0) {
694
0
        goto end;
695
0
    }
696
307
    result = Py_False;
697
698
515
end:
699
515
    Py_DECREF(impl);
700
515
    Py_XDECREF(subclasses);
701
515
    Py_XINCREF(result);
702
515
    return result;
703
307
}
704
705
706
static int
707
subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
708
                             PyObject **result)
709
307
{
710
    // Fast path: check subclass is in weakref directly.
711
307
    int ret = _in_weak_set(impl->_abc_registry, subclass);
712
307
    if (ret < 0) {
713
0
        *result = NULL;
714
0
        return -1;
715
0
    }
716
307
    if (ret > 0) {
717
0
        *result = Py_True;
718
0
        return 1;
719
0
    }
720
721
307
    if (impl->_abc_registry == NULL) {
722
174
        return 0;
723
174
    }
724
133
    Py_ssize_t registry_size = PySet_Size(impl->_abc_registry);
725
133
    if (registry_size == 0) {
726
0
        return 0;
727
0
    }
728
    // Weakref callback may remove entry from set.
729
    // So we take snapshot of registry first.
730
133
    PyObject **copy = PyMem_Malloc(sizeof(PyObject*) * registry_size);
731
133
    if (copy == NULL) {
732
0
        PyErr_NoMemory();
733
0
        return -1;
734
0
    }
735
133
    PyObject *key;
736
133
    Py_ssize_t pos = 0;
737
133
    Py_hash_t hash;
738
133
    Py_ssize_t i = 0;
739
740
384
    while (_PySet_NextEntry(impl->_abc_registry, &pos, &key, &hash)) {
741
251
        Py_INCREF(key);
742
251
        copy[i++] = key;
743
251
    }
744
133
    assert(i == registry_size);
745
746
384
    for (i = 0; i < registry_size; i++) {
747
251
        PyObject *rkey = PyWeakref_GetObject(copy[i]);
748
251
        if (rkey == NULL) {
749
            // Someone inject non-weakref type in the registry.
750
0
            ret = -1;
751
0
            break;
752
0
        }
753
251
        if (rkey == Py_None) {
754
0
            continue;
755
0
        }
756
251
        Py_INCREF(rkey);
757
251
        int r = PyObject_IsSubclass(subclass, rkey);
758
251
        Py_DECREF(rkey);
759
251
        if (r < 0) {
760
0
            ret = -1;
761
0
            break;
762
0
        }
763
251
        if (r > 0) {
764
0
            if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) {
765
0
                ret = -1;
766
0
                break;
767
0
            }
768
0
            *result = Py_True;
769
0
            ret = 1;
770
0
            break;
771
0
        }
772
251
    }
773
774
384
    for (i = 0; i < registry_size; i++) {
775
251
        Py_DECREF(copy[i]);
776
251
    }
777
133
    PyMem_Free(copy);
778
133
    return ret;
779
133
}
780
781
/*[clinic input]
782
_abc.get_cache_token
783
784
Returns the current ABC cache token.
785
786
The token is an opaque object (supporting equality testing) identifying the
787
current version of the ABC cache for virtual subclasses. The token changes
788
with every call to register() on any ABC.
789
[clinic start generated code]*/
790
791
static PyObject *
792
_abc_get_cache_token_impl(PyObject *module)
793
/*[clinic end generated code: output=c7d87841e033dacc input=70413d1c423ad9f9]*/
794
0
{
795
0
    return PyLong_FromUnsignedLongLong(abc_invalidation_counter);
796
0
}
797
798
static struct PyMethodDef module_functions[] = {
799
    _ABC_GET_CACHE_TOKEN_METHODDEF
800
    _ABC__ABC_INIT_METHODDEF
801
    _ABC__RESET_REGISTRY_METHODDEF
802
    _ABC__RESET_CACHES_METHODDEF
803
    _ABC__GET_DUMP_METHODDEF
804
    _ABC__ABC_REGISTER_METHODDEF
805
    _ABC__ABC_INSTANCECHECK_METHODDEF
806
    _ABC__ABC_SUBCLASSCHECK_METHODDEF
807
    {NULL,       NULL}          /* sentinel */
808
};
809
810
static struct PyModuleDef _abcmodule = {
811
    PyModuleDef_HEAD_INIT,
812
    "_abc",
813
    _abc__doc__,
814
    -1,
815
    module_functions,
816
    NULL,
817
    NULL,
818
    NULL,
819
    NULL
820
};
821
822
823
PyMODINIT_FUNC
824
PyInit__abc(void)
825
13
{
826
13
    if (PyType_Ready(&_abc_data_type) < 0) {
827
0
        return NULL;
828
0
    }
829
13
    _abc_data_type.tp_doc = abc_data_doc;
830
831
13
    return PyModule_Create(&_abcmodule);
832
13
}