summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorErlend E. Aasland <erlend.aasland@protonmail.com>2023-02-20 13:46:20 (GMT)
committerGitHub <noreply@github.com>2023-02-20 13:46:20 (GMT)
commitc00faf79438cc7f0d98af2679c695f747e4369a3 (patch)
tree9245f12ae35af5be4f308decb0d0e5512f4b0a1f /Modules
parent27136310414965a3ea7f835e416cf74b91cefb48 (diff)
downloadcpython-c00faf79438cc7f0d98af2679c695f747e4369a3.zip
cpython-c00faf79438cc7f0d98af2679c695f747e4369a3.tar.gz
cpython-c00faf79438cc7f0d98af2679c695f747e4369a3.tar.bz2
gh-101819: Adapt _io types to heap types, batch 1 (GH-101949)
Adapt StringIO, TextIOWrapper, FileIO, Buffered*, and BytesIO types. Automerge-Triggered-By: GH:erlend-aasland
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_io/_iomodule.c99
-rw-r--r--Modules/_io/_iomodule.h47
-rw-r--r--Modules/_io/bufferedio.c341
-rw-r--r--Modules/_io/bytesio.c77
-rw-r--r--Modules/_io/clinic/bufferedio.c.h4
-rw-r--r--Modules/_io/fileio.c90
-rw-r--r--Modules/_io/stringio.c85
-rw-r--r--Modules/_io/textio.c99
8 files changed, 373 insertions, 469 deletions
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c
index 811b1d2..55b6535 100644
--- a/Modules/_io/_iomodule.c
+++ b/Modules/_io/_iomodule.c
@@ -10,7 +10,6 @@
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "_iomodule.h"
-#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#ifdef HAVE_SYS_TYPES_H
@@ -315,8 +314,9 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
}
/* Create the Raw file stream */
+ _PyIO_State *state = get_io_state(module);
{
- PyObject *RawIO_class = (PyObject *)&PyFileIO_Type;
+ PyObject *RawIO_class = (PyObject *)state->PyFileIO_Type;
#ifdef MS_WINDOWS
const PyConfig *config = _Py_GetConfig();
if (!config->legacy_windows_stdio && _PyIO_get_console_type(path_or_fd) != '\0') {
@@ -390,12 +390,15 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
{
PyObject *Buffered_class;
- if (updating)
- Buffered_class = (PyObject *)&PyBufferedRandom_Type;
- else if (creating || writing || appending)
- Buffered_class = (PyObject *)&PyBufferedWriter_Type;
- else if (reading)
- Buffered_class = (PyObject *)&PyBufferedReader_Type;
+ if (updating) {
+ Buffered_class = (PyObject *)state->PyBufferedRandom_Type;
+ }
+ else if (creating || writing || appending) {
+ Buffered_class = (PyObject *)state->PyBufferedWriter_Type;
+ }
+ else if (reading) {
+ Buffered_class = (PyObject *)state->PyBufferedReader_Type;
+ }
else {
PyErr_Format(PyExc_ValueError,
"unknown mode: '%s'", mode);
@@ -417,7 +420,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
}
/* wraps into a TextIOWrapper */
- wrapper = PyObject_CallFunction((PyObject *)&PyTextIOWrapper_Type,
+ wrapper = PyObject_CallFunction((PyObject *)state->PyTextIOWrapper_Type,
"OsssO",
buffer,
encoding, errors, newline,
@@ -558,14 +561,6 @@ PyNumber_AsOff_t(PyObject *item, PyObject *err)
return result;
}
-static inline _PyIO_State*
-get_io_state(PyObject *module)
-{
- void *state = _PyModule_GetState(module);
- assert(state != NULL);
- return (_PyIO_State *)state;
-}
-
_PyIO_State *
_PyIO_get_module_state(void)
{
@@ -587,6 +582,15 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
return 0;
Py_VISIT(state->locale_module);
Py_VISIT(state->unsupported_operation);
+
+ Py_VISIT(state->PyBufferedRWPair_Type);
+ Py_VISIT(state->PyBufferedRandom_Type);
+ Py_VISIT(state->PyBufferedReader_Type);
+ Py_VISIT(state->PyBufferedWriter_Type);
+ Py_VISIT(state->PyBytesIO_Type);
+ Py_VISIT(state->PyFileIO_Type);
+ Py_VISIT(state->PyStringIO_Type);
+ Py_VISIT(state->PyTextIOWrapper_Type);
return 0;
}
@@ -599,6 +603,15 @@ iomodule_clear(PyObject *mod) {
if (state->locale_module != NULL)
Py_CLEAR(state->locale_module);
Py_CLEAR(state->unsupported_operation);
+
+ Py_CLEAR(state->PyBufferedRWPair_Type);
+ Py_CLEAR(state->PyBufferedRandom_Type);
+ Py_CLEAR(state->PyBufferedReader_Type);
+ Py_CLEAR(state->PyBufferedWriter_Type);
+ Py_CLEAR(state->PyBytesIO_Type);
+ Py_CLEAR(state->PyFileIO_Type);
+ Py_CLEAR(state->PyStringIO_Type);
+ Py_CLEAR(state->PyTextIOWrapper_Type);
return 0;
}
@@ -612,7 +625,9 @@ iomodule_free(PyObject *mod) {
* Module definition
*/
+#define clinic_state() (get_io_state(module))
#include "clinic/_iomodule.c.h"
+#undef clinic_state
static PyMethodDef module_methods[] = {
_IO_OPEN_METHODDEF
@@ -644,23 +659,11 @@ static PyTypeObject* static_types[] = {
&PyRawIOBase_Type,
&PyTextIOBase_Type,
- // PyBufferedIOBase_Type(PyIOBase_Type) subclasses
- &PyBytesIO_Type,
- &PyBufferedReader_Type,
- &PyBufferedWriter_Type,
- &PyBufferedRWPair_Type,
- &PyBufferedRandom_Type,
-
// PyRawIOBase_Type(PyIOBase_Type) subclasses
- &PyFileIO_Type,
&_PyBytesIOBuffer_Type,
#ifdef MS_WINDOWS
&PyWindowsConsoleIO_Type,
#endif
-
- // PyTextIOBase_Type(PyIOBase_Type) subclasses
- &PyStringIO_Type,
- &PyTextIOWrapper_Type,
};
@@ -673,6 +676,17 @@ _PyIO_Fini(void)
}
}
+#define ADD_TYPE(module, type, spec, base) \
+do { \
+ type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \
+ (PyObject *)base); \
+ if (type == NULL) { \
+ goto fail; \
+ } \
+ if (PyModule_AddType(module, type) < 0) { \
+ goto fail; \
+ } \
+} while (0)
PyMODINIT_FUNC
PyInit__io(void)
@@ -705,17 +719,9 @@ PyInit__io(void)
}
// Set type base classes
- PyFileIO_Type.tp_base = &PyRawIOBase_Type;
- PyBytesIO_Type.tp_base = &PyBufferedIOBase_Type;
- PyStringIO_Type.tp_base = &PyTextIOBase_Type;
#ifdef MS_WINDOWS
PyWindowsConsoleIO_Type.tp_base = &PyRawIOBase_Type;
#endif
- PyBufferedReader_Type.tp_base = &PyBufferedIOBase_Type;
- PyBufferedWriter_Type.tp_base = &PyBufferedIOBase_Type;
- PyBufferedRWPair_Type.tp_base = &PyBufferedIOBase_Type;
- PyBufferedRandom_Type.tp_base = &PyBufferedIOBase_Type;
- PyTextIOWrapper_Type.tp_base = &PyTextIOBase_Type;
// Add types
for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
@@ -725,6 +731,25 @@ PyInit__io(void)
}
}
+ // PyBufferedIOBase_Type(PyIOBase_Type) subclasses
+ ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, &PyBufferedIOBase_Type);
+ ADD_TYPE(m, state->PyBufferedWriter_Type, &bufferedwriter_spec,
+ &PyBufferedIOBase_Type);
+ ADD_TYPE(m, state->PyBufferedReader_Type, &bufferedreader_spec,
+ &PyBufferedIOBase_Type);
+ ADD_TYPE(m, state->PyBufferedRWPair_Type, &bufferedrwpair_spec,
+ &PyBufferedIOBase_Type);
+ ADD_TYPE(m, state->PyBufferedRandom_Type, &bufferedrandom_spec,
+ &PyBufferedIOBase_Type);
+
+ // PyRawIOBase_Type(PyIOBase_Type) subclasses
+ ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, &PyRawIOBase_Type);
+
+ // PyTextIOBase_Type(PyIOBase_Type) subclasses
+ ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, &PyTextIOBase_Type);
+ ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec,
+ &PyTextIOBase_Type);
+
state->initialized = 1;
return m;
diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h
index 7617cb8..02daef9 100644
--- a/Modules/_io/_iomodule.h
+++ b/Modules/_io/_iomodule.h
@@ -4,6 +4,9 @@
#include "exports.h"
+#include "pycore_moduleobject.h" // _PyModule_GetState()
+#include "structmember.h"
+
/* ABCs */
extern PyTypeObject PyIOBase_Type;
extern PyTypeObject PyRawIOBase_Type;
@@ -11,16 +14,18 @@ extern PyTypeObject PyBufferedIOBase_Type;
extern PyTypeObject PyTextIOBase_Type;
/* Concrete classes */
-extern PyTypeObject PyFileIO_Type;
-extern PyTypeObject PyBytesIO_Type;
-extern PyTypeObject PyStringIO_Type;
-extern PyTypeObject PyBufferedReader_Type;
-extern PyTypeObject PyBufferedWriter_Type;
-extern PyTypeObject PyBufferedRWPair_Type;
-extern PyTypeObject PyBufferedRandom_Type;
-extern PyTypeObject PyTextIOWrapper_Type;
extern PyTypeObject PyIncrementalNewlineDecoder_Type;
+/* Type specs */
+extern PyType_Spec bufferedrandom_spec;
+extern PyType_Spec bufferedreader_spec;
+extern PyType_Spec bufferedrwpair_spec;
+extern PyType_Spec bufferedwriter_spec;
+extern PyType_Spec bytesio_spec;
+extern PyType_Spec fileio_spec;
+extern PyType_Spec stringio_spec;
+extern PyType_Spec textiowrapper_spec;
+
#ifdef MS_WINDOWS
extern PyTypeObject PyWindowsConsoleIO_Type;
#endif /* MS_WINDOWS */
@@ -140,11 +145,37 @@ typedef struct {
PyObject *locale_module;
PyObject *unsupported_operation;
+
+ /* Types */
+ PyTypeObject *PyBufferedRWPair_Type;
+ PyTypeObject *PyBufferedRandom_Type;
+ PyTypeObject *PyBufferedReader_Type;
+ PyTypeObject *PyBufferedWriter_Type;
+ PyTypeObject *PyBytesIO_Type;
+ PyTypeObject *PyFileIO_Type;
+ PyTypeObject *PyStringIO_Type;
+ PyTypeObject *PyTextIOWrapper_Type;
} _PyIO_State;
#define IO_MOD_STATE(mod) ((_PyIO_State *)PyModule_GetState(mod))
#define IO_STATE() _PyIO_get_module_state()
+static inline _PyIO_State *
+get_io_state(PyObject *module)
+{
+ void *state = _PyModule_GetState(module);
+ assert(state != NULL);
+ return (_PyIO_State *)state;
+}
+
+static inline _PyIO_State *
+find_io_state_by_def(PyTypeObject *type)
+{
+ PyObject *mod = PyType_GetModuleByDef(type, &_PyIO_Module);
+ assert(mod != NULL);
+ return get_io_state(mod);
+}
+
extern _PyIO_State *_PyIO_get_module_state(void);
#ifdef MS_WINDOWS
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index ba8969f..56491f0 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -18,12 +18,12 @@
module _io
class _io._BufferedIOBase "PyObject *" "&PyBufferedIOBase_Type"
class _io._Buffered "buffered *" "&PyBufferedIOBase_Type"
-class _io.BufferedReader "buffered *" "&PyBufferedReader_Type"
-class _io.BufferedWriter "buffered *" "&PyBufferedWriter_Type"
-class _io.BufferedRWPair "rwpair *" "&PyBufferedRWPair_Type"
-class _io.BufferedRandom "buffered *" "&PyBufferedRandom_Type"
+class _io.BufferedReader "buffered *" "clinic_state()->PyBufferedReader_Type"
+class _io.BufferedWriter "buffered *" "clinic_state()->PyBufferedWriter_Type"
+class _io.BufferedRWPair "rwpair *" "clinic_state()->PyBufferedRWPair_Type"
+class _io.BufferedRandom "buffered *" "clinic_state()->PyBufferedRandom_Type"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=59460b9c5639984d]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=abd685b9d94b9888]*/
/*
* BufferedIOBase class, inherits from IOBase.
@@ -366,6 +366,7 @@ _enter_buffered_busy(buffered *self)
static void
buffered_dealloc(buffered *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
self->finalizing = 1;
if (_PyIOBase_finalize((PyObject *) self) < 0)
return;
@@ -383,7 +384,8 @@ buffered_dealloc(buffered *self)
self->lock = NULL;
}
Py_CLEAR(self->dict);
- Py_TYPE(self)->tp_free((PyObject *)self);
+ tp->tp_free((PyObject *)self);
+ Py_DECREF(tp);
}
static PyObject *
@@ -399,6 +401,7 @@ buffered_sizeof(buffered *self, PyObject *Py_UNUSED(ignored))
static int
buffered_traverse(buffered *self, visitproc visit, void *arg)
{
+ Py_VISIT(Py_TYPE(self));
Py_VISIT(self->raw);
Py_VISIT(self->dict);
return 0;
@@ -1328,9 +1331,11 @@ buffered_iternext(buffered *self)
CHECK_INITIALIZED(self);
+ _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
tp = Py_TYPE(self);
- if (tp == &PyBufferedReader_Type ||
- tp == &PyBufferedRandom_Type) {
+ if (Py_IS_TYPE(tp, state->PyBufferedReader_Type) ||
+ Py_IS_TYPE(tp, state->PyBufferedRandom_Type))
+ {
/* Skip method call overhead for speed */
line = _buffered_readline(self, -1);
}
@@ -1428,8 +1433,11 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw,
return -1;
_bufferedreader_reset_buf(self);
- self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedReader_Type) &&
- Py_IS_TYPE(raw, &PyFileIO_Type));
+ _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
+ self->fast_closed_checks = (
+ Py_IS_TYPE(self, state->PyBufferedReader_Type) &&
+ Py_IS_TYPE(raw, state->PyFileIO_Type)
+ );
self->ok = 1;
return 0;
@@ -1783,8 +1791,11 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
_bufferedwriter_reset_buf(self);
self->pos = 0;
- self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedWriter_Type) &&
- Py_IS_TYPE(raw, &PyFileIO_Type));
+ _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
+ self->fast_closed_checks = (
+ Py_IS_TYPE(self, state->PyBufferedWriter_Type) &&
+ Py_IS_TYPE(raw, state->PyFileIO_Type)
+ );
self->ok = 1;
return 0;
@@ -2090,13 +2101,16 @@ _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
if (_PyIOBase_check_writable(writer, Py_True) == NULL)
return -1;
+ _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
self->reader = (buffered *) PyObject_CallFunction(
- (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
+ (PyObject *)state->PyBufferedReader_Type,
+ "On", reader, buffer_size);
if (self->reader == NULL)
return -1;
self->writer = (buffered *) PyObject_CallFunction(
- (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
+ (PyObject *)state->PyBufferedWriter_Type,
+ "On", writer, buffer_size);
if (self->writer == NULL) {
Py_CLEAR(self->reader);
return -1;
@@ -2108,6 +2122,7 @@ _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
static int
bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
{
+ Py_VISIT(Py_TYPE(self));
Py_VISIT(self->dict);
return 0;
}
@@ -2124,13 +2139,15 @@ bufferedrwpair_clear(rwpair *self)
static void
bufferedrwpair_dealloc(rwpair *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
_PyObject_GC_UNTRACK(self);
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *)self);
Py_CLEAR(self->reader);
Py_CLEAR(self->writer);
Py_CLEAR(self->dict);
- Py_TYPE(self)->tp_free((PyObject *) self);
+ tp->tp_free((PyObject *) self);
+ Py_DECREF(tp);
}
static PyObject *
@@ -2295,14 +2312,17 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
_bufferedwriter_reset_buf(self);
self->pos = 0;
- self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedRandom_Type) &&
- Py_IS_TYPE(raw, &PyFileIO_Type));
+ _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
+ self->fast_closed_checks = (Py_IS_TYPE(self, state->PyBufferedRandom_Type) &&
+ Py_IS_TYPE(raw, state->PyFileIO_Type));
self->ok = 1;
return 0;
}
+#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
#include "clinic/bufferedio.c.h"
+#undef clinic_state
static PyMethodDef bufferediobase_methods[] = {
@@ -2394,6 +2414,8 @@ static PyMethodDef bufferedreader_methods[] = {
static PyMemberDef bufferedreader_members[] = {
{"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
{"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
+ {"__weaklistoffset__", T_PYSSIZET, offsetof(buffered, weakreflist), READONLY},
+ {"__dictoffset__", T_PYSSIZET, offsetof(buffered, dict), READONLY},
{NULL}
};
@@ -2405,58 +2427,27 @@ static PyGetSetDef bufferedreader_getset[] = {
};
-PyTypeObject PyBufferedReader_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.BufferedReader", /*tp_name*/
- sizeof(buffered), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)buffered_dealloc, /*tp_dealloc*/
- 0, /*tp_vectorcall_offset*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_as_async*/
- (reprfunc)buffered_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 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*/
- _io_BufferedReader___init____doc__, /* tp_doc */
- (traverseproc)buffered_traverse, /* tp_traverse */
- (inquiry)buffered_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
- 0, /* tp_iter */
- (iternextfunc)buffered_iternext, /* tp_iternext */
- bufferedreader_methods, /* tp_methods */
- bufferedreader_members, /* tp_members */
- bufferedreader_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(buffered, dict), /* tp_dictoffset */
- _io_BufferedReader___init__, /* tp_init */
- 0, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
- 0, /* tp_version_tag */
- 0, /* tp_finalize */
+static PyType_Slot bufferedreader_slots[] = {
+ {Py_tp_dealloc, buffered_dealloc},
+ {Py_tp_repr, buffered_repr},
+ {Py_tp_doc, (void *)_io_BufferedReader___init____doc__},
+ {Py_tp_traverse, buffered_traverse},
+ {Py_tp_clear, buffered_clear},
+ {Py_tp_iternext, buffered_iternext},
+ {Py_tp_methods, bufferedreader_methods},
+ {Py_tp_members, bufferedreader_members},
+ {Py_tp_getset, bufferedreader_getset},
+ {Py_tp_init, _io_BufferedReader___init__},
+ {0, NULL},
};
+PyType_Spec bufferedreader_spec = {
+ .name = "_io.BufferedReader",
+ .basicsize = sizeof(buffered),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = bufferedreader_slots,
+};
static PyMethodDef bufferedwriter_methods[] = {
/* BufferedIOMixin methods */
@@ -2480,6 +2471,8 @@ static PyMethodDef bufferedwriter_methods[] = {
static PyMemberDef bufferedwriter_members[] = {
{"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
{"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
+ {"__weaklistoffset__", T_PYSSIZET, offsetof(buffered, weakreflist), READONLY},
+ {"__dictoffset__", T_PYSSIZET, offsetof(buffered, dict), READONLY},
{NULL}
};
@@ -2491,58 +2484,26 @@ static PyGetSetDef bufferedwriter_getset[] = {
};
-PyTypeObject PyBufferedWriter_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.BufferedWriter", /*tp_name*/
- sizeof(buffered), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)buffered_dealloc, /*tp_dealloc*/
- 0, /*tp_vectorcall_offset*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_as_async*/
- (reprfunc)buffered_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 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*/
- _io_BufferedWriter___init____doc__, /* tp_doc */
- (traverseproc)buffered_traverse, /* tp_traverse */
- (inquiry)buffered_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
- 0, /* tp_iter */
- 0, /* tp_iternext */
- bufferedwriter_methods, /* tp_methods */
- bufferedwriter_members, /* tp_members */
- bufferedwriter_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(buffered, dict), /* tp_dictoffset */
- _io_BufferedWriter___init__, /* tp_init */
- 0, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
- 0, /* tp_version_tag */
- 0, /* tp_finalize */
+static PyType_Slot bufferedwriter_slots[] = {
+ {Py_tp_dealloc, buffered_dealloc},
+ {Py_tp_repr, buffered_repr},
+ {Py_tp_doc, (void *)_io_BufferedWriter___init____doc__},
+ {Py_tp_traverse, buffered_traverse},
+ {Py_tp_clear, buffered_clear},
+ {Py_tp_methods, bufferedwriter_methods},
+ {Py_tp_members, bufferedwriter_members},
+ {Py_tp_getset, bufferedwriter_getset},
+ {Py_tp_init, _io_BufferedWriter___init__},
+ {0, NULL},
};
+PyType_Spec bufferedwriter_spec = {
+ .name = "_io.BufferedWriter",
+ .basicsize = sizeof(buffered),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = bufferedwriter_slots,
+};
static PyMethodDef bufferedrwpair_methods[] = {
{"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
@@ -2563,61 +2524,35 @@ static PyMethodDef bufferedrwpair_methods[] = {
{NULL, NULL}
};
+static PyMemberDef bufferedrwpair_members[] = {
+ {"__weaklistoffset__", T_PYSSIZET, offsetof(rwpair, weakreflist), READONLY},
+ {"__dictoffset__", T_PYSSIZET, offsetof(rwpair, dict), READONLY},
+ {NULL}
+};
+
static PyGetSetDef bufferedrwpair_getset[] = {
{"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
{NULL}
};
-PyTypeObject PyBufferedRWPair_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.BufferedRWPair", /*tp_name*/
- sizeof(rwpair), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/
- 0, /*tp_vectorcall_offset*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_as_async*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 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 */
- _io_BufferedRWPair___init____doc__, /* tp_doc */
- (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
- (inquiry)bufferedrwpair_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
- 0, /* tp_iter */
- 0, /* tp_iternext */
- bufferedrwpair_methods, /* tp_methods */
- 0, /* tp_members */
- bufferedrwpair_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(rwpair, dict), /* tp_dictoffset */
- _io_BufferedRWPair___init__, /* tp_init */
- 0, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
- 0, /* tp_version_tag */
- 0, /* tp_finalize */
+static PyType_Slot bufferedrwpair_slots[] = {
+ {Py_tp_dealloc, bufferedrwpair_dealloc},
+ {Py_tp_doc, (void *)_io_BufferedRWPair___init____doc__},
+ {Py_tp_traverse, bufferedrwpair_traverse},
+ {Py_tp_clear, bufferedrwpair_clear},
+ {Py_tp_methods, bufferedrwpair_methods},
+ {Py_tp_members, bufferedrwpair_members},
+ {Py_tp_getset, bufferedrwpair_getset},
+ {Py_tp_init, _io_BufferedRWPair___init__},
+ {0, NULL},
+};
+
+PyType_Spec bufferedrwpair_spec = {
+ .name = "_io.BufferedRWPair",
+ .basicsize = sizeof(rwpair),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = bufferedrwpair_slots,
};
@@ -2651,6 +2586,8 @@ static PyMethodDef bufferedrandom_methods[] = {
static PyMemberDef bufferedrandom_members[] = {
{"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
{"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
+ {"__weaklistoffset__", T_PYSSIZET, offsetof(buffered, weakreflist), READONLY},
+ {"__dictoffset__", T_PYSSIZET, offsetof(buffered, dict), READONLY},
{NULL}
};
@@ -2662,54 +2599,24 @@ static PyGetSetDef bufferedrandom_getset[] = {
};
-PyTypeObject PyBufferedRandom_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.BufferedRandom", /*tp_name*/
- sizeof(buffered), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)buffered_dealloc, /*tp_dealloc*/
- 0, /*tp_vectorcall_offset*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_as_async*/
- (reprfunc)buffered_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 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*/
- _io_BufferedRandom___init____doc__, /* tp_doc */
- (traverseproc)buffered_traverse, /* tp_traverse */
- (inquiry)buffered_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
- 0, /* tp_iter */
- (iternextfunc)buffered_iternext, /* tp_iternext */
- bufferedrandom_methods, /* tp_methods */
- bufferedrandom_members, /* tp_members */
- bufferedrandom_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /*tp_dict*/
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(buffered, dict), /*tp_dictoffset*/
- _io_BufferedRandom___init__, /* tp_init */
- 0, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
- 0, /* tp_version_tag */
- 0, /* tp_finalize */
+static PyType_Slot bufferedrandom_slots[] = {
+ {Py_tp_dealloc, buffered_dealloc},
+ {Py_tp_repr, buffered_repr},
+ {Py_tp_doc, (void *)_io_BufferedRandom___init____doc__},
+ {Py_tp_traverse, buffered_traverse},
+ {Py_tp_clear, buffered_clear},
+ {Py_tp_iternext, buffered_iternext},
+ {Py_tp_methods, bufferedrandom_methods},
+ {Py_tp_members, bufferedrandom_members},
+ {Py_tp_getset, bufferedrandom_getset},
+ {Py_tp_init, _io_BufferedRandom___init__},
+ {0, NULL},
+};
+
+PyType_Spec bufferedrandom_spec = {
+ .name = "_io.BufferedRandom",
+ .basicsize = sizeof(buffered),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = bufferedrandom_slots,
};
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 6698c60..7e9d28b 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -5,9 +5,9 @@
/*[clinic input]
module _io
-class _io.BytesIO "bytesio *" "&PyBytesIO_Type"
+class _io.BytesIO "bytesio *" "clinic_state()->PyBytesIO_Type"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7f50ec034f5c0b26]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=48ede2f330f847c3]*/
typedef struct {
PyObject_HEAD
@@ -881,6 +881,7 @@ bytesio_setstate(bytesio *self, PyObject *state)
static void
bytesio_dealloc(bytesio *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
_PyObject_GC_UNTRACK(self);
if (self->exports > 0) {
PyErr_SetString(PyExc_SystemError,
@@ -891,7 +892,8 @@ bytesio_dealloc(bytesio *self)
Py_CLEAR(self->dict);
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
- Py_TYPE(self)->tp_free(self);
+ tp->tp_free(self);
+ Py_DECREF(tp);
}
static PyObject *
@@ -971,6 +973,7 @@ bytesio_sizeof(bytesio *self, void *unused)
static int
bytesio_traverse(bytesio *self, visitproc visit, void *arg)
{
+ Py_VISIT(Py_TYPE(self));
Py_VISIT(self->dict);
return 0;
}
@@ -983,7 +986,9 @@ bytesio_clear(bytesio *self)
}
+#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
#include "clinic/bytesio.c.h"
+#undef clinic_state
static PyGetSetDef bytesio_getsetlist[] = {
{"closed", (getter)bytesio_get_closed, NULL,
@@ -1016,48 +1021,34 @@ static struct PyMethodDef bytesio_methods[] = {
{NULL, NULL} /* sentinel */
};
-PyTypeObject PyBytesIO_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.BytesIO", /*tp_name*/
- sizeof(bytesio), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)bytesio_dealloc, /*tp_dealloc*/
- 0, /*tp_vectorcall_offset*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_as_async*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 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*/
- _io_BytesIO___init____doc__, /*tp_doc*/
- (traverseproc)bytesio_traverse, /*tp_traverse*/
- (inquiry)bytesio_clear, /*tp_clear*/
- 0, /*tp_richcompare*/
- offsetof(bytesio, weakreflist), /*tp_weaklistoffset*/
- PyObject_SelfIter, /*tp_iter*/
- (iternextfunc)bytesio_iternext, /*tp_iternext*/
- bytesio_methods, /*tp_methods*/
- 0, /*tp_members*/
- bytesio_getsetlist, /*tp_getset*/
- 0, /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- offsetof(bytesio, dict), /*tp_dictoffset*/
- _io_BytesIO___init__, /*tp_init*/
- 0, /*tp_alloc*/
- bytesio_new, /*tp_new*/
+static PyMemberDef bytesio_members[] = {
+ {"__weaklistoffset__", T_PYSSIZET, offsetof(bytesio, weakreflist), READONLY},
+ {"__dictoffset__", T_PYSSIZET, offsetof(bytesio, dict), READONLY},
+ {NULL}
};
+static PyType_Slot bytesio_slots[] = {
+ {Py_tp_dealloc, bytesio_dealloc},
+ {Py_tp_doc, (void *)_io_BytesIO___init____doc__},
+ {Py_tp_traverse, bytesio_traverse},
+ {Py_tp_clear, bytesio_clear},
+ {Py_tp_iter, PyObject_SelfIter},
+ {Py_tp_iternext, bytesio_iternext},
+ {Py_tp_methods, bytesio_methods},
+ {Py_tp_members, bytesio_members},
+ {Py_tp_getset, bytesio_getsetlist},
+ {Py_tp_init, _io_BytesIO___init__},
+ {Py_tp_new, bytesio_new},
+ {0, NULL},
+};
+
+PyType_Spec bytesio_spec = {
+ .name = "_io.BytesIO",
+ .basicsize = sizeof(bytesio),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = bytesio_slots,
+};
/*
* Implementation of the small intermediate object used by getbuffer().
diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h
index 38ea756..d44321b 100644
--- a/Modules/_io/clinic/bufferedio.c.h
+++ b/Modules/_io/clinic/bufferedio.c.h
@@ -601,7 +601,7 @@ static int
_io_BufferedRWPair___init__(PyObject *self, PyObject *args, PyObject *kwargs)
{
int return_value = -1;
- PyTypeObject *base_tp = &PyBufferedRWPair_Type;
+ PyTypeObject *base_tp = clinic_state()->PyBufferedRWPair_Type;
PyObject *reader;
PyObject *writer;
Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
@@ -714,4 +714,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=953f1577e96e8d86 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=8412b10c04259bb8 input=a9049054013a1b77]*/
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index d1a183c..f424fb8 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -51,9 +51,9 @@
/*[clinic input]
module _io
-class _io.FileIO "fileio *" "&PyFileIO_Type"
+class _io.FileIO "fileio *" "clinic_state()->PyFileIO_Type"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1c77708b41fda70c]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ac25ec278f4d6703]*/
typedef struct {
PyObject_HEAD
@@ -70,9 +70,7 @@ typedef struct {
PyObject *dict;
} fileio;
-PyTypeObject PyFileIO_Type;
-
-#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type))
+#define PyFileIO_Check(state, op) (PyObject_TypeCheck((op), state->PyFileIO_Type))
/* Forward declarations */
static PyObject* portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_error);
@@ -242,7 +240,10 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
int fstat_result;
int async_err = 0;
- assert(PyFileIO_Check(self));
+#ifdef Py_DEBUG
+ _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
+ assert(PyFileIO_Check(state, self));
+#endif
if (self->fd >= 0) {
if (self->closefd) {
/* Have to close the existing file first. */
@@ -503,6 +504,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
static int
fileio_traverse(fileio *self, visitproc visit, void *arg)
{
+ Py_VISIT(Py_TYPE(self));
Py_VISIT(self->dict);
return 0;
}
@@ -517,6 +519,7 @@ fileio_clear(fileio *self)
static void
fileio_dealloc(fileio *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
self->finalizing = 1;
if (_PyIOBase_finalize((PyObject *) self) < 0)
return;
@@ -524,7 +527,8 @@ fileio_dealloc(fileio *self)
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
Py_CLEAR(self->dict);
- Py_TYPE(self)->tp_free((PyObject *)self);
+ tp->tp_free((PyObject *)self);
+ Py_DECREF(tp);
}
static PyObject *
@@ -1177,57 +1181,29 @@ static PyGetSetDef fileio_getsetlist[] = {
static PyMemberDef fileio_members[] = {
{"_blksize", T_UINT, offsetof(fileio, blksize), 0},
{"_finalizing", T_BOOL, offsetof(fileio, finalizing), 0},
+ {"__weaklistoffset__", T_PYSSIZET, offsetof(fileio, weakreflist), READONLY},
+ {"__dictoffset__", T_PYSSIZET, offsetof(fileio, dict), READONLY},
{NULL}
};
-PyTypeObject PyFileIO_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.FileIO",
- sizeof(fileio),
- 0,
- (destructor)fileio_dealloc, /* tp_dealloc */
- 0, /* tp_vectorcall_offset */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_as_async */
- (reprfunc)fileio_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
- | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- _io_FileIO___init____doc__, /* tp_doc */
- (traverseproc)fileio_traverse, /* tp_traverse */
- (inquiry)fileio_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(fileio, weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- fileio_methods, /* tp_methods */
- fileio_members, /* tp_members */
- fileio_getsetlist, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(fileio, dict), /* tp_dictoffset */
- _io_FileIO___init__, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- fileio_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
- 0, /* tp_version_tag */
- 0, /* tp_finalize */
+static PyType_Slot fileio_slots[] = {
+ {Py_tp_dealloc, fileio_dealloc},
+ {Py_tp_repr, fileio_repr},
+ {Py_tp_doc, (void *)_io_FileIO___init____doc__},
+ {Py_tp_traverse, fileio_traverse},
+ {Py_tp_clear, fileio_clear},
+ {Py_tp_methods, fileio_methods},
+ {Py_tp_members, fileio_members},
+ {Py_tp_getset, fileio_getsetlist},
+ {Py_tp_init, _io_FileIO___init__},
+ {Py_tp_new, fileio_new},
+ {0, NULL},
+};
+
+PyType_Spec fileio_spec = {
+ .name = "_io.FileIO",
+ .basicsize = sizeof(fileio),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = fileio_slots,
};
diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c
index ae6c312..54c050f 100644
--- a/Modules/_io/stringio.c
+++ b/Modules/_io/stringio.c
@@ -13,9 +13,9 @@
/*[clinic input]
module _io
-class _io.StringIO "stringio *" "&PyStringIO_Type"
+class _io.StringIO "stringio *" "clinic_state()->PyStringIO_Type"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c17bc0f42165cd7d]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2693eada0658d470]*/
typedef struct {
PyObject_HEAD
@@ -43,6 +43,7 @@ typedef struct {
PyObject *dict;
PyObject *weakreflist;
+ _PyIO_State *module_state;
} stringio;
static int _io_StringIO___init__(PyObject *self, PyObject *args, PyObject *kwargs);
@@ -401,7 +402,7 @@ stringio_iternext(stringio *self)
CHECK_CLOSED(self);
ENSURE_REALIZED(self);
- if (Py_IS_TYPE(self, &PyStringIO_Type)) {
+ if (Py_IS_TYPE(self, self->module_state->PyStringIO_Type)) {
/* Skip method call overhead for speed */
line = _stringio_readline(self, -1);
}
@@ -581,6 +582,7 @@ _io_StringIO_close_impl(stringio *self)
static int
stringio_traverse(stringio *self, visitproc visit, void *arg)
{
+ Py_VISIT(Py_TYPE(self));
Py_VISIT(self->dict);
return 0;
}
@@ -595,6 +597,7 @@ stringio_clear(stringio *self)
static void
stringio_dealloc(stringio *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
_PyObject_GC_UNTRACK(self);
self->ok = 0;
if (self->buf) {
@@ -606,9 +609,11 @@ stringio_dealloc(stringio *self)
Py_CLEAR(self->writenl);
Py_CLEAR(self->decoder);
Py_CLEAR(self->dict);
- if (self->weakreflist != NULL)
+ if (self->weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject *) self);
- Py_TYPE(self)->tp_free(self);
+ }
+ tp->tp_free(self);
+ Py_DECREF(tp);
}
static PyObject *
@@ -745,7 +750,7 @@ _io_StringIO___init___impl(stringio *self, PyObject *value,
self->state = STATE_ACCUMULATING;
}
self->pos = 0;
-
+ self->module_state = find_io_state_by_def(Py_TYPE(self));
self->closed = 0;
self->ok = 1;
return 0;
@@ -963,7 +968,9 @@ stringio_newlines(stringio *self, void *context)
return PyObject_GetAttr(self->decoder, &_Py_ID(newlines));
}
+#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
#include "clinic/stringio.c.h"
+#undef clinic_state
static struct PyMethodDef stringio_methods[] = {
_IO_STRINGIO_CLOSE_METHODDEF
@@ -997,44 +1004,30 @@ static PyGetSetDef stringio_getset[] = {
{NULL}
};
-PyTypeObject PyStringIO_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.StringIO", /*tp_name*/
- sizeof(stringio), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)stringio_dealloc, /*tp_dealloc*/
- 0, /*tp_vectorcall_offset*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_as_async*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 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*/
- _io_StringIO___init____doc__, /*tp_doc*/
- (traverseproc)stringio_traverse, /*tp_traverse*/
- (inquiry)stringio_clear, /*tp_clear*/
- 0, /*tp_richcompare*/
- offsetof(stringio, weakreflist), /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- (iternextfunc)stringio_iternext, /*tp_iternext*/
- stringio_methods, /*tp_methods*/
- 0, /*tp_members*/
- stringio_getset, /*tp_getset*/
- 0, /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- offsetof(stringio, dict), /*tp_dictoffset*/
- _io_StringIO___init__, /*tp_init*/
- 0, /*tp_alloc*/
- stringio_new, /*tp_new*/
+static struct PyMemberDef stringio_members[] = {
+ {"__weaklistoffset__", T_PYSSIZET, offsetof(stringio, weakreflist), READONLY},
+ {"__dictoffset__", T_PYSSIZET, offsetof(stringio, dict), READONLY},
+ {NULL},
+};
+
+static PyType_Slot stringio_slots[] = {
+ {Py_tp_dealloc, stringio_dealloc},
+ {Py_tp_doc, (void *)_io_StringIO___init____doc__},
+ {Py_tp_traverse, stringio_traverse},
+ {Py_tp_clear, stringio_clear},
+ {Py_tp_iternext, stringio_iternext},
+ {Py_tp_methods, stringio_methods},
+ {Py_tp_members, stringio_members},
+ {Py_tp_getset, stringio_getset},
+ {Py_tp_init, _io_StringIO___init__},
+ {Py_tp_new, stringio_new},
+ {0, NULL},
+};
+
+PyType_Spec stringio_spec = {
+ .name = "_io.StringIO",
+ .basicsize = sizeof(stringio),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = stringio_slots,
};
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index ea2ea32..fbf0bf4 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -19,9 +19,9 @@
/*[clinic input]
module _io
class _io.IncrementalNewlineDecoder "nldecoder_object *" "&PyIncrementalNewlineDecoder_Type"
-class _io.TextIOWrapper "textio *" "&TextIOWrapper_Type"
+class _io.TextIOWrapper "textio *" "clinic_state()->TextIOWrapper_Type"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ed072384f8aada2c]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d3f032e90f74c8f2]*/
/* TextIOBase */
@@ -682,6 +682,8 @@ typedef struct
PyObject *weakreflist;
PyObject *dict;
+
+ _PyIO_State *state;
} textio;
static void
@@ -1175,15 +1177,16 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
/* Finished sorting out the codec details */
Py_CLEAR(codec_info);
- if (Py_IS_TYPE(buffer, &PyBufferedReader_Type) ||
- Py_IS_TYPE(buffer, &PyBufferedWriter_Type) ||
- Py_IS_TYPE(buffer, &PyBufferedRandom_Type))
+ _PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
+ if (Py_IS_TYPE(buffer, state->PyBufferedReader_Type) ||
+ Py_IS_TYPE(buffer, state->PyBufferedWriter_Type) ||
+ Py_IS_TYPE(buffer, state->PyBufferedRandom_Type))
{
if (_PyObject_LookupAttr(buffer, &_Py_ID(raw), &raw) < 0)
goto error;
/* Cache the raw FileIO object to speed up 'closed' checks */
if (raw != NULL) {
- if (Py_IS_TYPE(raw, &PyFileIO_Type))
+ if (Py_IS_TYPE(raw, state->PyFileIO_Type))
self->raw = raw;
else
Py_DECREF(raw);
@@ -1211,6 +1214,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
goto error;
}
+ self->state = state;
self->ok = 1;
return 0;
@@ -1387,6 +1391,7 @@ textiowrapper_clear(textio *self)
static void
textiowrapper_dealloc(textio *self)
{
+ PyTypeObject *tp = Py_TYPE(self);
self->finalizing = 1;
if (_PyIOBase_finalize((PyObject *) self) < 0)
return;
@@ -1395,12 +1400,14 @@ textiowrapper_dealloc(textio *self)
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *)self);
textiowrapper_clear(self);
- Py_TYPE(self)->tp_free((PyObject *)self);
+ tp->tp_free((PyObject *)self);
+ Py_DECREF(tp);
}
static int
textiowrapper_traverse(textio *self, visitproc visit, void *arg)
{
+ Py_VISIT(Py_TYPE(self));
Py_VISIT(self->buffer);
Py_VISIT(self->encoding);
Py_VISIT(self->encoder);
@@ -1424,7 +1431,7 @@ textiowrapper_closed_get(textio *self, void *context);
do { \
int r; \
PyObject *_res; \
- if (Py_IS_TYPE(self, &PyTextIOWrapper_Type)) { \
+ if (Py_IS_TYPE(self, self->state->PyTextIOWrapper_Type)) { \
if (self->raw != NULL) \
r = _PyFileIO_closed(self->raw); \
else { \
@@ -3053,7 +3060,7 @@ textiowrapper_iternext(textio *self)
CHECK_ATTACHED(self);
self->telling = 0;
- if (Py_IS_TYPE(self, &PyTextIOWrapper_Type)) {
+ if (Py_IS_TYPE(self, self->state->PyTextIOWrapper_Type)) {
/* Skip method call overhead for speed */
line = _textiowrapper_readline(self, -1);
}
@@ -3145,7 +3152,9 @@ textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context)
return 0;
}
+#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
#include "clinic/textio.c.h"
+#undef clinic_state
static PyMethodDef incrementalnewlinedecoder_methods[] = {
_IO_INCREMENTALNEWLINEDECODER_DECODE_METHODDEF
@@ -3229,6 +3238,8 @@ static PyMemberDef textiowrapper_members[] = {
{"line_buffering", T_BOOL, offsetof(textio, line_buffering), READONLY},
{"write_through", T_BOOL, offsetof(textio, write_through), READONLY},
{"_finalizing", T_BOOL, offsetof(textio, finalizing), 0},
+ {"__weaklistoffset__", T_PYSSIZET, offsetof(textio, weakreflist), READONLY},
+ {"__dictoffset__", T_PYSSIZET, offsetof(textio, dict), READONLY},
{NULL}
};
@@ -3244,54 +3255,24 @@ static PyGetSetDef textiowrapper_getset[] = {
{NULL}
};
-PyTypeObject PyTextIOWrapper_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_io.TextIOWrapper", /*tp_name*/
- sizeof(textio), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)textiowrapper_dealloc, /*tp_dealloc*/
- 0, /*tp_vectorcall_offset*/
- 0, /*tp_getattr*/
- 0, /*tps_etattr*/
- 0, /*tp_as_async*/
- (reprfunc)textiowrapper_repr,/*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 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*/
- _io_TextIOWrapper___init____doc__, /* tp_doc */
- (traverseproc)textiowrapper_traverse, /* tp_traverse */
- (inquiry)textiowrapper_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(textio, weakreflist), /*tp_weaklistoffset*/
- 0, /* tp_iter */
- (iternextfunc)textiowrapper_iternext, /* tp_iternext */
- textiowrapper_methods, /* tp_methods */
- textiowrapper_members, /* tp_members */
- textiowrapper_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(textio, dict), /*tp_dictoffset*/
- _io_TextIOWrapper___init__, /* tp_init */
- 0, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- 0, /* tp_del */
- 0, /* tp_version_tag */
- 0, /* tp_finalize */
+PyType_Slot textiowrapper_slots[] = {
+ {Py_tp_dealloc, textiowrapper_dealloc},
+ {Py_tp_repr, textiowrapper_repr},
+ {Py_tp_doc, (void *)_io_TextIOWrapper___init____doc__},
+ {Py_tp_traverse, textiowrapper_traverse},
+ {Py_tp_clear, textiowrapper_clear},
+ {Py_tp_iternext, textiowrapper_iternext},
+ {Py_tp_methods, textiowrapper_methods},
+ {Py_tp_members, textiowrapper_members},
+ {Py_tp_getset, textiowrapper_getset},
+ {Py_tp_init, _io_TextIOWrapper___init__},
+ {0, NULL},
+};
+
+PyType_Spec textiowrapper_spec = {
+ .name = "_io.TextIOWrapper",
+ .basicsize = sizeof(textio),
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = textiowrapper_slots,
};