gh-101819: Isolate _io (#101948)

Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
Erlend E. Aasland 2023-05-15 11:26:27 +02:00 committed by GitHub
parent 35bf0916d9
commit 186bf39f5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 208 additions and 365 deletions

View file

@ -4242,6 +4242,7 @@ def test_warn_on_dealloc_fd(self):
def test_pickling(self):
# Pickling file objects is forbidden
msg = "cannot pickle"
for kwargs in [
{"mode": "w"},
{"mode": "wb"},
@ -4256,8 +4257,10 @@ def test_pickling(self):
if "b" not in kwargs["mode"]:
kwargs["encoding"] = "utf-8"
for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
with self.open(os_helper.TESTFN, **kwargs) as f:
self.assertRaises(TypeError, pickle.dumps, f, protocol)
with self.subTest(protocol=protocol, kwargs=kwargs):
with self.open(os_helper.TESTFN, **kwargs) as f:
with self.assertRaisesRegex(TypeError, msg):
pickle.dumps(f, protocol)
@unittest.skipIf(
support.is_emscripten, "fstat() of a pipe fd is not supported"

View file

@ -0,0 +1,2 @@
Isolate the :mod:`io` extension module by applying :pep:`687`. Patch by
Kumar Aditya, Victor Stinner, and Erlend E. Aasland.

View file

@ -561,25 +561,9 @@ PyNumber_AsOff_t(PyObject *item, PyObject *err)
return result;
}
_PyIO_State *
_PyIO_get_module_state(void)
{
PyObject *mod = PyState_FindModule(&_PyIO_Module);
_PyIO_State *state;
if (mod == NULL || (state = get_io_state(mod)) == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"could not find io module state "
"(interpreter shutdown?)");
return NULL;
}
return state;
}
static int
iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
_PyIO_State *state = get_io_state(mod);
if (!state->initialized)
return 0;
Py_VISIT(state->unsupported_operation);
Py_VISIT(state->PyIOBase_Type);
@ -606,8 +590,6 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) {
static int
iomodule_clear(PyObject *mod) {
_PyIO_State *state = get_io_state(mod);
if (!state->initialized)
return 0;
Py_CLEAR(state->unsupported_operation);
Py_CLEAR(state->PyIOBase_Type);
@ -652,115 +634,57 @@ static PyMethodDef module_methods[] = {
{NULL, NULL}
};
struct PyModuleDef _PyIO_Module = {
PyModuleDef_HEAD_INIT,
"io",
module_doc,
sizeof(_PyIO_State),
module_methods,
NULL,
iomodule_traverse,
iomodule_clear,
(freefunc)iomodule_free,
};
static PyTypeObject* static_types[] = {
// Base classes
&PyIOBase_Type,
// PyIOBase_Type subclasses
&PyBufferedIOBase_Type,
&PyRawIOBase_Type,
&PyTextIOBase_Type,
};
PyStatus
_PyIO_InitTypes(PyInterpreterState *interp)
{
for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
PyTypeObject *type = static_types[i];
if (_PyStaticType_InitBuiltin(interp, type) < 0) {
return _PyStatus_ERR("Can't initialize builtin type");
}
}
return _PyStatus_OK();
}
void
_PyIO_FiniTypes(PyInterpreterState *interp)
{
// Deallocate types in the reverse order to deallocate subclasses before
// their base classes.
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types) - 1; i >= 0; i--) {
PyTypeObject *type = static_types[i];
_PyStaticType_Dealloc(interp, type);
}
}
#define ADD_TYPE(module, type, spec, base) \
do { \
type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \
(PyObject *)base); \
if (type == NULL) { \
goto fail; \
return -1; \
} \
if (PyModule_AddType(module, type) < 0) { \
goto fail; \
return -1; \
} \
} while (0)
PyMODINIT_FUNC
PyInit__io(void)
static int
iomodule_exec(PyObject *m)
{
PyObject *m = PyModule_Create(&_PyIO_Module);
_PyIO_State *state = NULL;
if (m == NULL)
return NULL;
state = get_io_state(m);
state->initialized = 0;
_PyIO_State *state = get_io_state(m);
/* DEFAULT_BUFFER_SIZE */
if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0)
goto fail;
return -1;
/* UnsupportedOperation inherits from ValueError and OSError */
state->unsupported_operation = PyObject_CallFunction(
(PyObject *)&PyType_Type, "s(OO){}",
"UnsupportedOperation", PyExc_OSError, PyExc_ValueError);
if (state->unsupported_operation == NULL)
goto fail;
return -1;
if (PyModule_AddObjectRef(m, "UnsupportedOperation",
state->unsupported_operation) < 0)
{
goto fail;
return -1;
}
/* BlockingIOError, for compatibility */
if (PyModule_AddObjectRef(m, "BlockingIOError",
(PyObject *) PyExc_BlockingIOError) < 0) {
goto fail;
}
// Add types
for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
PyTypeObject *type = static_types[i];
if (PyModule_AddType(m, type) < 0) {
goto fail;
}
return -1;
}
// Base classes
state->PyIOBase_Type = (PyTypeObject *)Py_NewRef(&PyIOBase_Type);
ADD_TYPE(m, state->PyIncrementalNewlineDecoder_Type, &nldecoder_spec, NULL);
ADD_TYPE(m, state->PyBytesIOBuffer_Type, &bytesiobuf_spec, NULL);
ADD_TYPE(m, state->PyIOBase_Type, &iobase_spec, NULL);
// PyIOBase_Type subclasses
state->PyRawIOBase_Type = (PyTypeObject *)Py_NewRef(&PyRawIOBase_Type);
state->PyBufferedIOBase_Type = (PyTypeObject *)Py_NewRef(&PyBufferedIOBase_Type);
state->PyTextIOBase_Type = (PyTypeObject *)Py_NewRef(&PyTextIOBase_Type);
ADD_TYPE(m, state->PyTextIOBase_Type, &textiobase_spec,
state->PyIOBase_Type);
ADD_TYPE(m, state->PyBufferedIOBase_Type, &bufferediobase_spec,
state->PyIOBase_Type);
ADD_TYPE(m, state->PyRawIOBase_Type, &rawiobase_spec,
state->PyIOBase_Type);
// PyBufferedIOBase_Type(PyIOBase_Type) subclasses
ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, state->PyBufferedIOBase_Type);
@ -775,6 +699,7 @@ PyInit__io(void)
// PyRawIOBase_Type(PyIOBase_Type) subclasses
ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, state->PyRawIOBase_Type);
#ifdef HAVE_WINDOWS_CONSOLE_IO
ADD_TYPE(m, state->PyWindowsConsoleIO_Type, &winconsoleio_spec,
state->PyRawIOBase_Type);
@ -785,11 +710,30 @@ PyInit__io(void)
ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec,
state->PyTextIOBase_Type);
state->initialized = 1;
return m;
fail:
Py_DECREF(m);
return NULL;
#undef ADD_TYPE
return 0;
}
static struct PyModuleDef_Slot iomodule_slots[] = {
{Py_mod_exec, iomodule_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
{0, NULL},
};
struct PyModuleDef _PyIO_Module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "io",
.m_doc = module_doc,
.m_size = sizeof(_PyIO_State),
.m_methods = module_methods,
.m_traverse = iomodule_traverse,
.m_clear = iomodule_clear,
.m_free = iomodule_free,
.m_slots = iomodule_slots,
};
PyMODINIT_FUNC
PyInit__io(void)
{
return PyModuleDef_Init(&_PyIO_Module);
}

