[Python-checkins] [3.12] gh-107735: Add C API tests for PySys_GetObject() and PySys_SetObject() (GH-107736) (#107740)
Yhg1s
webhook-mailer at python.org
Wed Aug 16 08:28:17 EDT 2023
https://github.com/python/cpython/commit/72534ca85c64d4d33a9cf30492e037be05140fd2
commit: 72534ca85c64d4d33a9cf30492e037be05140fd2
branch: 3.12
author: Serhiy Storchaka <storchaka at gmail.com>
committer: Yhg1s <thomas at python.org>
date: 2023-08-16T14:28:14+02:00
summary:
[3.12] gh-107735: Add C API tests for PySys_GetObject() and PySys_SetObject() (GH-107736) (#107740)
[3.12] gh-107735: Add C API tests for PySys_GetObject() and PySys_SetObject() (GH-107736).
(cherry picked from commit bea5f93196d213d6fbf4ba8984caf4c3cd1da882)
files:
M Lib/test/test_capi/test_misc.py
M Modules/_testcapimodule.c
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py
index 3f2736da7d93a..3d494975c71e2 100644
--- a/Lib/test/test_capi/test_misc.py
+++ b/Lib/test/test_capi/test_misc.py
@@ -51,6 +51,8 @@
import _testinternalcapi
+NULL = None
+
def decode_stderr(err):
return err.decode('utf-8', 'replace').replace('\r', '')
@@ -1121,6 +1123,46 @@ class Data(_testcapi.ObjExtraData):
del d.extra
self.assertIsNone(d.extra)
+ def test_sys_getobject(self):
+ getobject = _testcapi.sys_getobject
+
+ self.assertIs(getobject(b'stdout'), sys.stdout)
+ with support.swap_attr(sys, '\U0001f40d', 42):
+ self.assertEqual(getobject('\U0001f40d'.encode()), 42)
+
+ self.assertIs(getobject(b'nonexisting'), AttributeError)
+ self.assertIs(getobject(b'\xff'), AttributeError)
+ # CRASHES getobject(NULL)
+
+ def test_sys_setobject(self):
+ setobject = _testcapi.sys_setobject
+
+ value = ['value']
+ value2 = ['value2']
+ try:
+ self.assertEqual(setobject(b'newattr', value), 0)
+ self.assertIs(sys.newattr, value)
+ self.assertEqual(setobject(b'newattr', value2), 0)
+ self.assertIs(sys.newattr, value2)
+ self.assertEqual(setobject(b'newattr', NULL), 0)
+ self.assertFalse(hasattr(sys, 'newattr'))
+ self.assertEqual(setobject(b'newattr', NULL), 0)
+ finally:
+ with contextlib.suppress(AttributeError):
+ del sys.newattr
+ try:
+ self.assertEqual(setobject('\U0001f40d'.encode(), value), 0)
+ self.assertIs(getattr(sys, '\U0001f40d'), value)
+ self.assertEqual(setobject('\U0001f40d'.encode(), NULL), 0)
+ self.assertFalse(hasattr(sys, '\U0001f40d'))
+ finally:
+ with contextlib.suppress(AttributeError):
+ delattr(sys, '\U0001f40d')
+
+ with self.assertRaises(UnicodeDecodeError):
+ setobject(b'\xff', value)
+ # CRASHES setobject(NULL, value)
+
@requires_limited_api
class TestHeapTypeRelative(unittest.TestCase):
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 6523734131c2d..098d2cfa6d8ad 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -45,6 +45,16 @@
// Include definitions from there.
#include "_testcapi/parts.h"
+#define NULLABLE(x) do { if (x == Py_None) x = NULL; } while (0);
+
+#define RETURN_INT(value) do { \
+ int _ret = (value); \
+ if (_ret == -1) { \
+ return NULL; \
+ } \
+ return PyLong_FromLong(_ret); \
+ } while (0)
+
// Forward declarations
static struct PyModuleDef _testcapimodule;
static PyObject *TestError; /* set to exception object in init */
@@ -3336,6 +3346,35 @@ test_atexit(PyObject *self, PyObject *Py_UNUSED(args))
}
+static PyObject *
+sys_getobject(PyObject *Py_UNUSED(module), PyObject *arg)
+{
+ const char *name;
+ Py_ssize_t size;
+ if (!PyArg_Parse(arg, "z#", &name, &size)) {
+ return NULL;
+ }
+ PyObject *result = PySys_GetObject(name);
+ if (result == NULL) {
+ result = PyExc_AttributeError;
+ }
+ return Py_NewRef(result);
+}
+
+static PyObject *
+sys_setobject(PyObject *Py_UNUSED(module), PyObject *args)
+{
+ const char *name;
+ Py_ssize_t size;
+ PyObject *value;
+ if (!PyArg_ParseTuple(args, "z#O", &name, &size, &value)) {
+ return NULL;
+ }
+ NULLABLE(value);
+ RETURN_INT(PySys_SetObject(name, value));
+}
+
+
static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
static PyMethodDef TestMethods[] = {
@@ -3482,6 +3521,8 @@ static PyMethodDef TestMethods[] = {
{"function_get_kw_defaults", function_get_kw_defaults, METH_O, NULL},
{"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL},
{"test_atexit", test_atexit, METH_NOARGS},
+ {"sys_getobject", sys_getobject, METH_O},
+ {"sys_setobject", sys_setobject, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
More information about the Python-checkins
mailing list