summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/init_config.rst8
-rw-r--r--Include/cpython/initconfig.h3
-rw-r--r--Lib/test/test_embed.py16
-rw-r--r--Programs/_testembed.c8
-rw-r--r--Python/initconfig.c29
5 files changed, 51 insertions, 13 deletions
diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
index d2c1f9a2..5fd836d 100644
--- a/Doc/c-api/init_config.rst
+++ b/Doc/c-api/init_config.rst
@@ -72,8 +72,12 @@ PyWideStringList
.. c:function:: PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item)
- Insert *item* into *list* at *index*. If *index* is greater than *list*
- length, just append *item* to *list*.
+ Insert *item* into *list* at *index*.
+
+ If *index* is greater than or equal to *list* length, append *item* to
+ *list*.
+
+ *index* must be greater than or equal to 0.
Python must be preinitialized to call this function.
diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h
index bd07a48..047f511 100644
--- a/Include/cpython/initconfig.h
+++ b/Include/cpython/initconfig.h
@@ -37,6 +37,9 @@ typedef struct {
PyAPI_FUNC(PyStatus) PyWideStringList_Append(PyWideStringList *list,
const wchar_t *item);
+PyAPI_FUNC(PyStatus) PyWideStringList_Insert(PyWideStringList *list,
+ Py_ssize_t index,
+ const wchar_t *item);
/* --- PyPreConfig ----------------------------------------------- */
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index 37f542b..6fb4012 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -500,7 +500,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
self.fail(f"fail to decode stdout: {stdout!r}")
def get_expected_config(self, expected_preconfig, expected, env, api,
- add_path=None):
+ modify_path_cb=None):
cls = self.__class__
if cls.EXPECTED_CONFIG is None:
cls.EXPECTED_CONFIG = self._get_expected_config(env)
@@ -556,8 +556,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
prepend_path = expected['pythonpath_env']
if prepend_path is not None:
expected['module_search_paths'] = [prepend_path, *expected['module_search_paths']]
- if add_path is not None:
- expected['module_search_paths'] = [*expected['module_search_paths'], add_path]
+ if modify_path_cb is not None:
+ expected['module_search_paths'] = expected['module_search_paths'].copy()
+ modify_path_cb(expected['module_search_paths'])
for key in self.COPY_PRE_CONFIG:
if key not in expected_preconfig:
@@ -602,7 +603,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
self.assertEqual(configs['global_config'], expected)
def check_all_configs(self, testname, expected_config=None,
- expected_preconfig=None, add_path=None, stderr=None,
+ expected_preconfig=None, modify_path_cb=None, stderr=None,
*, api):
env = remove_python_envvars()
@@ -628,7 +629,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
self.get_expected_config(expected_preconfig,
expected_config, env,
- api, add_path)
+ api, modify_path_cb)
out, err = self.run_embedded_interpreter(testname, env=env)
if stderr is None and not expected_config['verbose']:
@@ -894,9 +895,12 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'program_name': './init_read_set',
'executable': 'my_executable',
}
+ def modify_path(path):
+ path.insert(1, "test_path_insert1")
+ path.append("test_path_append")
self.check_all_configs("test_init_read_set", config,
api=API_PYTHON,
- add_path="init_read_set_path")
+ modify_path_cb=modify_path)
def test_init_run_main(self):
code = ('import _testinternalcapi, json; '
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index 3d27ed2..3873009 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -1350,8 +1350,14 @@ static int test_init_read_set(void)
goto fail;
}
+ status = PyWideStringList_Insert(&config.module_search_paths,
+ 1, L"test_path_insert1");
+ if (PyStatus_Exception(status)) {
+ goto fail;
+ }
+
status = PyWideStringList_Append(&config.module_search_paths,
- L"init_read_set_path");
+ L"test_path_append");
if (PyStatus_Exception(status)) {
goto fail;
}
diff --git a/Python/initconfig.c b/Python/initconfig.c
index 5bd7d4f..b706f4c 100644
--- a/Python/initconfig.c
+++ b/Python/initconfig.c
@@ -297,26 +297,40 @@ _PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2)
PyStatus
-PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
+PyWideStringList_Insert(PyWideStringList *list,
+ Py_ssize_t index, const wchar_t *item)
{
- if (list->length == PY_SSIZE_T_MAX) {
+ Py_ssize_t len = list->length;
+ if (len == PY_SSIZE_T_MAX) {
/* length+1 would overflow */
return _PyStatus_NO_MEMORY();
}
+ if (index < 0) {
+ return _PyStatus_ERR("PyWideStringList_Insert index must be >= 0");
+ }
+ if (index > len) {
+ index = len;
+ }
wchar_t *item2 = _PyMem_RawWcsdup(item);
if (item2 == NULL) {
return _PyStatus_NO_MEMORY();
}
- size_t size = (list->length + 1) * sizeof(list->items[0]);
+ size_t size = (len + 1) * sizeof(list->items[0]);
wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size);
if (items2 == NULL) {
PyMem_RawFree(item2);
return _PyStatus_NO_MEMORY();
}
- items2[list->length] = item2;
+ if (index < len) {
+ memmove(&items2[index + 1],
+ &items2[index],
+ (len - index) * sizeof(items2[0]));
+ }
+
+ items2[index] = item2;
list->items = items2;
list->length++;
return _PyStatus_OK();
@@ -324,6 +338,13 @@ PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
PyStatus
+PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
+{
+ return PyWideStringList_Insert(list, list->length, item);
+}
+
+
+PyStatus
_PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2)
{
for (Py_ssize_t i = 0; i < list2->length; i++) {