| 908 | } |
| 909 | |
| 910 | PyObject* IsNamedtuple(PyObject* o, bool strict) { |
| 911 | // Must be subclass of tuple |
| 912 | if (!PyTuple_Check(o)) { |
| 913 | Py_RETURN_FALSE; |
| 914 | } |
| 915 | |
| 916 | // If strict, o.__class__.__base__ must be tuple |
| 917 | if (strict) { |
| 918 | PyObject* klass = PyObject_GetAttrString(o, "__class__"); |
| 919 | if (klass == nullptr) return nullptr; |
| 920 | PyObject* base = PyObject_GetAttrString(klass, "__base__"); |
| 921 | Py_DECREF(klass); |
| 922 | if (base == nullptr) return nullptr; |
| 923 | |
| 924 | const PyTypeObject* base_type = reinterpret_cast<PyTypeObject*>(base); |
| 925 | // built-in object types are singletons |
| 926 | bool tuple_base = base_type == &PyTuple_Type; |
| 927 | Py_DECREF(base); |
| 928 | if (!tuple_base) { |
| 929 | Py_RETURN_FALSE; |
| 930 | } |
| 931 | } |
| 932 | |
| 933 | // o must have attribute '_fields' and every element in |
| 934 | // '_fields' must be a string. |
| 935 | int has_fields = PyObject_HasAttrString(o, "_fields"); |
| 936 | if (!has_fields) { |
| 937 | Py_RETURN_FALSE; |
| 938 | } |
| 939 | |
| 940 | Safe_PyObjectPtr fields = make_safe(PyObject_GetAttrString(o, "_fields")); |
| 941 | int is_instance = IsInstanceOfRegisteredType(fields.get(), "Sequence"); |
| 942 | if (is_instance == 0) { |
| 943 | Py_RETURN_FALSE; |
| 944 | } else if (is_instance == -1) { |
| 945 | return nullptr; |
| 946 | } |
| 947 | |
| 948 | Safe_PyObjectPtr seq = make_safe(PySequence_Fast(fields.get(), "")); |
| 949 | const Py_ssize_t s = PySequence_Fast_GET_SIZE(seq.get()); |
| 950 | for (Py_ssize_t i = 0; i < s; ++i) { |
| 951 | // PySequence_Fast_GET_ITEM returns borrowed ref |
| 952 | PyObject* elem = PySequence_Fast_GET_ITEM(seq.get(), i); |
| 953 | if (!IsString(elem)) { |
| 954 | Py_RETURN_FALSE; |
| 955 | } |
| 956 | } |
| 957 | |
| 958 | Py_RETURN_TRUE; |
| 959 | } |
| 960 | |
| 961 | PyObject* SameNamedtuples(PyObject* o1, PyObject* o2) { |
| 962 | Safe_PyObjectPtr f1 = make_safe(PyObject_GetAttrString(o1, "_fields")); |
no test coverage detected