Coverage Report

Created: 2026-10-31 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Modules/_abc.c
Line
Count
Source
1
/* ABCMeta implementation */
2
#ifndef Py_BUILD_CORE_BUILTIN
3
#  define Py_BUILD_CORE_MODULE 1
4
#endif
5
6
#include "Python.h"
7
#include "pycore_moduleobject.h"  // _PyModule_GetState()
8
#include "pycore_object.h"        // _PyType_GetSubclasses()
9
#include "pycore_runtime.h"       // _Py_ID()
10
#include "pycore_setobject.h"     // _PySet_NextEntry()
11
#include "pycore_weakref.h"       // _PyWeakref_GET_REF()
12
#include "clinic/_abc.c.h"
13
14
/*[clinic input]
15
module _abc
16
[clinic start generated code]*/
17
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=964f5328e1aefcda]*/
18
19
PyDoc_STRVAR(_abc__doc__,
20
"Module contains faster C implementation of abc.ABCMeta");
21
22
typedef struct {
23
    PyTypeObject *_abc_data_type;
24
    uint64_t abc_invalidation_counter;
25
} _abcmodule_state;
26
27
static inline _abcmodule_state*
28
get_abc_state(PyObject *module)
29
255k
{
30
255k
    void *state = _PyModule_GetState(module);
31
255k
    assert(state != NULL);
32
255k
    return (_abcmodule_state *)state;
33
255k
}
34
35
static inline uint64_t
36
get_invalidation_counter(_abcmodule_state *state)
37
116k
{
38
#ifdef Py_GIL_DISABLED
39
    return _Py_atomic_load_uint64(&state->abc_invalidation_counter);
40
#else
41
116k
    return state->abc_invalidation_counter;
42
116k
#endif
43
116k
}
44
45
static inline void
46
increment_invalidation_counter(_abcmodule_state *state)
47
989
{
48
#ifdef Py_GIL_DISABLED
49
    _Py_atomic_add_uint64(&state->abc_invalidation_counter, 1);
50
#else
51
989
    state->abc_invalidation_counter++;
52
989
#endif
53
989
}
54
55
/* This object stores internal state for ABCs.
56
   Note that we can use normal sets for caches,
57
   since they are never iterated over. */