View file

@ -8,13 +8,8 @@
#include "pycore_typeobject.h" // _PyType_GetModuleState()
#include "structmember.h"
/* ABCs */
extern PyTypeObject PyIOBase_Type;
extern PyTypeObject PyRawIOBase_Type;
extern PyTypeObject PyBufferedIOBase_Type;
extern PyTypeObject PyTextIOBase_Type;
/* Type specs */
extern PyType_Spec bufferediobase_spec;
extern PyType_Spec bufferedrandom_spec;
extern PyType_Spec bufferedreader_spec;
extern PyType_Spec bufferedrwpair_spec;
@ -22,8 +17,11 @@ extern PyType_Spec bufferedwriter_spec;
extern PyType_Spec bytesio_spec;
extern PyType_Spec bytesiobuf_spec;
extern PyType_Spec fileio_spec;
extern PyType_Spec iobase_spec;
extern PyType_Spec nldecoder_spec;
extern PyType_Spec rawiobase_spec;
extern PyType_Spec stringio_spec;
extern PyType_Spec textiobase_spec;
extern PyType_Spec textiowrapper_spec;
#ifdef HAVE_WINDOWS_CONSOLE_IO
@ -168,9 +166,6 @@ struct _io_state {
#endif
};
#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)
{
@ -195,7 +190,7 @@ find_io_state_by_def(PyTypeObject *type)
return get_io_state(mod);
}
extern _PyIO_State *_PyIO_get_module_state(void);
extern PyObject *_PyIOBase_cannot_pickle(PyObject *self, PyObject *args);
#ifdef HAVE_WINDOWS_CONSOLE_IO
extern char _PyIO_get_console_type(PyObject *);

