Coverage Report

Created: 2026-10-17 06:15

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
221k
{
30
221k
    void *state = _PyModule_GetState(module);
31
221k
    assert(state != NULL);
32
221k
    return (_abcmodule_state *)state;
33
221k
}
34
35
static inline uint64_t
36
get_invalidation_counter(_abcmodule_state *state)
37
101k
{
38
#ifdef Py_GIL_DISABLED
39
    return _Py_atomic_load_uint64(&state->abc_invalidation_counter);
40
#else
41
101k
    return state->abc_invalidation_counter;
42
101k
#endif
43
101k
}
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
77.1k
#define _abc_data_CAST(op)  ((_abc_data *)(op))
71
72
static inline uint64_t
73
get_cache_version(_abc_data *impl)
74
99.0k
{
75
#ifdef Py_GIL_DISABLED
76
    return _Py_atomic_load_uint64(&impl->_abc_negative_cache_version);
77
#else
78
99.0k
    return impl->_abc_negative_cache_version;
79
99.0k
#endif
80
99.0k
}
81
82
static inline void
83
set_cache_version(_abc_data *impl, uint64_t version)
84
806
{
85
#ifdef Py_GIL_DISABLED
86
    _Py_atomic_store_uint64(&impl->_abc_negative_cache_version, version);
87
#else
88
806
    impl->_abc_negative_cache_version = version;
89
806
#endif
90
806
}
91
92
static int
93
abc_data_traverse(PyObject *op, visitproc visit, void *arg)
94
77.1k
{
95
77.1k
    _abc_data *self = _abc_data_CAST(op);
96
77.1k
    Py_VISIT(Py_TYPE(self));
97
77.1k
    Py_VISIT(self->_abc_registry);
98
77.1k
    Py_VISIT(self->_abc_cache);
99
77.1k
    Py_VISIT(self->_abc_negative_cache);
100
77.1k
    return 0;
101
77.1k
}
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
2.01k
{
126
2.01k
    _abc_data *self = (_abc_data *) type->tp_alloc(type, 0);
127
2.01k
    _abcmodule_state *state = NULL;
128
2.01k
    if (self == NULL) {
129
0
        return NULL;
130
0
    }
131
132
2.01k
    state = _PyType_GetModuleState(type);
133
2.01k
    if (state == NULL) {
134
0
        Py_DECREF(self);
135
0
        return NULL;
136
0
    }
137
138
2.01k
    self->_abc_registry = NULL;
139
2.01k
    self->_abc_cache = NULL;
140
2.01k
    self->_abc_negative_cache = NULL;
141
2.01k
    self->_abc_negative_cache_version = get_invalidation_counter(state);
142
2.01k
    return (PyObject *) self;
143
2.01k
}
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
118k
{
167
118k
    _abcmodule_state *state = get_abc_state(module);
168
118k
    PyObject *impl = PyObject_GetAttr(self, &_Py_ID(_abc_impl));
169
118k
    if (impl == NULL) {
170
0
        return NULL;
171
0
    }
172
118k
    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
118k
    return (_abc_data *)impl;
178
118k
}
179
180
static int
181
_in_weak_set(_abc_data *impl, PyObject **pset, PyObject *obj)
182
234k
{
183
234k
    PyObject *set;
184
234k
    Py_BEGIN_CRITICAL_SECTION(impl);
185
234k
    set = *pset;
186
234k
    Py_END_CRITICAL_SECTION();
187
234k
    if (set == NULL || PySet_GET_SIZE(set) == 0) {
188
51.6k
        return 0;
189
51.6k
    }
190
182k
    PyObject *ref = PyWeakref_NewRef(obj, NULL);
191
182k
    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
182k
    int res = PySet_Contains(set, ref);
199
182k
    Py_DECREF(ref);
200
182k
    return res;
201
182k
}
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.94k
{
225
2.94k
    PyObject *set;
226
2.94k
    Py_BEGIN_CRITICAL_SECTION(impl);
227
2.94k
    set = *pset;
228
2.94k
    if (set == NULL) {
229
1.26k
        set = *pset = PySet_New(NULL);
230
1.26k
    }
231
2.94k
    Py_END_CRITICAL_SECTION();
232
2.94k
    if (set == NULL) {
233
0
        return -1;
234
0
    }
235
236
2.94k
    PyObject *ref, *wr;
237
2.94k
    PyObject *destroy_cb;
238
2.94k
    wr = PyWeakref_NewRef(set, NULL);
239
2.94k
    if (wr == NULL) {
240
0
        return -1;
241
0
    }
242
2.94k
    destroy_cb = PyCFunction_NewEx(&_destroy_def, wr, NULL);
243
2.94k
    if (destroy_cb == NULL) {
244
0
        Py_DECREF(wr);
245
0
        return -1;
246
0
    }
247
2.94k
    ref = PyWeakref_NewRef(obj, destroy_cb);
248
2.94k
    Py_DECREF(destroy_cb);
249
2.94k
    if (ref == NULL) {
250
0
        Py_DECREF(wr);
251
0
        return -1;
252
0
    }
253
2.94k
    int ret = PySet_Add(set, ref);
254
2.94k
    Py_DECREF(wr);
255
2.94k
    Py_DECREF(ref);
256
2.94k
    return ret;
257
2.94k
}
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
2.01k
{
364
2.01k
    int ret = -1;
365
2.01k
    PyObject *abstracts = PyFrozenSet_New(NULL);
366
2.01k
    if (abstracts == NULL) {
367
0
        return -1;
368
0
    }
369
370
2.01k
    PyObject *ns = NULL, *items = NULL, *bases = NULL;  // Py_XDECREF()ed on error.
371
372
    /* Stage 1: direct abstract methods. */
373
2.01k
    ns = PyObject_GetAttr(self, &_Py_ID(__dict__));
374
2.01k
    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
2.01k
    items = PyMapping_Items(ns);
381
2.01k
    if (!items) {
382
0
        goto error;
383
0
    }
384
2.01k
    assert(PyList_Check(items));
385
27.0k
    for (Py_ssize_t pos = 0; pos < PyList_GET_SIZE(items); pos++) {
386
25.0k
        PyObject *it = PySequence_Fast(
387
25.0k
                PyList_GET_ITEM(items, pos),
388
25.0k
                "items() returned non-iterable");
389
25.0k
        if (!it) {
390
0
            goto error;
391
0
        }
392
25.0k
        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
25.0k
        PyObject *key = PySequence_Fast_GET_ITEM(it, 0);
401
25.0k
        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
25.0k
        Py_INCREF(key);
405
25.0k
        int is_abstract = _PyObject_IsAbstract(value);
406
25.0k
        if (is_abstract < 0 ||
407
25.0k
                (is_abstract && PySet_Add(abstracts, key) < 0)) {
408
0
            Py_DECREF(it);
409
0
            Py_DECREF(key);
410
0
            goto error;
411
0
        }
412
25.0k
        Py_DECREF(key);
413
25.0k
        Py_DECREF(it);
414
25.0k
    }
415
416
    /* Stage 2: inherited abstract methods. */
417
2.01k
    bases = PyObject_GetAttr(self, &_Py_ID(__bases__));
418
2.01k
    if (!bases) {
419
0
        goto error;
420
0
    }
421
2.01k
    if (!PyTuple_Check(bases)) {
422
0
        PyErr_SetString(PyExc_TypeError, "__bases__ is not tuple");
423
0
        goto error;
424
0
    }
425
426
4.42k
    for (Py_ssize_t pos = 0; pos < PyTuple_GET_SIZE(bases); pos++) {
427
2.40k
        PyObject *item = PyTuple_GET_ITEM(bases, pos);  // borrowed
428
2.40k
        PyObject *base_abstracts, *iter;
429
430
2.40k
        if (PyObject_GetOptionalAttr(item, &_Py_ID(__abstractmethods__),
431
2.40k
                                 &base_abstracts) < 0) {
432
0
            goto error;
433
0
        }
434
2.40k
        if (base_abstracts == NULL) {
435
601
            continue;
436
601
        }
437
1.80k
        if (!(iter = PyObject_GetIter(base_abstracts))) {
438
0
            Py_DECREF(base_abstracts);
439
0
            goto error;
440
0
        }
441
1.80k
        Py_DECREF(base_abstracts);
442
1.80k
        PyObject *key, *value;
443
4.96k
        while ((key = PyIter_Next(iter))) {
444
3.15k
            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.15k
            if (value == NULL) {
450
0
                Py_DECREF(key);
451
0
                continue;
452
0
            }
453
454
3.15k
            int is_abstract = _PyObject_IsAbstract(value);
455
3.15k
            Py_DECREF(value);
456
3.15k
            if (is_abstract < 0 ||
457
3.15k
                    (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.15k
            Py_DECREF(key);
464
3.15k
        }
465
1.80k
        Py_DECREF(iter);
466
1.80k
        if (PyErr_Occurred()) {
467
0
            goto error;
468
0
        }
469
1.80k
    }
470
471
2.01k
    if (PyObject_SetAttr(self, &_Py_ID(__abstractmethods__), abstracts) < 0) {
472
0
        goto error;
473
0
    }
474
475
2.01k
    ret = 0;
476
2.01k
error:
477
2.01k
    Py_DECREF(abstracts);
478
2.01k
    Py_XDECREF(ns);
479
2.01k
    Py_XDECREF(items);
480
2.01k
    Py_XDECREF(bases);
481
2.01k
    return ret;
482
2.01k
}
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
2.01k
{
500
2.01k
    _abcmodule_state *state = get_abc_state(module);
501
2.01k
    PyObject *data;
502
2.01k
    if (compute_abstract_methods(self) < 0) {
503
0
        return NULL;
504
0
    }
505
506
    /* Set up inheritance registry. */
507
2.01k
    data = abc_data_new(state->_abc_data_type, NULL, NULL);
508
2.01k
    if (data == NULL) {
509
0
        return NULL;
510
0
    }
511
2.01k
    if (PyObject_SetAttr(self, &_Py_ID(_abc_impl), data) < 0) {
512
0
        Py_DECREF(data);
513
0
        return NULL;
514
0
    }
515
2.01k
    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
2.01k
    if (PyType_Check(self)) {
521
2.01k
        PyTypeObject *cls = (PyTypeObject *)self;
522
2.01k
        PyObject *dict = _PyType_GetDict(cls);
523
2.01k
        PyObject *flags = NULL;
524
2.01k
        if (PyDict_Pop(dict, &_Py_ID(__abc_tpflags__), &flags) < 0) {
525
0
            return NULL;
526
0
        }
527
2.01k
        if (flags == NULL || !PyLong_CheckExact(flags)) {
528
1.94k
            Py_XDECREF(flags);
529
1.94k
            Py_RETURN_NONE;
530
1.94k
        }
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
2.01k
    Py_RETURN_NONE;
544
2.01k
}
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
97.4k
{
626
97.4k
    PyObject *subtype, *result = NULL, *subclass = NULL;
627
97.4k
    _abc_data *impl = _get_impl(module, self);
628
97.4k
    if (impl == NULL) {
629
0
        return NULL;
630
0
    }
631
632
97.4k
    if (PyObject_GetOptionalAttr(instance, &_Py_ID(__class__), &subclass) < 0) {
633
0
        Py_DECREF(impl);
634
0
        return NULL;
635
0
    }
636
97.4k
    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
97.4k
    int incache = _in_weak_set(impl, &impl->_abc_cache, subclass);
643
97.4k
    if (incache < 0) {
644
0
        goto end;
645
0
    }
646
97.4k
    if (incache > 0) {
647
18.2k
        result = Py_NewRef(Py_True);
648
18.2k
        goto end;
649
18.2k
    }
650
79.2k
    subtype = (PyObject *)Py_TYPE(instance);
651
79.2k
    if (subtype == subclass) {
652
79.2k
        if (get_cache_version(impl) == get_invalidation_counter(get_abc_state(module))) {
653
79.2k
            incache = _in_weak_set(impl, &impl->_abc_negative_cache, subclass);
654
79.2k
            if (incache < 0) {
655
0
                goto end;
656
0
            }
657
79.2k
            if (incache > 0) {
658
61.4k
                result = Py_NewRef(Py_False);
659
61.4k
                goto end;
660
61.4k
            }
661
79.2k
        }
662
        /* Fall back to the subclass check. */
663
17.7k
        result = PyObject_CallMethodOneArg(self, &_Py_ID(__subclasscheck__),
664
17.7k
                                           subclass);
665
17.7k
        goto end;
666
79.2k
    }
667
0
    result = PyObject_CallMethodOneArg(self, &_Py_ID(__subclasscheck__),
668
0
                                       subclass);
669
0
    if (result == NULL) {
670
0
        goto end;
671
0
    }
672
673
0
    switch (PyObject_IsTrue(result)) {
674
0
    case -1:
675
0
        Py_SETREF(result, NULL);
676
0
        break;
677
0
    case 0:
678
0
        Py_DECREF(result);
679
0
        result = PyObject_CallMethodOneArg(self, &_Py_ID(__subclasscheck__),
680
0
                                           subtype);
681
0
        break;
682
0
    case 1:  // Nothing to do.
683
0
        break;
684
0
    default:
685
0
        Py_UNREACHABLE();
686
0
    }
687
688
97.4k
end:
689
97.4k
    Py_XDECREF(impl);
690
97.4k
    Py_XDECREF(subclass);
691
97.4k
    return result;
692
0
}
693
694
695
// Return -1 when exception occurred.
696
// Return 1 when result is set.
697
// Return 0 otherwise.
698
static int subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
699
                                        PyObject **result);
700
701
/*[clinic input]
702
@permit_long_summary
703
_abc._abc_subclasscheck
704
705
    self: object
706
    subclass: object
707
    /
708
709
Internal ABC helper for subclasss checks. Should be never used outside abc module.
710
[clinic start generated code]*/
711
712
static PyObject *
713
_abc__abc_subclasscheck_impl(PyObject *module, PyObject *self,
714
                             PyObject *subclass)
715
/*[clinic end generated code: output=b56c9e4a530e3894 input=5bf1ef712f5d3610]*/
716
19.7k
{
717
19.7k
    if (!PyType_Check(subclass)) {
718
0
        PyErr_SetString(PyExc_TypeError, "issubclass() arg 1 must be a class");
719
0
        return NULL;
720
0
    }
721
722
19.7k
    PyObject *ok, *subclasses = NULL, *result = NULL;
723
19.7k
    _abcmodule_state *state = NULL;
724
19.7k
    Py_ssize_t pos;
725
19.7k
    int incache;
726
19.7k
    _abc_data *impl = _get_impl(module, self);
727
19.7k
    if (impl == NULL) {
728
0
        return NULL;
729
0
    }
730
731
    /* 1. Check cache. */
732
19.7k
    incache = _in_weak_set(impl, &impl->_abc_cache, subclass);
733
19.7k
    if (incache < 0) {
734
0
        goto end;
735
0
    }
736
19.7k
    if (incache > 0) {
737
4
        result = Py_True;
738
4
        goto end;
739
4
    }
740
741
19.7k
    state = get_abc_state(module);
742
    /* 2. Check negative cache; may have to invalidate. */
743
19.7k
    uint64_t invalidation_counter = get_invalidation_counter(state);
744
19.7k
    if (get_cache_version(impl) < invalidation_counter) {
745
        /* Invalidate the negative cache. */
746
806
        PyObject *negative_cache;
747
806
        Py_BEGIN_CRITICAL_SECTION(impl);
748
806
        negative_cache = impl->_abc_negative_cache;
749
806
        Py_END_CRITICAL_SECTION();
750
806
        if (negative_cache != NULL && PySet_Clear(negative_cache) < 0) {
751
0
            goto end;
752
0
        }
753
806
        set_cache_version(impl, invalidation_counter);
754
806
    }
755
18.9k
    else {
756
18.9k
        incache = _in_weak_set(impl, &impl->_abc_negative_cache, subclass);
757
18.9k
        if (incache < 0) {
758
0
            goto end;
759
0
        }
760
18.9k
        if (incache > 0) {
761
32
            result = Py_False;
762
32
            goto end;
763
32
        }
764
18.9k
    }
765
766
    /* 3. Check the subclass hook. */
767
19.7k
    ok = PyObject_CallMethodOneArg(
768
19.7k
            (PyObject *)self, &_Py_ID(__subclasshook__), subclass);
769
19.7k
    if (ok == NULL) {
770
0
        goto end;
771
0
    }
772
19.7k
    if (ok == Py_True) {
773
604
        Py_DECREF(ok);
774
604
        if (_add_to_weak_set(impl, &impl->_abc_cache, subclass) < 0) {
775
0
            goto end;
776
0
        }
777
604
        result = Py_True;
778
604
        goto end;
779
604
    }
780
19.1k
    if (ok == Py_False) {
781
0
        Py_DECREF(ok);
782
0
        if (_add_to_weak_set(impl, &impl->_abc_negative_cache, subclass) < 0) {
783
0
            goto end;
784
0
        }
785
0
        result = Py_False;
786
0
        goto end;
787
0
    }
788
19.1k
    if (ok != Py_NotImplemented) {
789
0
        Py_DECREF(ok);
790
0
        PyErr_SetString(PyExc_AssertionError, "__subclasshook__ must return either"
791
0
                                              " False, True, or NotImplemented");
792
0
        goto end;
793
0
    }
794
19.1k
    Py_DECREF(ok);
795
796
    /* 4. Check if it's a direct subclass. */
797
19.1k
    if (PyType_IsSubtype((PyTypeObject *)subclass, (PyTypeObject *)self)) {
798
6
        if (_add_to_weak_set(impl, &impl->_abc_cache, subclass) < 0) {
799
0
            goto end;
800
0
        }
801
6
        result = Py_True;
802
6
        goto end;
803
6
    }
804
805
    /* 5. Check if it's a subclass of a registered class (recursive). */
806
19.1k
    if (subclasscheck_check_registry(impl, subclass, &result)) {
807
        // Exception occurred or result is set.
808
17.7k
        goto end;
809
17.7k
    }
810
811
    /* 6. Check if it's a subclass of a subclass (recursive). */
812
1.33k
    subclasses = PyObject_CallMethod(self, "__subclasses__", NULL);
813
1.33k
    if (subclasses == NULL) {
814
0
        goto end;
815
0
    }
816
1.33k
    if (!PyList_Check(subclasses)) {
817
0
        PyErr_SetString(PyExc_TypeError, "__subclasses__() must return a list");
818
0
        goto end;
819
0
    }
820
1.70k
    for (pos = 0; pos < PyList_GET_SIZE(subclasses); pos++) {
821
364
        PyObject *scls = PyList_GetItemRef(subclasses, pos);
822
364
        if (scls == NULL) {
823
0
            goto end;
824
0
        }
825
364
        int r = PyObject_IsSubclass(subclass, scls);
826
364
        Py_DECREF(scls);
827
364
        if (r > 0) {
828
2
            if (_add_to_weak_set(impl, &impl->_abc_cache, subclass) < 0) {
829
0
                goto end;
830
0
            }
831
2
            result = Py_True;
832
2
            goto end;
833
2
        }
834
362
        if (r < 0) {
835
0
            goto end;
836
0
        }
837
362
    }
838
839
    /* No dice; update negative cache. */
840
1.33k
    if (_add_to_weak_set(impl, &impl->_abc_negative_cache, subclass) < 0) {
841
0
        goto end;
842
0
    }
843
1.33k
    result = Py_False;
844
845
19.7k
end:
846
19.7k
    Py_DECREF(impl);
847
19.7k
    Py_XDECREF(subclasses);
848
19.7k
    return Py_XNewRef(result);
849
1.33k
}
850
851
852
static int
853
subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
854
                             PyObject **result)
855
19.1k
{
856
    // Fast path: check subclass is in weakref directly.
857
19.1k
    int ret = _in_weak_set(impl, &impl->_abc_registry, subclass);
858
19.1k
    if (ret < 0) {
859
0
        *result = NULL;
860
0
        return -1;
861
0
    }
862
19.1k
    if (ret > 0) {
863
17.7k
        *result = Py_True;
864
17.7k
        return 1;
865
17.7k
    }
866
867
1.34k
    PyObject *registry_shared;
868
1.34k
    Py_BEGIN_CRITICAL_SECTION(impl);
869
1.34k
    registry_shared = impl->_abc_registry;
870
1.34k
    Py_END_CRITICAL_SECTION();
871
1.34k
    if (registry_shared == NULL) {
872
731
        return 0;
873
731
    }
874
875
    // Make a local copy of the registry to protect against concurrent
876
    // modifications of _abc_registry.
877
611
    PyObject *registry = PyFrozenSet_New(registry_shared);
878
611
    if (registry == NULL) {
879
0
        return -1;
880
0
    }
881
611
    PyObject *key;
882
611
    Py_ssize_t pos = 0;
883
611
    Py_hash_t hash;
884
885
1.81k
    while (_PySet_NextEntry(registry, &pos, &key, &hash)) {
886
1.20k
        PyObject *rkey;
887
1.20k
        if (PyWeakref_GetRef(key, &rkey) < 0) {
888
            // Someone inject non-weakref type in the registry.
889
0
            ret = -1;
890
0
            break;
891
0
        }
892
893
1.20k
        if (rkey == NULL) {
894
0
            continue;
895
0
        }
896
1.20k
        int r = PyObject_IsSubclass(subclass, rkey);
897
1.20k
        Py_DECREF(rkey);
898
1.20k
        if (r < 0) {
899
0
            ret = -1;
900
0
            break;
901
0
        }
902
1.20k
        if (r > 0) {
903
4
            if (_add_to_weak_set(impl, &impl->_abc_cache, subclass) < 0) {
904
0
                ret = -1;
905
0
                break;
906
0
            }
907
4
            *result = Py_True;
908
4
            ret = 1;
909
4
            break;
910
4
        }
911
1.20k
    }
912
913
611
    Py_DECREF(registry);
914
611
    return ret;
915
611
}
916
917
/*[clinic input]
918
_abc.get_cache_token
919
920
Returns the current ABC cache token.
921
922
The token is an opaque object (supporting equality testing) identifying
923
the current version of the ABC cache for virtual subclasses.  The token
924
changes with every call to register() on any ABC.
925
[clinic start generated code]*/
926
927
static PyObject *
928
_abc_get_cache_token_impl(PyObject *module)
929
/*[clinic end generated code: output=c7d87841e033dacc input=d87acc04492f6bf3]*/
930
0
{
931
0
    _abcmodule_state *state = get_abc_state(module);
932
0
    return PyLong_FromUnsignedLongLong(get_invalidation_counter(state));
933
0
}
934
935
static struct PyMethodDef _abcmodule_methods[] = {
936
    _ABC_GET_CACHE_TOKEN_METHODDEF
937
    _ABC__ABC_INIT_METHODDEF
938
    _ABC__RESET_REGISTRY_METHODDEF
939
    _ABC__RESET_CACHES_METHODDEF
940
    _ABC__GET_DUMP_METHODDEF
941
    _ABC__ABC_REGISTER_METHODDEF
942
    _ABC__ABC_INSTANCECHECK_METHODDEF
943
    _ABC__ABC_SUBCLASSCHECK_METHODDEF
944
    {NULL,       NULL}          /* sentinel */
945
};
946
947
static int
948
_abcmodule_exec(PyObject *module)
949
37
{
950
37
    _abcmodule_state *state = get_abc_state(module);
951
37
    state->abc_invalidation_counter = 0;
952
37
    state->_abc_data_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &_abc_data_type_spec, NULL);
953
37
    if (state->_abc_data_type == NULL) {
954
0
        return -1;
955
0
    }
956
957
37
    return 0;
958
37
}
959
960
static int
961
_abcmodule_traverse(PyObject *module, visitproc visit, void *arg)
962
1.61k
{
963
1.61k
    _abcmodule_state *state = get_abc_state(module);
964
1.61k
    Py_VISIT(state->_abc_data_type);
965
1.61k
    return 0;
966
1.61k
}
967
968
static int
969
_abcmodule_clear(PyObject *module)
970
0
{
971
0
    _abcmodule_state *state = get_abc_state(module);
972
0
    Py_CLEAR(state->_abc_data_type);
973
0
    return 0;
974
0
}
975
976
static void
977
_abcmodule_free(void *module)
978
0
{
979
0
    (void)_abcmodule_clear((PyObject *)module);
980
0
}
981
982
static PyModuleDef_Slot _abcmodule_slots[] = {
983
    _Py_ABI_SLOT,
984
    {Py_mod_exec, _abcmodule_exec},
985
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
986
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
987
    {0, NULL}
988
};
989
990
static struct PyModuleDef _abcmodule = {
991
    PyModuleDef_HEAD_INIT,
992
    .m_name = "_abc",
993
    .m_doc = _abc__doc__,
994
    .m_size = sizeof(_abcmodule_state),
995
    .m_methods = _abcmodule_methods,
996
    .m_slots = _abcmodule_slots,
997
    .m_traverse = _abcmodule_traverse,
998
    .m_clear = _abcmodule_clear,
999
    .m_free = _abcmodule_free,
1000
};
1001
1002
PyMODINIT_FUNC
1003
PyInit__abc(void)
1004
37
{
1005
37
    return PyModuleDef_Init(&_abcmodule);
1006
37
}