Coverage Report

Created: 2025-07-11 06:59

/src/Python-3.8.3/Modules/_abc.c
Line
Count
Source (jump to first uncovered line)
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
457
{
53
457
    _abc_data *self = (_abc_data *) type->tp_alloc(type, 0);
54
457
    if (self == NULL) {
55
0
        return NULL;
56
0
    }
57
58
457
    self->_abc_registry = NULL;
59
457
    self->_abc_cache = NULL;
60
457
    self->_abc_negative_cache = NULL;
61
457
    self->_abc_negative_cache_version = abc_invalidation_counter;
62
457
    return (PyObject *) self;
63
457
}
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
891
{
81
891
    PyObject *impl = _PyObject_GetAttrId(self, &PyId__abc_impl);
82
891
    if (impl == NULL) {
83
0
        return NULL;
84
0
    }
85
891
    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
891
    return (_abc_data *)impl;
91
891
}
92
93
static int
94
_in_weak_set(PyObject *set, PyObject *obj)
95
1.29k
{
96
1.29k
    if (set == NULL || PySet_GET_SIZE(set) == 0) {
97
969
        return 0;
98
969
    }
99
324
    PyObject *ref = PyWeakref_NewRef(obj, NULL);
100
324
    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
324
    int res = PySet_Contains(set, ref);
108
324
    Py_DECREF(ref);
109
324
    return res;
110
324
}
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
877
{
136
877
    if (*pset == NULL) {
137
425
        *pset = PySet_New(NULL);
138
425
        if (*pset == NULL) {
139
0
            return -1;
140
0
        }
141
425
    }
142
143
877
    PyObject *set = *pset;
144
877
    PyObject *ref, *wr;
145
877
    PyObject *destroy_cb;
146
877
    wr = PyWeakref_NewRef(set, NULL);
147
877
    if (wr == NULL) {
148
0
        return -1;
149
0
    }
150
877
    destroy_cb = PyCFunction_NewEx(&_destroy_def, wr, NULL);
151
877
    if (destroy_cb == NULL) {
152
0
        Py_DECREF(wr);
153
0
        return -1;
154
0
    }
155
877
    ref = PyWeakref_NewRef(obj, destroy_cb);
156
877
    Py_DECREF(destroy_cb);
157
877
    if (ref == NULL) {
158
0
        Py_DECREF(wr);
159
0
        return -1;
160
0
    }
161
877
    int ret = PySet_Add(set, ref);
162
877
    Py_DECREF(wr);
163
877
    Py_DECREF(ref);
164
877
    return ret;
165
877
}
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
457
{
261
457
    int ret = -1;
262
457
    PyObject *abstracts = PyFrozenSet_New(NULL);
263
457
    if (abstracts == NULL) {
264
0
        return -1;
265
0
    }
266
267
457
    PyObject *ns = NULL, *items = NULL, *bases = NULL;  // Py_XDECREF()ed on error.
268
269
    /* Stage 1: direct abstract methods. */
270
457
    ns = _PyObject_GetAttrId(self, &PyId___dict__);
271
457
    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
457
    items = PyMapping_Items(ns);
278
457
    if (!items) {
279
0
        goto error;
280
0
    }
281
457
    assert(PyList_Check(items));
282
3.65k
    for (Py_ssize_t pos = 0; pos < PyList_GET_SIZE(items); pos++) {
283
3.19k
        PyObject *it = PySequence_Fast(
284
3.19k
                PyList_GET_ITEM(items, pos),
285
3.19k
                "items() returned non-iterable");
286
3.19k
        if (!it) {
287
0
            goto error;
288
0
        }
289
3.19k
        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
3.19k
        PyObject *key = PySequence_Fast_GET_ITEM(it, 0);
298
3.19k
        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
3.19k
        Py_INCREF(key);
302
3.19k
        int is_abstract = _PyObject_IsAbstract(value);
303
3.19k
        if (is_abstract < 0 ||
304
3.19k
                (is_abstract && PySet_Add(abstracts, key) < 0)) {
305
0
            Py_DECREF(it);
306
0
            Py_DECREF(key);
307
0
            goto error;
308
0
        }
309
3.19k
        Py_DECREF(key);
310
3.19k
        Py_DECREF(it);
311
3.19k
    }
312
313
    /* Stage 2: inherited abstract methods. */
314
457
    bases = _PyObject_GetAttrId(self, &PyId___bases__);
315
457
    if (!bases) {
316
0
        goto error;
317
0
    }
318
457
    if (!PyTuple_Check(bases)) {
319
0
        PyErr_SetString(PyExc_TypeError, "__bases__ is not tuple");
320
0
        goto error;
321
0
    }
322
323
1.04k
    for (Py_ssize_t pos = 0; pos < PyTuple_GET_SIZE(bases); pos++) {
324
583
        PyObject *item = PyTuple_GET_ITEM(bases, pos);  // borrowed
325
583
        PyObject *base_abstracts, *iter;
326
327
583
        if (_PyObject_LookupAttrId(item, &PyId___abstractmethods__,
328
583
                                   &base_abstracts) < 0) {
329
0
            goto error;
330
0
        }
331
583
        if (base_abstracts == NULL) {
332
168
            continue;
333
168
        }
334
415
        if (!(iter = PyObject_GetIter(base_abstracts))) {
335
0
            Py_DECREF(base_abstracts);
336
0
            goto error;
337
0
        }
338
415
        Py_DECREF(base_abstracts);
339
415
        PyObject *key, *value;
340
1.07k
        while ((key = PyIter_Next(iter))) {
341
657
            if (_PyObject_LookupAttr(self, key, &value) < 0) {
342
0
                Py_DECREF(key);
343
0
                Py_DECREF(iter);
344
0
                goto error;
345
0
            }
346
657
            if (value == NULL) {
347
0
                Py_DECREF(key);
348
0
                continue;
349
0
            }
350
351
657
            int is_abstract = _PyObject_IsAbstract(value);
352
657
            Py_DECREF(value);
353
657
            if (is_abstract < 0 ||
354
657
                    (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
657
            Py_DECREF(key);
361
657
        }
362
415
        Py_DECREF(iter);
363
415
        if (PyErr_Occurred()) {
364
0
            goto error;
365
0
        }
366
415
    }
367
368
457
    if (_PyObject_SetAttrId(self, &PyId___abstractmethods__, abstracts) < 0) {
369
0
        goto error;
370
0
    }
371
372
457
    ret = 0;
373
457
error:
374
457
    Py_DECREF(abstracts);
375
457
    Py_XDECREF(ns);
376
457
    Py_XDECREF(items);
377
457
    Py_XDECREF(bases);
378
457
    return ret;
379
457
}
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
457
{
394
457
    PyObject *data;
395
457
    if (compute_abstract_methods(self) < 0) {
396
0
        return NULL;
397
0
    }
398
399
    /* Set up inheritance registry. */
400
457
    data = abc_data_new(&_abc_data_type, NULL, NULL);
401
457
    if (data == NULL) {
402
0
        return NULL;
403
0
    }
404
457
    if (_PyObject_SetAttrId(self, &PyId__abc_impl, data) < 0) {
405
0
        Py_DECREF(data);
406
0
        return NULL;
407
0
    }
408
457
    Py_DECREF(data);
409
457
    Py_RETURN_NONE;
410
457
}
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
547
{
426
547
    if (!PyType_Check(subclass)) {
427
0
        PyErr_SetString(PyExc_TypeError, "Can only register classes");
428
0
        return NULL;
429
0
    }
430
547
    int result = PyObject_IsSubclass(subclass, self);
431
547
    if (result > 0) {
432
224
        Py_INCREF(subclass);
433
224
        return subclass;  /* Already a subclass. */
434
224
    }
435
323
    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
323
    result = PyObject_IsSubclass(self, subclass);
441
323
    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
323
    if (result < 0) {
447
0
        return NULL;
448
0
    }
449
323
    _abc_data *impl = _get_impl(self);
450
323
    if (impl == NULL) {
451
0
        return NULL;
452
0
    }
453
323
    if (_add_to_weak_set(&impl->_abc_registry, subclass) < 0) {
454
0
        Py_DECREF(impl);
455
0
        return NULL;
456
0
    }
457
323
    Py_DECREF(impl);
458
459
    /* Invalidate negative cache */
460
323
    abc_invalidation_counter++;
461
462
323
    Py_INCREF(subclass);
463
323
    return subclass;
464
323
}
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
554
{
571
554
    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
554
    PyObject *ok, *subclasses = NULL, *result = NULL;
577
554
    Py_ssize_t pos;
578
554
    int incache;
579
554
    _abc_data *impl = _get_impl(self);
580
554
    if (impl == NULL) {
581
0
        return NULL;
582
0
    }
583
584
    /* 1. Check cache. */
585
554
    incache = _in_weak_set(impl->_abc_cache, subclass);
586
554
    if (incache < 0) {
587
0
        goto end;
588
0
    }
589
554
    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
554
    if (impl->_abc_negative_cache_version < abc_invalidation_counter) {
596
        /* Invalidate the negative cache. */
597
172
        if (impl->_abc_negative_cache != NULL &&
598
172
                PySet_Clear(impl->_abc_negative_cache) < 0)
599
0
        {
600
0
            goto end;
601
0
        }
602
172
        impl->_abc_negative_cache_version = abc_invalidation_counter;
603
172
    }
604
382
    else {
605
382
        incache = _in_weak_set(impl->_abc_negative_cache, subclass);
606
382
        if (incache < 0) {
607
0
            goto end;
608
0
        }
609
382
        if (incache > 0) {
610
0
            result = Py_False;
611
0
            goto end;
612
0
        }
613
382
    }
614
615
    /* 3. Check the subclass hook. */
616
554
    ok = _PyObject_CallMethodIdObjArgs((PyObject *)self, &PyId___subclasshook__,
617
554
                                       subclass, NULL);
618
554
    if (ok == NULL) {
619
0
        goto end;
620
0
    }
621
554
    if (ok == Py_True) {
622
224
        Py_DECREF(ok);
623
224
        if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) {
624
0
            goto end;
625
0
        }
626
224
        result = Py_True;
627
224
        goto end;
628
224
    }
629
330
    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
330
    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
330
    Py_DECREF(ok);
644
645
    /* 4. Check if it's a direct subclass. */
646
330
    PyObject *mro = ((PyTypeObject *)subclass)->tp_mro;
647
330
    assert(PyTuple_Check(mro));
648
1.21k
    for (pos = 0; pos < PyTuple_GET_SIZE(mro); pos++) {
649
884
        PyObject *mro_item = PyTuple_GET_ITEM(mro, pos);
650
884
        assert(mro_item != NULL);
651
884
        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
884
    }
659
660
    /* 5. Check if it's a subclass of a registered class (recursive). */
661
330
    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
330
    subclasses = PyObject_CallMethod(self, "__subclasses__", NULL);
668
330
    if (subclasses == NULL) {
669
0
        goto end;
670
0
    }
671
330
    if (!PyList_Check(subclasses)) {
672
0
        PyErr_SetString(PyExc_TypeError, "__subclasses__() must return a list");
673
0
        goto end;
674
0
    }
675
336
    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
330
    if (_add_to_weak_set(&impl->_abc_negative_cache, subclass) < 0) {
694
0
        goto end;
695
0
    }
696
330
    result = Py_False;
697
698
554
end:
699
554
    Py_DECREF(impl);
700
554
    Py_XDECREF(subclasses);
701
554
    Py_XINCREF(result);
702
554
    return result;
703
330
}
704
705
706
static int
707
subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
708
                             PyObject **result)