View file

@ -16,14 +16,14 @@
/*[clinic input]
module _io
class _io._BufferedIOBase "PyObject *" "&PyBufferedIOBase_Type"
class _io._Buffered "buffered *" "&PyBufferedIOBase_Type"
class _io._BufferedIOBase "PyObject *" "clinic_state()->PyBufferedIOBase_Type"
class _io._Buffered "buffered *" "clinic_state()->PyBufferedIOBase_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=abd685b9d94b9888]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3b3ef9cbbbad4590]*/
/*
* BufferedIOBase class, inherits from IOBase.
@ -128,7 +128,7 @@ static PyObject *
_io__BufferedIOBase_detach_impl(PyObject *self, PyTypeObject *cls)
/*[clinic end generated code: output=b87b135d67cd4448 input=0b61a7b4357c1ea7]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return bufferediobase_unsupported(state, "detach");
}
@ -162,7 +162,7 @@ _io__BufferedIOBase_read_impl(PyObject *self, PyTypeObject *cls,
PyObject *args)
/*[clinic end generated code: output=4521b30940fd7b67 input=390205758adc8510]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return bufferediobase_unsupported(state, "read");
}
@ -184,7 +184,7 @@ _io__BufferedIOBase_read1_impl(PyObject *self, PyTypeObject *cls,
PyObject *args)
/*[clinic end generated code: output=636fd241c21e050a input=ef546a1238c5b41c]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return bufferediobase_unsupported(state, "read1");
}
@ -209,7 +209,7 @@ _io__BufferedIOBase_write_impl(PyObject *self, PyTypeObject *cls,
PyObject *args)
/*[clinic end generated code: output=d51feea4bcac9892 input=f79b72c4dccb3dc2]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return bufferediobase_unsupported(state, "write");
}
@ -394,6 +394,15 @@ _enter_buffered_busy(buffered *self)
(self->buffer_size * (size / self->buffer_size)))
static int
buffered_clear(buffered *self)
{
self->ok = 0;
Py_CLEAR(self->raw);
Py_CLEAR(self->dict);
return 0;
}
static void
buffered_dealloc(buffered *self)
{
@ -405,7 +414,6 @@ buffered_dealloc(buffered *self)
self->ok = 0;
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *)self);
Py_CLEAR(self->raw);
if (self->buffer) {
PyMem_Free(self->buffer);
self->buffer = NULL;
@ -414,7 +422,7 @@ buffered_dealloc(buffered *self)
PyThread_free_lock(self->lock);
self->lock = NULL;
}
Py_CLEAR(self->dict);
(void)buffered_clear(self);
tp->tp_free((PyObject *)self);
Py_DECREF(tp);
}
@ -443,15 +451,6 @@ buffered_traverse(buffered *self, visitproc visit, void *arg)
return 0;
}
static int
buffered_clear(buffered *self)
{
self->ok = 0;
Py_CLEAR(self->raw);
Py_CLEAR(self->dict);
return 0;
}
/* Because this can call arbitrary code, it shouldn't be called when
the refcount is 0 (that is, not directly from tp_dealloc unless
the refcount has been temporarily re-incremented). */
@ -2220,6 +2219,8 @@ bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->dict);
Py_VISIT(self->reader);
Py_VISIT(self->writer);
return 0;
}
@ -2239,9 +2240,7 @@ bufferedrwpair_dealloc(rwpair *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);
(void)bufferedrwpair_clear(self);
tp->tp_free((PyObject *) self);
Py_DECREF(tp);
}
@ -2424,6 +2423,12 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
#include "clinic/bufferedio.c.h"
#undef clinic_state
static int
bufferediobase_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
return 0;
}
static PyMethodDef bufferediobase_methods[] = {
_IO__BUFFEREDIOBASE_DETACH_METHODDEF
@ -2435,57 +2440,19 @@ static PyMethodDef bufferediobase_methods[] = {
{NULL, NULL}
};
PyTypeObject PyBufferedIOBase_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_io._BufferedIOBase", /*tp_name*/
0, /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*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, /*tp_flags*/
bufferediobase_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
bufferediobase_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PyIOBase_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* 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 bufferediobase_slots[] = {
{Py_tp_doc, (void *)bufferediobase_doc},
{Py_tp_methods, bufferediobase_methods},
{Py_tp_traverse, bufferediobase_traverse},
{0, NULL},
};
PyType_Spec bufferediobase_spec = {
.name = "_io._BufferedIOBase",
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = bufferediobase_slots,
};
static PyMethodDef bufferedreader_methods[] = {
/* BufferedIOMixin methods */
@ -2508,6 +2475,9 @@ static PyMethodDef bufferedreader_methods[] = {
_IO__BUFFERED_TELL_METHODDEF
_IO__BUFFERED_TRUNCATE_METHODDEF
_IO__BUFFERED___SIZEOF___METHODDEF
{"__reduce__", _PyIOBase_cannot_pickle, METH_VARARGS},
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_VARARGS},
{NULL, NULL}
};
@ -2565,6 +2535,9 @@ static PyMethodDef bufferedwriter_methods[] = {
_IO__BUFFERED_SEEK_METHODDEF
_IO__BUFFERED_TELL_METHODDEF
_IO__BUFFERED___SIZEOF___METHODDEF
{"__reduce__", _PyIOBase_cannot_pickle, METH_VARARGS},
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_VARARGS},
{NULL, NULL}
};
@ -2680,6 +2653,9 @@ static PyMethodDef bufferedrandom_methods[] = {
_IO__BUFFERED_PEEK_METHODDEF
_IO_BUFFEREDWRITER_WRITE_METHODDEF
_IO__BUFFERED___SIZEOF___METHODDEF
{"__reduce__", _PyIOBase_cannot_pickle, METH_VARARGS},
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_VARARGS},
{NULL, NULL}
};