58
typedef struct {
59
    PyObject_HEAD
60
    /* These sets of weak references are lazily created. Once created, they
61
       will point to the same sets until the ABCMeta object is destroyed or
62
       cleared, both of which will only happen while the object is visible to a
63
       single thread. */
64
    PyObject *_abc_registry;
65
    PyObject *_abc_cache;
66
    PyObject *_abc_negative_cache;
67
    uint64_t _abc_negative_cache_version;
68
} _abc_data;
69
70
79.2k
#define _abc_data_CAST(op)  ((_abc_data *)(op))
71
72
static inline uint64_t
73
get_cache_version(_abc_data *impl)
74
114k
{
75
#ifdef Py_GIL_DISABLED
76
    return _Py_atomic_load_uint64(&impl->_abc_negative_cache_version);
77
#else
78
114k
    return impl->_abc_negative_cache_version;
79
114k
#endif
80
114k
}
81
82
static inline void
83
set_cache_version(_abc_data *impl, uint64_t version)
84
798
{
85
#ifdef Py_GIL_DISABLED
86
    _Py_atomic_store_uint64(&impl->_abc_negative_cache_version, version);
87
#else
88
798
    impl->_abc_negative_cache_version = version;
89
798
#endif
90
798
}
91
92
static int
93
abc_data_traverse(PyObject *op, visitproc visit, void *arg)
94
79.2k
{
95
79.2k
    _abc_data *self = _abc_data_CAST(op);
96
79.2k
    Py_VISIT(Py_TYPE(self));
97
79.2k
    Py_VISIT(self->_abc_registry);
98
79.2k
    Py_VISIT(self->_abc_cache);
99
79.2k
    Py_VISIT(self->_abc_negative_cache);
100
79.2k
    return 0;
101
79.2k
}
102
103
static int
104
abc_data_clear(PyObject *op)
105
0
{
106
0
    _abc_data *self = _abc_data_CAST(op);
107
0
    Py_CLEAR(self->_abc_registry);
108
0
    Py_CLEAR(self->_abc_cache);
109
0
    Py_CLEAR(self->_abc_negative_cache);
110
0
    return 0;
111
0
}
112
113
static void
114
abc_data_dealloc(PyObject *self)
115
0
{
116
0
    PyObject_GC_UnTrack(self);
117
0
    PyTypeObject *tp = Py_TYPE(self);
118
0
    (void)abc_data_clear(self);
119
0
    tp->tp_free(self);
120
0
    Py_DECREF(tp);
121
0
}
122
123
static PyObject *
124
abc_data_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
125
1.99k
{
126
1.99k
    _abc_data *self = (_abc_data *) type->tp_alloc(type, 0);
127
1.99k
    _abcmodule_state *state = NULL;
128
1.99k
    if (self == NULL) {
129
0
        return NULL;
130
0
    }
131
132
1.99k
    state = _PyType_GetModuleState(type);
133
1.99k
    if (state == NULL) {
134
0
        Py_DECREF(self);
135
0
        return NULL;
136
0
    }
137
138
1.99k
    self->_abc_registry = NULL;
139
1.99k
    self->_abc_cache = NULL;
140
1.99k
    self->_abc_negative_cache = NULL;
141
1.99k
    self->_abc_negative_cache_version = get_invalidation_counter(state);
142
1.99k
    return (PyObject *) self;
143
1.99k
}
144
145
PyDoc_STRVAR(abc_data_doc,
146
"Internal state held by ABC machinery.");
147
148
static PyType_Slot _abc_data_type_spec_slots[] = {
149
    {Py_tp_doc, (void *)abc_data_doc},
150
    {Py_tp_new, abc_data_new},
151
    {Py_tp_dealloc, abc_data_dealloc},
152
    {Py_tp_traverse, abc_data_traverse},
153
    {Py_tp_clear, abc_data_clear},
154
    {0, 0}
155
};
156
157
static PyType_Spec _abc_data_type_spec = {
158
    .name = "_abc._abc_data",
159
    .basicsize = sizeof(_abc_data),
160
    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
161
    .slots = _abc_data_type_spec_slots,
162
};
163
164
static _abc_data *
165
_get_impl(PyObject *module, PyObject *self)
166
136k
{
167
136k
    _abcmodule_state *state = get_abc_state(module);
168
136k
    PyObject *impl = PyObject_GetAttr(self, &_Py_ID(_abc_impl));
169
136k
    if (impl == NULL) {
170
0
        return NULL;
171
0
    }
172
136k
    if (!Py_IS_TYPE(impl, state->_abc_data_type)) {
173
0
        PyErr_SetString(PyExc_TypeError, "_abc_impl is set to a wrong type");
174
0
        Py_DECREF(impl);
175
0
        return NULL;
176
0
    }
177
136k
    return (_abc_data *)impl;
178
136k
}
179
180
static int
181
_in_weak_set(_abc_data *impl, PyObject **pset, PyObject *obj)
182
270k
{
183
270k
    PyObject *set;
184
270k
    Py_BEGIN_CRITICAL_SECTION(impl);
185
270k
    set = *pset;
186
270k
    Py_END_CRITICAL_SECTION();
187
270k
    if (set == NULL || PySet_GET_SIZE(set) == 0) {
188
62.2k
        return 0;
189
62.2k
    }
190
208k
    PyObject *ref = PyWeakref_NewRef(obj, NULL);
191
208k
    if (ref == NULL) {
192
0
        if (PyErr_ExceptionMatches(PyExc_TypeError)) {
193
0
            PyErr_Clear();
194
0
            return 0;
195
0
        }
196
0
        return -1;
197
0
    }
198
208k
    int res = PySet_Contains(set, ref);
199
208k
    Py_DECREF(ref);
200
208k
    return res;
201
208k
}
202
203
static PyObject *
204
_destroy(PyObject *setweakref, PyObject *objweakref)
205
0
{
206
0
    PyObject *set = _PyWeakref_GET_REF(setweakref);
207
0
    if (set == NULL) {
208
0
        Py_RETURN_NONE;
209
0
    }
210
0
    if (PySet_Discard(set, objweakref) < 0) {
211
0
        Py_DECREF(set);
212
0
        return NULL;
213
0
    }
214
0
    Py_DECREF(set);
215
0
    Py_RETURN_NONE;
216
0
}
217
218
static PyMethodDef _destroy_def = {
219
    "_destroy", _destroy, METH_O
220
};
221
222
static int
223
_add_to_weak_set(_abc_data *impl, PyObject **pset, PyObject *obj)
224
2.93k
{
225
2.93k
    PyObject *set;
226
2.93k
    Py_BEGIN_CRITICAL_SECTION(impl);
227
2.93k
    set = *pset;
228
2.93k
    if (set == NULL) {
229
1.25k
        set = *pset = PySet_New(NULL);
230
1.25k
    }
231
2.93k
    Py_END_CRITICAL_SECTION();
232
2.93k
    if (set == NULL) {
233
0
        return -1;
234
0
    }
235
236
2.93k
    PyObject *ref, *wr;
237
2.93k
    PyObject *destroy_cb;
238
2.93k
    wr = PyWeakref_NewRef(set, NULL);
239
2.93k
    if (wr == NULL) {
240
0
        return -1;
241
0
    }
242
2.93k
    destroy_cb = PyCFunction_NewEx(&_destroy_def, wr, NULL);
243
2.93k
    if (destroy_cb == NULL) {
244
0
        Py_DECREF(wr);
245
0
        return -1;
246
0
    }
247
2.93k
    ref = PyWeakref_NewRef(obj, destroy_cb);
248
2.93k
    Py_DECREF(destroy_cb);
249
2.93k
    if (ref == NULL) {
250
0
        Py_DECREF(wr);
251
0
        return -1;
252
0
    }
253
2.93k
    int ret = PySet_Add(set, ref);
254
2.93k
    Py_DECREF(wr);
255
2.93k
    Py_DECREF(ref);
256
2.93k
    return ret;
257
2.93k
}
258
259
/*[clinic input]
260
_abc._reset_registry
261
262
    self: object
263
    /
264
265
Internal ABC helper to reset registry of a given class.
266
267
Should be only used by refleak.py
268
[clinic start generated code]*/
269
270
static PyObject *
271
_abc__reset_registry(PyObject *module, PyObject *self)
272
/*[clinic end generated code: output=92d591a43566cc10 input=12a0b7eb339ac35c]*/
273
0
{
274
0
    _abc_data *impl = _get_impl(module, self);
275
0
    if (impl == NULL) {
276
0
        return NULL;
277
0
    }
278
0
    PyObject *registry;
279
0
    Py_BEGIN_CRITICAL_SECTION(impl);
280
0
    registry = impl->_abc_registry;
281
0
    Py_END_CRITICAL_SECTION();
282
0
    if (registry != NULL && PySet_Clear(registry) < 0) {
283
0
        Py_DECREF(impl);
284
0
        return NULL;
285
0
    }
286
0
    Py_DECREF(impl);
287
0
    Py_RETURN_NONE;
288
0
}
289
290
/*[clinic input]
291
_abc._reset_caches
292
293
    self: object
294
    /
295
296
Internal ABC helper to reset both caches of a given class.
297
298
Should be only used by refleak.py
299
[clinic start generated code]*/
300
301
static PyObject *
302
_abc__reset_caches(PyObject *module, PyObject *self)
303
/*[clinic end generated code: output=f296f0d5c513f80c input=c0ac616fd8acfb6f]*/
304
0
{
305
0
    _abc_data *impl = _get_impl(module, self);
306
0
    if (impl == NULL) {
307
0
        return NULL;
308
0
    }
309
0
    PyObject *cache, *negative_cache;
310
0
    Py_BEGIN_CRITICAL_SECTION(impl);
311
0
    cache = impl->_abc_cache;
312
0
    negative_cache = impl->_abc_negative_cache;
313
0
    Py_END_CRITICAL_SECTION();
314
0
    if (cache != NULL && PySet_Clear(cache) < 0) {
315
0
        Py_DECREF(impl);
316
0
        return NULL;
317
0
    }
318
    /* also the second cache */
319
0
    if (negative_cache != NULL && PySet_Clear(negative_cache) < 0) {
320
0
        Py_DECREF(impl);
321
0
        return NULL;
322
0
    }
323
0
    Py_DECREF(impl);
324
0
    Py_RETURN_NONE;
325
0
}
326
327
/*[clinic input]
328
_abc._get_dump
329
330
    self: object
331
    /
332
333
Internal ABC helper for cache and registry debugging.
334
335
Return shallow copies of registry, of both caches, and
336
negative cache version. Don't call this function directly,
337
instead use ABC._dump_registry() for a nice repr.
338
[clinic start generated code]*/
339
340
static PyObject *
341
_abc__get_dump(PyObject *module, PyObject *self)
342
/*[clinic end generated code: output=9d9569a8e2c1c443 input=2c5deb1bfe9e3c79]*/
343
0
{
344
0
    _abc_data *impl = _get_impl(module, self);
345
0
    if (impl == NULL) {
346
0
        return NULL;
347
0
    }
348
0
    PyObject *res;
349
0
    Py_BEGIN_CRITICAL_SECTION(impl);
350
0
    res = Py_BuildValue("NNNK",
351
0
                        PySet_New(impl->_abc_registry),
352
0
                        PySet_New(impl->_abc_cache),
353
0
                        PySet_New(impl->_abc_negative_cache),
354
0
                        get_cache_version(impl));
355
0
    Py_END_CRITICAL_SECTION();
356
0
    Py_DECREF(impl);
357
0
    return res;
358
0
}
359
360
// Compute set of abstract method names.
361
static int
362
compute_abstract_methods(PyObject *self)
363
1.99k
{
364
1.99k
    int ret = -1;
365
1.99k
    PyObject *abstracts = PyFrozenSet_New(NULL);
366
1.99k
    if (abstracts == NULL) {
367
0
        return -1;
368
0
    }
369
370
1.99k
    PyObject *ns = NULL, *items = NULL, *bases = NULL;  // Py_XDECREF()ed on error.
371
372
    /* Stage 1: direct abstract methods. */
373
1.99k
    ns = PyObject_GetAttr(self, &_Py_ID(__dict__));
374
1.99k
    if (!ns) {
375
0
        goto error;
376
0
    }
377
378
    // We can't use PyDict_Next(ns) even when ns is dict because
379
    // _PyObject_IsAbstract() can mutate ns.
380
1.99k
    items = PyMapping_Items(ns);
381
1.99k
    if (!items) {
382
0
        goto error;
383
0
    }
384
1.99k
    assert(PyList_Check(items));
385
26.8k
    for (Py_ssize_t pos = 0; pos < PyList_GET_SIZE(items); pos++) {
386
24.8k
        PyObject *it = PySequence_Fast(
387
24.8k
                PyList_GET_ITEM(items, pos),
388
24.8k
                "items() returned non-iterable");
389
24.8k
        if (!it) {
390
0
            goto error;
391
0
        }
392
24.8k
        if (PySequence_Fast_GET_SIZE(it) != 2) {
393
0
            PyErr_SetString(PyExc_TypeError,
394
0
                            "items() returned item which size is not 2");
395
0
            Py_DECREF(it);
396
0
            goto error;
397
0
        }
398
399
        // borrowed
400
24.8k
        PyObject *key = PySequence_Fast_GET_ITEM(it, 0);
401
24.8k
        PyObject *value = PySequence_Fast_GET_ITEM(it, 1);
402
        // items or it may be cleared while accessing __abstractmethod__
403
        // So we need to keep strong reference for key
404
24.8k
        Py_INCREF(key);
405
24.8k
        int is_abstract = _PyObject_IsAbstract(value);
406
24.8k
        if (is_abstract < 0 ||
407
24.8k
                (is_abstract && PySet_Add(abstracts, key) < 0)) {
408
0
            Py_DECREF(it);
409
0
            Py_DECREF(key);
410
0
            goto error;
411
0
        }
412
24.8k
        Py_DECREF(key);
413
24.8k
        Py_DECREF(it);
414
24.8k
    }
415
416
    /* Stage 2: inherited abstract methods. */
417
1.99k
    bases = PyObject_GetAttr(self, &_Py_ID(__bases__));
418
1.99k
    if (!bases) {
419
0
        goto error;
420
0
    }
421
1.99k
    if (!PyTuple_Check(bases)) {
422
0
        PyErr_SetString(PyExc_TypeError, "__bases__ is not tuple");
423
0
        goto error;
424
0
    }
425
426
4.39k
    for (Py_ssize_t pos = 0; pos < PyTuple_GET_SIZE(bases); pos++) {
427
2.39k
        PyObject *item = PyTuple_GET_ITEM(bases, pos);  // borrowed
428
2.39k
        PyObject *base_abstracts, *iter;
429
430
2.39k
        if (PyObject_GetOptionalAttr(item, &_Py_ID(__abstractmethods__),
431
2.39k
                                 &base_abstracts) < 0) {
432
0
            goto error;
433
0
        }
434
2.39k
        if (base_abstracts == NULL) {
435
597
            continue;
436
597
        }
437
1.79k
        if (!(iter = PyObject_GetIter(base_abstracts))) {
438
0
            Py_DECREF(base_abstracts);
439
0
            goto error;
440
0
        }
441
1.79k
        Py_DECREF(base_abstracts);
442
1.79k
        PyObject *key, *value;
443
4.92k
        while ((key = PyIter_Next(iter))) {
444
3.13k
            if (PyObject_GetOptionalAttr(self, key, &value) < 0) {
445
0
                Py_DECREF(key);
446
0
                Py_DECREF(iter);
447
0
                goto error;
448
0
            }
449
3.13k
            if (value == NULL) {
450
0
                Py_DECREF(key);
451
0
                continue;
452
0
            }
453
454
3.13k
            int is_abstract = _PyObject_IsAbstract(value);
455
3.13k
            Py_DECREF(value);
456
3.13k
            if (is_abstract < 0 ||
457
3.13k
                    (is_abstract && PySet_Add(abstracts, key) < 0))
458
0
            {
459
0
                Py_DECREF(key);
460
0
                Py_DECREF(iter);
461
0
                goto error;
462
0
            }
463
3.13k
            Py_DECREF(key);
464
3.13k
        }
465
1.79k
        Py_DECREF(iter);
466
1.79k
        if (PyErr_Occurred()) {
467
0
            goto error;
468
0
        }
469
1.79k
    }
470
471
1.99k
    if (PyObject_SetAttr(self, &_Py_ID(__abstractmethods__), abstracts) < 0) {
472
0
        goto error;
473
0
    }
474
475
1.99k
    ret = 0;
476
1.99k
error:
477
1.99k
    Py_DECREF(abstracts);
478
1.99k
    Py_XDECREF(ns);
479
1.99k
    Py_XDECREF(items);
480
1.99k
    Py_XDECREF(bases);
481
1.99k
    return ret;
482
1.99k
}
483
484
1.72k
#define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING)
485
486
/*[clinic input]
487
@permit_long_summary
488
_abc._abc_init
489
490
    self: object
491
    /
492
493
Internal ABC helper for class set-up. Should be never used outside abc module.
494
[clinic start generated code]*/
495
496
static PyObject *
497
_abc__abc_init(PyObject *module, PyObject *self)
498
/*[clinic end generated code: output=594757375714cda1 input=0b3513f947736d39]*/
499
1.99k
{
500
1.99k
    _abcmodule_state *state = get_abc_state(module);
501
1.99k
    PyObject *data;
502
1.99k
    if (compute_abstract_methods(self) < 0) {
503
0
        return NULL;
504
0
    }
505
506
    /* Set up inheritance registry. */
507
1.99k
    data = abc_data_new(state->_abc_data_type, NULL, NULL);
508
1.99k
    if (data == NULL) {
509
0
        return NULL;
510
0
    }
511
1.99k
    if (PyObject_SetAttr(self, &_Py_ID(_abc_impl), data) < 0) {
512
0
        Py_DECREF(data);
513
0
        return NULL;
514
0
    }
515
1.99k
    Py_DECREF(data);
516
    /* If __abc_tpflags__ & COLLECTION_FLAGS is set, then set the corresponding bit(s)
517
     * in the new class.
518
     * Used by collections.abc.Sequence and collections.abc.Mapping to indicate
519
     * their special status w.r.t. pattern matching. */
520
1.99k
    if (PyType_Check(self)) {
521
1.99k
        PyTypeObject *cls = (PyTypeObject *)self;
522
1.99k
        PyObject *dict = _PyType_GetDict(cls);
523
1.99k
        PyObject *flags = NULL;
524
1.99k
        if (PyDict_Pop(dict, &_Py_ID(__abc_tpflags__), &flags) < 0) {
525
0
            return NULL;
526
0
        }
527
1.99k
        if (flags == NULL || !PyLong_CheckExact(flags)) {
528
1.92k
            Py_XDECREF(flags);
529
1.92k
            Py_RETURN_NONE;
530
1.92k
        }
531
532
74
        long val = PyLong_AsLong(flags);
533
74
        Py_DECREF(flags);
534
74
        if (val == -1 && PyErr_Occurred()) {
535
0
            return NULL;
536
0
        }
537
74
        if ((val & COLLECTION_FLAGS) == COLLECTION_FLAGS) {
538
0
            PyErr_SetString(PyExc_TypeError, "__abc_tpflags__ cannot be both Py_TPFLAGS_SEQUENCE and Py_TPFLAGS_MAPPING");
539
0
            return NULL;
540
0
        }
541
74
        _PyType_SetFlags((PyTypeObject *)self, 0, val & COLLECTION_FLAGS);
542
74
    }
543
1.99k
    Py_RETURN_NONE;
544
1.99k
}
545
546
/*[clinic input]
547
@permit_long_summary
548
_abc._abc_register
549
550
    self: object
551
    subclass: object
552
    /
553
554
Internal ABC helper for subclasss registration. Should be never used outside abc module.
555
[clinic start generated code]*/
556
557
static PyObject *
558
_abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass)
559
/*[clinic end generated code: output=7851e7668c963524 input=135ab13a581b4414]*/
560
1.64k
{
561
1.64k
    if (!PyType_Check(subclass)) {
562
0
        PyErr_SetString(PyExc_TypeError, "Can only register classes");
563
0
        return NULL;
564
0
    }
565
1.64k
    int result = PyObject_IsSubclass(subclass, self);
566
1.64k
    if (result > 0) {
567
656
        return Py_NewRef(subclass);  /* Already a subclass. */
568
656
    }
569
989
    if (result < 0) {
570
0
        return NULL;
571
0
    }
572
    /* Subtle: test for cycles *after* testing for "already a subclass";
573
       this means we allow X.register(X) and interpret it as a no-op. */
574
989
    result = PyObject_IsSubclass(self, subclass);
575
989
    if (result > 0) {
576
        /* This would create a cycle, which is bad for the algorithm below. */
577
0
        PyErr_SetString(PyExc_RuntimeError, "Refusing to create an inheritance cycle");
578
0
        return NULL;
579
0
    }
580
989
    if (result < 0) {
581
0
        return NULL;
582
0
    }
583
989
    _abc_data *impl = _get_impl(module, self);
584
989
    if (impl == NULL) {
585
0
        return NULL;
586
0
    }
587
989
    if (_add_to_weak_set(impl, &impl->_abc_registry, subclass) < 0) {
588
0
        Py_DECREF(impl);
589
0
        return NULL;
590
0
    }
591
989
    Py_DECREF(impl);
592
593
    /* Invalidate negative cache */
594
989
    increment_invalidation_counter(get_abc_state(module));
595
596
    /* Set Py_TPFLAGS_SEQUENCE or Py_TPFLAGS_MAPPING flag */
597
989
    if (PyType_Check(self)) {
598
989
        unsigned long collection_flag =
599
989
            PyType_GetFlags((PyTypeObject *)self) & COLLECTION_FLAGS;
600
989
        if (collection_flag) {
601
518
            _PyType_SetFlagsRecursive((PyTypeObject *)subclass,
602
518
                                      COLLECTION_FLAGS,
603
518
                                      collection_flag);
604
518
        }
605
989
    }
606
989
    return Py_NewRef(subclass);
607
989
}
608
609
610
/*[clinic input]
611
@permit_long_summary
612
_abc._abc_instancecheck
613
614
    self: object
615
    instance: object
616
    /
617
618
Internal ABC helper for instance checks. Should be never used outside abc module.
619
[clinic start generated code]*/
620
621
static PyObject *
622
_abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
623
                             PyObject *instance)
