blob: 7c040ef80ba3da81eae39fcaf5abdee117fdc943 [file] [log] [blame]
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +00001/* ABCMeta implementation */
2
3#include "Python.h"
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +00004#include "clinic/_abc.c.h"
5
6/*[clinic input]
7module _abc
8[clinic start generated code]*/
9/*[clinic end generated code: output=da39a3ee5e6b4b0d input=964f5328e1aefcda]*/
10
11PyDoc_STRVAR(_abc__doc__,
12"Module contains faster C implementation of abc.ABCMeta");
13
14_Py_IDENTIFIER(__abstractmethods__);
15_Py_IDENTIFIER(__class__);
16_Py_IDENTIFIER(__dict__);
17_Py_IDENTIFIER(__bases__);
18_Py_IDENTIFIER(_abc_impl);
19_Py_IDENTIFIER(__subclasscheck__);
20_Py_IDENTIFIER(__subclasshook__);
21
Dong-hee Na53e4c912020-03-30 23:35:38 +090022typedef struct {
23 PyTypeObject *_abc_data_type;
24} _abcmodule_state;
25
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000026/* A global counter that is incremented each time a class is
27 registered as a virtual subclass of anything. It forces the
28 negative cache to be cleared before its next use.
29 Note: this counter is private. Use `abc.get_cache_token()` for
30 external code. */
Dong-hee Na53e4c912020-03-30 23:35:38 +090031// FIXME: PEP 573: Move abc_invalidation_counter into _abcmodule_state.
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000032static unsigned long long abc_invalidation_counter = 0;
33
Dong-hee Na53e4c912020-03-30 23:35:38 +090034static inline _abcmodule_state*
35get_abc_state(PyObject *module)
36{
37 void *state = PyModule_GetState(module);
38 assert(state != NULL);
39 return (_abcmodule_state *)state;
40}
41
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000042/* This object stores internal state for ABCs.
43 Note that we can use normal sets for caches,
44 since they are never iterated over. */
45typedef struct {
46 PyObject_HEAD
47 PyObject *_abc_registry;
48 PyObject *_abc_cache; /* Normal set of weak references. */
49 PyObject *_abc_negative_cache; /* Normal set of weak references. */
50 unsigned long long _abc_negative_cache_version;
51} _abc_data;
52
Victor Stinner9cc3ebd2020-04-07 18:36:04 +020053static int
54abc_data_traverse(_abc_data *self, visitproc visit, void *arg)
55{
56 Py_VISIT(self->_abc_registry);
57 Py_VISIT(self->_abc_cache);
58 Py_VISIT(self->_abc_negative_cache);
59 return 0;
60}
61
62static int
63abc_data_clear(_abc_data *self)
64{
65 Py_CLEAR(self->_abc_registry);
66 Py_CLEAR(self->_abc_cache);
67 Py_CLEAR(self->_abc_negative_cache);
68 return 0;
69}
70
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000071static void
72abc_data_dealloc(_abc_data *self)
73{
Dong-hee Na53e4c912020-03-30 23:35:38 +090074 PyTypeObject *tp = Py_TYPE(self);
Victor Stinner9cc3ebd2020-04-07 18:36:04 +020075 (void)abc_data_clear(self);
Dong-hee Na53e4c912020-03-30 23:35:38 +090076 tp->tp_free(self);
77 Py_DECREF(tp);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +000078}
79
80static PyObject *
81abc_data_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
82{
83 _abc_data *self = (_abc_data *) type->tp_alloc(type, 0);
84 if (self == NULL) {
85 return NULL;
86 }
87
88 self->_abc_registry = NULL;
89 self->_abc_cache = NULL;
90 self->_abc_negative_cache = NULL;
91 self->_abc_negative_cache_version = abc_invalidation_counter;
92 return (PyObject *) self;
93}
94
95PyDoc_STRVAR(abc_data_doc,
96"Internal state held by ABC machinery.");
97
Dong-hee Na53e4c912020-03-30 23:35:38 +090098static PyType_Slot _abc_data_type_spec_slots[] = {
99 {Py_tp_doc, (void *)abc_data_doc},
100 {Py_tp_new, abc_data_new},
101 {Py_tp_dealloc, abc_data_dealloc},
Victor Stinner9cc3ebd2020-04-07 18:36:04 +0200102 {Py_tp_traverse, abc_data_traverse},
103 {Py_tp_clear, abc_data_clear},
Dong-hee Na53e4c912020-03-30 23:35:38 +0900104 {0, 0}
105};
106
107static PyType_Spec _abc_data_type_spec = {
108 .name = "_abc._abc_data",
109 .basicsize = sizeof(_abc_data),
Victor Stinner9cc3ebd2020-04-07 18:36:04 +0200110 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
Dong-hee Na53e4c912020-03-30 23:35:38 +0900111 .slots = _abc_data_type_spec_slots,
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000112};
113
114static _abc_data *
Dong-hee Na53e4c912020-03-30 23:35:38 +0900115_get_impl(PyObject *module, PyObject *self)
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000116{
Dong-hee Na53e4c912020-03-30 23:35:38 +0900117 _abcmodule_state *state = get_abc_state(module);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000118 PyObject *impl = _PyObject_GetAttrId(self, &PyId__abc_impl);
119 if (impl == NULL) {
120 return NULL;
121 }
Dong-hee Na53e4c912020-03-30 23:35:38 +0900122 if (!Py_IS_TYPE(impl, state->_abc_data_type)) {
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000123 PyErr_SetString(PyExc_TypeError, "_abc_impl is set to a wrong type");
124 Py_DECREF(impl);
125 return NULL;
126 }
127 return (_abc_data *)impl;
128}
129
130static int
131_in_weak_set(PyObject *set, PyObject *obj)
132{
133 if (set == NULL || PySet_GET_SIZE(set) == 0) {
134 return 0;
135 }
136 PyObject *ref = PyWeakref_NewRef(obj, NULL);
137 if (ref == NULL) {
138 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
139 PyErr_Clear();
140 return 0;
141 }
142 return -1;
143 }
144 int res = PySet_Contains(set, ref);
145 Py_DECREF(ref);
146 return res;
147}
148
149static PyObject *
150_destroy(PyObject *setweakref, PyObject *objweakref)
151{
152 PyObject *set;
153 set = PyWeakref_GET_OBJECT(setweakref);
154 if (set == Py_None) {
155 Py_RETURN_NONE;
156 }
157 Py_INCREF(set);
158 if (PySet_Discard(set, objweakref) < 0) {
159 Py_DECREF(set);
160 return NULL;
161 }
162 Py_DECREF(set);
163 Py_RETURN_NONE;
164}
165
166static PyMethodDef _destroy_def = {
167 "_destroy", (PyCFunction) _destroy, METH_O
168};
169
170static int
171_add_to_weak_set(PyObject **pset, PyObject *obj)
172{
173 if (*pset == NULL) {
174 *pset = PySet_New(NULL);
175 if (*pset == NULL) {
176 return -1;
177 }
178 }
179
180 PyObject *set = *pset;
181 PyObject *ref, *wr;
182 PyObject *destroy_cb;
183 wr = PyWeakref_NewRef(set, NULL);
184 if (wr == NULL) {
185 return -1;
186 }
187 destroy_cb = PyCFunction_NewEx(&_destroy_def, wr, NULL);
188 if (destroy_cb == NULL) {
189 Py_DECREF(wr);
190 return -1;
191 }
192 ref = PyWeakref_NewRef(obj, destroy_cb);
193 Py_DECREF(destroy_cb);
194 if (ref == NULL) {
195 Py_DECREF(wr);
196 return -1;
197 }
198 int ret = PySet_Add(set, ref);
199 Py_DECREF(wr);
200 Py_DECREF(ref);
201 return ret;
202}
203
204/*[clinic input]
205_abc._reset_registry
206
207 self: object
208 /
209
210Internal ABC helper to reset registry of a given class.
211
212Should be only used by refleak.py
213[clinic start generated code]*/
214
215static PyObject *
216_abc__reset_registry(PyObject *module, PyObject *self)
217/*[clinic end generated code: output=92d591a43566cc10 input=12a0b7eb339ac35c]*/
218{
Dong-hee Na53e4c912020-03-30 23:35:38 +0900219 _abc_data *impl = _get_impl(module, self);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000220 if (impl == NULL) {
221 return NULL;
222 }
223 if (impl->_abc_registry != NULL && PySet_Clear(impl->_abc_registry) < 0) {
224 Py_DECREF(impl);
225 return NULL;
226 }
227 Py_DECREF(impl);
228 Py_RETURN_NONE;
229}
230
231/*[clinic input]
232_abc._reset_caches
233
234 self: object
235 /
236
237Internal ABC helper to reset both caches of a given class.
238
239Should be only used by refleak.py
240[clinic start generated code]*/
241
242static PyObject *
243_abc__reset_caches(PyObject *module, PyObject *self)
244/*[clinic end generated code: output=f296f0d5c513f80c input=c0ac616fd8acfb6f]*/
245{
Dong-hee Na53e4c912020-03-30 23:35:38 +0900246 _abc_data *impl = _get_impl(module, self);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000247 if (impl == NULL) {
248 return NULL;
249 }
250 if (impl->_abc_cache != NULL && PySet_Clear(impl->_abc_cache) < 0) {
251 Py_DECREF(impl);
252 return NULL;
253 }
254 /* also the second cache */
255 if (impl->_abc_negative_cache != NULL &&
256 PySet_Clear(impl->_abc_negative_cache) < 0) {
257 Py_DECREF(impl);
258 return NULL;
259 }
260 Py_DECREF(impl);
261 Py_RETURN_NONE;
262}
263
264/*[clinic input]
265_abc._get_dump
266
267 self: object
268 /
269
270Internal ABC helper for cache and registry debugging.
271
272Return shallow copies of registry, of both caches, and
273negative cache version. Don't call this function directly,
274instead use ABC._dump_registry() for a nice repr.
275[clinic start generated code]*/
276
277static PyObject *
278_abc__get_dump(PyObject *module, PyObject *self)
279/*[clinic end generated code: output=9d9569a8e2c1c443 input=2c5deb1bfe9e3c79]*/
280{
Dong-hee Na53e4c912020-03-30 23:35:38 +0900281 _abc_data *impl = _get_impl(module, self);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000282 if (impl == NULL) {
283 return NULL;
284 }
285 PyObject *res = Py_BuildValue("NNNK",
286 PySet_New(impl->_abc_registry),
287 PySet_New(impl->_abc_cache),
288 PySet_New(impl->_abc_negative_cache),
289 impl->_abc_negative_cache_version);
290 Py_DECREF(impl);
291 return res;
292}
293
294// Compute set of abstract method names.
295static int
296compute_abstract_methods(PyObject *self)
297{
298 int ret = -1;
299 PyObject *abstracts = PyFrozenSet_New(NULL);
300 if (abstracts == NULL) {
301 return -1;
302 }
303
304 PyObject *ns = NULL, *items = NULL, *bases = NULL; // Py_XDECREF()ed on error.
305
306 /* Stage 1: direct abstract methods. */
307 ns = _PyObject_GetAttrId(self, &PyId___dict__);
308 if (!ns) {
309 goto error;
310 }
311
312 // We can't use PyDict_Next(ns) even when ns is dict because
313 // _PyObject_IsAbstract() can mutate ns.
314 items = PyMapping_Items(ns);
315 if (!items) {
316 goto error;
317 }
318 assert(PyList_Check(items));
319 for (Py_ssize_t pos = 0; pos < PyList_GET_SIZE(items); pos++) {
320 PyObject *it = PySequence_Fast(
321 PyList_GET_ITEM(items, pos),
322 "items() returned non-iterable");
323 if (!it) {
324 goto error;
325 }
326 if (PySequence_Fast_GET_SIZE(it) != 2) {
327 PyErr_SetString(PyExc_TypeError,
328 "items() returned item which size is not 2");
329 Py_DECREF(it);
330 goto error;
331 }
332
333 // borrowed
334 PyObject *key = PySequence_Fast_GET_ITEM(it, 0);
335 PyObject *value = PySequence_Fast_GET_ITEM(it, 1);
336 // items or it may be cleared while accessing __abstractmethod__
337 // So we need to keep strong reference for key
338 Py_INCREF(key);
339 int is_abstract = _PyObject_IsAbstract(value);
340 if (is_abstract < 0 ||
341 (is_abstract && PySet_Add(abstracts, key) < 0)) {
342 Py_DECREF(it);
343 Py_DECREF(key);
344 goto error;
345 }
346 Py_DECREF(key);
347 Py_DECREF(it);
348 }
349
350 /* Stage 2: inherited abstract methods. */
351 bases = _PyObject_GetAttrId(self, &PyId___bases__);
352 if (!bases) {
353 goto error;
354 }
355 if (!PyTuple_Check(bases)) {
356 PyErr_SetString(PyExc_TypeError, "__bases__ is not tuple");
357 goto error;
358 }
359
360 for (Py_ssize_t pos = 0; pos < PyTuple_GET_SIZE(bases); pos++) {
361 PyObject *item = PyTuple_GET_ITEM(bases, pos); // borrowed
362 PyObject *base_abstracts, *iter;
363
364 if (_PyObject_LookupAttrId(item, &PyId___abstractmethods__,
365 &base_abstracts) < 0) {
366 goto error;
367 }
368 if (base_abstracts == NULL) {
369 continue;
370 }
371 if (!(iter = PyObject_GetIter(base_abstracts))) {
372 Py_DECREF(base_abstracts);
373 goto error;
374 }
375 Py_DECREF(base_abstracts);
376 PyObject *key, *value;
377 while ((key = PyIter_Next(iter))) {
378 if (_PyObject_LookupAttr(self, key, &value) < 0) {
379 Py_DECREF(key);
380 Py_DECREF(iter);
381 goto error;
382 }
383 if (value == NULL) {
384 Py_DECREF(key);
385 continue;
386 }
387
388 int is_abstract = _PyObject_IsAbstract(value);
389 Py_DECREF(value);
390 if (is_abstract < 0 ||
391 (is_abstract && PySet_Add(abstracts, key) < 0))
392 {
393 Py_DECREF(key);
394 Py_DECREF(iter);
395 goto error;
396 }
397 Py_DECREF(key);
398 }
399 Py_DECREF(iter);
400 if (PyErr_Occurred()) {
401 goto error;
402 }
403 }
404
405 if (_PyObject_SetAttrId(self, &PyId___abstractmethods__, abstracts) < 0) {
406 goto error;
407 }
408
409 ret = 0;
410error:
411 Py_DECREF(abstracts);
412 Py_XDECREF(ns);
413 Py_XDECREF(items);
414 Py_XDECREF(bases);
415 return ret;
416}
417
418/*[clinic input]
419_abc._abc_init
420
421 self: object
422 /
423
424Internal ABC helper for class set-up. Should be never used outside abc module.
425[clinic start generated code]*/
426
427static PyObject *
428_abc__abc_init(PyObject *module, PyObject *self)
429/*[clinic end generated code: output=594757375714cda1 input=8d7fe470ff77f029]*/
430{
Dong-hee Na53e4c912020-03-30 23:35:38 +0900431 _abcmodule_state *state = get_abc_state(module);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000432 PyObject *data;
433 if (compute_abstract_methods(self) < 0) {
434 return NULL;
435 }
436
437 /* Set up inheritance registry. */
Dong-hee Na53e4c912020-03-30 23:35:38 +0900438 data = abc_data_new(state->_abc_data_type, NULL, NULL);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000439 if (data == NULL) {
440 return NULL;
441 }
442 if (_PyObject_SetAttrId(self, &PyId__abc_impl, data) < 0) {
443 Py_DECREF(data);
444 return NULL;
445 }
446 Py_DECREF(data);
447 Py_RETURN_NONE;
448}
449
450/*[clinic input]
451_abc._abc_register
452
453 self: object
454 subclass: object
455 /
456
457Internal ABC helper for subclasss registration. Should be never used outside abc module.
458[clinic start generated code]*/
459
460static PyObject *
461_abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass)
462/*[clinic end generated code: output=7851e7668c963524 input=ca589f8c3080e67f]*/
463{
464 if (!PyType_Check(subclass)) {
465 PyErr_SetString(PyExc_TypeError, "Can only register classes");
466 return NULL;
467 }
468 int result = PyObject_IsSubclass(subclass, self);
469 if (result > 0) {
470 Py_INCREF(subclass);
471 return subclass; /* Already a subclass. */
472 }
473 if (result < 0) {
474 return NULL;
475 }
476 /* Subtle: test for cycles *after* testing for "already a subclass";
477 this means we allow X.register(X) and interpret it as a no-op. */
478 result = PyObject_IsSubclass(self, subclass);
479 if (result > 0) {
480 /* This would create a cycle, which is bad for the algorithm below. */
481 PyErr_SetString(PyExc_RuntimeError, "Refusing to create an inheritance cycle");
482 return NULL;
483 }
484 if (result < 0) {
485 return NULL;
486 }
Dong-hee Na53e4c912020-03-30 23:35:38 +0900487 _abc_data *impl = _get_impl(module, self);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000488 if (impl == NULL) {
489 return NULL;
490 }
491 if (_add_to_weak_set(&impl->_abc_registry, subclass) < 0) {
492 Py_DECREF(impl);
493 return NULL;
494 }
495 Py_DECREF(impl);
496
497 /* Invalidate negative cache */
498 abc_invalidation_counter++;
499
500 Py_INCREF(subclass);
501 return subclass;
502}
503
504
505/*[clinic input]
506_abc._abc_instancecheck
507
508 self: object
509 instance: object
510 /
511
512Internal ABC helper for instance checks. Should be never used outside abc module.
513[clinic start generated code]*/
514
515static PyObject *
516_abc__abc_instancecheck_impl(PyObject *module, PyObject *self,
517 PyObject *instance)
518/*[clinic end generated code: output=b8b5148f63b6b56f input=a4f4525679261084]*/
519{
520 PyObject *subtype, *result = NULL, *subclass = NULL;
Dong-hee Na53e4c912020-03-30 23:35:38 +0900521 _abc_data *impl = _get_impl(module, self);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000522 if (impl == NULL) {
523 return NULL;
524 }
525
526 subclass = _PyObject_GetAttrId(instance, &PyId___class__);
527 if (subclass == NULL) {
528 Py_DECREF(impl);
529 return NULL;
530 }
531 /* Inline the cache checking. */
532 int incache = _in_weak_set(impl->_abc_cache, subclass);
533 if (incache < 0) {
534 goto end;
535 }
536 if (incache > 0) {
537 result = Py_True;
538 Py_INCREF(result);
539 goto end;
540 }
541 subtype = (PyObject *)Py_TYPE(instance);
542 if (subtype == subclass) {
543 if (impl->_abc_negative_cache_version == abc_invalidation_counter) {
544 incache = _in_weak_set(impl->_abc_negative_cache, subclass);
545 if (incache < 0) {
546 goto end;
547 }
548 if (incache > 0) {
549 result = Py_False;
550 Py_INCREF(result);
551 goto end;
552 }
553 }
554 /* Fall back to the subclass check. */
Jeroen Demeyer59ad1102019-07-11 10:59:05 +0200555 result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__,
556 subclass);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000557 goto end;
558 }
Jeroen Demeyer59ad1102019-07-11 10:59:05 +0200559 result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__,
560 subclass);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000561 if (result == NULL) {
562 goto end;
563 }
564
565 switch (PyObject_IsTrue(result)) {
566 case -1:
567 Py_DECREF(result);
568 result = NULL;
569 break;
570 case 0:
571 Py_DECREF(result);
Jeroen Demeyer59ad1102019-07-11 10:59:05 +0200572 result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__,
573 subtype);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000574 break;
575 case 1: // Nothing to do.
576 break;
577 default:
578 Py_UNREACHABLE();
579 }
580
581end:
582 Py_XDECREF(impl);
583 Py_XDECREF(subclass);
584 return result;
585}
586
587
Min ho Kimf7d72e42019-07-06 07:39:32 +1000588// Return -1 when exception occurred.
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000589// Return 1 when result is set.
590// Return 0 otherwise.
591static int subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
592 PyObject **result);
593
594/*[clinic input]
595_abc._abc_subclasscheck
596
597 self: object
598 subclass: object
599 /
600
601Internal ABC helper for subclasss checks. Should be never used outside abc module.
602[clinic start generated code]*/
603
604static PyObject *
605_abc__abc_subclasscheck_impl(PyObject *module, PyObject *self,
606 PyObject *subclass)
607/*[clinic end generated code: output=b56c9e4a530e3894 input=1d947243409d10b8]*/
608{
jab40472dd2018-03-23 00:26:06 +1300609 if (!PyType_Check(subclass)) {
610 PyErr_SetString(PyExc_TypeError, "issubclass() arg 1 must be a class");
611 return NULL;
612 }
613
INADA Naokif757b722018-03-22 21:52:42 +0900614 PyObject *ok, *subclasses = NULL, *result = NULL;
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000615 Py_ssize_t pos;
616 int incache;
Dong-hee Na53e4c912020-03-30 23:35:38 +0900617 _abc_data *impl = _get_impl(module, self);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000618 if (impl == NULL) {
619 return NULL;
620 }
621
622 /* 1. Check cache. */
623 incache = _in_weak_set(impl->_abc_cache, subclass);
624 if (incache < 0) {
625 goto end;
626 }
627 if (incache > 0) {
628 result = Py_True;
629 goto end;
630 }
631
632 /* 2. Check negative cache; may have to invalidate. */
633 if (impl->_abc_negative_cache_version < abc_invalidation_counter) {
634 /* Invalidate the negative cache. */
635 if (impl->_abc_negative_cache != NULL &&
636 PySet_Clear(impl->_abc_negative_cache) < 0)
637 {
638 goto end;
639 }
640 impl->_abc_negative_cache_version = abc_invalidation_counter;
641 }
642 else {
643 incache = _in_weak_set(impl->_abc_negative_cache, subclass);
644 if (incache < 0) {
645 goto end;
646 }
647 if (incache > 0) {
648 result = Py_False;
649 goto end;
650 }
651 }
652
653 /* 3. Check the subclass hook. */
Jeroen Demeyer59ad1102019-07-11 10:59:05 +0200654 ok = _PyObject_CallMethodIdOneArg((PyObject *)self, &PyId___subclasshook__,
655 subclass);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000656 if (ok == NULL) {
657 goto end;
658 }
659 if (ok == Py_True) {
660 Py_DECREF(ok);
661 if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) {
662 goto end;
663 }
664 result = Py_True;
665 goto end;
666 }
667 if (ok == Py_False) {
668 Py_DECREF(ok);
669 if (_add_to_weak_set(&impl->_abc_negative_cache, subclass) < 0) {
670 goto end;
671 }
672 result = Py_False;
673 goto end;
674 }
675 if (ok != Py_NotImplemented) {
676 Py_DECREF(ok);
677 PyErr_SetString(PyExc_AssertionError, "__subclasshook__ must return either"
678 " False, True, or NotImplemented");
679 goto end;
680 }
681 Py_DECREF(ok);
682
INADA Naokif757b722018-03-22 21:52:42 +0900683 /* 4. Check if it's a direct subclass. */
684 PyObject *mro = ((PyTypeObject *)subclass)->tp_mro;
685 assert(PyTuple_Check(mro));
686 for (pos = 0; pos < PyTuple_GET_SIZE(mro); pos++) {
687 PyObject *mro_item = PyTuple_GET_ITEM(mro, pos);
INADA Naokic65bf3f2018-03-23 18:19:34 +0900688 assert(mro_item != NULL);
INADA Naokif757b722018-03-22 21:52:42 +0900689 if ((PyObject *)self == mro_item) {
690 if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) {
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000691 goto end;
692 }
INADA Naokif757b722018-03-22 21:52:42 +0900693 result = Py_True;
694 goto end;
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000695 }
696 }
697
698 /* 5. Check if it's a subclass of a registered class (recursive). */
699 if (subclasscheck_check_registry(impl, subclass, &result)) {
Min ho Kimf7d72e42019-07-06 07:39:32 +1000700 // Exception occurred or result is set.
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000701 goto end;
702 }
703
704 /* 6. Check if it's a subclass of a subclass (recursive). */
705 subclasses = PyObject_CallMethod(self, "__subclasses__", NULL);
Alexey Izbyshevcdbf50c2018-08-20 23:04:19 +0300706 if (subclasses == NULL) {
707 goto end;
708 }
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000709 if (!PyList_Check(subclasses)) {
710 PyErr_SetString(PyExc_TypeError, "__subclasses__() must return a list");
711 goto end;
712 }
713 for (pos = 0; pos < PyList_GET_SIZE(subclasses); pos++) {
714 PyObject *scls = PyList_GET_ITEM(subclasses, pos);
715 Py_INCREF(scls);
716 int r = PyObject_IsSubclass(subclass, scls);
717 Py_DECREF(scls);
718 if (r > 0) {
719 if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) {
720 goto end;
721 }
722 result = Py_True;
723 goto end;
724 }
725 if (r < 0) {
726 goto end;
727 }
728 }
729
730 /* No dice; update negative cache. */
731 if (_add_to_weak_set(&impl->_abc_negative_cache, subclass) < 0) {
732 goto end;
733 }
734 result = Py_False;
735
736end:
INADA Naokifc7df0e2018-03-07 16:27:01 +0900737 Py_DECREF(impl);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000738 Py_XDECREF(subclasses);
739 Py_XINCREF(result);
740 return result;
741}
742
743
744static int
745subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
746 PyObject **result)
747{
748 // Fast path: check subclass is in weakref directly.
749 int ret = _in_weak_set(impl->_abc_registry, subclass);
750 if (ret < 0) {
751 *result = NULL;
752 return -1;
753 }
754 if (ret > 0) {
755 *result = Py_True;
756 return 1;
757 }
758
759 if (impl->_abc_registry == NULL) {
760 return 0;
761 }
762 Py_ssize_t registry_size = PySet_Size(impl->_abc_registry);
763 if (registry_size == 0) {
764 return 0;
765 }
766 // Weakref callback may remove entry from set.
767 // So we take snapshot of registry first.
768 PyObject **copy = PyMem_Malloc(sizeof(PyObject*) * registry_size);
Zackery Spytz4c49da02018-12-07 03:11:30 -0700769 if (copy == NULL) {
770 PyErr_NoMemory();
771 return -1;
772 }
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000773 PyObject *key;
774 Py_ssize_t pos = 0;
775 Py_hash_t hash;
776 Py_ssize_t i = 0;
777
778 while (_PySet_NextEntry(impl->_abc_registry, &pos, &key, &hash)) {
779 Py_INCREF(key);
780 copy[i++] = key;
781 }
782 assert(i == registry_size);
783
784 for (i = 0; i < registry_size; i++) {
785 PyObject *rkey = PyWeakref_GetObject(copy[i]);
786 if (rkey == NULL) {
787 // Someone inject non-weakref type in the registry.
788 ret = -1;
789 break;
790 }
791 if (rkey == Py_None) {
792 continue;
793 }
794 Py_INCREF(rkey);
795 int r = PyObject_IsSubclass(subclass, rkey);
796 Py_DECREF(rkey);
797 if (r < 0) {
798 ret = -1;
799 break;
800 }
801 if (r > 0) {
802 if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) {
803 ret = -1;
804 break;
805 }
806 *result = Py_True;
807 ret = 1;
808 break;
809 }
810 }
811
812 for (i = 0; i < registry_size; i++) {
813 Py_DECREF(copy[i]);
814 }
815 PyMem_Free(copy);
816 return ret;
817}
818
819/*[clinic input]
820_abc.get_cache_token
821
822Returns the current ABC cache token.
823
824The token is an opaque object (supporting equality testing) identifying the
825current version of the ABC cache for virtual subclasses. The token changes
826with every call to register() on any ABC.
827[clinic start generated code]*/
828
829static PyObject *
830_abc_get_cache_token_impl(PyObject *module)
831/*[clinic end generated code: output=c7d87841e033dacc input=70413d1c423ad9f9]*/
832{
833 return PyLong_FromUnsignedLongLong(abc_invalidation_counter);
834}
835
Dong-hee Na53e4c912020-03-30 23:35:38 +0900836static struct PyMethodDef _abcmodule_methods[] = {
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000837 _ABC_GET_CACHE_TOKEN_METHODDEF
838 _ABC__ABC_INIT_METHODDEF
839 _ABC__RESET_REGISTRY_METHODDEF
840 _ABC__RESET_CACHES_METHODDEF
841 _ABC__GET_DUMP_METHODDEF
842 _ABC__ABC_REGISTER_METHODDEF
843 _ABC__ABC_INSTANCECHECK_METHODDEF
844 _ABC__ABC_SUBCLASSCHECK_METHODDEF
845 {NULL, NULL} /* sentinel */
846};
847
Hai Shi4c1b6a62020-02-17 21:50:35 +0800848static int
Dong-hee Na53e4c912020-03-30 23:35:38 +0900849_abcmodule_exec(PyObject *module)
Hai Shi4c1b6a62020-02-17 21:50:35 +0800850{
Dong-hee Na53e4c912020-03-30 23:35:38 +0900851 _abcmodule_state *state = get_abc_state(module);
852 state->_abc_data_type = (PyTypeObject *)PyType_FromSpec(&_abc_data_type_spec);
853 if (state->_abc_data_type == NULL) {
Hai Shi4c1b6a62020-02-17 21:50:35 +0800854 return -1;
855 }
Dong-hee Na53e4c912020-03-30 23:35:38 +0900856
Hai Shi4c1b6a62020-02-17 21:50:35 +0800857 return 0;
858}
859
Dong-hee Na53e4c912020-03-30 23:35:38 +0900860static int
861_abcmodule_traverse(PyObject *module, visitproc visit, void *arg)
862{
863 _abcmodule_state *state = get_abc_state(module);
864 Py_VISIT(state->_abc_data_type);
865 return 0;
866}
867
868static int
869_abcmodule_clear(PyObject *module)
870{
871 _abcmodule_state *state = get_abc_state(module);
872 Py_CLEAR(state->_abc_data_type);
873 return 0;
874}
875
876static void
877_abcmodule_free(void *module)
878{
879 _abcmodule_clear((PyObject *)module);
880}
881
882static PyModuleDef_Slot _abcmodule_slots[] = {
883 {Py_mod_exec, _abcmodule_exec},
Hai Shi4c1b6a62020-02-17 21:50:35 +0800884 {0, NULL}
885};
886
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000887static struct PyModuleDef _abcmodule = {
888 PyModuleDef_HEAD_INIT,
889 "_abc",
890 _abc__doc__,
Dong-hee Na53e4c912020-03-30 23:35:38 +0900891 sizeof(_abcmodule_state),
892 _abcmodule_methods,
893 _abcmodule_slots,
894 _abcmodule_traverse,
895 _abcmodule_clear,
896 _abcmodule_free,
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000897};
898
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000899PyMODINIT_FUNC
900PyInit__abc(void)
901{
Hai Shi4c1b6a62020-02-17 21:50:35 +0800902 return PyModuleDef_Init(&_abcmodule);
Ivan Levkivskyi03e3c342018-02-18 12:41:58 +0000903}