709
330
{
710
    // Fast path: check subclass is in weakref directly.
711
330
    int ret = _in_weak_set(impl->_abc_registry, subclass);
712
330
    if (ret < 0) {
713
0
        *result = NULL;
714
0
        return -1;
715
0
    }
716
330
    if (ret > 0) {
717
0
        *result = Py_True;
718
0
        return 1;
719
0
    }
720
721
330
    if (impl->_abc_registry == NULL) {
722
187
        return 0;
723
187
    }
724
143
    Py_ssize_t registry_size = PySet_Size(impl->_abc_registry);
725
143
    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
143
    PyObject **copy = PyMem_Malloc(sizeof(PyObject*) * registry_size);
731
143
    if (copy == NULL) {
732
0
        PyErr_NoMemory();
733
0
        return -1;
734
0
    }
735
143
    PyObject *key;
736
143
    Py_ssize_t pos = 0;
737
143
    Py_hash_t hash;
738
143
    Py_ssize_t i = 0;
739
740
413
    while (_PySet_NextEntry(impl->_abc_registry, &pos, &key, &hash)) {
741
270
        Py_INCREF(key);
742
270
        copy[i++] = key;
743
270
    }
744
143
    assert(i == registry_size);
745
746
413
    for (i = 0; i < registry_size; i++) {
747
270
        PyObject *rkey = PyWeakref_GetObject(copy[i]);
748
270
        if (rkey == NULL) {
749
            // Someone inject non-weakref type in the registry.
750
0
            ret = -1;
751
0
            break;
752
0
        }
753
270
        if (rkey == Py_None) {
754
0
            continue;
755
0
        }
756
270
        Py_INCREF(rkey);
757
270
        int r = PyObject_IsSubclass(subclass, rkey);
758
270
        Py_DECREF(rkey);
759
270
        if (r < 0) {
760
0
            ret = -1;
761
0
            break;
762
0
        }
763
270
        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
270
    }
773
774
413
    for (i = 0; i < registry_size; i++) {
775
270
        Py_DECREF(copy[i]);
776
270
    }
777
143
    PyMem_Free(copy);
778
143
    return ret;
779
143
}
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
14
{
826
14
    if (PyType_Ready(&_abc_data_type) < 0) {
827
0
        return NULL;
828
0
    }
829
14
    _abc_data_type.tp_doc = abc_data_doc;
830
831
14
    return PyModule_Create(&_abcmodule);
832
14
}