624
/*[clinic end generated code: output=b8b5148f63b6b56f input=0bbc8da0ea346719]*/
625
112k
{
626
112k
    PyObject *subtype, *result = NULL, *subclass = NULL;
627
112k
    _abc_data *impl = _get_impl(module, self);
628
112k
    if (impl == NULL) {
629
0
        return NULL;
630
0
    }
631
632
112k
    if (PyObject_GetOptionalAttr(instance, &_Py_ID(__class__), &subclass) < 0) {
633
0
        Py_DECREF(impl);
634
0
        return NULL;
635
0
    }
636
112k
    if (subclass == NULL) {
637
        /* Fall back to the type when the instance has no __class__, matching
638
           the behaviour of the built-in isinstance() (gh-153772). */
639
0
        subclass = Py_NewRef((PyObject *)Py_TYPE(instance));
640
0
    }
641
    /* Inline the cache checking. */
642
112k
    int incache = _in_weak_set(impl, &impl->_abc_cache, subclass);
643
112k
    if (incache < 0) {
644
0
        goto end;
645
0
    }
646
112k
    if (incache > 0) {
647
20.4k
        result = Py_NewRef(Py_True);
648
20.4k
        goto end;
649
20.4k
    }
650
92.1k
    subtype = (PyObject *)Py_TYPE(instance);
651
92.1k
    if (subtype == subclass) {
652
92.1k
        if (get_cache_version(impl) == get_invalidation_counter(get_abc_state(module))) {
653
92.1k
            incache = _in_weak_set(impl, &impl->_abc_negative_cache, subclass);
654
92.1k
            if (incache < 0) {
655
0
                goto end;
656
0
            }
657
92.1k
            if (incache > 0) {
658
71.7k
                result = Py_NewRef(Py_False);
659
71.7k
                goto end;
660
71.7k
            }
661
92.1k
        }
662
        /* Fall back to the subclass check. */
663
20.3k
        result = PyObject_CallMethodOneArg(self, &_Py_ID(__subclasscheck__),
664
20.3k
                                           subclass);
665
20.3k
        goto end;
666
92.1k
    }
667
    /* A subclass check can change the instance's actual type. */
668
0
    Py_INCREF(subtype);
669
0
    result = PyObject_CallMethodOneArg(self, &_Py_ID(__subclasscheck__),
670
0
                                       subclass);
671
0
    if (result == NULL) {
672
0
        Py_DECREF(subtype);
673
0
        goto end;
674
0
    }
675
676
0
    switch (PyObject_IsTrue(result)) {
677
0
    case -1:
678
0
        Py_SETREF(result, NULL);
679
0
        break;
680
0
    case 0:
681
0
        Py_DECREF(result);
682
0
        result = PyObject_CallMethodOneArg(self, &_Py_ID(__subclasscheck__),
683
0
                                           subtype);
684
0
        break;
685
0
    case 1:  // Nothing to do.
686
0
        break;
687
0
    default:
688
0
        Py_UNREACHABLE();
689
0
    }
690
0
    Py_DECREF(subtype);
691
692
112k
end:
693
112k
    Py_XDECREF(impl);
694
112k
    Py_XDECREF(subclass);
695
112k
    return result;
696
0
}
697
698
699
// Return -1 when exception occurred.
700
// Return 1 when result is set.
701
// Return 0 otherwise.
702
static int subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
703
                                        PyObject **result);
