|
38 | 38 | #include "PySlab.hpp" |
39 | 39 | #include "PyModuleRepresentation.hpp" |
40 | 40 | #include "_types.hpp" |
| 41 | +#include "CompilerVisibleObjectVisitor.hpp" |
41 | 42 |
|
42 | 43 | PyObject *MakeTupleOrListOfType(PyObject* nullValue, PyObject* args, bool isTuple) { |
43 | 44 | std::vector<Type*> types; |
@@ -2709,6 +2710,46 @@ PyObject *isRecursive(PyObject* nullValue, PyObject* args) { |
2709 | 2710 | }); |
2710 | 2711 | } |
2711 | 2712 |
|
| 2713 | +PyDoc_STRVAR( |
| 2714 | + resetCompilerVisibleObjectHashCache_doc, |
| 2715 | + "resetCompilerVisibleObjectHashCache() -> None\n\n" |
| 2716 | + "Reset the list of objects the identity hasher has seen. This is used in test to allow\n" |
| 2717 | + "us to inject a fault and then verify we detect it, and not leave that fault lying around." |
| 2718 | +); |
| 2719 | + |
| 2720 | +PyObject *resetCompilerVisibleObjectHashCache(PyObject* nullValue, PyObject* args) { |
| 2721 | + return translateExceptionToPyObject([&]() { |
| 2722 | + CompilerVisibleObjectVisitor::singleton().resetCache(); |
| 2723 | + |
| 2724 | + return incref(Py_None); |
| 2725 | + }); |
| 2726 | +} |
| 2727 | + |
| 2728 | +PyDoc_STRVAR( |
| 2729 | + checkForHashInstability_doc, |
| 2730 | + "checkForHashInstability() -> OneOf(None, str)\n\n" |
| 2731 | + "Walk every object that's been seen by the MutuallyRecursiveTypeGroup framework and verify\n" |
| 2732 | + "that the exact sequence of objects visible to it have not changed. If they have, return\n" |
| 2733 | + "a string detailing which objects changed and how (which could be very large).\n\n" |
| 2734 | + "During normal execution, this should always return None. However, if anything visible to\n" |
| 2735 | + "the compiler, such as a method on a class, or the identity of a module-level variable \n" |
| 2736 | + "changes, this function will find it. If such errors go undetected, it can cause various\n" |
| 2737 | + "errors, including multiple copies of the same type (since the hash is not stable) or \n" |
| 2738 | + "errors while computing hashes because the assumptions of the hasher are violated." |
| 2739 | +); |
| 2740 | + |
| 2741 | +PyObject *checkForHashInstability(PyObject* nullValue, PyObject* args) { |
| 2742 | + return translateExceptionToPyObject([&]() { |
| 2743 | + try { |
| 2744 | + CompilerVisibleObjectVisitor::singleton().checkForInstability(); |
| 2745 | + |
| 2746 | + return incref(Py_None); |
| 2747 | + } catch(std::runtime_error& err) { |
| 2748 | + return PyUnicode_FromString(err.what()); |
| 2749 | + } |
| 2750 | + }); |
| 2751 | +} |
| 2752 | + |
2712 | 2753 | PyObject *typesAndObjectsVisibleToCompilerFrom(PyObject* nullValue, PyObject* args) { |
2713 | 2754 | if (PyTuple_Size(args) != 1) { |
2714 | 2755 | PyErr_SetString(PyExc_TypeError, "typesAndObjectsVisibleToCompilerFrom takes 1 positional argument"); |
@@ -3260,6 +3301,8 @@ static PyMethodDef module_methods[] = { |
3260 | 3301 | {"recursiveTypeGroupRepr", (PyCFunction)recursiveTypeGroupRepr, METH_VARARGS, NULL}, |
3261 | 3302 | {"recursiveTypeGroupDeepRepr", (PyCFunction)recursiveTypeGroupDeepRepr, METH_VARARGS, NULL}, |
3262 | 3303 | {"recursiveTypeGroupHash", (PyCFunction)recursiveTypeGroupHash, METH_VARARGS, NULL}, |
| 3304 | + {"checkForHashInstability", (PyCFunction)checkForHashInstability, METH_VARARGS, checkForHashInstability_doc}, |
| 3305 | + {"resetCompilerVisibleObjectHashCache", (PyCFunction)resetCompilerVisibleObjectHashCache, METH_VARARGS, resetCompilerVisibleObjectHashCache_doc}, |
3263 | 3306 | {"typesAndObjectsVisibleToCompilerFrom", (PyCFunction)typesAndObjectsVisibleToCompilerFrom, METH_VARARGS, NULL}, |
3264 | 3307 | {"isRecursive", (PyCFunction)isRecursive, METH_VARARGS, NULL}, |
3265 | 3308 | {"referencedTypes", (PyCFunction)referencedTypes, METH_VARARGS, NULL}, |
|
0 commit comments