Skip to content

Commit 1805a62

Browse files
committed
Issue python#16129: Py_SetStandardStreamEncoding cleanups
- don't call PyErr_NoMemory with interpreter is not initialised - note that it's OK to call _PyMem_RawStrDup here - don't include this in the limited API - capitalise "IO" - be explicit that a non-zero return indicates an error - include versionadded marker in docs
1 parent ac1a248 commit 1805a62

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

Doc/c-api/init.rst

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ Process-wide parameters
9393
single: main()
9494
triple: stdin; stdout; sdterr
9595
96-
This function should be called before :c:func:`Py_Initialize`. It
97-
specifies which encoding and error handling to use with standard io,
98-
with the same meanings as in :func:`str.encode`.
96+
This function should be called before :c:func:`Py_Initialize`, if it is
97+
called at all. It specifies which encoding and error handling to use
98+
with standard IO, with the same meanings as in :func:`str.encode`.
9999
100100
It overrides :envvar:`PYTHONIOENCODING` values, and allows embedding code
101-
to control io encoding when the environment variable does not work.
101+
to control IO encoding when the environment variable does not work.
102102
103103
``encoding`` and/or ``errors`` may be NULL to use
104104
:envvar:`PYTHONIOENCODING` and/or default values (depending on other
@@ -110,7 +110,10 @@ Process-wide parameters
110110
If :c:func:`Py_Finalize` is called, this function will need to be called
111111
again in order to affect subsequent calls to :c:func:`Py_Initialize`.
112112
113-
Returns 0 if successful.
113+
Returns 0 if successful, a nonzero value on error (e.g. calling after the
114+
interpreter has already been initialized).
115+
116+
.. versionadded:: 3.4
114117
115118
116119
.. c:function:: void Py_SetProgramName(wchar_t *name)

Include/pythonrun.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ PyAPI_FUNC(wchar_t *) Py_GetProgramName(void);
2828
PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *);
2929
PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
3030

31+
#ifndef Py_LIMITED_API
32+
/* Only used by applications that embed the interpreter and need to
33+
* override the standard encoding determination mechanism
34+
*/
3135
PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding,
3236
const char *errors);
37+
#endif
3338

3439
PyAPI_FUNC(void) Py_Initialize(void);
3540
PyAPI_FUNC(void) Py_InitializeEx(int);

Python/pythonrun.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,17 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
148148
/* This is too late to have any effect */
149149
return -1;
150150
}
151+
/* Can't call PyErr_NoMemory() on errors, as Python hasn't been
152+
* initialised yet.
153+
*
154+
* However, the raw memory allocators are initialised appropriately
155+
* as C static variables, so _PyMem_RawStrdup is OK even though
156+
* Py_Initialize hasn't been called yet.
157+
*/
151158
if (encoding) {
152159
_Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
153160
if (!_Py_StandardStreamEncoding) {
154-
PyErr_NoMemory();
155-
return -1;
161+
return -2;
156162
}
157163
}
158164
if (errors) {
@@ -161,8 +167,7 @@ Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
161167
if (_Py_StandardStreamEncoding) {
162168
PyMem_RawFree(_Py_StandardStreamEncoding);
163169
}
164-
PyErr_NoMemory();
165-
return -1;
170+
return -3;
166171
}
167172
}
168173
return 0;

0 commit comments

Comments
 (0)