704
705
/*[clinic input]
706
@permit_long_summary
707
_abc._abc_subclasscheck
708
709
    self: object
710
    subclass: object
711
    /
712
713
Internal ABC helper for subclasss checks. Should be never used outside abc module.
714
[clinic start generated code]*/
715
716
static PyObject *
717
_abc__abc_subclasscheck_impl(PyObject *module, PyObject *self,
718
                             PyObject *subclass)
719
/*[clinic end generated code: output=b56c9e4a530e3894 input=5bf1ef712f5d3610]*/
720
22.3k
{
721
22.3k
    if (!PyType_Check(subclass)) {
722
0
        PyErr_SetString(PyExc_TypeError, "issubclass() arg 1 must be a class");
723
0
        return NULL;
724
0
    }
725
726
22.3k
    PyObject *ok, *subclasses = NULL, *result = NULL;
727
22.3k
    _abcmodule_state *state = NULL;
728
22.3k
    Py_ssize_t pos;
729
22.3k
    int incache;
730
22.3k
    _abc_data *impl = _get_impl(module, self);
731
22.3k
    if (impl == NULL) {
732
0
        return NULL;
733
0
    }
734
735
    /* 1. Check cache. */
736
22.3k
    incache = _in_weak_set(impl, &impl->_abc_cache, subclass);
737
22.3k
    if (incache < 0) {
738
0
        goto end;
739
0
    }
740
22.3k
    if (incache > 0) {
741
4
        result = Py_True;
742
4
        goto end;
743
4
    }
744
745
22.3k
    state = get_abc_state(module);
746
    /* 2. Check negative cache; may have to invalidate. */
747
22.3k
    uint64_t invalidation_counter = get_invalidation_counter(state);
748
22.3k
    if (get_cache_version(impl) < invalidation_counter) {
749
        /* Invalidate the negative cache. */
750
798
        PyObject *negative_cache;
751
798
        Py_BEGIN_CRITICAL_SECTION(impl);
752
798
        negative_cache = impl->_abc_negative_cache;
753
798
        Py_END_CRITICAL_SECTION();
754
798
        if (negative_cache != NULL && PySet_Clear(negative_cache) < 0) {
755
0
            goto end;
756
0
        }
757
798
        set_cache_version(impl, invalidation_counter);
758
798
    }
759
21.5k
    else {
760
21.5k
        incache = _in_weak_set(impl, &impl->_abc_negative_cache, subclass);
761
21.5k
        if (incache < 0) {
762
0
            goto end;
763
0
        }
764
21.5k
        if (incache > 0) {
765
32
            result = Py_False;
766
32
            goto end;
767
32
        }
768
21.5k
    }
769
770
    /* 3. Check the subclass hook. */
771
22.3k
    ok = PyObject_CallMethodOneArg(
772
22.3k
            (PyObject *)self, &_Py_ID(__subclasshook__), subclass);
773
22.3k
    if (ok == NULL) {
774
0
        goto end;
775
0
    }
776
22.3k
    if (ok == Py_True) {
777
604
        Py_DECREF(ok);
778
604
        if (_add_to_weak_set(impl, &impl->_abc_cache, subclass) < 0) {
779
0
            goto end;
780
0
        }
781
604
        result = Py_True;
782
604
        goto end;
783
604
    }
784
21.7k
    if (ok == Py_False) {
785
0
        Py_DECREF(ok);
786
0
        if (_add_to_weak_set(impl, &impl->_abc_negative_cache, subclass) < 0) {
787
0
            goto end;
788
0
        }
789
0
        result = Py_False;
790
0
        goto end;
791
0
    }
792
21.7k
    if (ok != Py_NotImplemented) {
793
0
        Py_DECREF(ok);
794
0
        PyErr_SetString(PyExc_AssertionError, "__subclasshook__ must return either"
795
0
                                              " False, True, or NotImplemented");
796
0
        goto end;
797
0
    }
798
21.7k
    Py_DECREF(ok);
799
800
    /* 4. Check if it's a direct subclass. */
801
21.7k
    if (PyType_IsSubtype((PyTypeObject *)subclass, (PyTypeObject *)self)) {
802
6
        if (_add_to_weak_set(impl, &impl->_abc_cache, subclass) < 0) {
803
0
            goto end;
804
0
        }
805
6
        result = Py_True;
806
6
        goto end;
807
6
    }
808
809
    /* 5. Check if it's a subclass of a registered class (recursive). */
810
21.7k
    if (subclasscheck_check_registry(impl, subclass, &result)) {
811
        // Exception occurred or result is set.
812
20.4k
        goto end;
813
20.4k
    }
814
815
    /* 6. Check if it's a subclass of a subclass (recursive). */
816
1.33k
    subclasses = PyObject_CallMethod(self, "__subclasses__", NULL);
817
1.33k
    if (subclasses == NULL) {
818
0
        goto end;
819
0
    }
820
1.33k
    if (!PyList_Check(subclasses)) {
821
0
        PyErr_SetString(PyExc_TypeError, "__subclasses__() must return a list");
822
0
        goto end;
823
0
    }
824
1.68k
    for (pos = 0; pos < PyList_GET_SIZE(subclasses); pos++) {
825
356
        PyObject *scls = PyList_GetItemRef(subclasses, pos);
826
356
        if (scls == NULL) {
827
0
            goto end;
828
0
        }
829
356
        int r = PyObject_IsSubclass(subclass, scls);
830
356
        Py_DECREF(scls);
831
356
        if (r > 0) {
832
2
            if (_add_to_weak_set(impl, &impl->_abc_cache, subclass) < 0) {
833
0
                goto end;
834
0
            }
835
2
            result = Py_True;
836
2
            goto end;
837
2
        }
838
354
        if (r < 0) {
839
0
            goto end;
840
0
        }
841
354
    }
842
843
    /* No dice; update negative cache. */
844
1.32k
    if (_add_to_weak_set(impl, &impl->_abc_negative_cache, subclass) < 0) {
845
0
        goto end;
846
0
    }
847
1.32k
    result = Py_False;
848
849
22.3k
end:
850
22.3k
    Py_DECREF(impl);
851
22.3k
    Py_XDECREF(subclasses);
852
22.3k
    return Py_XNewRef(result);
853
1.32k
}
854
855
856
static int
857
subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
858
                             PyObject **result)