View file

@ -979,6 +979,7 @@ bytesio_traverse(bytesio *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->dict);
Py_VISIT(self->buf);
return 0;
}
@ -986,6 +987,7 @@ static int
bytesio_clear(bytesio *self)
{
Py_CLEAR(self->dict);
Py_CLEAR(self->buf);
return 0;
}

View file

@ -536,7 +536,7 @@ fileio_dealloc(fileio *self)
_PyObject_GC_UNTRACK(self);
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
Py_CLEAR(self->dict);
(void)fileio_clear(self);
tp->tp_free((PyObject *)self);
Py_DECREF(tp);
}
@ -1166,6 +1166,8 @@ static PyMethodDef fileio_methods[] = {
_IO_FILEIO_FILENO_METHODDEF
_IO_FILEIO_ISATTY_METHODDEF
{"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL},
{"__reduce__", _PyIOBase_cannot_pickle, METH_VARARGS},
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_VARARGS},
{NULL, NULL} /* sentinel */
};

View file

@ -17,10 +17,10 @@
/*[clinic input]
module _io
class _io._IOBase "PyObject *" "&PyIOBase_Type"
class _io._RawIOBase "PyObject *" "&PyRawIOBase_Type"
class _io._IOBase "PyObject *" "clinic_state()->PyIOBase_Type"
class _io._RawIOBase "PyObject *" "clinic_state()->PyRawIOBase_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d29a4d076c2b211c]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9006b7802ab8ea85]*/
/*
* IOBase class, an abstract class
@ -101,7 +101,7 @@ static PyObject *
_io__IOBase_seek_impl(PyObject *self, PyTypeObject *cls, PyObject *args)
/*[clinic end generated code: output=1dd694ac9de260fa input=ebb5476eb22fc5d4]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return iobase_unsupported(state, "seek");
}
@ -134,7 +134,7 @@ static PyObject *
_io__IOBase_truncate_impl(PyObject *self, PyTypeObject *cls, PyObject *args)
/*[clinic end generated code: output=b7eed4649cbe22c1 input=ad90582a1d8b5cc9]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return iobase_unsupported(state, "truncate");
}
@ -220,24 +220,32 @@ _PyIOBase_check_closed(PyObject *self, PyObject *args)
static PyObject *
iobase_check_seekable(PyObject *self, PyObject *args)
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
return _PyIOBase_check_seekable(state, self, args);
}
static PyObject *
iobase_check_readable(PyObject *self, PyObject *args)
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
return _PyIOBase_check_readable(state, self, args);
}
static PyObject *
iobase_check_writable(PyObject *self, PyObject *args)
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
return _PyIOBase_check_writable(state, self, args);
}
PyObject *
_PyIOBase_cannot_pickle(PyObject *self, PyObject *args)
{
PyErr_Format(PyExc_TypeError,
"cannot pickle '%.100s' instances", _PyType_Name(Py_TYPE(self)));
return NULL;
}
/* XXX: IOBase thinks it has to maintain its own internal state in
`__IOBase_closed` and call flush() by itself, but it is redundant with
whatever behaviour a non-trivial derived class will implement. */
@ -351,6 +359,7 @@ _PyIOBase_finalize(PyObject *self)
static int
iobase_traverse(iobase *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->dict);
return 0;
}
@ -380,11 +389,13 @@ iobase_dealloc(iobase *self)
}
return;
}
PyTypeObject *tp = Py_TYPE(self);
_PyObject_GC_UNTRACK(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);
}
/* Inquiry methods */
@ -523,7 +534,7 @@ static PyObject *
_io__IOBase_fileno_impl(PyObject *self, PyTypeObject *cls)
/*[clinic end generated code: output=7caaa32a6f4ada3d input=1927c8bea5c85099]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return iobase_unsupported(state, "fileno");
}
@ -821,7 +832,9 @@ _io__IOBase_writelines(PyObject *self, PyObject *lines)
Py_RETURN_NONE;
}
#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
#include "clinic/iobase.c.h"
#undef clinic_state
static PyMethodDef iobase_methods[] = {
_IO__IOBASE_SEEK_METHODDEF
@ -858,60 +871,35 @@ static PyGetSetDef iobase_getset[] = {
{NULL}
};
PyTypeObject PyIOBase_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_io._IOBase", /*tp_name*/
sizeof(iobase), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)iobase_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*/
iobase_doc, /* tp_doc */
(traverseproc)iobase_traverse, /* tp_traverse */
(inquiry)iobase_clear, /* tp_clear */
0, /* tp_richcompare */
offsetof(iobase, weakreflist), /* tp_weaklistoffset */
iobase_iter, /* tp_iter */
iobase_iternext, /* tp_iternext */
iobase_methods, /* tp_methods */
0, /* tp_members */
iobase_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(iobase, dict), /* tp_dictoffset */
0, /* 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 */
iobase_finalize, /* tp_finalize */
static struct PyMemberDef iobase_members[] = {
{"__weaklistoffset__", T_PYSSIZET, offsetof(iobase, weakreflist), READONLY},
{"__dictoffset__", T_PYSSIZET, offsetof(iobase, dict), READONLY},
{NULL},
};
static PyType_Slot iobase_slots[] = {
{Py_tp_dealloc, iobase_dealloc},
{Py_tp_doc, (void *)iobase_doc},
{Py_tp_traverse, iobase_traverse},
{Py_tp_clear, iobase_clear},
{Py_tp_iter, iobase_iter},
{Py_tp_iternext, iobase_iternext},
{Py_tp_methods, iobase_methods},
{Py_tp_members, iobase_members},
{Py_tp_getset, iobase_getset},
{Py_tp_finalize, iobase_finalize},
{0, NULL},
};
PyType_Spec iobase_spec = {
.name = "_io._IOBase",
.basicsize = sizeof(iobase),
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = iobase_slots,
};
/*
* RawIOBase class, Inherits from IOBase.
*/
@ -1045,6 +1033,13 @@ rawiobase_write(PyObject *self, PyObject *args)
return NULL;
}
static int
rawiobase_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
return 0;
}
static PyMethodDef rawiobase_methods[] = {
_IO__RAWIOBASE_READ_METHODDEF
_IO__RAWIOBASE_READALL_METHODDEF
@ -1053,53 +1048,16 @@ static PyMethodDef rawiobase_methods[] = {
{NULL, NULL}
};
PyTypeObject PyRawIOBase_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_io._RawIOBase", /*tp_name*/
0, /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*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, /*tp_flags*/
rawiobase_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
rawiobase_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PyIOBase_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* 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 rawiobase_slots[] = {
{Py_tp_doc, (void *)rawiobase_doc},
{Py_tp_methods, rawiobase_methods},
{Py_tp_traverse, rawiobase_traverse},
{0, NULL},
};
PyType_Spec rawiobase_spec = {
.name = "_io._RawIOBase",
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = rawiobase_slots,
};

View file

@ -583,6 +583,9 @@ static int
stringio_traverse(stringio *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->readnl);
Py_VISIT(self->writenl);
Py_VISIT(self->decoder);
Py_VISIT(self->dict);
return 0;
}
@ -590,6 +593,9 @@ stringio_traverse(stringio *self, visitproc visit, void *arg)
static int
stringio_clear(stringio *self)
{
Py_CLEAR(self->readnl);
Py_CLEAR(self->writenl);
Py_CLEAR(self->decoder);
Py_CLEAR(self->dict);
return 0;
}
@ -605,10 +611,7 @@ stringio_dealloc(stringio *self)
self->buf = NULL;
}
_PyUnicodeWriter_Dealloc(&self->writer);
Py_CLEAR(self->readnl);
Py_CLEAR(self->writenl);
Py_CLEAR(self->decoder);
Py_CLEAR(self->dict);
(void)stringio_clear(self);
if (self->weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject *) self);
}

