Skip to content

Commit 72534ca

Browse files
[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 bea5f93)
1 parent 9864f9a commit 72534ca

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

Lib/test/test_capi/test_misc.py

+42
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
import _testinternalcapi
5252

5353

54+
NULL = None
55+
5456
def decode_stderr(err):
5557
return err.decode('utf-8', 'replace').replace('\r', '')
5658

@@ -1121,6 +1123,46 @@ class Data(_testcapi.ObjExtraData):
11211123
del d.extra
11221124
self.assertIsNone(d.extra)
11231125

1126+
def test_sys_getobject(self):
1127+
getobject = _testcapi.sys_getobject
1128+
1129+
self.assertIs(getobject(b'stdout'), sys.stdout)
1130+
with support.swap_attr(sys, '\U0001f40d', 42):
1131+
self.assertEqual(getobject('\U0001f40d'.encode()), 42)
1132+
1133+
self.assertIs(getobject(b'nonexisting'), AttributeError)
1134+
self.assertIs(getobject(b'\xff'), AttributeError)
1135+
# CRASHES getobject(NULL)
1136+
1137+
def test_sys_setobject(self):
1138+
setobject = _testcapi.sys_setobject
1139+
1140+
value = ['value']
1141+
value2 = ['value2']
1142+
try:
1143+
self.assertEqual(setobject(b'newattr', value), 0)
1144+
self.assertIs(sys.newattr, value)
1145+
self.assertEqual(setobject(b'newattr', value2), 0)
1146+
self.assertIs(sys.newattr, value2)
1147+
self.assertEqual(setobject(b'newattr', NULL), 0)
1148+
self.assertFalse(hasattr(sys, 'newattr'))
1149+
self.assertEqual(setobject(b'newattr', NULL), 0)
1150+
finally:
1151+
with contextlib.suppress(AttributeError):
1152+
del sys.newattr
1153+
try:
1154+
self.assertEqual(setobject('\U0001f40d'.encode(), value), 0)
1155+
self.assertIs(getattr(sys, '\U0001f40d'), value)
1156+
self.assertEqual(setobject('\U0001f40d'.encode(), NULL), 0)
1157+
self.assertFalse(hasattr(sys, '\U0001f40d'))
1158+
finally:
1159+
with contextlib.suppress(AttributeError):
1160+
delattr(sys, '\U0001f40d')
1161+
1162+
with self.assertRaises(UnicodeDecodeError):
1163+
setobject(b'\xff', value)
1164+
# CRASHES setobject(NULL, value)
1165+
11241166

11251167
@requires_limited_api
11261168
class TestHeapTypeRelative(unittest.TestCase):

Modules/_testcapimodule.c

+41
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@
4545
// Include definitions from there.
4646
#include "_testcapi/parts.h"
4747

48+
#define NULLABLE(x) do { if (x == Py_None) x = NULL; } while (0);
49+
50+
#define RETURN_INT(value) do { \
51+
int _ret = (value); \
52+
if (_ret == -1) { \
53+
return NULL; \
54+
} \
55+
return PyLong_FromLong(_ret); \
56+
} while (0)
57+
4858
// Forward declarations
4959
static struct PyModuleDef _testcapimodule;
5060
static PyObject *TestError; /* set to exception object in init */
@@ -3336,6 +3346,35 @@ test_atexit(PyObject *self, PyObject *Py_UNUSED(args))
33363346
}
33373347

33383348

3349+
static PyObject *
3350+
sys_getobject(PyObject *Py_UNUSED(module), PyObject *arg)
3351+
{
3352+
const char *name;
3353+
Py_ssize_t size;
3354+
if (!PyArg_Parse(arg, "z#", &name, &size)) {
3355+
return NULL;
3356+
}
3357+
PyObject *result = PySys_GetObject(name);
3358+
if (result == NULL) {
3359+
result = PyExc_AttributeError;
3360+
}
3361+
return Py_NewRef(result);
3362+
}
3363+
3364+
static PyObject *
3365+
sys_setobject(PyObject *Py_UNUSED(module), PyObject *args)
3366+
{
3367+
const char *name;
3368+
Py_ssize_t size;
3369+
PyObject *value;
3370+
if (!PyArg_ParseTuple(args, "z#O", &name, &size, &value)) {
3371+
return NULL;
3372+
}
3373+
NULLABLE(value);
3374+
RETURN_INT(PySys_SetObject(name, value));
3375+
}
3376+
3377+
33393378
static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
33403379

33413380
static PyMethodDef TestMethods[] = {
@@ -3482,6 +3521,8 @@ static PyMethodDef TestMethods[] = {
34823521
{"function_get_kw_defaults", function_get_kw_defaults, METH_O, NULL},
34833522
{"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL},
34843523
{"test_atexit", test_atexit, METH_NOARGS},
3524+
{"sys_getobject", sys_getobject, METH_O},
3525+
{"sys_setobject", sys_setobject, METH_VARARGS},
34853526
{NULL, NULL} /* sentinel */
34863527
};
34873528

0 commit comments

Comments
 (0)