summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMonadChains <monadchains@gmail.com>2022-10-03 20:37:15 (GMT)
committerGitHub <noreply@github.com>2022-10-03 20:37:15 (GMT)
commit9302e331c7e2edf1bb42f6b31085408a315195f5 (patch)
tree17e9ee3a9c62ea301d9943f78b50fc93c994abf6
parent3a49dbb98ccc1b90554ed181386316efa38adfba (diff)
downloadcpython-9302e331c7e2edf1bb42f6b31085408a315195f5.zip
cpython-9302e331c7e2edf1bb42f6b31085408a315195f5.tar.gz
cpython-9302e331c7e2edf1bb42f6b31085408a315195f5.tar.bz2
gh-94808: Add test coverage for PyObject_HasAttrString (#96627)
* gh-94808: Add test for HasAttrString * Harmonize to Python C code style guidelines * Add check to verify no exception thrown
-rw-r--r--Lib/test/test_class.py14
-rw-r--r--Modules/_testcapimodule.c26
2 files changed, 40 insertions, 0 deletions
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py
index 91c53b7..61df81b 100644
--- a/Lib/test/test_class.py
+++ b/Lib/test/test_class.py
@@ -445,6 +445,20 @@ class ClassTests(unittest.TestCase):
del testme.cardinal
self.assertCallStack([('__delattr__', (testme, "cardinal"))])
+ def testHasAttrString(self):
+ import sys
+ from test.support import import_helper
+ _testcapi = import_helper.import_module('_testcapi')
+
+ class A:
+ def __init__(self):
+ self.attr = 1
+
+ a = A()
+ self.assertEqual(_testcapi.hasattr_string(a, "attr"), True)
+ self.assertEqual(_testcapi.hasattr_string(a, "noattr"), False)
+ self.assertEqual(sys.exc_info(), (None, None, None))
+
def testDel(self):
x = []
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index b8f71d4..3d6535f 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -4846,6 +4846,31 @@ sequence_setitem(PyObject *self, PyObject *args)
}
+static PyObject *
+hasattr_string(PyObject *self, PyObject* args)
+{
+ PyObject* obj;
+ PyObject* attr_name;
+
+ if (!PyArg_UnpackTuple(args, "hasattr_string", 2, 2, &obj, &attr_name)) {
+ return NULL;
+ }
+
+ if (!PyUnicode_Check(attr_name)) {
+ PyErr_SetString(PyExc_TypeError, "attribute name must a be string");
+ return PyErr_Occurred();
+ }
+
+ const char *name_str = PyUnicode_AsUTF8(attr_name);
+ if (PyObject_HasAttrString(obj, name_str)) {
+ Py_RETURN_TRUE;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
+}
+
+
/* Functions for testing C calling conventions (METH_*) are named meth_*,
* e.g. "meth_varargs" for METH_VARARGS.
*
@@ -5707,6 +5732,7 @@ static PyMethodDef TestMethods[] = {
{"write_unraisable_exc", test_write_unraisable_exc, METH_VARARGS},
{"sequence_getitem", sequence_getitem, METH_VARARGS},
{"sequence_setitem", sequence_setitem, METH_VARARGS},
+ {"hasattr_string", hasattr_string, METH_VARARGS},
{"meth_varargs", meth_varargs, METH_VARARGS},
{"meth_varargs_keywords", _PyCFunction_CAST(meth_varargs_keywords), METH_VARARGS|METH_KEYWORDS},
{"meth_o", meth_o, METH_O},