diff -r 5b00781e8574 Modules/_csv.c --- a/Modules/_csv.c Mon May 28 13:19:57 2012 +0200 +++ b/Modules/_csv.c Mon May 28 18:19:48 2012 +0200 @@ -20,6 +20,9 @@ PyObject *error_obj; /* CSV exception */ PyObject *dialects; /* Dialect registry */ long field_limit; /* max parsed field size */ + PyObject *Writer_Type; + PyObject *Reader_Type; + PyObject *Dialect_Type; } _csvstate; #define _csvstate(o) ((_csvstate *)PyModule_GetState(o)) @@ -87,8 +90,6 @@ int strict; /* raise exception on bad CSV */ } DialectObj; -static PyTypeObject Dialect_Type; - typedef struct { PyObject_HEAD @@ -105,9 +106,7 @@ unsigned long line_num; /* Source-file line number */ } ReaderObj; -static PyTypeObject Reader_Type; - -#define ReaderObject_Check(v) (Py_TYPE(v) == &Reader_Type) +#define ReaderObject_Check(v) (Py_TYPE(v) == _csvstate_global->Reader_Type) typedef struct { PyObject_HEAD @@ -122,8 +121,6 @@ int num_fields; /* number of fields in record */ } WriterObj; -static PyTypeObject Writer_Type; - /* * DIALECT class */ @@ -361,7 +358,7 @@ else Py_INCREF(dialect); /* Can we reuse this instance? */ - if (PyObject_TypeCheck(dialect, &Dialect_Type) && + if (PyObject_TypeCheck(dialect, (PyTypeObject *)(_csvstate_global)->Dialect_Type) && delimiter == 0 && doublequote == 0 && escapechar == 0 && @@ -457,47 +454,21 @@ "\n" "The Dialect type records CSV parsing and generation options.\n"); -static PyTypeObject Dialect_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_csv.Dialect", /* tp_name */ - sizeof(DialectObj), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)Dialect_dealloc, /* tp_dealloc */ - (printfunc)0, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - Dialect_Type_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - Dialect_memberlist, /* tp_members */ - Dialect_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - dialect_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot Dialect_Type_slots[] = { + {Py_tp_dealloc, (destructor)Dialect_dealloc}, + {Py_tp_doc, Dialect_Type_doc}, + {Py_tp_members, Dialect_memberlist}, + {Py_tp_getset, Dialect_getsetlist}, + {Py_tp_new, dialect_new}, + {0, 0}, +}; + +static PyType_Spec Dialect_Type_spec = { + "_csv.Dialect", + sizeof(DialectObj), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Dialect_Type_slots }; /* @@ -513,7 +484,7 @@ ctor_args = Py_BuildValue(dialect_inst ? "(O)" : "()", dialect_inst); if (ctor_args == NULL) return NULL; - dialect = PyObject_Call((PyObject *)&Dialect_Type, ctor_args, kwargs); + dialect = PyObject_Call(_csvstate_global->Dialect_Type, ctor_args, kwargs); Py_DECREF(ctor_args); return dialect; } @@ -877,48 +848,33 @@ { NULL } }; +static PyType_Slot Reader_Type_slots[] = { + {Py_tp_doc, Reader_Type_doc}, + {Py_tp_dealloc, Reader_dealloc}, + {Py_tp_traverse, Reader_traverse}, + {Py_tp_clear, Reader_clear}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, Reader_iternext}, + {Py_tp_methods, Reader_methods}, + {Py_tp_members, Reader_memberlist}, + {0, 0}, +}; -static PyTypeObject Reader_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_csv.reader", /*tp_name*/ - sizeof(ReaderObj), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)Reader_dealloc, /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - 0, /*tp_reserved*/ - (reprfunc)0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)0, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - Reader_Type_doc, /*tp_doc*/ - (traverseproc)Reader_traverse, /*tp_traverse*/ - (inquiry)Reader_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - PyObject_SelfIter, /*tp_iter*/ - (getiterfunc)Reader_iternext, /*tp_iternext*/ - Reader_methods, /*tp_methods*/ - Reader_memberlist, /*tp_members*/ - 0, /*tp_getset*/ - +static PyType_Spec Reader_Type_spec = { + "_csv.reader", + sizeof(ReaderObj), + 0, + Py_TPFLAGS_DEFAULT | + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, + Reader_Type_slots }; static PyObject * csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args) { PyObject * iterator, * dialect = NULL; - ReaderObj * self = PyObject_GC_New(ReaderObj, &Reader_Type); + ReaderObj * self = PyObject_GC_New(ReaderObj, (PyTypeObject *)(_csvstate_global)->Reader_Type); if (!self) return NULL; @@ -1304,46 +1260,32 @@ "in CSV format from sequence input.\n" ); -static PyTypeObject Writer_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_csv.writer", /*tp_name*/ - sizeof(WriterObj), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)Writer_dealloc, /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - 0, /*tp_reserved*/ - (reprfunc)0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)0, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - Writer_Type_doc, - (traverseproc)Writer_traverse, /*tp_traverse*/ - (inquiry)Writer_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - (getiterfunc)0, /*tp_iter*/ - (getiterfunc)0, /*tp_iternext*/ - Writer_methods, /*tp_methods*/ - Writer_memberlist, /*tp_members*/ - 0, /*tp_getset*/ +static PyType_Slot Writer_Type_slots[] = { + {Py_tp_doc, Writer_Type_doc}, + {Py_tp_dealloc, Writer_dealloc}, + {Py_tp_traverse, Writer_traverse}, + {Py_tp_clear, Writer_clear}, + {Py_tp_methods, Writer_methods}, + {Py_tp_members, Writer_memberlist}, + {0, 0}, +}; + +static PyType_Spec Writer_Type_spec = { + "_csv.writer", + sizeof(WriterObj), + 0, + Py_TPFLAGS_DEFAULT | + Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, + Writer_Type_slots }; static PyObject * csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args) { PyObject * output_file, * dialect = NULL; - WriterObj * self = PyObject_GC_New(WriterObj, &Writer_Type); + WriterObj * self = PyObject_GC_New(WriterObj, + (PyTypeObject *)(_csvstate_global)->Writer_Type); _Py_IDENTIFIER(write); if (!self) @@ -1599,24 +1541,27 @@ PyObject *module; StyleDesc *style; - if (PyType_Ready(&Dialect_Type) < 0) - return NULL; - - if (PyType_Ready(&Reader_Type) < 0) - return NULL; - - if (PyType_Ready(&Writer_Type) < 0) - return NULL; - /* Create the module and add the functions */ module = PyModule_Create(&_csvmodule); if (module == NULL) - return NULL; + goto fail; + + _csvstate(module)->Dialect_Type = PyType_FromSpec(&Dialect_Type_spec); + if (_csvstate(module)->Dialect_Type == NULL) + goto fail; + + _csvstate(module)->Reader_Type = PyType_FromSpec(&Reader_Type_spec); + if (_csvstate(module)->Reader_Type == NULL) + goto fail; + + _csvstate(module)->Writer_Type = PyType_FromSpec(&Writer_Type_spec); + if (_csvstate(module)->Writer_Type == NULL) + goto fail; /* Add version to the module. */ if (PyModule_AddStringConstant(module, "__version__", MODULE_VERSION) == -1) - return NULL; + goto fail; /* Set the field limit */ _csvstate(module)->field_limit = 128 * 1024; @@ -1625,28 +1570,31 @@ /* Add _dialects dictionary */ _csvstate(module)->dialects = PyDict_New(); if (_csvstate(module)->dialects == NULL) - return NULL; + goto fail; Py_INCREF(_csvstate(module)->dialects); if (PyModule_AddObject(module, "_dialects", _csvstate(module)->dialects)) - return NULL; + goto fail; /* Add quote styles into dictionary */ for (style = quote_styles; style->name; style++) { if (PyModule_AddIntConstant(module, style->name, style->style) == -1) - return NULL; + goto fail; } /* Add the Dialect type */ - Py_INCREF(&Dialect_Type); - if (PyModule_AddObject(module, "Dialect", (PyObject *)&Dialect_Type)) - return NULL; + Py_INCREF(_csvstate(module)->Dialect_Type); + if (PyModule_AddObject(module, "Dialect", _csvstate(module)->Dialect_Type)) + goto fail; /* Add the CSV exception object to the module. */ _csvstate(module)->error_obj = PyErr_NewException("_csv.Error", NULL, NULL); if (_csvstate(module)->error_obj == NULL) - return NULL; + goto fail; Py_INCREF(_csvstate(module)->error_obj); PyModule_AddObject(module, "Error", _csvstate(module)->error_obj); return module; + fail: + Py_XDECREF(module); + return NULL; }