View file

@ -62,7 +62,7 @@ static PyObject *
_io__TextIOBase_detach_impl(PyObject *self, PyTypeObject *cls)
/*[clinic end generated code: output=50915f40c609eaa4 input=987ca3640d0a3776]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return _unsupported(state, "detach");
}
@ -82,7 +82,7 @@ static PyObject *
_io__TextIOBase_read_impl(PyObject *self, PyTypeObject *cls, PyObject *args)
/*[clinic end generated code: output=3adf28998831f461 input=cee1e84664a20de0]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return _unsupported(state, "read");
}
@ -102,7 +102,7 @@ _io__TextIOBase_readline_impl(PyObject *self, PyTypeObject *cls,
PyObject *args)
/*[clinic end generated code: output=3073a948d02319f3 input=58f801259f7ff3ef]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return _unsupported(state, "readline");
}
@ -122,7 +122,7 @@ static PyObject *
_io__TextIOBase_write_impl(PyObject *self, PyTypeObject *cls, PyObject *args)
/*[clinic end generated code: output=5d985eb529472bc4 input=21b6961b5cba9496]*/
{
_PyIO_State *state = IO_STATE();
_PyIO_State *state = get_io_state_by_cls(cls);
return _unsupported(state, "write");
}
@ -164,6 +164,12 @@ textiobase_errors_get(PyObject *self, void *context)
Py_RETURN_NONE;
}
static int
textiobase_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
return 0;
}
static PyMethodDef textiobase_methods[] = {
_IO__TEXTIOBASE_DETACH_METHODDEF
@ -180,57 +186,20 @@ static PyGetSetDef textiobase_getset[] = {
{NULL}
};
PyTypeObject PyTextIOBase_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_io._TextIOBase", /*tp_name*/
0, /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*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, /*tp_flags*/
textiobase_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
textiobase_methods, /* tp_methods */
0, /* tp_members */
textiobase_getset, /* tp_getset */
&PyIOBase_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* 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 textiobase_slots[] = {
{Py_tp_doc, (void *)textiobase_doc},
{Py_tp_methods, textiobase_methods},
{Py_tp_getset, textiobase_getset},
{Py_tp_traverse, textiobase_traverse},
{0, NULL},
};
PyType_Spec textiobase_spec = {
.name = "_io._TextIOBase",
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = textiobase_slots,
};
/* IncrementalNewlineDecoder */
@ -1456,7 +1425,7 @@ textiowrapper_dealloc(textio *self)
_PyObject_GC_UNTRACK(self);
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *)self);
textiowrapper_clear(self);
(void)textiowrapper_clear(self);
tp->tp_free((PyObject *)self);
Py_DECREF(tp);
}
@ -3267,6 +3236,9 @@ static PyMethodDef textiowrapper_methods[] = {
_IO_TEXTIOWRAPPER_SEEK_METHODDEF
_IO_TEXTIOWRAPPER_TELL_METHODDEF
_IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF
{"__reduce__", _PyIOBase_cannot_pickle, METH_VARARGS},
{"__reduce_ex__", _PyIOBase_cannot_pickle, METH_VARARGS},
{NULL, NULL}
};

