Skip to content

Commit bea5f93

Browse files
gh-107735: Add C API tests for PySys_GetObject() and PySys_SetObject() (GH-107736)
1 parent 430632d commit bea5f93

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

Lib/test/test_capi/test_misc.py

+43
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

@@ -2576,5 +2578,46 @@ def testfunc(it):
25762578
with self.assertRaises(StopIteration):
25772579
next(it)
25782580

2581+
def test_sys_getobject(self):
2582+
getobject = _testcapi.sys_getobject
2583+
2584+
self.assertIs(getobject(b'stdout'), sys.stdout)
2585+
with support.swap_attr(sys, '\U0001f40d', 42):
2586+
self.assertEqual(getobject('\U0001f40d'.encode()), 42)
2587+
2588+
self.assertIs(getobject(b'nonexisting'), AttributeError)
2589+
self.assertIs(getobject(b'\xff'), AttributeError)
2590+
# CRASHES getobject(NULL)
2591+
2592+
def test_sys_setobject(self):
2593+
setobject = _testcapi.sys_setobject
2594+
2595+
value = ['value']
2596+
value2 = ['value2']
2597+
try:
2598+
self.assertEqual(setobject(b'newattr', value), 0)
2599+
self.assertIs(sys.newattr, value)
2600+
self.assertEqual(setobject(b'newattr', value2), 0)
2601+
self.assertIs(sys.newattr, value2)
2602+
self.assertEqual(setobject(b'newattr', NULL), 0)
2603+
self.assertFalse(hasattr(sys, 'newattr'))
2604+
self.assertEqual(setobject(b'newattr', NULL), 0)
2605+
finally:
2606+
with contextlib.suppress(AttributeError):
2607+
del sys.newattr
2608+
try:
2609+
self.assertEqual(setobject('\U0001f40d'.encode(), value), 0)
2610+
self.assertIs(getattr(sys, '\U0001f40d'), value)
2611+
self.assertEqual(setobject('\U0001f40d'.encode(), NULL), 0)
2612+
self.assertFalse(hasattr(sys, '\U0001f40d'))
2613+
finally:
2614+
with contextlib.suppress(AttributeError):
2615+
delattr(sys, '\U0001f40d')
2616+
2617+
with self.assertRaises(UnicodeDecodeError):
2618+
setobject(b'\xff', value)
2619+
# CRASHES setobject(NULL, value)
2620+
2621+
25792622
if __name__ == "__main__":
25802623
unittest.main()

Modules/_testcapimodule.c

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

47+
#define NULLABLE(x) do { if (x == Py_None) x = NULL; } while (0);
48+
49+
#define RETURN_INT(value) do { \
50+
int _ret = (value); \
51+
if (_ret == -1) { \
52+
return NULL; \
53+
} \
54+
return PyLong_FromLong(_ret); \
55+
} while (0)
56+
4757
// Forward declarations
4858
static struct PyModuleDef _testcapimodule;
4959
static PyObject *TestError; /* set to exception object in init */
@@ -3505,6 +3515,35 @@ test_dict_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
35053515
}
35063516

35073517

3518+
static PyObject *
3519+
sys_getobject(PyObject *Py_UNUSED(module), PyObject *arg)
3520+
{
3521+
const char *name;
3522+
Py_ssize_t size;
3523+
if (!PyArg_Parse(arg, "z#", &name, &size)) {
3524+
return NULL;
3525+
}
3526+
PyObject *result = PySys_GetObject(name);
3527+
if (result == NULL) {
3528+
result = PyExc_AttributeError;
3529+
}
3530+
return Py_NewRef(result);
3531+
}
3532+
3533+
static PyObject *
3534+
sys_setobject(PyObject *Py_UNUSED(module), PyObject *args)
3535+
{
3536+
const char *name;
3537+
Py_ssize_t size;
3538+
PyObject *value;
3539+
if (!PyArg_ParseTuple(args, "z#O", &name, &size, &value)) {
3540+
return NULL;
3541+
}
3542+
NULLABLE(value);
3543+
RETURN_INT(PySys_SetObject(name, value));
3544+
}
3545+
3546+
35083547
static PyMethodDef TestMethods[] = {
35093548
{"set_errno", set_errno, METH_VARARGS},
35103549
{"test_config", test_config, METH_NOARGS},
@@ -3640,6 +3679,8 @@ static PyMethodDef TestMethods[] = {
36403679
{"check_pyimport_addmodule", check_pyimport_addmodule, METH_VARARGS},
36413680
{"test_weakref_capi", test_weakref_capi, METH_NOARGS},
36423681
{"test_dict_capi", test_dict_capi, METH_NOARGS},
3682+
{"sys_getobject", sys_getobject, METH_O},
3683+
{"sys_setobject", sys_setobject, METH_VARARGS},
36433684
{NULL, NULL} /* sentinel */
36443685
};
36453686

0 commit comments

Comments
 (0)