859
21.7k
{
860
    // Fast path: check subclass is in weakref directly.
861
21.7k
    int ret = _in_weak_set(impl, &impl->_abc_registry, subclass);
862
21.7k
    if (ret < 0) {
863
0
        *result = NULL;
864
0
        return -1;
865
0
    }
866
21.7k
    if (ret > 0) {
867
20.4k
        *result = Py_True;
868
20.4k
        return 1;
869
20.4k
    }
870
871
1.33k
    PyObject *registry_shared;
872
1.33k
    Py_BEGIN_CRITICAL_SECTION(impl);
873
1.33k
    registry_shared = impl->_abc_registry;
874
1.33k
    Py_END_CRITICAL_SECTION();
875
1.33k
    if (registry_shared == NULL) {
876
723
        return 0;
877
723
    }
878
879
    // Make a local copy of the registry to protect against concurrent
880
    // modifications of _abc_registry.
881
611
    PyObject *registry = PyFrozenSet_New(registry_shared);
882
611
    if (registry == NULL) {
883
0
        return -1;
884
0
    }
885
611
    PyObject *key;
886
611
    Py_ssize_t pos = 0;
887
611
    Py_hash_t hash;
888
889
1.81k
    while (_PySet_NextEntry(registry, &pos, &key, &hash)) {
890
1.20k
        PyObject *rkey;
891
1.20k
        if (PyWeakref_GetRef(key, &rkey) < 0) {
892
            // Someone inject non-weakref type in the registry.
893
0
            ret = -1;
894
0
            break;
895
0
        }
896
897
1.20k
        if (rkey == NULL) {
898
0
            continue;
899
0
        }
900
1.20k
        int r = PyObject_IsSubclass(subclass, rkey);
901
1.20k
        Py_DECREF(rkey);
902
1.20k
        if (r < 0) {
903
0
            ret = -1;
904
0
            break;
905
0
        }
906
1.20k
        if (r > 0) {
907
4
            if (_add_to_weak_set(impl, &impl->_abc_cache, subclass) < 0) {
908
0
                ret = -1;
909
0
                break;
910
0
            }
911
4
            *result = Py_True;
912
4
            ret = 1;
913
4
            break;
914
4
        }
915
1.20k
    }
916
917
611
    Py_DECREF(registry);
918
611
    return ret;
919
611
}
920
921
/*[clinic input]
922
_abc.get_cache_token
923
924
Returns the current ABC cache token.
925
926
The token is an opaque object (supporting equality testing) identifying
927
the current version of the ABC cache for virtual subclasses.  The token
928
changes with every call to register() on any ABC.
929
[clinic start generated code]*/
930
931
static PyObject *
932
_abc_get_cache_token_impl(PyObject *module)
933
/*[clinic end generated code: output=c7d87841e033dacc input=d87acc04492f6bf3]*/
934
0
{
935
0
    _abcmodule_state *state = get_abc_state(module);
936
0
    return PyLong_FromUnsignedLongLong(get_invalidation_counter(state));
937
0
}
938
939
static struct PyMethodDef _abcmodule_methods[] = {
940
    _ABC_GET_CACHE_TOKEN_METHODDEF
941
    _ABC__ABC_INIT_METHODDEF
942
    _ABC__RESET_REGISTRY_METHODDEF
943
    _ABC__RESET_CACHES_METHODDEF
944
    _ABC__GET_DUMP_METHODDEF
945
    _ABC__ABC_REGISTER_METHODDEF
946
    _ABC__ABC_INSTANCECHECK_METHODDEF
947
    _ABC__ABC_SUBCLASSCHECK_METHODDEF
948
    {NULL,       NULL}          /* sentinel */
949
};
950
951
static int
952
_abcmodule_exec(PyObject *module)
953
37
{
954
37
    _abcmodule_state *state = get_abc_state(module);
955
37
    state->abc_invalidation_counter = 0;
956
37
    state->_abc_data_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &_abc_data_type_spec, NULL);