View file

@ -1096,7 +1096,7 @@ _io__WindowsConsoleIO_isatty_impl(winconsoleio *self)
Py_RETURN_TRUE;
}
#define clinic_state() (IO_STATE())
#define clinic_state() (find_io_state_by_def(Py_TYPE(self)))
#include "clinic/winconsoleio.c.h"
#undef clinic_state

View file

@ -29,9 +29,6 @@
#include "pycore_unicodeobject.h" // _PyUnicode_InitTypes()
#include "opcode.h"
extern PyStatus _PyIO_InitTypes(PyInterpreterState *interp);
extern void _PyIO_FiniTypes(PyInterpreterState *interp);
#include <locale.h> // setlocale()
#include <stdlib.h> // getenv()
@ -706,11 +703,6 @@ pycore_init_types(PyInterpreterState *interp)
return _PyStatus_ERR("failed to initialize an exception type");
}
status = _PyIO_InitTypes(interp);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
status = _PyExc_InitGlobalObjects(interp);
if (_PyStatus_EXCEPTION(status)) {
return status;
@ -1667,8 +1659,6 @@ flush_std_files(void)
static void
finalize_interp_types(PyInterpreterState *interp)
{
_PyIO_FiniTypes(interp);
_PyUnicode_FiniTypes(interp);
_PySys_FiniTypes(interp);
_PyExc_Fini(interp);

View file

@ -317,10 +317,6 @@ Python/instrumentation.c - _PyInstrumentation_MISSING -
##-----------------------
## static types
Modules/_io/bufferedio.c - PyBufferedIOBase_Type -
Modules/_io/iobase.c - PyIOBase_Type -
Modules/_io/iobase.c - PyRawIOBase_Type -
Modules/_io/textio.c - PyTextIOBase_Type -
Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type -
Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type -
Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type -

Can't render this file because it has a wrong number of fields in line 4.