[issue39461] [RFE] os.environ should support Path-like values, like subprocess(..., env=...)
Eryk Sun
report at bugs.python.org
Tue Jan 28 16:19:03 EST 2020
Eryk Sun <eryksun at gmail.com> added the comment:
> as long as the behavior is *consistent* with the env kwarg to
> subprocess.run()
subprocess isn't consistent with itself across platforms. The env parameter in Windows is strictly an str->str mapping, like os.environ. This is coded in getenvironment in Modules/_winapi.c:
if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
PyErr_SetString(PyExc_TypeError,
"environment can only contain strings");
goto error;
}
At a lower level, should the env parameter of os.spawnve and os.execve allow path-like objects? Should (Unix) os.putenv allow the name and value to be path-like?
Currently these cases use PyUnicode_FSConverter and PyUnicode_FSDecoder, which support __fspath__ via PyOS_FSPath. PyUnicode_FSDecoder also supports the buffer protocol, with a warning.
Since we have cases like this where the filesystem encoding is used for string data that's not actually a file path, should alternate ParseTuple converters be added that are limited to just str and bytes? Maybe name them PyUnicode_FSStringEncoder and PyUnicode_FSStringDecoder, where "String" emphasizes that fspath and buffer objects are not allowed. For example:
int
PyUnicode_FSStringEncoder(PyObject *path, void *addr)
{
PyObject *output = NULL;
if (path == NULL) {
Py_DECREF(*(PyObject **)addr);
*(PyObject **)addr = NULL;
return 1;
}
if (PyBytes_Check(path)) {
output = path;
Py_INCREF(output);
}
else if (PyUnicode_Check(path)) {
output = PyUnicode_EncodeFSDefault(path);
if (!output)
return 0;
}
else {
PyErr_Format(PyExc_TypeError, "path should be str or bytes, not "
"%.200s", _PyType_Name(Py_TYPE(path)));
return 0;
}
if ((size_t)PyBytes_GET_SIZE(output) !=
strlen(PyBytes_AS_STRING(output)))
{
PyErr_SetString(PyExc_ValueError, "embedded null byte");
Py_DECREF(output);
return 0;
}
*(PyObject **)addr = output;
return Py_CLEANUP_SUPPORTED;
}
int
PyUnicode_FSStringDecoder(PyObject *path, void *addr)
{
PyObject *output = NULL;
if (arg == NULL) {
Py_DECREF(*(PyObject **)addr);
*(PyObject **)addr = NULL;
return 1;
}
if (PyUnicode_Check(path)) {
output = path;
Py_INCREF(output);
}
else if (PyBytes_Check(path)) {
output = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(path),
PyBytes_GET_SIZE(path));
if (!output)
return 0;
}
else {
PyErr_Format(PyExc_TypeError, "path should be str or bytes, not "
"%.200s", _PyType_Name(Py_TYPE(path)));
return 0;
}
if (PyUnicode_READY(output) == -1) {
Py_DECREF(output);
return 0;
}
if (findchar(PyUnicode_DATA(output), PyUnicode_KIND(output),
PyUnicode_GET_LENGTH(output), 0, 1) >= 0) {
PyErr_SetString(PyExc_ValueError, "embedded null character");
Py_DECREF(output);
return 0;
}
*(PyObject **)addr = output;
return Py_CLEANUP_SUPPORTED;
}
----------
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue39461>
_______________________________________
More information about the Python-bugs-list
mailing list