957
37
    if (state->_abc_data_type == NULL) {
958
0
        return -1;
959
0
    }
960
961
37
    return 0;
962
37
}
963
964
static int
965
_abcmodule_traverse(PyObject *module, visitproc visit, void *arg)
966
1.64k
{
967
1.64k
    _abcmodule_state *state = get_abc_state(module);
968
1.64k
    Py_VISIT(state->_abc_data_type);
969
1.64k
    return 0;
970
1.64k
}
971
972
static int
973
_abcmodule_clear(PyObject *module)
974
0
{
975
0
    _abcmodule_state *state = get_abc_state(module);
976
0
    Py_CLEAR(state->_abc_data_type);
977
0
    return 0;
978
0
}
979
980
static void
981
_abcmodule_free(void *module)
982
0
{
983
0
    (void)_abcmodule_clear((PyObject *)module);
984
0
}
985
986
static PyModuleDef_Slot _abcmodule_slots[] = {
987
    _Py_ABI_SLOT,
988
    {Py_mod_exec, _abcmodule_exec},
989
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
990
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
991
    {0, NULL}
992
};
993
994
static struct PyModuleDef _abcmodule = {
995
    PyModuleDef_HEAD_INIT,
996
    .m_name = "_abc",
997
    .m_doc = _abc__doc__,
998
    .m_size = sizeof(_abcmodule_state),
999
    .m_methods = _abcmodule_methods,
1000
    .m_slots = _abcmodule_slots,
1001
    .m_traverse = _abcmodule_traverse,
1002
    .m_clear = _abcmodule_clear,
1003
    .m_free = _abcmodule_free,
1004
};
1005
1006
PyMODINIT_FUNC
1007
PyInit__abc(void)
1008
37
{
1009
37
    return PyModuleDef_Init(&_abcmodule);
1010
37
}