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