bpo-31862: Port binascii to PEP 489 multiphase initialization (GH-4108)
This commit is contained in:
parent
77aa396bb9
commit
33e71e01e9
|
@ -473,6 +473,19 @@ class SubinterpreterTest(unittest.TestCase):
|
||||||
self.assertNotEqual(pickle.load(f), id(sys.modules))
|
self.assertNotEqual(pickle.load(f), id(sys.modules))
|
||||||
self.assertNotEqual(pickle.load(f), id(builtins))
|
self.assertNotEqual(pickle.load(f), id(builtins))
|
||||||
|
|
||||||
|
def test_mutate_exception(self):
|
||||||
|
"""
|
||||||
|
Exceptions saved in global module state get shared between
|
||||||
|
individual module instances. This test checks whether or not
|
||||||
|
a change in one interpreter's module gets reflected into the
|
||||||
|
other ones.
|
||||||
|
"""
|
||||||
|
import binascii
|
||||||
|
|
||||||
|
support.run_in_subinterp("import binascii; binascii.Error.foobar = 'foobar'")
|
||||||
|
|
||||||
|
self.assertFalse(hasattr(binascii.Error, "foobar"))
|
||||||
|
|
||||||
|
|
||||||
class TestThreadState(unittest.TestCase):
|
class TestThreadState(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Port binascii to PEP 489 multiphase initialization.
|
||||||
|
Patch by Marcel Plch.
|
|
@ -61,8 +61,10 @@
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static PyObject *Error;
|
typedef struct binascii_state {
|
||||||
static PyObject *Incomplete;
|
PyObject *Error;
|
||||||
|
PyObject *Incomplete;
|
||||||
|
} binascii_state;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** hqx lookup table, ascii->binary.
|
** hqx lookup table, ascii->binary.
|
||||||
|
@ -263,6 +265,7 @@ binascii_a2b_uu_impl(PyObject *module, Py_buffer *data)
|
||||||
unsigned int leftchar = 0;
|
unsigned int leftchar = 0;
|
||||||
PyObject *rv;
|
PyObject *rv;
|
||||||
Py_ssize_t ascii_len, bin_len;
|
Py_ssize_t ascii_len, bin_len;
|
||||||
|
binascii_state *state;
|
||||||
|
|
||||||
ascii_data = data->buf;
|
ascii_data = data->buf;
|
||||||
ascii_len = data->len;
|
ascii_len = data->len;
|
||||||
|
@ -294,7 +297,11 @@ binascii_a2b_uu_impl(PyObject *module, Py_buffer *data)
|
||||||
** '`' as zero instead of space.
|
** '`' as zero instead of space.
|
||||||
*/
|
*/
|
||||||
if ( this_ch < ' ' || this_ch > (' ' + 64)) {
|
if ( this_ch < ' ' || this_ch > (' ' + 64)) {
|
||||||
PyErr_SetString(Error, "Illegal char");
|
state = PyModule_GetState(module);
|
||||||
|
if (state == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_SetString(state->Error, "Illegal char");
|
||||||
Py_DECREF(rv);
|
Py_DECREF(rv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -322,7 +329,11 @@ binascii_a2b_uu_impl(PyObject *module, Py_buffer *data)
|
||||||
/* Extra '`' may be written as padding in some cases */
|
/* Extra '`' may be written as padding in some cases */
|
||||||
if ( this_ch != ' ' && this_ch != ' '+64 &&
|
if ( this_ch != ' ' && this_ch != ' '+64 &&
|
||||||
this_ch != '\n' && this_ch != '\r' ) {
|
this_ch != '\n' && this_ch != '\r' ) {
|
||||||
PyErr_SetString(Error, "Trailing garbage");
|
state = PyModule_GetState(module);
|
||||||
|
if (state == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_SetString(state->Error, "Trailing garbage");
|
||||||
Py_DECREF(rv);
|
Py_DECREF(rv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -350,6 +361,7 @@ binascii_b2a_uu_impl(PyObject *module, Py_buffer *data, int backtick)
|
||||||
int leftbits = 0;
|
int leftbits = 0;
|
||||||
unsigned char this_ch;
|
unsigned char this_ch;
|
||||||
unsigned int leftchar = 0;
|
unsigned int leftchar = 0;
|
||||||
|
binascii_state *state;
|
||||||
Py_ssize_t bin_len, out_len;
|
Py_ssize_t bin_len, out_len;
|
||||||
_PyBytesWriter writer;
|
_PyBytesWriter writer;
|
||||||
|
|
||||||
|
@ -358,7 +370,11 @@ binascii_b2a_uu_impl(PyObject *module, Py_buffer *data, int backtick)
|
||||||
bin_len = data->len;
|
bin_len = data->len;
|
||||||
if ( bin_len > 45 ) {
|
if ( bin_len > 45 ) {
|
||||||
/* The 45 is a limit that appears in all uuencode's */
|
/* The 45 is a limit that appears in all uuencode's */
|
||||||
PyErr_SetString(Error, "At most 45 bytes at once");
|
state = PyModule_GetState(module);
|
||||||
|
if (state == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_SetString(state->Error, "At most 45 bytes at once");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,6 +461,7 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data)
|
||||||
Py_ssize_t ascii_len, bin_len;
|
Py_ssize_t ascii_len, bin_len;
|
||||||
int quad_pos = 0;
|
int quad_pos = 0;
|
||||||
_PyBytesWriter writer;
|
_PyBytesWriter writer;
|
||||||
|
binascii_state *state;
|
||||||
|
|
||||||
ascii_data = data->buf;
|
ascii_data = data->buf;
|
||||||
ascii_len = data->len;
|
ascii_len = data->len;
|
||||||
|
@ -512,19 +529,23 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leftbits != 0) {
|
if (leftbits != 0) {
|
||||||
|
state = PyModule_GetState(module);
|
||||||
|
if (state == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (leftbits == 6) {
|
if (leftbits == 6) {
|
||||||
/*
|
/*
|
||||||
** There is exactly one extra valid, non-padding, base64 character.
|
** There is exactly one extra valid, non-padding, base64 character.
|
||||||
** This is an invalid length, as there is no possible input that
|
** This is an invalid length, as there is no possible input that
|
||||||
** could encoded into such a base64 string.
|
** could encoded into such a base64 string.
|
||||||
*/
|
*/
|
||||||
PyErr_Format(Error,
|
PyErr_Format(state->Error,
|
||||||
"Invalid base64-encoded string: "
|
"Invalid base64-encoded string: "
|
||||||
"number of data characters (%zd) cannot be 1 more "
|
"number of data characters (%zd) cannot be 1 more "
|
||||||
"than a multiple of 4",
|
"than a multiple of 4",
|
||||||
(bin_data - bin_data_start) / 3 * 4 + 1);
|
(bin_data - bin_data_start) / 3 * 4 + 1);
|
||||||
} else {
|
} else {
|
||||||
PyErr_SetString(Error, "Incorrect padding");
|
PyErr_SetString(state->Error, "Incorrect padding");
|
||||||
}
|
}
|
||||||
_PyBytesWriter_Dealloc(&writer);
|
_PyBytesWriter_Dealloc(&writer);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -556,6 +577,7 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int newline)
|
||||||
unsigned int leftchar = 0;
|
unsigned int leftchar = 0;
|
||||||
Py_ssize_t bin_len, out_len;
|
Py_ssize_t bin_len, out_len;
|
||||||
_PyBytesWriter writer;
|
_PyBytesWriter writer;
|
||||||
|
binascii_state *state;
|
||||||
|
|
||||||
bin_data = data->buf;
|
bin_data = data->buf;
|
||||||
bin_len = data->len;
|
bin_len = data->len;
|
||||||
|
@ -564,7 +586,11 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int newline)
|
||||||
assert(bin_len >= 0);
|
assert(bin_len >= 0);
|
||||||
|
|
||||||
if ( bin_len > BASE64_MAXBIN ) {
|
if ( bin_len > BASE64_MAXBIN ) {
|
||||||
PyErr_SetString(Error, "Too much data for base64 line");
|
state = PyModule_GetState(module);
|
||||||
|
if (state == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_SetString(state->Error, "Too much data for base64 line");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,6 +652,7 @@ binascii_a2b_hqx_impl(PyObject *module, Py_buffer *data)
|
||||||
Py_ssize_t len;
|
Py_ssize_t len;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
_PyBytesWriter writer;
|
_PyBytesWriter writer;
|
||||||
|
binascii_state *state;
|
||||||
|
|
||||||
ascii_data = data->buf;
|
ascii_data = data->buf;
|
||||||
len = data->len;
|
len = data->len;
|
||||||
|
@ -649,7 +676,11 @@ binascii_a2b_hqx_impl(PyObject *module, Py_buffer *data)
|
||||||
if ( this_ch == SKIP )
|
if ( this_ch == SKIP )
|
||||||
continue;
|
continue;
|
||||||
if ( this_ch == FAIL ) {
|
if ( this_ch == FAIL ) {
|
||||||
PyErr_SetString(Error, "Illegal char");
|
state = PyModule_GetState(module);
|
||||||
|
if (state == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_SetString(state->Error, "Illegal char");
|
||||||
_PyBytesWriter_Dealloc(&writer);
|
_PyBytesWriter_Dealloc(&writer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -670,7 +701,11 @@ binascii_a2b_hqx_impl(PyObject *module, Py_buffer *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( leftbits && !done ) {
|
if ( leftbits && !done ) {
|
||||||
PyErr_SetString(Incomplete,
|
state = PyModule_GetState(module);
|
||||||
|
if (state == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_SetString(state->Incomplete,
|
||||||
"String has incomplete number of bytes");
|
"String has incomplete number of bytes");
|
||||||
_PyBytesWriter_Dealloc(&writer);
|
_PyBytesWriter_Dealloc(&writer);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -822,6 +857,7 @@ binascii_rledecode_hqx_impl(PyObject *module, Py_buffer *data)
|
||||||
in_data = data->buf;
|
in_data = data->buf;
|
||||||
in_len = data->len;
|
in_len = data->len;
|
||||||
_PyBytesWriter_Init(&writer);
|
_PyBytesWriter_Init(&writer);
|
||||||
|
binascii_state *state;
|
||||||
|
|
||||||
assert(in_len >= 0);
|
assert(in_len >= 0);
|
||||||
|
|
||||||
|
@ -846,7 +882,11 @@ binascii_rledecode_hqx_impl(PyObject *module, Py_buffer *data)
|
||||||
#define INBYTE(b) \
|
#define INBYTE(b) \
|
||||||
do { \
|
do { \
|
||||||
if ( --in_len < 0 ) { \
|
if ( --in_len < 0 ) { \
|
||||||
PyErr_SetString(Incomplete, ""); \
|
state = PyModule_GetState(module); \
|
||||||
|
if (state == NULL) { \
|
||||||
|
return NULL; \
|
||||||
|
} \
|
||||||
|
PyErr_SetString(state->Incomplete, ""); \
|
||||||
goto error; \
|
goto error; \
|
||||||
} \
|
} \
|
||||||
b = *in_data++; \
|
b = *in_data++; \
|
||||||
|
@ -868,7 +908,11 @@ binascii_rledecode_hqx_impl(PyObject *module, Py_buffer *data)
|
||||||
/* Note Error, not Incomplete (which is at the end
|
/* Note Error, not Incomplete (which is at the end
|
||||||
** of the string only). This is a programmer error.
|
** of the string only). This is a programmer error.
|
||||||
*/
|
*/
|
||||||
PyErr_SetString(Error, "Orphaned RLE code at start");
|
state = PyModule_GetState(module);
|
||||||
|
if (state == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_SetString(state->Error, "Orphaned RLE code at start");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
*out_data++ = RUNCHAR;
|
*out_data++ = RUNCHAR;
|
||||||
|
@ -1166,6 +1210,7 @@ binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr)
|
||||||
PyObject *retval;
|
PyObject *retval;
|
||||||
char* retbuf;
|
char* retbuf;
|
||||||
Py_ssize_t i, j;
|
Py_ssize_t i, j;
|
||||||
|
binascii_state *state;
|
||||||
|
|
||||||
argbuf = hexstr->buf;
|
argbuf = hexstr->buf;
|
||||||
arglen = hexstr->len;
|
arglen = hexstr->len;
|
||||||
|
@ -1177,7 +1222,11 @@ binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr)
|
||||||
* raise an exception.
|
* raise an exception.
|
||||||
*/
|
*/
|
||||||
if (arglen % 2) {
|
if (arglen % 2) {
|
||||||
PyErr_SetString(Error, "Odd-length string");
|
state = PyModule_GetState(module);
|
||||||
|
if (state == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_SetString(state->Error, "Odd-length string");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1190,7 +1239,11 @@ binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr)
|
||||||
unsigned int top = _PyLong_DigitValue[Py_CHARMASK(argbuf[i])];
|
unsigned int top = _PyLong_DigitValue[Py_CHARMASK(argbuf[i])];
|
||||||
unsigned int bot = _PyLong_DigitValue[Py_CHARMASK(argbuf[i+1])];
|
unsigned int bot = _PyLong_DigitValue[Py_CHARMASK(argbuf[i+1])];
|
||||||
if (top >= 16 || bot >= 16) {
|
if (top >= 16 || bot >= 16) {
|
||||||
PyErr_SetString(Error,
|
state = PyModule_GetState(module);
|
||||||
|
if (state == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_SetString(state->Error,
|
||||||
"Non-hexadecimal digit found");
|
"Non-hexadecimal digit found");
|
||||||
goto finally;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
@ -1545,14 +1598,47 @@ static struct PyMethodDef binascii_module_methods[] = {
|
||||||
/* Initialization function for the module (*must* be called PyInit_binascii) */
|
/* Initialization function for the module (*must* be called PyInit_binascii) */
|
||||||
PyDoc_STRVAR(doc_binascii, "Conversion between binary data and ASCII");
|
PyDoc_STRVAR(doc_binascii, "Conversion between binary data and ASCII");
|
||||||
|
|
||||||
|
static int
|
||||||
|
binascii_exec(PyObject *m) {
|
||||||
|
int result;
|
||||||
|
binascii_state *state = PyModule_GetState(m);
|
||||||
|
if (state == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->Error = PyErr_NewException("binascii.Error", PyExc_ValueError, NULL);
|
||||||
|
if (state->Error == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
result = PyModule_AddObject(m, "Error", state->Error);
|
||||||
|
if (result == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->Incomplete = PyErr_NewException("binascii.Incomplete", NULL, NULL);
|
||||||
|
if (state->Incomplete == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
result = PyModule_AddObject(m, "Incomplete", state->Incomplete);
|
||||||
|
if (result == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyModuleDef_Slot binascii_slots[] = {
|
||||||
|
{Py_mod_exec, binascii_exec},
|
||||||
|
{0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
static struct PyModuleDef binasciimodule = {
|
static struct PyModuleDef binasciimodule = {
|
||||||
PyModuleDef_HEAD_INIT,
|
PyModuleDef_HEAD_INIT,
|
||||||
"binascii",
|
"binascii",
|
||||||
doc_binascii,
|
doc_binascii,
|
||||||
-1,
|
sizeof(binascii_state),
|
||||||
binascii_module_methods,
|
binascii_module_methods,
|
||||||
NULL,
|
binascii_slots,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
|
@ -1561,22 +1647,5 @@ static struct PyModuleDef binasciimodule = {
|
||||||
PyMODINIT_FUNC
|
PyMODINIT_FUNC
|
||||||
PyInit_binascii(void)
|
PyInit_binascii(void)
|
||||||
{
|
{
|
||||||
PyObject *m, *d;
|
return PyModuleDef_Init(&binasciimodule);
|
||||||
|
|
||||||
/* Create the module and add the functions */
|
|
||||||
m = PyModule_Create(&binasciimodule);
|
|
||||||
if (m == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
d = PyModule_GetDict(m);
|
|
||||||
|
|
||||||
Error = PyErr_NewException("binascii.Error", PyExc_ValueError, NULL);
|
|
||||||
PyDict_SetItemString(d, "Error", Error);
|
|
||||||
Incomplete = PyErr_NewException("binascii.Incomplete", NULL, NULL);
|
|
||||||
PyDict_SetItemString(d, "Incomplete", Incomplete);
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
Py_DECREF(m);
|
|
||||||
m = NULL;
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue