Issue #14732: The _csv module now uses PEP 3121 module initialization.
Patch by Robin Schreiber.
This commit is contained in:
parent
adbda17660
commit
e7672d38dc
|
@ -919,6 +919,7 @@ Ralf Schmitt
|
||||||
Michael Schneider
|
Michael Schneider
|
||||||
Peter Schneider-Kamp
|
Peter Schneider-Kamp
|
||||||
Arvin Schnell
|
Arvin Schnell
|
||||||
|
Robin Schreiber
|
||||||
Chad J. Schroeder
|
Chad J. Schroeder
|
||||||
Sam Schulenburg
|
Sam Schulenburg
|
||||||
Stefan Schwarzer
|
Stefan Schwarzer
|
||||||
|
|
|
@ -34,6 +34,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #14732: The _csv module now uses PEP 3121 module initialization.
|
||||||
|
Patch by Robin Schreiber.
|
||||||
|
|
||||||
- Issue #14809: Add HTTP status codes introduced by RFC 6585 to http.server
|
- Issue #14809: Add HTTP status codes introduced by RFC 6585 to http.server
|
||||||
and http.client. Patch by EungJun Yi.
|
and http.client. Patch by EungJun Yi.
|
||||||
|
|
||||||
|
|
105
Modules/_csv.c
105
Modules/_csv.c
|
@ -16,9 +16,39 @@ module instead.
|
||||||
#define IS_BASESTRING(o) \
|
#define IS_BASESTRING(o) \
|
||||||
PyUnicode_Check(o)
|
PyUnicode_Check(o)
|
||||||
|
|
||||||
static PyObject *error_obj; /* CSV exception */
|
typedef struct {
|
||||||
static PyObject *dialects; /* Dialect registry */
|
PyObject *error_obj; /* CSV exception */
|
||||||
static long field_limit = 128 * 1024; /* max parsed field size */
|
PyObject *dialects; /* Dialect registry */
|
||||||
|
long field_limit; /* max parsed field size */
|
||||||
|
} _csvstate;
|
||||||
|
|
||||||
|
#define _csvstate(o) ((_csvstate *)PyModule_GetState(o))
|
||||||
|
|
||||||
|
static int
|
||||||
|
_csv_clear(PyObject *m)
|
||||||
|
{
|
||||||
|
Py_CLEAR(_csvstate(m)->error_obj);
|
||||||
|
Py_CLEAR(_csvstate(m)->dialects);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_csv_traverse(PyObject *m, visitproc visit, void *arg)
|
||||||
|
{
|
||||||
|
Py_VISIT(_csvstate(m)->error_obj);
|
||||||
|
Py_VISIT(_csvstate(m)->dialects);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_csv_free(void *m)
|
||||||
|
{
|
||||||
|
_csv_clear((PyObject *)m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct PyModuleDef _csvmodule;
|
||||||
|
|
||||||
|
#define _csvstate_global ((_csvstate *)PyModule_GetState(PyState_FindModule(&_csvmodule)))
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD,
|
START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD,
|
||||||
|
@ -103,10 +133,10 @@ get_dialect_from_registry(PyObject * name_obj)
|
||||||
{
|
{
|
||||||
PyObject *dialect_obj;
|
PyObject *dialect_obj;
|
||||||
|
|
||||||
dialect_obj = PyDict_GetItem(dialects, name_obj);
|
dialect_obj = PyDict_GetItem(_csvstate_global->dialects, name_obj);
|
||||||
if (dialect_obj == NULL) {
|
if (dialect_obj == NULL) {
|
||||||
if (!PyErr_Occurred())
|
if (!PyErr_Occurred())
|
||||||
PyErr_Format(error_obj, "unknown dialect");
|
PyErr_Format(_csvstate_global->error_obj, "unknown dialect");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Py_INCREF(dialect_obj);
|
Py_INCREF(dialect_obj);
|
||||||
|
@ -544,9 +574,9 @@ parse_grow_buff(ReaderObj *self)
|
||||||
static int
|
static int
|
||||||
parse_add_char(ReaderObj *self, Py_UCS4 c)
|
parse_add_char(ReaderObj *self, Py_UCS4 c)
|
||||||
{
|
{
|
||||||
if (self->field_len >= field_limit) {
|
if (self->field_len >= _csvstate_global->field_limit) {
|
||||||
PyErr_Format(error_obj, "field larger than field limit (%ld)",
|
PyErr_Format(_csvstate_global->error_obj, "field larger than field limit (%ld)",
|
||||||
field_limit);
|
_csvstate_global->field_limit);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (self->field_len == self->field_size && !parse_grow_buff(self))
|
if (self->field_len == self->field_size && !parse_grow_buff(self))
|
||||||
|
@ -703,7 +733,7 @@ parse_process_char(ReaderObj *self, Py_UCS4 c)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* illegal */
|
/* illegal */
|
||||||
PyErr_Format(error_obj, "'%c' expected after '%c'",
|
PyErr_Format(_csvstate_global->error_obj, "'%c' expected after '%c'",
|
||||||
dialect->delimiter,
|
dialect->delimiter,
|
||||||
dialect->quotechar);
|
dialect->quotechar);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -716,7 +746,7 @@ parse_process_char(ReaderObj *self, Py_UCS4 c)
|
||||||
else if (c == '\0')
|
else if (c == '\0')
|
||||||
self->state = START_RECORD;
|
self->state = START_RECORD;
|
||||||
else {
|
else {
|
||||||
PyErr_Format(error_obj, "new-line character seen in unquoted field - do you need to open the file in universal-newline mode?");
|
PyErr_Format(_csvstate_global->error_obj, "new-line character seen in unquoted field - do you need to open the file in universal-newline mode?");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -755,12 +785,12 @@ Reader_iternext(ReaderObj *self)
|
||||||
if (lineobj == NULL) {
|
if (lineobj == NULL) {
|
||||||
/* End of input OR exception */
|
/* End of input OR exception */
|
||||||
if (!PyErr_Occurred() && self->field_len != 0)
|
if (!PyErr_Occurred() && self->field_len != 0)
|
||||||
PyErr_Format(error_obj,
|
PyErr_Format(_csvstate_global->error_obj,
|
||||||
"newline inside string");
|
"newline inside string");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!PyUnicode_Check(lineobj)) {
|
if (!PyUnicode_Check(lineobj)) {
|
||||||
PyErr_Format(error_obj,
|
PyErr_Format(_csvstate_global->error_obj,
|
||||||
"iterator should return strings, "
|
"iterator should return strings, "
|
||||||
"not %.200s "
|
"not %.200s "
|
||||||
"(did you open the file in text mode?)",
|
"(did you open the file in text mode?)",
|
||||||
|
@ -778,7 +808,7 @@ Reader_iternext(ReaderObj *self)
|
||||||
c = PyUnicode_READ(kind, data, pos);
|
c = PyUnicode_READ(kind, data, pos);
|
||||||
if (c == '\0') {
|
if (c == '\0') {
|
||||||
Py_DECREF(lineobj);
|
Py_DECREF(lineobj);
|
||||||
PyErr_Format(error_obj,
|
PyErr_Format(_csvstate_global->error_obj,
|
||||||
"line contains NULL byte");
|
"line contains NULL byte");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -994,7 +1024,7 @@ join_append_data(WriterObj *self, unsigned int field_kind, void *field_data,
|
||||||
}
|
}
|
||||||
if (want_escape) {
|
if (want_escape) {
|
||||||
if (!dialect->escapechar) {
|
if (!dialect->escapechar) {
|
||||||
PyErr_Format(error_obj,
|
PyErr_Format(_csvstate_global->error_obj,
|
||||||
"need to escape, but no escapechar set");
|
"need to escape, but no escapechar set");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1010,7 +1040,7 @@ join_append_data(WriterObj *self, unsigned int field_kind, void *field_data,
|
||||||
*/
|
*/
|
||||||
if (i == 0 && quote_empty) {
|
if (i == 0 && quote_empty) {
|
||||||
if (dialect->quoting == QUOTE_NONE) {
|
if (dialect->quoting == QUOTE_NONE) {
|
||||||
PyErr_Format(error_obj,
|
PyErr_Format(_csvstate_global->error_obj,
|
||||||
"single empty field record must be quoted");
|
"single empty field record must be quoted");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1127,7 +1157,7 @@ csv_writerow(WriterObj *self, PyObject *seq)
|
||||||
PyObject *line, *result;
|
PyObject *line, *result;
|
||||||
|
|
||||||
if (!PySequence_Check(seq))
|
if (!PySequence_Check(seq))
|
||||||
return PyErr_Format(error_obj, "sequence expected");
|
return PyErr_Format(_csvstate_global->error_obj, "sequence expected");
|
||||||
|
|
||||||
len = PySequence_Length(seq);
|
len = PySequence_Length(seq);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
|
@ -1353,7 +1383,7 @@ csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
csv_list_dialects(PyObject *module, PyObject *args)
|
csv_list_dialects(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
return PyDict_Keys(dialects);
|
return PyDict_Keys(_csvstate_global->dialects);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -1372,7 +1402,7 @@ csv_register_dialect(PyObject *module, PyObject *args, PyObject *kwargs)
|
||||||
dialect = _call_dialect(dialect_obj, kwargs);
|
dialect = _call_dialect(dialect_obj, kwargs);
|
||||||
if (dialect == NULL)
|
if (dialect == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (PyDict_SetItem(dialects, name_obj, dialect) < 0) {
|
if (PyDict_SetItem(_csvstate_global->dialects, name_obj, dialect) < 0) {
|
||||||
Py_DECREF(dialect);
|
Py_DECREF(dialect);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1384,8 +1414,8 @@ csv_register_dialect(PyObject *module, PyObject *args, PyObject *kwargs)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
csv_unregister_dialect(PyObject *module, PyObject *name_obj)
|
csv_unregister_dialect(PyObject *module, PyObject *name_obj)
|
||||||
{
|
{
|
||||||
if (PyDict_DelItem(dialects, name_obj) < 0)
|
if (PyDict_DelItem(_csvstate_global->dialects, name_obj) < 0)
|
||||||
return PyErr_Format(error_obj, "unknown dialect");
|
return PyErr_Format(_csvstate_global->error_obj, "unknown dialect");
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
@ -1400,7 +1430,7 @@ static PyObject *
|
||||||
csv_field_size_limit(PyObject *module, PyObject *args)
|
csv_field_size_limit(PyObject *module, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *new_limit = NULL;
|
PyObject *new_limit = NULL;
|
||||||
long old_limit = field_limit;
|
long old_limit = _csvstate_global->field_limit;
|
||||||
|
|
||||||
if (!PyArg_UnpackTuple(args, "field_size_limit", 0, 1, &new_limit))
|
if (!PyArg_UnpackTuple(args, "field_size_limit", 0, 1, &new_limit))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1410,9 +1440,9 @@ csv_field_size_limit(PyObject *module, PyObject *args)
|
||||||
"limit must be an integer");
|
"limit must be an integer");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
field_limit = PyLong_AsLong(new_limit);
|
_csvstate_global->field_limit = PyLong_AsLong(new_limit);
|
||||||
if (field_limit == -1 && PyErr_Occurred()) {
|
if (_csvstate_global->field_limit == -1 && PyErr_Occurred()) {
|
||||||
field_limit = old_limit;
|
_csvstate_global->field_limit = old_limit;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1551,17 +1581,16 @@ static struct PyMethodDef csv_methods[] = {
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static struct PyModuleDef _csvmodule = {
|
static struct PyModuleDef _csvmodule = {
|
||||||
PyModuleDef_HEAD_INIT,
|
PyModuleDef_HEAD_INIT,
|
||||||
"_csv",
|
"_csv",
|
||||||
csv_module_doc,
|
csv_module_doc,
|
||||||
-1,
|
sizeof(_csvstate),
|
||||||
csv_methods,
|
csv_methods,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
_csv_traverse,
|
||||||
NULL,
|
_csv_clear,
|
||||||
NULL
|
_csv_free
|
||||||
};
|
};
|
||||||
|
|
||||||
PyMODINIT_FUNC
|
PyMODINIT_FUNC
|
||||||
|
@ -1589,11 +1618,16 @@ PyInit__csv(void)
|
||||||
MODULE_VERSION) == -1)
|
MODULE_VERSION) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* Set the field limit */
|
||||||
|
_csvstate(module)->field_limit = 128 * 1024;
|
||||||
|
/* Do I still need to add this var to the Module Dict? */
|
||||||
|
|
||||||
/* Add _dialects dictionary */
|
/* Add _dialects dictionary */
|
||||||
dialects = PyDict_New();
|
_csvstate(module)->dialects = PyDict_New();
|
||||||
if (dialects == NULL)
|
if (_csvstate(module)->dialects == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (PyModule_AddObject(module, "_dialects", dialects))
|
Py_INCREF(_csvstate(module)->dialects);
|
||||||
|
if (PyModule_AddObject(module, "_dialects", _csvstate(module)->dialects))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Add quote styles into dictionary */
|
/* Add quote styles into dictionary */
|
||||||
|
@ -1609,9 +1643,10 @@ PyInit__csv(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Add the CSV exception object to the module. */
|
/* Add the CSV exception object to the module. */
|
||||||
error_obj = PyErr_NewException("_csv.Error", NULL, NULL);
|
_csvstate(module)->error_obj = PyErr_NewException("_csv.Error", NULL, NULL);
|
||||||
if (error_obj == NULL)
|
if (_csvstate(module)->error_obj == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
PyModule_AddObject(module, "Error", error_obj);
|
Py_INCREF(_csvstate(module)->error_obj);
|
||||||
|
PyModule_AddObject(module, "Error", _csvstate(module)->error_obj);
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue