From 6d0a37b18f696268f64209efce28e6a21b7a2a28 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 12 Feb 2023 22:48:03 +0100 Subject: [PATCH 01/54] Add tests --- Lib/test/test_io.py | 91 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index c5f2e5060a546d..45d5465b9dff99 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1042,6 +1042,95 @@ def close(self): support.gc_collect() self.assertIsNone(wr(), wr) +@support.cpython_only +class TestIOCTypes(unittest.TestCase): + def setUp(self): + _io = import_helper.import_module("_io") + self.types = ( + _io.BufferedRWPair, + _io.BufferedRandom, + _io.BufferedReader, + _io.BufferedWriter, + _io.BytesIO, + _io.FileIO, + _io.IncrementalNewlineDecoder, + _io.StringIO, + _io.TextIOWrapper, + _io._BufferedIOBase, + _io._BytesIOBuffer, + _io._IOBase, + _io._RawIOBase, + _io._TextIOBase, + ) + if sys.platform == "win32": + self.types.append(_io._WindowsConsoleIO) + self._io = _io + + def test_immutable_types(self): + for tp in self.types: + with self.subTest(tp=tp): + with self.assertRaisesRegex(TypeError, "immutable"): + tp.foo = "bar" + + def test_class_hierarchy(self): + def check_subs(types, base): + for tp in types: + with self.subTest(tp=tp, base=base): + self.assertTrue(issubclass(tp, base)) + + def recursive_check(d): + for k, v in d.items(): + if isinstance(v, dict): + recursive_check(v) + elif isinstance(v, set): + check_subs(v, k) + else: + self.fail("corrupt test dataset") + + _io = self._io + hierarchy = { + _io._IOBase: { + _io._BufferedIOBase: { + _io.BufferedRWPair, + _io.BufferedRandom, + _io.BufferedReader, + _io.BufferedWriter, + _io.BytesIO, + }, + _io._RawIOBase: { + _io.FileIO, + }, + _io._TextIOBase: { + _io.StringIO, + _io.TextIOWrapper, + }, + }, + } + if sys.platform == "win32": + hierarchy[_io._IOBase][_io._RawIOBase].add(_io._WindowsConsoleIO) + + recursive_check(hierarchy) + + def test_subclassing(self): + _io = self._io + dataset = {k: True for k in self.types} + dataset[_io._BytesIOBuffer] = False + + for tp, is_basetype in dataset.items(): + with self.subTest(tp=tp, is_basetype=is_basetype): + name = f"{tp.__name__}_subclass" + bases = (tp,) + if is_basetype: + _ = type(name, bases, {}) + else: + msg = "not an acceptable base type" + with self.assertRaisesRegex(TypeError, msg): + _ = type(name, bases, {}) + + def test_disallow_instantiation(self): + _io = self._io + support.check_disallow_instantiation(self, _io._BytesIOBuffer) + class PyIOTest(IOTest): pass @@ -4671,7 +4760,7 @@ def load_tests(loader, tests, pattern): CIncrementalNewlineDecoderTest, PyIncrementalNewlineDecoderTest, CTextIOWrapperTest, PyTextIOWrapperTest, CMiscIOTest, PyMiscIOTest, - CSignalsTest, PySignalsTest, + CSignalsTest, PySignalsTest, TestIOCTypes, ) # Put the namespaces of the IO module we are testing and some useful mock From bd19a20f18e048b368b6077de6964afe93564795 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 11 Feb 2023 09:42:23 +0100 Subject: [PATCH 02/54] StringIO type --- Modules/_io/_iomodule.c | 17 ++++- Modules/_io/_iomodule.h | 9 ++- Modules/_io/stringio.c | 83 ++++++++++----------- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 4 files changed, 61 insertions(+), 49 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 811b1d221a0122..4769b464432ece 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -612,7 +612,9 @@ iomodule_free(PyObject *mod) { * Module definition */ +#define clinic_state() (IO_STATE()) #include "clinic/_iomodule.c.h" +#undef clinic_state static PyMethodDef module_methods[] = { _IO_OPEN_METHODDEF @@ -659,7 +661,6 @@ static PyTypeObject* static_types[] = { #endif // PyTextIOBase_Type(PyIOBase_Type) subclasses - &PyStringIO_Type, &PyTextIOWrapper_Type, }; @@ -673,6 +674,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) @@ -707,7 +719,6 @@ 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 @@ -725,6 +736,8 @@ PyInit__io(void) } } + ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, &PyTextIOBase_Type); + state->initialized = 1; return m; diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 7617cb8fb70e43..517ba6bbb95ef2 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -4,6 +4,8 @@ #include "exports.h" +#include "structmember.h" + /* ABCs */ extern PyTypeObject PyIOBase_Type; extern PyTypeObject PyRawIOBase_Type; @@ -13,7 +15,6 @@ 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; @@ -21,6 +22,9 @@ extern PyTypeObject PyBufferedRandom_Type; extern PyTypeObject PyTextIOWrapper_Type; extern PyTypeObject PyIncrementalNewlineDecoder_Type; +/* Type specs */ +extern PyType_Spec stringio_spec; + #ifdef MS_WINDOWS extern PyTypeObject PyWindowsConsoleIO_Type; #endif /* MS_WINDOWS */ @@ -140,6 +144,9 @@ typedef struct { PyObject *locale_module; PyObject *unsupported_operation; + + /* Types */ + PyTypeObject *PyStringIO_Type; } _PyIO_State; #define IO_MOD_STATE(mod) ((_PyIO_State *)PyModule_GetState(mod)) diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index ae6c3125a2d9da..12ae5a09ca70a2 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 @@ -401,7 +401,8 @@ stringio_iternext(stringio *self) CHECK_CLOSED(self); ENSURE_REALIZED(self); - if (Py_IS_TYPE(self, &PyStringIO_Type)) { + _PyIO_State *state = IO_STATE(); + if (Py_IS_TYPE(self, 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 * @@ -963,7 +968,9 @@ stringio_newlines(stringio *self, void *context) return PyObject_GetAttr(self->decoder, &_Py_ID(newlines)); } +#define clinic_state() (IO_STATE()) #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/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 6011b1604508af..9ea82ad8b656bc 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -326,7 +326,6 @@ Modules/_io/bytesio.c - _PyBytesIOBuffer_Type - Modules/_io/fileio.c - PyFileIO_Type - Modules/_io/iobase.c - PyIOBase_Type - Modules/_io/iobase.c - PyRawIOBase_Type - -Modules/_io/stringio.c - PyStringIO_Type - Modules/_io/textio.c - PyIncrementalNewlineDecoder_Type - Modules/_io/textio.c - PyTextIOBase_Type - Modules/_io/textio.c - PyTextIOWrapper_Type - From 9af73fea92b88c6dc95fee7df45d41405850e70e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 11 Feb 2023 14:52:44 +0100 Subject: [PATCH 03/54] PyTextIOWrapper type --- Modules/_io/_iomodule.c | 10 +-- Modules/_io/_iomodule.h | 3 +- Modules/_io/textio.c | 91 ++++++++------------- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 4 files changed, 43 insertions(+), 62 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 4769b464432ece..9f89b0c68a2834 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -417,7 +417,8 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, } /* wraps into a TextIOWrapper */ - wrapper = PyObject_CallFunction((PyObject *)&PyTextIOWrapper_Type, + _PyIO_State *state = IO_STATE(); + wrapper = PyObject_CallFunction((PyObject *)state->PyTextIOWrapper_Type, "OsssO", buffer, encoding, errors, newline, @@ -659,9 +660,6 @@ static PyTypeObject* static_types[] = { #ifdef MS_WINDOWS &PyWindowsConsoleIO_Type, #endif - - // PyTextIOBase_Type(PyIOBase_Type) subclasses - &PyTextIOWrapper_Type, }; @@ -726,7 +724,6 @@ PyInit__io(void) 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++) { @@ -736,7 +733,10 @@ PyInit__io(void) } } + // 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; diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 517ba6bbb95ef2..d793bfd94e5f1a 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -19,11 +19,11 @@ 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 stringio_spec; +extern PyType_Spec textiowrapper_spec; #ifdef MS_WINDOWS extern PyTypeObject PyWindowsConsoleIO_Type; @@ -147,6 +147,7 @@ typedef struct { /* Types */ PyTypeObject *PyStringIO_Type; + PyTypeObject *PyTextIOWrapper_Type; } _PyIO_State; #define IO_MOD_STATE(mod) ((_PyIO_State *)PyModule_GetState(mod)) diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index ea2ea32c336954..0dbdcab5ac2995 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 @@ -1211,6 +1213,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, goto error; } + self->state = IO_STATE(); self->ok = 1; return 0; @@ -1387,6 +1390,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 +1399,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 +1430,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 +3059,8 @@ textiowrapper_iternext(textio *self) CHECK_ATTACHED(self); self->telling = 0; - if (Py_IS_TYPE(self, &PyTextIOWrapper_Type)) { + _PyIO_State *state = IO_STATE(); + if (Py_IS_TYPE(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() (IO_STATE()) #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, }; diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 9ea82ad8b656bc..208a9383cd3706 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -328,7 +328,6 @@ Modules/_io/iobase.c - PyIOBase_Type - Modules/_io/iobase.c - PyRawIOBase_Type - Modules/_io/textio.c - PyIncrementalNewlineDecoder_Type - Modules/_io/textio.c - PyTextIOBase_Type - -Modules/_io/textio.c - PyTextIOWrapper_Type - Modules/_io/winconsoleio.c - PyWindowsConsoleIO_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - From 4bd73bdd2753b40122ff09ff67476c03d785a1cd Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 11 Feb 2023 22:56:38 +0100 Subject: [PATCH 04/54] Move get_io_state() to main header --- Modules/_io/_iomodule.c | 9 --------- Modules/_io/_iomodule.h | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 9f89b0c68a2834..1b97f501423845 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 @@ -559,14 +558,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) { diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index d793bfd94e5f1a..194a53848bd7d0 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -4,6 +4,7 @@ #include "exports.h" +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "structmember.h" /* ABCs */ @@ -153,6 +154,14 @@ typedef struct { #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; +} + extern _PyIO_State *_PyIO_get_module_state(void); #ifdef MS_WINDOWS From 8d96a7aabd29f2ef8b643898ff5a969e941d6d67 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 11 Feb 2023 22:59:33 +0100 Subject: [PATCH 05/54] PyFileIO type --- Modules/_io/_iomodule.c | 8 +- Modules/_io/_iomodule.h | 3 +- Modules/_io/bufferedio.c | 9 ++- Modules/_io/fileio.c | 86 +++++++-------------- Modules/_io/textio.c | 5 +- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 6 files changed, 46 insertions(+), 66 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 1b97f501423845..1811f391c58d12 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -315,7 +315,8 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, /* Create the Raw file stream */ { - PyObject *RawIO_class = (PyObject *)&PyFileIO_Type; + _PyIO_State *state = get_io_state(module); + 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') { @@ -646,7 +647,6 @@ static PyTypeObject* static_types[] = { &PyBufferedRandom_Type, // PyRawIOBase_Type(PyIOBase_Type) subclasses - &PyFileIO_Type, &_PyBytesIOBuffer_Type, #ifdef MS_WINDOWS &PyWindowsConsoleIO_Type, @@ -706,7 +706,6 @@ PyInit__io(void) } // Set type base classes - PyFileIO_Type.tp_base = &PyRawIOBase_Type; PyBytesIO_Type.tp_base = &PyBufferedIOBase_Type; #ifdef MS_WINDOWS PyWindowsConsoleIO_Type.tp_base = &PyRawIOBase_Type; @@ -724,6 +723,9 @@ PyInit__io(void) } } + // 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, diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 194a53848bd7d0..993280b6916eb5 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -14,7 +14,6 @@ extern PyTypeObject PyBufferedIOBase_Type; extern PyTypeObject PyTextIOBase_Type; /* Concrete classes */ -extern PyTypeObject PyFileIO_Type; extern PyTypeObject PyBytesIO_Type; extern PyTypeObject PyBufferedReader_Type; extern PyTypeObject PyBufferedWriter_Type; @@ -23,6 +22,7 @@ extern PyTypeObject PyBufferedRandom_Type; extern PyTypeObject PyIncrementalNewlineDecoder_Type; /* Type specs */ +extern PyType_Spec fileio_spec; extern PyType_Spec stringio_spec; extern PyType_Spec textiowrapper_spec; @@ -147,6 +147,7 @@ typedef struct { PyObject *unsupported_operation; /* Types */ + PyTypeObject *PyFileIO_Type; PyTypeObject *PyStringIO_Type; PyTypeObject *PyTextIOWrapper_Type; } _PyIO_State; diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index ba8969f0bcd100..692e21c55e1861 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1428,8 +1428,9 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, return -1; _bufferedreader_reset_buf(self); + _PyIO_State *state = IO_STATE(); self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedReader_Type) && - Py_IS_TYPE(raw, &PyFileIO_Type)); + Py_IS_TYPE(raw, state->PyFileIO_Type)); self->ok = 1; return 0; @@ -1783,8 +1784,9 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, _bufferedwriter_reset_buf(self); self->pos = 0; + _PyIO_State *state = IO_STATE(); self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedWriter_Type) && - Py_IS_TYPE(raw, &PyFileIO_Type)); + Py_IS_TYPE(raw, state->PyFileIO_Type)); self->ok = 1; return 0; @@ -2295,8 +2297,9 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, _bufferedwriter_reset_buf(self); self->pos = 0; + _PyIO_State *state = IO_STATE(); self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedRandom_Type) && - Py_IS_TYPE(raw, &PyFileIO_Type)); + Py_IS_TYPE(raw, state->PyFileIO_Type)); self->ok = 1; return 0; diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index d1a183cedac53a..36e3b30de97d07 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -51,7 +51,7 @@ /*[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]*/ @@ -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,8 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, int fstat_result; int async_err = 0; - assert(PyFileIO_Check(self)); + _PyIO_State *state = IO_STATE(); + assert(PyFileIO_Check(state, self)); if (self->fd >= 0) { if (self->closefd) { /* Have to close the existing file first. */ @@ -503,6 +502,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 +517,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 +525,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 +1179,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/textio.c b/Modules/_io/textio.c index 0dbdcab5ac2995..7080ba935d9cc0 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -1177,6 +1177,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, /* Finished sorting out the codec details */ Py_CLEAR(codec_info); + _PyIO_State *state = IO_STATE(); if (Py_IS_TYPE(buffer, &PyBufferedReader_Type) || Py_IS_TYPE(buffer, &PyBufferedWriter_Type) || Py_IS_TYPE(buffer, &PyBufferedRandom_Type)) @@ -1185,7 +1186,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, 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); @@ -1213,7 +1214,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, goto error; } - self->state = IO_STATE(); + self->state = state; self->ok = 1; return 0; diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 208a9383cd3706..a7582e6ee89b66 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -323,7 +323,6 @@ Modules/_io/bufferedio.c - PyBufferedReader_Type - Modules/_io/bufferedio.c - PyBufferedWriter_Type - Modules/_io/bytesio.c - PyBytesIO_Type - Modules/_io/bytesio.c - _PyBytesIOBuffer_Type - -Modules/_io/fileio.c - PyFileIO_Type - Modules/_io/iobase.c - PyIOBase_Type - Modules/_io/iobase.c - PyRawIOBase_Type - Modules/_io/textio.c - PyIncrementalNewlineDecoder_Type - From 97f382f9070cc6b0d6f67bbc8ed67c00432e0797 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 12 Feb 2023 13:10:18 +0100 Subject: [PATCH 06/54] Buffered* types --- Modules/_io/_iomodule.c | 35 +- Modules/_io/_iomodule.h | 12 +- Modules/_io/bufferedio.c | 335 +++++++------------- Modules/_io/clinic/bufferedio.c.h | 4 +- Modules/_io/fileio.c | 2 +- Modules/_io/textio.c | 6 +- Tools/c-analyzer/cpython/globals-to-fix.tsv | 4 - 7 files changed, 153 insertions(+), 245 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 1811f391c58d12..e1ccb4d34c140a 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -386,16 +386,20 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, return result; } + _PyIO_State *state = IO_STATE(); /* wraps into a buffered file */ { 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 +421,6 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, } /* wraps into a TextIOWrapper */ - _PyIO_State *state = IO_STATE(); wrapper = PyObject_CallFunction((PyObject *)state->PyTextIOWrapper_Type, "OsssO", buffer, @@ -641,10 +644,6 @@ static PyTypeObject* static_types[] = { // PyBufferedIOBase_Type(PyIOBase_Type) subclasses &PyBytesIO_Type, - &PyBufferedReader_Type, - &PyBufferedWriter_Type, - &PyBufferedRWPair_Type, - &PyBufferedRandom_Type, // PyRawIOBase_Type(PyIOBase_Type) subclasses &_PyBytesIOBuffer_Type, @@ -710,10 +709,6 @@ PyInit__io(void) #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; // Add types for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) { @@ -723,6 +718,16 @@ PyInit__io(void) } } + // PyBufferedIOBase_Type(PyIOBase_Type) subclasses + 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); diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 993280b6916eb5..67a88a6969e103 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -15,13 +15,13 @@ extern PyTypeObject PyTextIOBase_Type; /* Concrete classes */ extern PyTypeObject PyBytesIO_Type; -extern PyTypeObject PyBufferedReader_Type; -extern PyTypeObject PyBufferedWriter_Type; -extern PyTypeObject PyBufferedRWPair_Type; -extern PyTypeObject PyBufferedRandom_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 fileio_spec; extern PyType_Spec stringio_spec; extern PyType_Spec textiowrapper_spec; @@ -147,6 +147,10 @@ typedef struct { PyObject *unsupported_operation; /* Types */ + PyTypeObject *PyBufferedRWPair_Type; + PyTypeObject *PyBufferedRandom_Type; + PyTypeObject *PyBufferedReader_Type; + PyTypeObject *PyBufferedWriter_Type; PyTypeObject *PyFileIO_Type; PyTypeObject *PyStringIO_Type; PyTypeObject *PyTextIOWrapper_Type; diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 692e21c55e1861..ad9c1dfa0a0684 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 = IO_STATE(); 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); } @@ -1429,8 +1434,10 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, _bufferedreader_reset_buf(self); _PyIO_State *state = IO_STATE(); - self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedReader_Type) && - Py_IS_TYPE(raw, state->PyFileIO_Type)); + self->fast_closed_checks = ( + Py_IS_TYPE(self, state->PyBufferedReader_Type) && + Py_IS_TYPE(raw, state->PyFileIO_Type) + ); self->ok = 1; return 0; @@ -1785,8 +1792,10 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, self->pos = 0; _PyIO_State *state = IO_STATE(); - self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedWriter_Type) && - Py_IS_TYPE(raw, state->PyFileIO_Type)); + self->fast_closed_checks = ( + Py_IS_TYPE(self, state->PyBufferedWriter_Type) && + Py_IS_TYPE(raw, state->PyFileIO_Type) + ); self->ok = 1; return 0; @@ -2092,13 +2101,16 @@ _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, if (_PyIOBase_check_writable(writer, Py_True) == NULL) return -1; + _PyIO_State *state = IO_STATE(); 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; @@ -2126,13 +2138,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 * @@ -2298,14 +2312,16 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, self->pos = 0; _PyIO_State *state = IO_STATE(); - self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedRandom_Type) && + 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() (IO_STATE()) #include "clinic/bufferedio.c.h" +#undef clinic_state static PyMethodDef bufferediobase_methods[] = { @@ -2397,6 +2413,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} }; @@ -2408,58 +2426,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 */ @@ -2483,6 +2470,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} }; @@ -2494,58 +2483,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}, @@ -2566,61 +2523,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, }; @@ -2654,6 +2585,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} }; @@ -2665,54 +2598,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/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h index 38ea756879c122..d44321bb8b960e 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 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) 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 36e3b30de97d07..9777b7614ef057 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -53,7 +53,7 @@ module _io 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 diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 7080ba935d9cc0..88198c795d3e49 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -1178,9 +1178,9 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, Py_CLEAR(codec_info); _PyIO_State *state = IO_STATE(); - if (Py_IS_TYPE(buffer, &PyBufferedReader_Type) || - Py_IS_TYPE(buffer, &PyBufferedWriter_Type) || - Py_IS_TYPE(buffer, &PyBufferedRandom_Type)) + 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; diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index a7582e6ee89b66..2cccbf18856104 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -317,10 +317,6 @@ Modules/_collectionsmodule.c - dequeiter_type - Modules/_collectionsmodule.c - dequereviter_type - Modules/_collectionsmodule.c - tuplegetter_type - Modules/_io/bufferedio.c - PyBufferedIOBase_Type - -Modules/_io/bufferedio.c - PyBufferedRWPair_Type - -Modules/_io/bufferedio.c - PyBufferedRandom_Type - -Modules/_io/bufferedio.c - PyBufferedReader_Type - -Modules/_io/bufferedio.c - PyBufferedWriter_Type - Modules/_io/bytesio.c - PyBytesIO_Type - Modules/_io/bytesio.c - _PyBytesIOBuffer_Type - Modules/_io/iobase.c - PyIOBase_Type - From eeb5c48dec9be5de95130a8de9984d3ff9961905 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 12 Feb 2023 13:22:53 +0100 Subject: [PATCH 07/54] PyBytesIO type --- Modules/_io/_iomodule.c | 5 +- Modules/_io/_iomodule.h | 3 +- Modules/_io/bytesio.c | 75 +++++++++------------ Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 4 files changed, 36 insertions(+), 48 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index e1ccb4d34c140a..1addab56abc4f3 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -642,9 +642,6 @@ static PyTypeObject* static_types[] = { &PyRawIOBase_Type, &PyTextIOBase_Type, - // PyBufferedIOBase_Type(PyIOBase_Type) subclasses - &PyBytesIO_Type, - // PyRawIOBase_Type(PyIOBase_Type) subclasses &_PyBytesIOBuffer_Type, #ifdef MS_WINDOWS @@ -705,7 +702,6 @@ PyInit__io(void) } // Set type base classes - PyBytesIO_Type.tp_base = &PyBufferedIOBase_Type; #ifdef MS_WINDOWS PyWindowsConsoleIO_Type.tp_base = &PyRawIOBase_Type; #endif @@ -719,6 +715,7 @@ 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, diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 67a88a6969e103..354788093f2e88 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -14,7 +14,6 @@ extern PyTypeObject PyBufferedIOBase_Type; extern PyTypeObject PyTextIOBase_Type; /* Concrete classes */ -extern PyTypeObject PyBytesIO_Type; extern PyTypeObject PyIncrementalNewlineDecoder_Type; /* Type specs */ @@ -22,6 +21,7 @@ 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; @@ -151,6 +151,7 @@ typedef struct { PyTypeObject *PyBufferedRandom_Type; PyTypeObject *PyBufferedReader_Type; PyTypeObject *PyBufferedWriter_Type; + PyTypeObject *PyBytesIO_Type; PyTypeObject *PyFileIO_Type; PyTypeObject *PyStringIO_Type; PyTypeObject *PyTextIOWrapper_Type; diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 6698c60355fcc5..ec5de6ffa4a670 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -5,7 +5,7 @@ /*[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]*/ @@ -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() (IO_STATE()) #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/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 2cccbf18856104..2e28c50c6ff69a 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -317,7 +317,6 @@ Modules/_collectionsmodule.c - dequeiter_type - Modules/_collectionsmodule.c - dequereviter_type - Modules/_collectionsmodule.c - tuplegetter_type - Modules/_io/bufferedio.c - PyBufferedIOBase_Type - -Modules/_io/bytesio.c - PyBytesIO_Type - Modules/_io/bytesio.c - _PyBytesIOBuffer_Type - Modules/_io/iobase.c - PyIOBase_Type - Modules/_io/iobase.c - PyRawIOBase_Type - From 4106c1b3b5549cef81059514eb0b4a1550de361e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 12 Feb 2023 14:31:27 +0100 Subject: [PATCH 08/54] PyTextIOBase type --- Modules/_io/_iomodule.c | 10 +-- Modules/_io/_iomodule.h | 3 +- Modules/_io/textio.c | 77 ++++++++------------- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 4 files changed, 36 insertions(+), 55 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 1addab56abc4f3..0bc46006a4d3ff 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -640,7 +640,6 @@ static PyTypeObject* static_types[] = { // PyIOBase_Type subclasses &PyBufferedIOBase_Type, &PyRawIOBase_Type, - &PyTextIOBase_Type, // PyRawIOBase_Type(PyIOBase_Type) subclasses &_PyBytesIOBuffer_Type, @@ -714,6 +713,9 @@ PyInit__io(void) } } + // PyIOBase_Type subclasses + ADD_TYPE(m, state->PyTextIOBase_Type, &textiobase_spec, &PyIOBase_Type); + // PyBufferedIOBase_Type(PyIOBase_Type) subclasses ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, &PyBufferedIOBase_Type); ADD_TYPE(m, state->PyBufferedWriter_Type, &bufferedwriter_spec, @@ -729,9 +731,9 @@ PyInit__io(void) 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); + PyTypeObject *base = state->PyTextIOBase_Type; + ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, base); + ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec, base); state->initialized = 1; diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 354788093f2e88..477474a1bf3ba4 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -11,7 +11,6 @@ extern PyTypeObject PyIOBase_Type; extern PyTypeObject PyRawIOBase_Type; extern PyTypeObject PyBufferedIOBase_Type; -extern PyTypeObject PyTextIOBase_Type; /* Concrete classes */ extern PyTypeObject PyIncrementalNewlineDecoder_Type; @@ -24,6 +23,7 @@ extern PyType_Spec bufferedwriter_spec; extern PyType_Spec bytesio_spec; extern PyType_Spec fileio_spec; extern PyType_Spec stringio_spec; +extern PyType_Spec textiobase_spec; extern PyType_Spec textiowrapper_spec; #ifdef MS_WINDOWS @@ -154,6 +154,7 @@ typedef struct { PyTypeObject *PyBytesIO_Type; PyTypeObject *PyFileIO_Type; PyTypeObject *PyStringIO_Type; + PyTypeObject *PyTextIOBase_Type; PyTypeObject *PyTextIOWrapper_Type; } _PyIO_State; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 88198c795d3e49..37ffdc572447e5 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -130,6 +130,21 @@ 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 void +textiobase_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + _PyObject_GC_UNTRACK(self); + tp->tp_free((PyObject *)self); + Py_DECREF(tp); +} static PyMethodDef textiobase_methods[] = { {"detach", textiobase_detach, METH_NOARGS, textiobase_detach_doc}, @@ -146,57 +161,21 @@ 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_dealloc, textiobase_dealloc}, + {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 */ diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 2e28c50c6ff69a..1a25b60c278301 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -321,7 +321,6 @@ Modules/_io/bytesio.c - _PyBytesIOBuffer_Type - Modules/_io/iobase.c - PyIOBase_Type - Modules/_io/iobase.c - PyRawIOBase_Type - Modules/_io/textio.c - PyIncrementalNewlineDecoder_Type - -Modules/_io/textio.c - PyTextIOBase_Type - Modules/_io/winconsoleio.c - PyWindowsConsoleIO_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - From 3eba87322b26c55be0c3ee218b05625c98ed362e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 12 Feb 2023 23:04:57 +0100 Subject: [PATCH 09/54] PyBufferedIOBase type --- Modules/_io/_iomodule.c | 22 +++--- Modules/_io/_iomodule.h | 3 +- Modules/_io/bufferedio.c | 82 ++++++++------------- Modules/_io/bytesio.c | 2 +- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 5 files changed, 43 insertions(+), 67 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 0bc46006a4d3ff..e4ecaba605b3bf 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -638,7 +638,6 @@ static PyTypeObject* static_types[] = { &PyIncrementalNewlineDecoder_Type, // PyIOBase_Type subclasses - &PyBufferedIOBase_Type, &PyRawIOBase_Type, // PyRawIOBase_Type(PyIOBase_Type) subclasses @@ -714,24 +713,23 @@ PyInit__io(void) } // PyIOBase_Type subclasses - ADD_TYPE(m, state->PyTextIOBase_Type, &textiobase_spec, &PyIOBase_Type); + PyTypeObject *base = &PyIOBase_Type; + ADD_TYPE(m, state->PyTextIOBase_Type, &textiobase_spec, base); + ADD_TYPE(m, state->PyBufferedIOBase_Type, &bufferediobase_spec, base); // 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); + base = state->PyBufferedIOBase_Type; + ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, base); + ADD_TYPE(m, state->PyBufferedWriter_Type, &bufferedwriter_spec, base); + ADD_TYPE(m, state->PyBufferedReader_Type, &bufferedreader_spec, base); + ADD_TYPE(m, state->PyBufferedRWPair_Type, &bufferedrwpair_spec, base); + ADD_TYPE(m, state->PyBufferedRandom_Type, &bufferedrandom_spec, base); // PyRawIOBase_Type(PyIOBase_Type) subclasses ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, &PyRawIOBase_Type); // PyTextIOBase_Type(PyIOBase_Type) subclasses - PyTypeObject *base = state->PyTextIOBase_Type; + base = state->PyTextIOBase_Type; ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, base); ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec, base); diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 477474a1bf3ba4..7f49971431f063 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -10,12 +10,12 @@ /* ABCs */ extern PyTypeObject PyIOBase_Type; extern PyTypeObject PyRawIOBase_Type; -extern PyTypeObject PyBufferedIOBase_Type; /* Concrete classes */ extern PyTypeObject PyIncrementalNewlineDecoder_Type; /* Type specs */ +extern PyType_Spec bufferediobase_spec; extern PyType_Spec bufferedrandom_spec; extern PyType_Spec bufferedreader_spec; extern PyType_Spec bufferedrwpair_spec; @@ -147,6 +147,7 @@ typedef struct { PyObject *unsupported_operation; /* Types */ + PyTypeObject *PyBufferedIOBase_Type; PyTypeObject *PyBufferedRWPair_Type; PyTypeObject *PyBufferedRandom_Type; PyTypeObject *PyBufferedReader_Type; diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index ad9c1dfa0a0684..706c694dc9a9d3 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -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. @@ -2323,6 +2323,21 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, #include "clinic/bufferedio.c.h" #undef clinic_state +static void +bufferediobase_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + _PyObject_GC_UNTRACK(self); + tp->tp_free(self); + Py_DECREF(tp); +} + +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 @@ -2334,57 +2349,20 @@ 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_dealloc, bufferediobase_dealloc}, + {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 */ diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index ec5de6ffa4a670..2cbc5260aa4aef 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -7,7 +7,7 @@ module _io 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 diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 1a25b60c278301..67cedd199e9388 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -316,7 +316,6 @@ Modules/_collectionsmodule.c - deque_type - Modules/_collectionsmodule.c - dequeiter_type - Modules/_collectionsmodule.c - dequereviter_type - Modules/_collectionsmodule.c - tuplegetter_type - -Modules/_io/bufferedio.c - PyBufferedIOBase_Type - Modules/_io/bytesio.c - _PyBytesIOBuffer_Type - Modules/_io/iobase.c - PyIOBase_Type - Modules/_io/iobase.c - PyRawIOBase_Type - From de3acf0395fbc5c26983530a4d3d43ebd0140409 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 13 Feb 2023 09:06:33 +0100 Subject: [PATCH 10/54] PyIncrementalNewlineDecoder type --- Modules/_io/_iomodule.c | 4 +- Modules/_io/_iomodule.h | 5 +- Modules/_io/stringio.c | 3 +- Modules/_io/textio.c | 95 +++++++++++---------- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 5 files changed, 55 insertions(+), 53 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index e4ecaba605b3bf..317ad7431c16c6 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -635,7 +635,6 @@ struct PyModuleDef _PyIO_Module = { static PyTypeObject* static_types[] = { // Base classes &PyIOBase_Type, - &PyIncrementalNewlineDecoder_Type, // PyIOBase_Type subclasses &PyRawIOBase_Type, @@ -712,6 +711,9 @@ PyInit__io(void) } } + // Concrete classes + ADD_TYPE(m, state->PyIncrementalNewlineDecoder_Type, &nldecoder_spec, NULL); + // PyIOBase_Type subclasses PyTypeObject *base = &PyIOBase_Type; ADD_TYPE(m, state->PyTextIOBase_Type, &textiobase_spec, base); diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 7f49971431f063..5c39192f8bff09 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -11,9 +11,6 @@ extern PyTypeObject PyIOBase_Type; extern PyTypeObject PyRawIOBase_Type; -/* Concrete classes */ -extern PyTypeObject PyIncrementalNewlineDecoder_Type; - /* Type specs */ extern PyType_Spec bufferediobase_spec; extern PyType_Spec bufferedrandom_spec; @@ -22,6 +19,7 @@ extern PyType_Spec bufferedrwpair_spec; extern PyType_Spec bufferedwriter_spec; extern PyType_Spec bytesio_spec; extern PyType_Spec fileio_spec; +extern PyType_Spec nldecoder_spec; extern PyType_Spec stringio_spec; extern PyType_Spec textiobase_spec; extern PyType_Spec textiowrapper_spec; @@ -154,6 +152,7 @@ typedef struct { PyTypeObject *PyBufferedWriter_Type; PyTypeObject *PyBytesIO_Type; PyTypeObject *PyFileIO_Type; + PyTypeObject *PyIncrementalNewlineDecoder_Type; PyTypeObject *PyStringIO_Type; PyTypeObject *PyTextIOBase_Type; PyTypeObject *PyTextIOWrapper_Type; diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 12ae5a09ca70a2..e0f3b6d8d26804 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -717,8 +717,9 @@ _io_StringIO___init___impl(stringio *self, PyObject *value, } if (self->readuniversal) { + _PyIO_State *state = IO_STATE(); self->decoder = PyObject_CallFunctionObjArgs( - (PyObject *)&PyIncrementalNewlineDecoder_Type, + (PyObject *)state->PyIncrementalNewlineDecoder_Type, Py_None, self->readtranslate ? Py_True : Py_False, NULL); if (self->decoder == NULL) return -1; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 37ffdc572447e5..1b0a310fc6191c 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -18,10 +18,10 @@ /*[clinic input] module _io -class _io.IncrementalNewlineDecoder "nldecoder_object *" "&PyIncrementalNewlineDecoder_Type" +class _io.IncrementalNewlineDecoder "nldecoder_object *" "clinic_state()->PyIncrementalNewlineDecoder_Type" class _io.TextIOWrapper "textio *" "clinic_state()->TextIOWrapper_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d3f032e90f74c8f2]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=81f67cf54eaa6001]*/ /* TextIOBase */ @@ -227,12 +227,32 @@ _io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self, return 0; } -static void -incrementalnewlinedecoder_dealloc(nldecoder_object *self) +static int +incrementalnewlinedecoder_traverse(nldecoder_object *self, visitproc visit, + void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->decoder); + Py_VISIT(self->errors); + return 0; +} + +static int +incrementalnewlinedecoder_clear(nldecoder_object *self) { Py_CLEAR(self->decoder); Py_CLEAR(self->errors); - Py_TYPE(self)->tp_free((PyObject *)self); + return 0; +} + +static void +incrementalnewlinedecoder_dealloc(nldecoder_object *self) +{ + PyTypeObject *tp = Py_TYPE(self); + _PyObject_GC_UNTRACK(self); + (void)incrementalnewlinedecoder_clear(self); + tp->tp_free((PyObject *)self); + Py_DECREF(tp); } static int @@ -851,8 +871,9 @@ _textiowrapper_set_decoder(textio *self, PyObject *codec_info, return -1; if (self->readuniversal) { + _PyIO_State *state = IO_STATE(); PyObject *incrementalDecoder = PyObject_CallFunctionObjArgs( - (PyObject *)&PyIncrementalNewlineDecoder_Type, + (PyObject *)state->PyIncrementalNewlineDecoder_Type, self->decoder, self->readtranslate ? Py_True : Py_False, NULL); if (incrementalDecoder == NULL) return -1; @@ -867,7 +888,8 @@ _textiowrapper_decode(PyObject *decoder, PyObject *bytes, int eof) { PyObject *chars; - if (Py_IS_TYPE(decoder, &PyIncrementalNewlineDecoder_Type)) + _PyIO_State *state = IO_STATE(); + if (Py_IS_TYPE(decoder, state->PyIncrementalNewlineDecoder_Type)) chars = _PyIncrementalNewlineDecoder_decode(decoder, bytes, eof); else chars = PyObject_CallMethodObjArgs(decoder, &_Py_ID(decode), bytes, @@ -1892,7 +1914,8 @@ _io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n) if (bytes == NULL) goto fail; - if (Py_IS_TYPE(self->decoder, &PyIncrementalNewlineDecoder_Type)) + _PyIO_State *state = self->state; + if (Py_IS_TYPE(self->decoder, state->PyIncrementalNewlineDecoder_Type)) decoded = _PyIncrementalNewlineDecoder_decode(self->decoder, bytes, 1); else @@ -3149,45 +3172,23 @@ static PyGetSetDef incrementalnewlinedecoder_getset[] = { {NULL} }; -PyTypeObject PyIncrementalNewlineDecoder_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.IncrementalNewlineDecoder", /*tp_name*/ - sizeof(nldecoder_object), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)incrementalnewlinedecoder_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, /*tp_flags*/ - _io_IncrementalNewlineDecoder___init____doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /*tp_weaklistoffset*/ - 0, /* tp_iter */ - 0, /* tp_iternext */ - incrementalnewlinedecoder_methods, /* tp_methods */ - 0, /* tp_members */ - incrementalnewlinedecoder_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - _io_IncrementalNewlineDecoder___init__, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ +static PyType_Slot nldecoder_slots[] = { + {Py_tp_dealloc, incrementalnewlinedecoder_dealloc}, + {Py_tp_doc, (void *)_io_IncrementalNewlineDecoder___init____doc__}, + {Py_tp_methods, incrementalnewlinedecoder_methods}, + {Py_tp_getset, incrementalnewlinedecoder_getset}, + {Py_tp_traverse, incrementalnewlinedecoder_traverse}, + {Py_tp_clear, incrementalnewlinedecoder_clear}, + {Py_tp_init, _io_IncrementalNewlineDecoder___init__}, + {0, NULL}, +}; + +PyType_Spec nldecoder_spec = { + .name = "_io.IncrementalNewlineDecoder", + .basicsize = sizeof(nldecoder_object), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = nldecoder_slots, }; diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 67cedd199e9388..a15e42717c35f1 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -319,7 +319,6 @@ Modules/_collectionsmodule.c - tuplegetter_type - Modules/_io/bytesio.c - _PyBytesIOBuffer_Type - Modules/_io/iobase.c - PyIOBase_Type - Modules/_io/iobase.c - PyRawIOBase_Type - -Modules/_io/textio.c - PyIncrementalNewlineDecoder_Type - Modules/_io/winconsoleio.c - PyWindowsConsoleIO_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - From bc3521868b0e4776cddeee0c40b97cd417da8f20 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 15 Feb 2023 11:35:29 +0100 Subject: [PATCH 11/54] PyBytesIOBuffer type --- Modules/_io/_iomodule.c | 4 +- Modules/_io/_iomodule.h | 4 +- Modules/_io/bytesio.c | 64 +++++++-------------- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 4 files changed, 23 insertions(+), 50 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 317ad7431c16c6..ee00d1ec9a46bd 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -638,9 +638,6 @@ static PyTypeObject* static_types[] = { // PyIOBase_Type subclasses &PyRawIOBase_Type, - - // PyRawIOBase_Type(PyIOBase_Type) subclasses - &_PyBytesIOBuffer_Type, #ifdef MS_WINDOWS &PyWindowsConsoleIO_Type, #endif @@ -729,6 +726,7 @@ PyInit__io(void) // PyRawIOBase_Type(PyIOBase_Type) subclasses ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, &PyRawIOBase_Type); + ADD_TYPE(m, state->PyBytesIOBuffer_Type, &bytesiobuf_spec, NULL); // XXX: should be subclass of PyRawIOBase_Type? // PyTextIOBase_Type(PyIOBase_Type) subclasses base = state->PyTextIOBase_Type; diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 5c39192f8bff09..aced6fb1cdd9cd 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -18,6 +18,7 @@ extern PyType_Spec bufferedreader_spec; extern PyType_Spec bufferedrwpair_spec; extern PyType_Spec bufferedwriter_spec; extern PyType_Spec bytesio_spec; +extern PyType_Spec bytesiobuf_spec; extern PyType_Spec fileio_spec; extern PyType_Spec nldecoder_spec; extern PyType_Spec stringio_spec; @@ -150,6 +151,7 @@ typedef struct { PyTypeObject *PyBufferedRandom_Type; PyTypeObject *PyBufferedReader_Type; PyTypeObject *PyBufferedWriter_Type; + PyTypeObject *PyBytesIOBuffer_Type; PyTypeObject *PyBytesIO_Type; PyTypeObject *PyFileIO_Type; PyTypeObject *PyIncrementalNewlineDecoder_Type; @@ -174,5 +176,3 @@ extern _PyIO_State *_PyIO_get_module_state(void); #ifdef MS_WINDOWS extern char _PyIO_get_console_type(PyObject *); #endif - -extern Py_EXPORTED_SYMBOL PyTypeObject _PyBytesIOBuffer_Type; diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 2cbc5260aa4aef..84db3c03084135 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -315,7 +315,8 @@ static PyObject * _io_BytesIO_getbuffer_impl(bytesio *self) /*[clinic end generated code: output=72cd7c6e13aa09ed input=8f738ef615865176]*/ { - PyTypeObject *type = &_PyBytesIOBuffer_Type; + _PyIO_State *state = IO_STATE(); + PyTypeObject *type = state->PyBytesIOBuffer_Type; bytesiobuf *buf; PyObject *view; @@ -1089,6 +1090,7 @@ bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view) static int bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); Py_VISIT(self->source); return 0; } @@ -1096,54 +1098,28 @@ bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg) static void bytesiobuf_dealloc(bytesiobuf *self) { + PyTypeObject *tp = Py_TYPE(self); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(self); Py_CLEAR(self->source); - Py_TYPE(self)->tp_free(self); + tp->tp_free(self); + Py_DECREF(tp); } -static PyBufferProcs bytesiobuf_as_buffer = { - (getbufferproc) bytesiobuf_getbuffer, - (releasebufferproc) bytesiobuf_releasebuffer, +static PyType_Slot bytesiobuf_slots[] = { + {Py_tp_dealloc, bytesiobuf_dealloc}, + {Py_tp_traverse, bytesiobuf_traverse}, + + // Buffer protocol + {Py_bf_getbuffer, bytesiobuf_getbuffer}, + {Py_bf_releasebuffer, bytesiobuf_releasebuffer}, + {0, NULL}, }; -Py_EXPORTED_SYMBOL PyTypeObject _PyBytesIOBuffer_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io._BytesIOBuffer", /*tp_name*/ - sizeof(bytesiobuf), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)bytesiobuf_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*/ - &bytesiobuf_as_buffer, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - 0, /*tp_doc*/ - (traverseproc)bytesiobuf_traverse, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*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*/ - 0, /*tp_new*/ +PyType_Spec bytesiobuf_spec = { + .name = "_io._BytesIOBuffer", + .basicsize = sizeof(bytesiobuf), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION), + .slots = bytesiobuf_slots, }; diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index a15e42717c35f1..cf118f82a1216b 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -316,7 +316,6 @@ Modules/_collectionsmodule.c - deque_type - Modules/_collectionsmodule.c - dequeiter_type - Modules/_collectionsmodule.c - dequereviter_type - Modules/_collectionsmodule.c - tuplegetter_type - -Modules/_io/bytesio.c - _PyBytesIOBuffer_Type - Modules/_io/iobase.c - PyIOBase_Type - Modules/_io/iobase.c - PyRawIOBase_Type - Modules/_io/winconsoleio.c - PyWindowsConsoleIO_Type - From 62a91e9775a6c1a7e6e82aba4c122f8adc910e81 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 15 Feb 2023 23:12:24 +0100 Subject: [PATCH 12/54] PyWindowsConsoleIO type --- Modules/_io/_iomodule.c | 16 ++-- Modules/_io/_iomodule.h | 8 +- Modules/_io/winconsoleio.c | 82 ++++++++------------- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 4 files changed, 41 insertions(+), 66 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index ee00d1ec9a46bd..ea25c9ef9ac031 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -320,7 +320,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, #ifdef MS_WINDOWS const PyConfig *config = _Py_GetConfig(); if (!config->legacy_windows_stdio && _PyIO_get_console_type(path_or_fd) != '\0') { - RawIO_class = (PyObject *)&PyWindowsConsoleIO_Type; + RawIO_class = (PyObject *)state->PyWindowsConsoleIO_Type; encoding = "utf-8"; } #endif @@ -638,9 +638,6 @@ static PyTypeObject* static_types[] = { // PyIOBase_Type subclasses &PyRawIOBase_Type, -#ifdef MS_WINDOWS - &PyWindowsConsoleIO_Type, -#endif }; @@ -695,11 +692,6 @@ PyInit__io(void) goto fail; } - // Set type base classes -#ifdef MS_WINDOWS - PyWindowsConsoleIO_Type.tp_base = &PyRawIOBase_Type; -#endif - // Add types for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) { PyTypeObject *type = static_types[i]; @@ -725,8 +717,12 @@ PyInit__io(void) ADD_TYPE(m, state->PyBufferedRandom_Type, &bufferedrandom_spec, base); // PyRawIOBase_Type(PyIOBase_Type) subclasses - ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, &PyRawIOBase_Type); + base = &PyRawIOBase_Type; + ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, base); ADD_TYPE(m, state->PyBytesIOBuffer_Type, &bytesiobuf_spec, NULL); // XXX: should be subclass of PyRawIOBase_Type? +#ifdef MS_WINDOWS + ADD_TYPE(m, state->PyWindowsConsoleIO_Type, &winconsoleio_spec, base); +#endif // PyTextIOBase_Type(PyIOBase_Type) subclasses base = state->PyTextIOBase_Type; diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index aced6fb1cdd9cd..b634bdadbed422 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -24,10 +24,9 @@ extern PyType_Spec nldecoder_spec; extern PyType_Spec stringio_spec; extern PyType_Spec textiobase_spec; extern PyType_Spec textiowrapper_spec; - #ifdef MS_WINDOWS -extern PyTypeObject PyWindowsConsoleIO_Type; -#endif /* MS_WINDOWS */ +extern PyType_Spec winconsoleio_spec; +#endif /* These functions are used as METH_NOARGS methods, are normally called * with args=NULL, and return a new reference. @@ -158,6 +157,9 @@ typedef struct { PyTypeObject *PyStringIO_Type; PyTypeObject *PyTextIOBase_Type; PyTypeObject *PyTextIOWrapper_Type; +#ifdef MS_WINDOWS + PyTypeObject *PyWindowsConsoleIO_Type; +#endif } _PyIO_State; #define IO_MOD_STATE(mod) ((_PyIO_State *)PyModule_GetState(mod)) diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index e913d831874617..030ed728111497 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -135,7 +135,7 @@ char _PyIO_get_console_type(PyObject *path_or_fd) { /*[clinic input] module _io -class _io._WindowsConsoleIO "winconsoleio *" "&PyWindowsConsoleIO_Type" +class _io._WindowsConsoleIO "winconsoleio *" "clinic_state()->PyWindowsConsoleIO_Type" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=e897fdc1fba4e131]*/ @@ -412,6 +412,7 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj, static int winconsoleio_traverse(winconsoleio *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); return 0; } @@ -426,6 +427,7 @@ winconsoleio_clear(winconsoleio *self) static void winconsoleio_dealloc(winconsoleio *self) { + PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; if (_PyIOBase_finalize((PyObject *) self) < 0) return; @@ -433,7 +435,8 @@ winconsoleio_dealloc(winconsoleio *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 * @@ -1073,7 +1076,9 @@ _io__WindowsConsoleIO_isatty_impl(winconsoleio *self) Py_RETURN_TRUE; } +#define clinic_state() (IO_STATE()) #include "clinic/winconsoleio.c.h" +#undef clinic_state static PyMethodDef winconsoleio_methods[] = { _IO__WINDOWSCONSOLEIO_READ_METHODDEF @@ -1119,59 +1124,32 @@ static PyGetSetDef winconsoleio_getsetlist[] = { static PyMemberDef winconsoleio_members[] = { {"_blksize", T_UINT, offsetof(winconsoleio, blksize), 0}, {"_finalizing", T_BOOL, offsetof(winconsoleio, finalizing), 0}, + {"__weaklistoffset__", T_PYSSIZET, offsetof(winconsoleio, weakreflist), READONLY}, + {"__dictoffset__", T_PYSSIZET, offsetof(winconsoleio, dict), READONLY}, {NULL} }; -PyTypeObject PyWindowsConsoleIO_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io._WindowsConsoleIO", - sizeof(winconsoleio), - 0, - (destructor)winconsoleio_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)winconsoleio_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__WindowsConsoleIO___init____doc__, /* tp_doc */ - (traverseproc)winconsoleio_traverse, /* tp_traverse */ - (inquiry)winconsoleio_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(winconsoleio, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - winconsoleio_methods, /* tp_methods */ - winconsoleio_members, /* tp_members */ - winconsoleio_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(winconsoleio, dict), /* tp_dictoffset */ - _io__WindowsConsoleIO___init__, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - winconsoleio_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 winconsoleio_slots[] = { + {Py_tp_dealloc, winconsoleio_dealloc}, + {Py_tp_repr, winconsoleio_repr}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)_io__WindowsConsoleIO___init____doc__}, + {Py_tp_traverse, winconsoleio_traverse}, + {Py_tp_clear, winconsoleio_clear}, + {Py_tp_methods, winconsoleio_methods}, + {Py_tp_members, winconsoleio_members}, + {Py_tp_getset, winconsoleio_getsetlist}, + {Py_tp_init, _io__WindowsConsoleIO___init__}, + {Py_tp_new, winconsoleio_new}, + {0, NULL}, +}; + +PyType_Spec winconsoleio_spec = { + .name = "_io._WindowsConsoleIO", + .basicsize = sizeof(winconsoleio), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = winconsoleio_slots, }; #endif /* MS_WINDOWS */ diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index cf118f82a1216b..c6b0a7f5b742a0 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -318,7 +318,6 @@ Modules/_collectionsmodule.c - dequereviter_type - Modules/_collectionsmodule.c - tuplegetter_type - Modules/_io/iobase.c - PyIOBase_Type - Modules/_io/iobase.c - PyRawIOBase_Type - -Modules/_io/winconsoleio.c - PyWindowsConsoleIO_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type - From 23b79ebc8c017b0cb9297da473f9ba3f0e135f5a Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 15 Feb 2023 23:25:45 +0100 Subject: [PATCH 13/54] RawIOBase type --- Modules/_io/_iomodule.c | 6 +- Modules/_io/_iomodule.h | 3 +- Modules/_io/fileio.c | 4 +- Modules/_io/iobase.c | 84 ++++++++------------- Modules/_io/winconsoleio.c | 6 +- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 6 files changed, 44 insertions(+), 60 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index ea25c9ef9ac031..0f4181c28b05a0 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -635,9 +635,6 @@ struct PyModuleDef _PyIO_Module = { static PyTypeObject* static_types[] = { // Base classes &PyIOBase_Type, - - // PyIOBase_Type subclasses - &PyRawIOBase_Type, }; @@ -707,6 +704,7 @@ PyInit__io(void) PyTypeObject *base = &PyIOBase_Type; ADD_TYPE(m, state->PyTextIOBase_Type, &textiobase_spec, base); ADD_TYPE(m, state->PyBufferedIOBase_Type, &bufferediobase_spec, base); + ADD_TYPE(m, state->PyRawIOBase_Type, &rawiobase_spec, base); // PyBufferedIOBase_Type(PyIOBase_Type) subclasses base = state->PyBufferedIOBase_Type; @@ -717,7 +715,7 @@ PyInit__io(void) ADD_TYPE(m, state->PyBufferedRandom_Type, &bufferedrandom_spec, base); // PyRawIOBase_Type(PyIOBase_Type) subclasses - base = &PyRawIOBase_Type; + base = state->PyRawIOBase_Type; ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, base); ADD_TYPE(m, state->PyBytesIOBuffer_Type, &bytesiobuf_spec, NULL); // XXX: should be subclass of PyRawIOBase_Type? #ifdef MS_WINDOWS diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index b634bdadbed422..6020d1842bed58 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -9,7 +9,6 @@ /* ABCs */ extern PyTypeObject PyIOBase_Type; -extern PyTypeObject PyRawIOBase_Type; /* Type specs */ extern PyType_Spec bufferediobase_spec; @@ -21,6 +20,7 @@ extern PyType_Spec bytesio_spec; extern PyType_Spec bytesiobuf_spec; extern PyType_Spec fileio_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; @@ -154,6 +154,7 @@ typedef struct { PyTypeObject *PyBytesIO_Type; PyTypeObject *PyFileIO_Type; PyTypeObject *PyIncrementalNewlineDecoder_Type; + PyTypeObject *PyRawIOBase_Type; PyTypeObject *PyStringIO_Type; PyTypeObject *PyTextIOBase_Type; PyTypeObject *PyTextIOWrapper_Type; diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 9777b7614ef057..15b2a9fe5639b5 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -142,7 +142,9 @@ _io_FileIO_close_impl(fileio *self) PyObject *res; PyObject *exc, *val, *tb; int rc; - res = PyObject_CallMethodOneArg((PyObject*)&PyRawIOBase_Type, + + _PyIO_State *state = IO_STATE(); + res = PyObject_CallMethodOneArg((PyObject*)state->PyRawIOBase_Type, &_Py_ID(close), (PyObject *)self); if (!self->closefd) { self->fd = -1; diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 7b9391ec54d732..2937690869d348 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -18,9 +18,9 @@ /*[clinic input] module _io class _io._IOBase "PyObject *" "&PyIOBase_Type" -class _io._RawIOBase "PyObject *" "&PyRawIOBase_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=248f8b2f8bd58b45]*/ /* * IOBase class, an abstract class @@ -786,7 +786,9 @@ _io__IOBase_writelines(PyObject *self, PyObject *lines) Py_RETURN_NONE; } +#define clinic_state() (IO_STATE()) #include "clinic/iobase.c.h" +#undef clinic_state static PyMethodDef iobase_methods[] = { {"seek", iobase_seek, METH_VARARGS, iobase_seek_doc}, @@ -1010,6 +1012,22 @@ rawiobase_write(PyObject *self, PyObject *args) return NULL; } +static void +rawiobase_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + _PyObject_GC_UNTRACK(self); + tp->tp_free(self); + Py_DECREF(tp); +} + +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 @@ -1018,53 +1036,17 @@ 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_dealloc, rawiobase_dealloc}, + {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, }; diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 030ed728111497..6925f088ab7fba 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -137,7 +137,7 @@ char _PyIO_get_console_type(PyObject *path_or_fd) { module _io class _io._WindowsConsoleIO "winconsoleio *" "clinic_state()->PyWindowsConsoleIO_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e897fdc1fba4e131]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=05526e723011ab36]*/ typedef struct { PyObject_HEAD @@ -194,7 +194,9 @@ _io__WindowsConsoleIO_close_impl(winconsoleio *self) PyObject *res; PyObject *exc, *val, *tb; int rc; - res = PyObject_CallMethodOneArg((PyObject*)&PyRawIOBase_Type, + + _PyIO_State *state = IO_STATE(); + res = PyObject_CallMethodOneArg((PyObject*)state->PyRawIOBase_Type, &_Py_ID(close), (PyObject*)self); if (!self->closefd) { self->fd = -1; diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index c6b0a7f5b742a0..26f37c630d257e 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -317,7 +317,6 @@ Modules/_collectionsmodule.c - dequeiter_type - Modules/_collectionsmodule.c - dequereviter_type - Modules/_collectionsmodule.c - tuplegetter_type - Modules/_io/iobase.c - PyIOBase_Type - -Modules/_io/iobase.c - PyRawIOBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type - From be64029e94e565aa0c1ef958460315814917c327 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 15 Feb 2023 23:42:41 +0100 Subject: [PATCH 14/54] IOBase type --- Modules/_io/_iomodule.c | 24 ++---- Modules/_io/_iomodule.h | 5 +- Modules/_io/iobase.c | 84 ++++++++------------- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 - 4 files changed, 38 insertions(+), 76 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 0f4181c28b05a0..1e3142d6f844d8 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -632,19 +632,10 @@ struct PyModuleDef _PyIO_Module = { }; -static PyTypeObject* static_types[] = { - // Base classes - &PyIOBase_Type, -}; - - void _PyIO_Fini(void) { - for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types) - 1; i >= 0; i--) { - PyTypeObject *exc = static_types[i]; - _PyStaticType_Dealloc(exc); - } + return; } #define ADD_TYPE(module, type, spec, base) \ @@ -689,19 +680,14 @@ PyInit__io(void) 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; - } - } - // Concrete classes ADD_TYPE(m, state->PyIncrementalNewlineDecoder_Type, &nldecoder_spec, NULL); + // Base classes + ADD_TYPE(m, state->PyIOBase_Type, &iobase_spec, NULL); + // PyIOBase_Type subclasses - PyTypeObject *base = &PyIOBase_Type; + PyTypeObject *base = state->PyIOBase_Type; ADD_TYPE(m, state->PyTextIOBase_Type, &textiobase_spec, base); ADD_TYPE(m, state->PyBufferedIOBase_Type, &bufferediobase_spec, base); ADD_TYPE(m, state->PyRawIOBase_Type, &rawiobase_spec, base); diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 6020d1842bed58..67432afcf50a5b 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -7,9 +7,6 @@ #include "pycore_moduleobject.h" // _PyModule_GetState() #include "structmember.h" -/* ABCs */ -extern PyTypeObject PyIOBase_Type; - /* Type specs */ extern PyType_Spec bufferediobase_spec; extern PyType_Spec bufferedrandom_spec; @@ -19,6 +16,7 @@ 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; @@ -153,6 +151,7 @@ typedef struct { PyTypeObject *PyBytesIOBuffer_Type; PyTypeObject *PyBytesIO_Type; PyTypeObject *PyFileIO_Type; + PyTypeObject *PyIOBase_Type; PyTypeObject *PyIncrementalNewlineDecoder_Type; PyTypeObject *PyRawIOBase_Type; PyTypeObject *PyStringIO_Type; diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 2937690869d348..98ee3d8c39bd1c 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -17,10 +17,10 @@ /*[clinic input] module _io -class _io._IOBase "PyObject *" "&PyIOBase_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=248f8b2f8bd58b45]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9006b7802ab8ea85]*/ /* * IOBase class, an abstract class @@ -319,6 +319,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; } @@ -348,11 +349,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 */ @@ -825,59 +828,34 @@ static PyGetSetDef iobase_getset[] = { {NULL} }; +static struct PyMemberDef iobase_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(iobase, weakreflist), READONLY}, + {"__dictoffset__", T_PYSSIZET, offsetof(iobase, dict), READONLY}, + {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 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. diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 26f37c630d257e..3ea97aaaf825d9 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -316,7 +316,6 @@ Modules/_collectionsmodule.c - deque_type - Modules/_collectionsmodule.c - dequeiter_type - Modules/_collectionsmodule.c - dequereviter_type - Modules/_collectionsmodule.c - tuplegetter_type - -Modules/_io/iobase.c - PyIOBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorBase_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorDerived_Type - Modules/_testcapi/vectorcall.c - MethodDescriptorNopGet_Type - From 55234a28035bce68e6cc31d48081afe783cfcad4 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 15 Feb 2023 23:43:54 +0100 Subject: [PATCH 15/54] Remove crud --- Modules/_io/_iomodule.c | 7 ------- Python/pylifecycle.c | 6 ------ 2 files changed, 13 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 1e3142d6f844d8..cb516b98c12d3e 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -631,13 +631,6 @@ struct PyModuleDef _PyIO_Module = { (freefunc)iomodule_free, }; - -void -_PyIO_Fini(void) -{ - return; -} - #define ADD_TYPE(module, type, spec, base) \ do { \ type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \ diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 045a2996e8988b..83e17279307d57 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -31,8 +31,6 @@ #include "pycore_unicodeobject.h" // _PyUnicode_InitTypes() #include "opcode.h" -extern void _PyIO_Fini(void); - #include // setlocale() #include // getenv() @@ -1767,10 +1765,6 @@ finalize_interp_clear(PyThreadState *tstate) /* Clear interpreter state and all thread states */ _PyInterpreterState_Clear(tstate); - if (is_main_interp) { - _PyIO_Fini(); - } - /* Clear all loghooks */ /* Both _PySys_Audit function and users still need PyObject, such as tuple. Call _PySys_ClearAuditHooks when PyObject available. */ From 0328a3490e7a6d1ee46ff4a2f5d5147dca4811ef Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 15 Feb 2023 23:45:29 +0100 Subject: [PATCH 16/54] Fixup module def init --- Modules/_io/_iomodule.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index cb516b98c12d3e..c94890e0bfbac0 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -620,15 +620,14 @@ static PyMethodDef module_methods[] = { }; struct PyModuleDef _PyIO_Module = { - PyModuleDef_HEAD_INIT, - "io", - module_doc, - sizeof(_PyIO_State), - module_methods, - NULL, - iomodule_traverse, - iomodule_clear, - (freefunc)iomodule_free, + .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, }; #define ADD_TYPE(module, type, spec, base) \ From a83cf1f6906b7d87574b5f02730c35fb4ab98c4c Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 16 Feb 2023 12:25:51 +0100 Subject: [PATCH 17/54] WIP module state / multi-phase init --- Modules/_io/_iomodule.c | 167 ++++++++++++++++------------ Modules/_io/_iomodule.h | 20 +++- Modules/_io/bufferedio.c | 45 ++++---- Modules/_io/bytesio.c | 11 +- Modules/_io/clinic/bufferedio.c.h | 43 +++++-- Modules/_io/clinic/bytesio.c.h | 14 ++- Modules/_io/clinic/fileio.c.h | 134 ++++++++++++++++------ Modules/_io/clinic/iobase.c.h | 14 ++- Modules/_io/clinic/winconsoleio.c.h | 75 ++++++++++--- Modules/_io/fileio.c | 62 ++++++----- Modules/_io/iobase.c | 33 +++--- Modules/_io/stringio.c | 6 +- Modules/_io/textio.c | 46 ++++---- Modules/_io/winconsoleio.c | 46 +++++--- 14 files changed, 465 insertions(+), 251 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index c94890e0bfbac0..14b0a28ba9ece3 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -386,7 +386,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, return result; } - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = get_io_state(module); /* wraps into a buffered file */ { PyObject *Buffered_class; @@ -562,45 +562,65 @@ 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) { +iomodule_traverse(PyObject *mod, visitproc visit, void *arg) +{ _PyIO_State *state = get_io_state(mod); - if (!state->initialized) - return 0; Py_VISIT(state->locale_module); Py_VISIT(state->unsupported_operation); + + Py_VISIT(state->PyBufferedIOBase_Type); + Py_VISIT(state->PyBufferedRWPair_Type); + Py_VISIT(state->PyBufferedRandom_Type); + Py_VISIT(state->PyBufferedReader_Type); + Py_VISIT(state->PyBufferedWriter_Type); + Py_VISIT(state->PyBytesIOBuffer_Type); + Py_VISIT(state->PyBytesIO_Type); + Py_VISIT(state->PyFileIO_Type); + Py_VISIT(state->PyIOBase_Type); + Py_VISIT(state->PyIncrementalNewlineDecoder_Type); + Py_VISIT(state->PyRawIOBase_Type); + Py_VISIT(state->PyStringIO_Type); + Py_VISIT(state->PyTextIOBase_Type); + Py_VISIT(state->PyTextIOWrapper_Type); +#ifdef MS_WINDOWS + Py_VISIT(state->PyWindowsConsoleIO_Type); +#endif return 0; } static int -iomodule_clear(PyObject *mod) { +iomodule_clear(PyObject *mod) +{ _PyIO_State *state = get_io_state(mod); - if (!state->initialized) - return 0; - if (state->locale_module != NULL) - Py_CLEAR(state->locale_module); + Py_CLEAR(state->locale_module); Py_CLEAR(state->unsupported_operation); + + Py_CLEAR(state->PyBufferedIOBase_Type); + Py_CLEAR(state->PyBufferedRWPair_Type); + Py_CLEAR(state->PyBufferedRandom_Type); + Py_CLEAR(state->PyBufferedReader_Type); + Py_CLEAR(state->PyBufferedWriter_Type); + Py_CLEAR(state->PyBytesIOBuffer_Type); + Py_CLEAR(state->PyBytesIO_Type); + Py_CLEAR(state->PyFileIO_Type); + Py_CLEAR(state->PyIOBase_Type); + Py_CLEAR(state->PyIncrementalNewlineDecoder_Type); + Py_CLEAR(state->PyRawIOBase_Type); + Py_CLEAR(state->PyStringIO_Type); + Py_CLEAR(state->PyTextIOBase_Type); + Py_CLEAR(state->PyTextIOWrapper_Type); +#ifdef MS_WINDOWS + Py_CLEAR(state->PyWindowsConsoleIO_Type); +#endif return 0; } static void -iomodule_free(PyObject *mod) { - iomodule_clear(mod); +iomodule_free(void *mod) +{ + (void)iomodule_clear(mod); } @@ -608,7 +628,7 @@ iomodule_free(PyObject *mod) { * Module definition */ -#define clinic_state() (IO_STATE()) +#define clinic_state() (get_io_state(module)) #include "clinic/_iomodule.c.h" #undef clinic_state @@ -619,59 +639,48 @@ static PyMethodDef module_methods[] = { {NULL, 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, -}; - -#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) +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; + if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0) { + 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; + if (state->unsupported_operation == NULL) { + return -1; + } if (PyModule_AddObject(m, "UnsupportedOperation", Py_NewRef(state->unsupported_operation)) < 0) - goto fail; + { + return -1; + } /* BlockingIOError, for compatibility */ if (PyModule_AddObjectRef(m, "BlockingIOError", - (PyObject *) PyExc_BlockingIOError) < 0) { - goto fail; + (PyObject *) PyExc_BlockingIOError) < 0) + { + return -1; } +#define ADD_TYPE(module, type, spec, base) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \ + (PyObject *)base); \ + if (type == NULL) { \ + return -1; \ + } \ + if (PyModule_AddType(module, type) < 0) { \ + return -1; \ + } \ +} while (0) + // Concrete classes ADD_TYPE(m, state->PyIncrementalNewlineDecoder_Type, &nldecoder_spec, NULL); @@ -705,12 +714,30 @@ PyInit__io(void) ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, base); ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec, base); - state->initialized = 1; +#undef ADD_TYPE - return m; + return 0; +} - fail: - Py_XDECREF(state->unsupported_operation); - Py_DECREF(m); - return NULL; +static struct PyModuleDef_Slot iomodule_slots[] = { + {Py_mod_exec, iomodule_exec}, + {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); } diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 67432afcf50a5b..e90bfd9e4d7ee1 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -137,7 +137,6 @@ extern Py_off_t PyNumber_AsOff_t(PyObject *item, PyObject *err); extern PyModuleDef _PyIO_Module; typedef struct { - int initialized; PyObject *locale_module; PyObject *unsupported_operation; @@ -162,9 +161,6 @@ typedef struct { #endif } _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) { @@ -173,7 +169,21 @@ get_io_state(PyObject *module) return (_PyIO_State *)state; } -extern _PyIO_State *_PyIO_get_module_state(void); +static inline _PyIO_State * +get_io_state_by_cls(PyTypeObject *cls) +{ + void *state = PyType_GetModuleState(cls); + 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); +} #ifdef MS_WINDOWS extern char _PyIO_get_console_type(PyObject *); diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 706c694dc9a9d3..fc3815bbb2ff1a 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -106,17 +106,18 @@ _io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer) } static PyObject * -bufferediobase_unsupported(const char *message) +bufferediobase_unsupported(_PyIO_State *state, const char *message) { - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_SetString(state->unsupported_operation, message); + PyErr_SetString(state->unsupported_operation, message); return NULL; } /*[clinic input] _io._BufferedIOBase.detach + cls: defining_class + / + Disconnect this buffer from its underlying raw stream and return it. After the raw stream has been detached, the buffer is in an unusable @@ -124,10 +125,11 @@ state. [clinic start generated code]*/ static PyObject * -_io__BufferedIOBase_detach_impl(PyObject *self) -/*[clinic end generated code: output=754977c8d10ed88c input=822427fb58fe4169]*/ +_io__BufferedIOBase_detach_impl(PyObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=b87b135d67cd4448 input=0b61a7b4357c1ea7]*/ { - return bufferediobase_unsupported("detach"); + _PyIO_State *state = get_io_state_by_cls(cls); + return bufferediobase_unsupported(state, "detach"); } PyDoc_STRVAR(bufferediobase_read_doc, @@ -151,7 +153,8 @@ PyDoc_STRVAR(bufferediobase_read_doc, static PyObject * bufferediobase_read(PyObject *self, PyObject *args) { - return bufferediobase_unsupported("read"); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + return bufferediobase_unsupported(state, "read"); } PyDoc_STRVAR(bufferediobase_read1_doc, @@ -164,7 +167,8 @@ PyDoc_STRVAR(bufferediobase_read1_doc, static PyObject * bufferediobase_read1(PyObject *self, PyObject *args) { - return bufferediobase_unsupported("read1"); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + return bufferediobase_unsupported(state, "read1"); } PyDoc_STRVAR(bufferediobase_write_doc, @@ -179,7 +183,8 @@ PyDoc_STRVAR(bufferediobase_write_doc, static PyObject * bufferediobase_write(PyObject *self, PyObject *args) { - return bufferediobase_unsupported("write"); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + return bufferediobase_unsupported(state, "write"); } @@ -1287,20 +1292,22 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) /*[clinic input] _io._Buffered.truncate + cls: defining_class pos: object = None / [clinic start generated code]*/ static PyObject * -_io__Buffered_truncate_impl(buffered *self, PyObject *pos) -/*[clinic end generated code: output=667ca03c60c270de input=8a1be34d57cca2d3]*/ +_io__Buffered_truncate_impl(buffered *self, PyTypeObject *cls, PyObject *pos) +/*[clinic end generated code: output=fe3882fbffe79f1a input=f5b737d97d76303f]*/ { PyObject *res = NULL; CHECK_INITIALIZED(self) CHECK_CLOSED(self, "truncate of closed file") if (!self->writable) { - return bufferediobase_unsupported("truncate"); + _PyIO_State *state = get_io_state_by_cls(cls); + return bufferediobase_unsupported(state, "truncate"); } if (!ENTER_BUFFERED(self)) return NULL; @@ -1331,7 +1338,7 @@ buffered_iternext(buffered *self) CHECK_INITIALIZED(self); - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); tp = Py_TYPE(self); if (Py_IS_TYPE(tp, state->PyBufferedReader_Type) || Py_IS_TYPE(tp, state->PyBufferedRandom_Type)) @@ -1433,7 +1440,7 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, return -1; _bufferedreader_reset_buf(self); - _PyIO_State *state = IO_STATE(); + _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) @@ -1791,7 +1798,7 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, _bufferedwriter_reset_buf(self); self->pos = 0; - _PyIO_State *state = IO_STATE(); + _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) @@ -2101,7 +2108,7 @@ _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, if (_PyIOBase_check_writable(writer, Py_True) == NULL) return -1; - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); self->reader = (buffered *) PyObject_CallFunction( (PyObject *)state->PyBufferedReader_Type, "On", reader, buffer_size); @@ -2311,7 +2318,7 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, _bufferedwriter_reset_buf(self); self->pos = 0; - _PyIO_State *state = IO_STATE(); + _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)); @@ -2319,7 +2326,7 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, return 0; } -#define clinic_state() (IO_STATE()) +#define clinic_state() (find_io_state_by_def(Py_TYPE(self))) #include "clinic/bufferedio.c.h" #undef clinic_state diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 84db3c03084135..6a7d9fad8a2a83 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -308,14 +308,17 @@ _io_BytesIO_flush_impl(bytesio *self) /*[clinic input] _io.BytesIO.getbuffer + cls: defining_class + / + Get a read-write view over the contents of the BytesIO object. [clinic start generated code]*/ static PyObject * -_io_BytesIO_getbuffer_impl(bytesio *self) -/*[clinic end generated code: output=72cd7c6e13aa09ed input=8f738ef615865176]*/ +_io_BytesIO_getbuffer_impl(bytesio *self, PyTypeObject *cls) +/*[clinic end generated code: output=045091d7ce87fe4e input=0668fbb48f95dffa]*/ { - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = get_io_state_by_cls(cls); PyTypeObject *type = state->PyBytesIOBuffer_Type; bytesiobuf *buf; PyObject *view; @@ -987,7 +990,7 @@ bytesio_clear(bytesio *self) } -#define clinic_state() (IO_STATE()) +#define clinic_state() (find_io_state_by_def(Py_TYPE(self))) #include "clinic/bytesio.c.h" #undef clinic_state diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h index d44321bb8b960e..f92bade7435f03 100644 --- a/Modules/_io/clinic/bufferedio.c.h +++ b/Modules/_io/clinic/bufferedio.c.h @@ -92,15 +92,19 @@ PyDoc_STRVAR(_io__BufferedIOBase_detach__doc__, "state."); #define _IO__BUFFEREDIOBASE_DETACH_METHODDEF \ - {"detach", (PyCFunction)_io__BufferedIOBase_detach, METH_NOARGS, _io__BufferedIOBase_detach__doc__}, + {"detach", _PyCFunction_CAST(_io__BufferedIOBase_detach), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__BufferedIOBase_detach__doc__}, static PyObject * -_io__BufferedIOBase_detach_impl(PyObject *self); +_io__BufferedIOBase_detach_impl(PyObject *self, PyTypeObject *cls); static PyObject * -_io__BufferedIOBase_detach(PyObject *self, PyObject *Py_UNUSED(ignored)) +_io__BufferedIOBase_detach(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _io__BufferedIOBase_detach_impl(self); + if (nargs) { + PyErr_SetString(PyExc_TypeError, "detach() takes no arguments"); + return NULL; + } + return _io__BufferedIOBase_detach_impl(self, cls); } PyDoc_STRVAR(_io__Buffered_peek__doc__, @@ -369,26 +373,41 @@ PyDoc_STRVAR(_io__Buffered_truncate__doc__, "\n"); #define _IO__BUFFERED_TRUNCATE_METHODDEF \ - {"truncate", _PyCFunction_CAST(_io__Buffered_truncate), METH_FASTCALL, _io__Buffered_truncate__doc__}, + {"truncate", _PyCFunction_CAST(_io__Buffered_truncate), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__Buffered_truncate__doc__}, static PyObject * -_io__Buffered_truncate_impl(buffered *self, PyObject *pos); +_io__Buffered_truncate_impl(buffered *self, PyTypeObject *cls, PyObject *pos); static PyObject * -_io__Buffered_truncate(buffered *self, PyObject *const *args, Py_ssize_t nargs) +_io__Buffered_truncate(buffered *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "truncate", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; PyObject *pos = Py_None; - if (!_PyArg_CheckPositional("truncate", nargs, 0, 1)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { goto exit; } if (nargs < 1) { - goto skip_optional; + goto skip_optional_posonly; } pos = args[0]; -skip_optional: - return_value = _io__Buffered_truncate_impl(self, pos); +skip_optional_posonly: + return_value = _io__Buffered_truncate_impl(self, cls, pos); exit: return return_value; @@ -714,4 +733,4 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=8412b10c04259bb8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=da047f54b16cb309 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bytesio.c.h b/Modules/_io/clinic/bytesio.c.h index 84b58db6c7a702..9550c8728c251e 100644 --- a/Modules/_io/clinic/bytesio.c.h +++ b/Modules/_io/clinic/bytesio.c.h @@ -87,15 +87,19 @@ PyDoc_STRVAR(_io_BytesIO_getbuffer__doc__, "Get a read-write view over the contents of the BytesIO object."); #define _IO_BYTESIO_GETBUFFER_METHODDEF \ - {"getbuffer", (PyCFunction)_io_BytesIO_getbuffer, METH_NOARGS, _io_BytesIO_getbuffer__doc__}, + {"getbuffer", _PyCFunction_CAST(_io_BytesIO_getbuffer), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io_BytesIO_getbuffer__doc__}, static PyObject * -_io_BytesIO_getbuffer_impl(bytesio *self); +_io_BytesIO_getbuffer_impl(bytesio *self, PyTypeObject *cls); static PyObject * -_io_BytesIO_getbuffer(bytesio *self, PyObject *Py_UNUSED(ignored)) +_io_BytesIO_getbuffer(bytesio *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _io_BytesIO_getbuffer_impl(self); + if (nargs) { + PyErr_SetString(PyExc_TypeError, "getbuffer() takes no arguments"); + return NULL; + } + return _io_BytesIO_getbuffer_impl(self, cls); } PyDoc_STRVAR(_io_BytesIO_getvalue__doc__, @@ -534,4 +538,4 @@ _io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=a44770efbaeb80dd input=a9049054013a1b77]*/ +/*[clinic end generated code: output=098584d485420b65 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/fileio.c.h b/Modules/_io/clinic/fileio.c.h index b6e9bd5b65a029..33a37a389d223d 100644 --- a/Modules/_io/clinic/fileio.c.h +++ b/Modules/_io/clinic/fileio.c.h @@ -18,15 +18,19 @@ PyDoc_STRVAR(_io_FileIO_close__doc__, "called more than once without error."); #define _IO_FILEIO_CLOSE_METHODDEF \ - {"close", (PyCFunction)_io_FileIO_close, METH_NOARGS, _io_FileIO_close__doc__}, + {"close", _PyCFunction_CAST(_io_FileIO_close), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io_FileIO_close__doc__}, static PyObject * -_io_FileIO_close_impl(fileio *self); +_io_FileIO_close_impl(fileio *self, PyTypeObject *cls); static PyObject * -_io_FileIO_close(fileio *self, PyObject *Py_UNUSED(ignored)) +_io_FileIO_close(fileio *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _io_FileIO_close_impl(self); + if (nargs) { + PyErr_SetString(PyExc_TypeError, "close() takes no arguments"); + return NULL; + } + return _io_FileIO_close_impl(self, cls); } PyDoc_STRVAR(_io_FileIO___init____doc__, @@ -211,27 +215,45 @@ PyDoc_STRVAR(_io_FileIO_readinto__doc__, "Same as RawIOBase.readinto()."); #define _IO_FILEIO_READINTO_METHODDEF \ - {"readinto", (PyCFunction)_io_FileIO_readinto, METH_O, _io_FileIO_readinto__doc__}, + {"readinto", _PyCFunction_CAST(_io_FileIO_readinto), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io_FileIO_readinto__doc__}, static PyObject * -_io_FileIO_readinto_impl(fileio *self, Py_buffer *buffer); +_io_FileIO_readinto_impl(fileio *self, PyTypeObject *cls, Py_buffer *buffer); static PyObject * -_io_FileIO_readinto(fileio *self, PyObject *arg) +_io_FileIO_readinto(fileio *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "readinto", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; Py_buffer buffer = {NULL, NULL}; - if (PyObject_GetBuffer(arg, &buffer, PyBUF_WRITABLE) < 0) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (PyObject_GetBuffer(args[0], &buffer, PyBUF_WRITABLE) < 0) { PyErr_Clear(); - _PyArg_BadArgument("readinto", "argument", "read-write bytes-like object", arg); + _PyArg_BadArgument("readinto", "argument 1", "read-write bytes-like object", args[0]); goto exit; } if (!PyBuffer_IsContiguous(&buffer, 'C')) { - _PyArg_BadArgument("readinto", "argument", "contiguous buffer", arg); + _PyArg_BadArgument("readinto", "argument 1", "contiguous buffer", args[0]); goto exit; } - return_value = _io_FileIO_readinto_impl(self, &buffer); + return_value = _io_FileIO_readinto_impl(self, cls, &buffer); exit: /* Cleanup for buffer */ @@ -274,28 +296,43 @@ PyDoc_STRVAR(_io_FileIO_read__doc__, "Return an empty bytes object at EOF."); #define _IO_FILEIO_READ_METHODDEF \ - {"read", _PyCFunction_CAST(_io_FileIO_read), METH_FASTCALL, _io_FileIO_read__doc__}, + {"read", _PyCFunction_CAST(_io_FileIO_read), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io_FileIO_read__doc__}, static PyObject * -_io_FileIO_read_impl(fileio *self, Py_ssize_t size); +_io_FileIO_read_impl(fileio *self, PyTypeObject *cls, Py_ssize_t size); static PyObject * -_io_FileIO_read(fileio *self, PyObject *const *args, Py_ssize_t nargs) +_io_FileIO_read(fileio *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "read", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; Py_ssize_t size = -1; - if (!_PyArg_CheckPositional("read", nargs, 0, 1)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { goto exit; } if (nargs < 1) { - goto skip_optional; + goto skip_optional_posonly; } if (!_Py_convert_optional_to_ssize_t(args[0], &size)) { goto exit; } -skip_optional: - return_value = _io_FileIO_read_impl(self, size); +skip_optional_posonly: + return_value = _io_FileIO_read_impl(self, cls, size); exit: return return_value; @@ -312,25 +349,43 @@ PyDoc_STRVAR(_io_FileIO_write__doc__, "returns None if the write would block."); #define _IO_FILEIO_WRITE_METHODDEF \ - {"write", (PyCFunction)_io_FileIO_write, METH_O, _io_FileIO_write__doc__}, + {"write", _PyCFunction_CAST(_io_FileIO_write), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io_FileIO_write__doc__}, static PyObject * -_io_FileIO_write_impl(fileio *self, Py_buffer *b); +_io_FileIO_write_impl(fileio *self, PyTypeObject *cls, Py_buffer *b); static PyObject * -_io_FileIO_write(fileio *self, PyObject *arg) +_io_FileIO_write(fileio *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "write", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; Py_buffer b = {NULL, NULL}; - if (PyObject_GetBuffer(arg, &b, PyBUF_SIMPLE) != 0) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (PyObject_GetBuffer(args[0], &b, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument 1", "contiguous buffer", args[0]); goto exit; } - return_value = _io_FileIO_write_impl(self, &b); + return_value = _io_FileIO_write_impl(self, cls, &b); exit: /* Cleanup for b */ @@ -418,26 +473,41 @@ PyDoc_STRVAR(_io_FileIO_truncate__doc__, "The current file position is changed to the value of size."); #define _IO_FILEIO_TRUNCATE_METHODDEF \ - {"truncate", _PyCFunction_CAST(_io_FileIO_truncate), METH_FASTCALL, _io_FileIO_truncate__doc__}, + {"truncate", _PyCFunction_CAST(_io_FileIO_truncate), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io_FileIO_truncate__doc__}, static PyObject * -_io_FileIO_truncate_impl(fileio *self, PyObject *posobj); +_io_FileIO_truncate_impl(fileio *self, PyTypeObject *cls, PyObject *posobj); static PyObject * -_io_FileIO_truncate(fileio *self, PyObject *const *args, Py_ssize_t nargs) +_io_FileIO_truncate(fileio *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "truncate", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; PyObject *posobj = Py_None; - if (!_PyArg_CheckPositional("truncate", nargs, 0, 1)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { goto exit; } if (nargs < 1) { - goto skip_optional; + goto skip_optional_posonly; } posobj = args[0]; -skip_optional: - return_value = _io_FileIO_truncate_impl(self, posobj); +skip_optional_posonly: + return_value = _io_FileIO_truncate_impl(self, cls, posobj); exit: return return_value; @@ -466,4 +536,4 @@ _io_FileIO_isatty(fileio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO_FILEIO_TRUNCATE_METHODDEF #define _IO_FILEIO_TRUNCATE_METHODDEF #endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */ -/*[clinic end generated code: output=27f883807a6c29ae input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bef47b31b644996a input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/iobase.c.h b/Modules/_io/clinic/iobase.c.h index 01c035dad2641e..d3d537f6a1a0ef 100644 --- a/Modules/_io/clinic/iobase.c.h +++ b/Modules/_io/clinic/iobase.c.h @@ -136,15 +136,19 @@ PyDoc_STRVAR(_io__IOBase_fileno__doc__, "OSError is raised if the IO object does not use a file descriptor."); #define _IO__IOBASE_FILENO_METHODDEF \ - {"fileno", (PyCFunction)_io__IOBase_fileno, METH_NOARGS, _io__IOBase_fileno__doc__}, + {"fileno", _PyCFunction_CAST(_io__IOBase_fileno), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__IOBase_fileno__doc__}, static PyObject * -_io__IOBase_fileno_impl(PyObject *self); +_io__IOBase_fileno_impl(PyObject *self, PyTypeObject *cls); static PyObject * -_io__IOBase_fileno(PyObject *self, PyObject *Py_UNUSED(ignored)) +_io__IOBase_fileno(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _io__IOBase_fileno_impl(self); + if (nargs) { + PyErr_SetString(PyExc_TypeError, "fileno() takes no arguments"); + return NULL; + } + return _io__IOBase_fileno_impl(self, cls); } PyDoc_STRVAR(_io__IOBase_isatty__doc__, @@ -316,4 +320,4 @@ _io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored)) { return _io__RawIOBase_readall_impl(self); } -/*[clinic end generated code: output=b7246a2087eb966b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=98f212f95ac26d74 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/winconsoleio.c.h b/Modules/_io/clinic/winconsoleio.c.h index df834dbde40f5b..d5544a3cd5b077 100644 --- a/Modules/_io/clinic/winconsoleio.c.h +++ b/Modules/_io/clinic/winconsoleio.c.h @@ -20,15 +20,19 @@ PyDoc_STRVAR(_io__WindowsConsoleIO_close__doc__, "close() may be called more than once without error."); #define _IO__WINDOWSCONSOLEIO_CLOSE_METHODDEF \ - {"close", (PyCFunction)_io__WindowsConsoleIO_close, METH_NOARGS, _io__WindowsConsoleIO_close__doc__}, + {"close", _PyCFunction_CAST(_io__WindowsConsoleIO_close), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__WindowsConsoleIO_close__doc__}, static PyObject * -_io__WindowsConsoleIO_close_impl(winconsoleio *self); +_io__WindowsConsoleIO_close_impl(winconsoleio *self, PyTypeObject *cls); static PyObject * -_io__WindowsConsoleIO_close(winconsoleio *self, PyObject *Py_UNUSED(ignored)) +_io__WindowsConsoleIO_close(winconsoleio *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _io__WindowsConsoleIO_close_impl(self); + if (nargs) { + PyErr_SetString(PyExc_TypeError, "close() takes no arguments"); + return NULL; + } + return _io__WindowsConsoleIO_close_impl(self, cls); } #endif /* defined(MS_WINDOWS) */ @@ -278,28 +282,44 @@ PyDoc_STRVAR(_io__WindowsConsoleIO_read__doc__, "Return an empty bytes object at EOF."); #define _IO__WINDOWSCONSOLEIO_READ_METHODDEF \ - {"read", _PyCFunction_CAST(_io__WindowsConsoleIO_read), METH_FASTCALL, _io__WindowsConsoleIO_read__doc__}, + {"read", _PyCFunction_CAST(_io__WindowsConsoleIO_read), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__WindowsConsoleIO_read__doc__}, static PyObject * -_io__WindowsConsoleIO_read_impl(winconsoleio *self, Py_ssize_t size); +_io__WindowsConsoleIO_read_impl(winconsoleio *self, PyTypeObject *cls, + Py_ssize_t size); static PyObject * -_io__WindowsConsoleIO_read(winconsoleio *self, PyObject *const *args, Py_ssize_t nargs) +_io__WindowsConsoleIO_read(winconsoleio *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "read", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; Py_ssize_t size = -1; - if (!_PyArg_CheckPositional("read", nargs, 0, 1)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { goto exit; } if (nargs < 1) { - goto skip_optional; + goto skip_optional_posonly; } if (!_Py_convert_optional_to_ssize_t(args[0], &size)) { goto exit; } -skip_optional: - return_value = _io__WindowsConsoleIO_read_impl(self, size); +skip_optional_posonly: + return_value = _io__WindowsConsoleIO_read_impl(self, cls, size); exit: return return_value; @@ -319,25 +339,44 @@ PyDoc_STRVAR(_io__WindowsConsoleIO_write__doc__, "The number of bytes actually written is returned."); #define _IO__WINDOWSCONSOLEIO_WRITE_METHODDEF \ - {"write", (PyCFunction)_io__WindowsConsoleIO_write, METH_O, _io__WindowsConsoleIO_write__doc__}, + {"write", _PyCFunction_CAST(_io__WindowsConsoleIO_write), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__WindowsConsoleIO_write__doc__}, static PyObject * -_io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b); +_io__WindowsConsoleIO_write_impl(winconsoleio *self, PyTypeObject *cls, + Py_buffer *b); static PyObject * -_io__WindowsConsoleIO_write(winconsoleio *self, PyObject *arg) +_io__WindowsConsoleIO_write(winconsoleio *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "write", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; Py_buffer b = {NULL, NULL}; - if (PyObject_GetBuffer(arg, &b, PyBUF_SIMPLE) != 0) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (PyObject_GetBuffer(args[0], &b, PyBUF_SIMPLE) != 0) { goto exit; } if (!PyBuffer_IsContiguous(&b, 'C')) { - _PyArg_BadArgument("write", "argument", "contiguous buffer", arg); + _PyArg_BadArgument("write", "argument 1", "contiguous buffer", args[0]); goto exit; } - return_value = _io__WindowsConsoleIO_write_impl(self, &b); + return_value = _io__WindowsConsoleIO_write_impl(self, cls, &b); exit: /* Cleanup for b */ @@ -407,4 +446,4 @@ _io__WindowsConsoleIO_isatty(winconsoleio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #define _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #endif /* !defined(_IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF) */ -/*[clinic end generated code: output=4920e9068e0cf08a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0bee002cc60d86d0 input=a9049054013a1b77]*/ diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 15b2a9fe5639b5..73987e0250ad08 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -129,6 +129,9 @@ internal_close(fileio *self) /*[clinic input] _io.FileIO.close + cls: defining_class + / + Close the file. A closed file cannot be used for further I/O operations. close() may be @@ -136,14 +139,14 @@ called more than once without error. [clinic start generated code]*/ static PyObject * -_io_FileIO_close_impl(fileio *self) -/*[clinic end generated code: output=7737a319ef3bad0b input=f35231760d54a522]*/ +_io_FileIO_close_impl(fileio *self, PyTypeObject *cls) +/*[clinic end generated code: output=c30cbe9d1f23ca58 input=70da49e63db7c64d]*/ { PyObject *res; PyObject *exc, *val, *tb; int rc; - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = get_io_state_by_cls(cls); res = PyObject_CallMethodOneArg((PyObject*)state->PyRawIOBase_Type, &_Py_ID(close), (PyObject *)self); if (!self->closefd) { @@ -242,7 +245,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, int fstat_result; int async_err = 0; - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); assert(PyFileIO_Check(state, self)); if (self->fd >= 0) { if (self->closefd) { @@ -539,12 +542,9 @@ err_closed(void) } static PyObject * -err_mode(const char *action) +err_mode(_PyIO_State *state, const char *action) { - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_Format(state->unsupported_operation, - "File not open for %s", action); + PyErr_Format(state->unsupported_operation, "File not open for %s", action); return NULL; } @@ -621,6 +621,7 @@ _io_FileIO_seekable_impl(fileio *self) /*[clinic input] _io.FileIO.readinto + cls: defining_class buffer: Py_buffer(accept={rwbuffer}) / @@ -628,16 +629,18 @@ Same as RawIOBase.readinto(). [clinic start generated code]*/ static PyObject * -_io_FileIO_readinto_impl(fileio *self, Py_buffer *buffer) -/*[clinic end generated code: output=b01a5a22c8415cb4 input=4721d7b68b154eaf]*/ +_io_FileIO_readinto_impl(fileio *self, PyTypeObject *cls, Py_buffer *buffer) +/*[clinic end generated code: output=97f0f3d69534db34 input=fd20323e18ce1ec8]*/ { Py_ssize_t n; int err; if (self->fd < 0) return err_closed(); - if (!self->readable) - return err_mode("reading"); + if (!self->readable) { + _PyIO_State *state = get_io_state_by_cls(cls); + return err_mode(state, "reading"); + } n = _Py_read(self->fd, buffer->buf, buffer->len); /* copy errno because PyBuffer_Release() can indirectly modify it */ @@ -774,6 +777,7 @@ _io_FileIO_readall_impl(fileio *self) /*[clinic input] _io.FileIO.read + cls: defining_class size: Py_ssize_t(accept={int, NoneType}) = -1 / @@ -785,8 +789,8 @@ Return an empty bytes object at EOF. [clinic start generated code]*/ static PyObject * -_io_FileIO_read_impl(fileio *self, Py_ssize_t size) -/*[clinic end generated code: output=42528d39dd0ca641 input=bec9a2c704ddcbc9]*/ +_io_FileIO_read_impl(fileio *self, PyTypeObject *cls, Py_ssize_t size) +/*[clinic end generated code: output=bbd749c7c224143e input=f613d2057e4a1918]*/ { char *ptr; Py_ssize_t n; @@ -794,8 +798,10 @@ _io_FileIO_read_impl(fileio *self, Py_ssize_t size) if (self->fd < 0) return err_closed(); - if (!self->readable) - return err_mode("reading"); + if (!self->readable) { + _PyIO_State *state = get_io_state_by_cls(cls); + return err_mode(state, "reading"); + } if (size < 0) return _io_FileIO_readall_impl(self); @@ -833,6 +839,7 @@ _io_FileIO_read_impl(fileio *self, Py_ssize_t size) /*[clinic input] _io.FileIO.write + cls: defining_class b: Py_buffer / @@ -844,16 +851,18 @@ returns None if the write would block. [clinic start generated code]*/ static PyObject * -_io_FileIO_write_impl(fileio *self, Py_buffer *b) -/*[clinic end generated code: output=b4059db3d363a2f7 input=6e7908b36f0ce74f]*/ +_io_FileIO_write_impl(fileio *self, PyTypeObject *cls, Py_buffer *b) +/*[clinic end generated code: output=927e25be80f3b77b input=2776314f043088f5]*/ { Py_ssize_t n; int err; if (self->fd < 0) return err_closed(); - if (!self->writable) - return err_mode("writing"); + if (!self->writable) { + _PyIO_State *state = get_io_state_by_cls(cls); + return err_mode(state, "writing"); + } n = _Py_write(self->fd, b->buf, b->len); /* copy errno because PyBuffer_Release() can indirectly modify it */ @@ -984,6 +993,7 @@ _io_FileIO_tell_impl(fileio *self) #ifdef HAVE_FTRUNCATE /*[clinic input] _io.FileIO.truncate + cls: defining_class size as posobj: object = None / @@ -994,8 +1004,8 @@ The current file position is changed to the value of size. [clinic start generated code]*/ static PyObject * -_io_FileIO_truncate_impl(fileio *self, PyObject *posobj) -/*[clinic end generated code: output=e49ca7a916c176fa input=b0ac133939823875]*/ +_io_FileIO_truncate_impl(fileio *self, PyTypeObject *cls, PyObject *posobj) +/*[clinic end generated code: output=d936732a49e8d5a2 input=c367fb45d6bb2c18]*/ { Py_off_t pos; int ret; @@ -1004,8 +1014,10 @@ _io_FileIO_truncate_impl(fileio *self, PyObject *posobj) fd = self->fd; if (fd < 0) return err_closed(); - if (!self->writable) - return err_mode("writing"); + if (!self->writable) { + _PyIO_State *state = get_io_state_by_cls(cls); + return err_mode(state, "writing"); + } if (posobj == Py_None) { /* Get the current position. */ diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 98ee3d8c39bd1c..de79f6c5b545d6 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -71,11 +71,9 @@ PyDoc_STRVAR(iobase_doc, /* Internal methods */ static PyObject * -iobase_unsupported(const char *message) +iobase_unsupported(_PyIO_State *state, const char *message) { - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_SetString(state->unsupported_operation, message); + PyErr_SetString(state->unsupported_operation, message); return NULL; } @@ -97,7 +95,8 @@ PyDoc_STRVAR(iobase_seek_doc, static PyObject * iobase_seek(PyObject *self, PyObject *args) { - return iobase_unsupported("seek"); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + return iobase_unsupported(state, "seek"); } /*[clinic input] @@ -122,7 +121,8 @@ PyDoc_STRVAR(iobase_truncate_doc, static PyObject * iobase_truncate(PyObject *self, PyObject *args) { - return iobase_unsupported("truncate"); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + return iobase_unsupported(state, "truncate"); } static int @@ -384,7 +384,8 @@ _PyIOBase_check_seekable(PyObject *self, PyObject *args) return NULL; if (res != Py_True) { Py_CLEAR(res); - iobase_unsupported("File or stream is not seekable."); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + iobase_unsupported(state, "File or stream is not seekable."); return NULL; } if (args == Py_True) { @@ -417,7 +418,8 @@ _PyIOBase_check_readable(PyObject *self, PyObject *args) return NULL; if (res != Py_True) { Py_CLEAR(res); - iobase_unsupported("File or stream is not readable."); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + iobase_unsupported(state, "File or stream is not readable."); return NULL; } if (args == Py_True) { @@ -450,7 +452,8 @@ _PyIOBase_check_writable(PyObject *self, PyObject *args) return NULL; if (res != Py_True) { Py_CLEAR(res); - iobase_unsupported("File or stream is not writable."); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + iobase_unsupported(state, "File or stream is not writable."); return NULL; } if (args == Py_True) { @@ -483,16 +486,20 @@ iobase_exit(PyObject *self, PyObject *args) /*[clinic input] _io._IOBase.fileno + cls: defining_class + / + Returns underlying file descriptor if one exists. OSError is raised if the IO object does not use a file descriptor. [clinic start generated code]*/ static PyObject * -_io__IOBase_fileno_impl(PyObject *self) -/*[clinic end generated code: output=7cc0973f0f5f3b73 input=4e37028947dc1cc8]*/ +_io__IOBase_fileno_impl(PyObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=7caaa32a6f4ada3d input=9e960cc21e8889a3]*/ { - return iobase_unsupported("fileno"); + _PyIO_State *state = get_io_state_by_cls(cls); + return iobase_unsupported(state, "fileno"); } /*[clinic input] @@ -789,7 +796,7 @@ _io__IOBase_writelines(PyObject *self, PyObject *lines) Py_RETURN_NONE; } -#define clinic_state() (IO_STATE()) +#define clinic_state() (find_io_state_by_def(Py_TYPE(self))) #include "clinic/iobase.c.h" #undef clinic_state diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index e0f3b6d8d26804..1b4a0120a4c02f 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -401,7 +401,7 @@ stringio_iternext(stringio *self) CHECK_CLOSED(self); ENSURE_REALIZED(self); - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); if (Py_IS_TYPE(self, state->PyStringIO_Type)) { /* Skip method call overhead for speed */ line = _stringio_readline(self, -1); @@ -717,7 +717,7 @@ _io_StringIO___init___impl(stringio *self, PyObject *value, } if (self->readuniversal) { - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); self->decoder = PyObject_CallFunctionObjArgs( (PyObject *)state->PyIncrementalNewlineDecoder_Type, Py_None, self->readtranslate ? Py_True : Py_False, NULL); @@ -969,7 +969,7 @@ stringio_newlines(stringio *self, void *context) return PyObject_GetAttr(self->decoder, &_Py_ID(newlines)); } -#define clinic_state() (IO_STATE()) +#define clinic_state() (find_io_state_by_def(Py_TYPE(self))) #include "clinic/stringio.c.h" #undef clinic_state diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 1b0a310fc6191c..b4c74fa8e7ade7 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -34,11 +34,9 @@ PyDoc_STRVAR(textiobase_doc, ); static PyObject * -_unsupported(const char *message) +_unsupported(_PyIO_State *state, const char *message) { - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_SetString(state->unsupported_operation, message); + PyErr_SetString(state->unsupported_operation, message); return NULL; } @@ -52,7 +50,8 @@ PyDoc_STRVAR(textiobase_detach_doc, static PyObject * textiobase_detach(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return _unsupported("detach"); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + return _unsupported(state, "detach"); } PyDoc_STRVAR(textiobase_read_doc, @@ -65,7 +64,8 @@ PyDoc_STRVAR(textiobase_read_doc, static PyObject * textiobase_read(PyObject *self, PyObject *args) { - return _unsupported("read"); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + return _unsupported(state, "read"); } PyDoc_STRVAR(textiobase_readline_doc, @@ -77,7 +77,8 @@ PyDoc_STRVAR(textiobase_readline_doc, static PyObject * textiobase_readline(PyObject *self, PyObject *args) { - return _unsupported("readline"); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + return _unsupported(state, "readline"); } PyDoc_STRVAR(textiobase_write_doc, @@ -89,7 +90,8 @@ PyDoc_STRVAR(textiobase_write_doc, static PyObject * textiobase_write(PyObject *self, PyObject *args) { - return _unsupported("write"); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + return _unsupported(state, "write"); } PyDoc_STRVAR(textiobase_encoding_doc, @@ -871,7 +873,7 @@ _textiowrapper_set_decoder(textio *self, PyObject *codec_info, return -1; if (self->readuniversal) { - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = self->state; PyObject *incrementalDecoder = PyObject_CallFunctionObjArgs( (PyObject *)state->PyIncrementalNewlineDecoder_Type, self->decoder, self->readtranslate ? Py_True : Py_False, NULL); @@ -888,7 +890,7 @@ _textiowrapper_decode(PyObject *decoder, PyObject *bytes, int eof) { PyObject *chars; - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(decoder)); if (Py_IS_TYPE(decoder, state->PyIncrementalNewlineDecoder_Type)) chars = _PyIncrementalNewlineDecoder_decode(decoder, bytes, eof); else @@ -1178,7 +1180,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, /* Finished sorting out the codec details */ Py_CLEAR(codec_info); - _PyIO_State *state = IO_STATE(); + _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)) @@ -1328,7 +1330,8 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding, /* Check if something is in the read buffer */ if (self->decoded_chars != NULL) { if (encoding != Py_None || errors != Py_None || newline_obj != NULL) { - _unsupported("It is not possible to set the encoding or newline " + _unsupported(self->state, + "It is not possible to set the encoding or newline " "of stream after the first read"); return NULL; } @@ -1596,7 +1599,7 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text) CHECK_CLOSED(self); if (self->encoder == NULL) - return _unsupported("not writable"); + return _unsupported(self->state, "not writable"); Py_INCREF(text); @@ -1777,7 +1780,7 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint) */ if (self->decoder == NULL) { - _unsupported("not readable"); + _unsupported(self->state, "not readable"); return -1; } @@ -1902,7 +1905,7 @@ _io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n) CHECK_CLOSED(self); if (self->decoder == NULL) - return _unsupported("not readable"); + return _unsupported(self->state, "not readable"); if (_textiowrapper_writeflush(self) < 0) return NULL; @@ -2433,7 +2436,7 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) Py_INCREF(cookieObj); if (!self->seekable) { - _unsupported("underlying stream is not seekable"); + _unsupported(self->state, "underlying stream is not seekable"); goto fail; } @@ -2447,7 +2450,7 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) goto fail; if (cmp == 0) { - _unsupported("can't do nonzero cur-relative seeks"); + _unsupported(self->state, "can't do nonzero cur-relative seeks"); goto fail; } @@ -2467,7 +2470,7 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) goto fail; if (cmp == 0) { - _unsupported("can't do nonzero end-relative seeks"); + _unsupported(self->state, "can't do nonzero end-relative seeks"); goto fail; } @@ -2630,7 +2633,7 @@ _io_TextIOWrapper_tell_impl(textio *self) CHECK_CLOSED(self); if (!self->seekable) { - _unsupported("underlying stream is not seekable"); + _unsupported(self->state, "underlying stream is not seekable"); goto fail; } if (!self->telling) { @@ -3062,8 +3065,7 @@ textiowrapper_iternext(textio *self) CHECK_ATTACHED(self); self->telling = 0; - _PyIO_State *state = IO_STATE(); - if (Py_IS_TYPE(self, state->PyTextIOWrapper_Type)) { + if (Py_IS_TYPE(self, self->state->PyTextIOWrapper_Type)) { /* Skip method call overhead for speed */ line = _textiowrapper_readline(self, -1); } @@ -3155,7 +3157,7 @@ textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context) return 0; } -#define clinic_state() (IO_STATE()) +#define clinic_state() (find_io_state_by_def(Py_TYPE(self))) #include "clinic/textio.c.h" #undef clinic_state diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 6925f088ab7fba..4e4343a63480a8 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -181,6 +181,9 @@ internal_close(winconsoleio *self) /*[clinic input] _io._WindowsConsoleIO.close + cls: defining_class + / + Close the console object. A closed console object cannot be used for further I/O operations. @@ -188,14 +191,14 @@ close() may be called more than once without error. [clinic start generated code]*/ static PyObject * -_io__WindowsConsoleIO_close_impl(winconsoleio *self) -/*[clinic end generated code: output=27ef95b66c29057b input=68c4e5754f8136c2]*/ +_io__WindowsConsoleIO_close_impl(winconsoleio *self, PyTypeObject *cls) +/*[clinic end generated code: output=e50c1808c063e1e2 input=f200f26059fb2ecf]*/ { PyObject *res; PyObject *exc, *val, *tb; int rc; - _PyIO_State *state = IO_STATE(); + _PyIO_State *state = get_io_state_by_cls(cls); res = PyObject_CallMethodOneArg((PyObject*)state->PyRawIOBase_Type, &_Py_ID(close), (PyObject*)self); if (!self->closefd) { @@ -449,12 +452,10 @@ err_closed(void) } static PyObject * -err_mode(const char *action) +err_mode(_PyIO_State *state, const char *action) { - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_Format(state->unsupported_operation, - "Console buffer does not support %s", action); + PyErr_Format(state->unsupported_operation, + "Console buffer does not support %s", action); return NULL; } @@ -639,7 +640,8 @@ readinto(winconsoleio *self, char *buf, Py_ssize_t len) return -1; } if (!self->readable) { - err_mode("reading"); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + err_mode(state, "reading"); return -1; } if (len == 0) @@ -893,6 +895,7 @@ _io__WindowsConsoleIO_readall_impl(winconsoleio *self) /*[clinic input] _io._WindowsConsoleIO.read + cls: defining_class size: Py_ssize_t(accept={int, NoneType}) = -1 / @@ -904,16 +907,19 @@ Return an empty bytes object at EOF. [clinic start generated code]*/ static PyObject * -_io__WindowsConsoleIO_read_impl(winconsoleio *self, Py_ssize_t size) -/*[clinic end generated code: output=57df68af9f4b22d0 input=8bc73bc15d0fa072]*/ +_io__WindowsConsoleIO_read_impl(winconsoleio *self, PyTypeObject *cls, + Py_ssize_t size) +/*[clinic end generated code: output=7e569a586537c0ae input=a14570a5da273365]*/ { PyObject *bytes; Py_ssize_t bytes_size; if (self->fd == -1) return err_closed(); - if (!self->readable) - return err_mode("reading"); + if (!self->readable) { + _PyIO_State *state = get_io_state_by_cls(cls); + return err_mode(state, "reading"); + } if (size < 0) return _io__WindowsConsoleIO_readall_impl(self); @@ -944,6 +950,7 @@ _io__WindowsConsoleIO_read_impl(winconsoleio *self, Py_ssize_t size) /*[clinic input] _io._WindowsConsoleIO.write + cls: defining_class b: Py_buffer / @@ -954,8 +961,9 @@ The number of bytes actually written is returned. [clinic start generated code]*/ static PyObject * -_io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b) -/*[clinic end generated code: output=775bdb16fbf9137b input=be35fb624f97c941]*/ +_io__WindowsConsoleIO_write_impl(winconsoleio *self, PyTypeObject *cls, + Py_buffer *b) +/*[clinic end generated code: output=e8019f480243cb29 input=10ac37c19339dfbe]*/ { BOOL res = TRUE; wchar_t *wbuf; @@ -964,8 +972,10 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b) if (self->fd == -1) return err_closed(); - if (!self->writable) - return err_mode("writing"); + if (!self->writable) { + _PyIO_State *state = get_io_state_by_cls(cls); + return err_mode(state, "writing"); + } handle = _Py_get_osfhandle(self->fd); if (handle == INVALID_HANDLE_VALUE) @@ -1078,7 +1088,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 From 4e641987eab2f7c196e60a3a42840a6e42424fc0 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Mon, 20 Feb 2023 22:19:20 +0530 Subject: [PATCH 18/54] Fix state assignment --- Modules/_io/textio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index b4c74fa8e7ade7..9e74f892990a4f 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -1169,6 +1169,8 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, self->buffer = Py_NewRef(buffer); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + self->state = state; /* Build the decoder object */ if (_textiowrapper_set_decoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0) goto error; @@ -1180,7 +1182,6 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, /* Finished sorting out the codec details */ Py_CLEAR(codec_info); - _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)) @@ -1216,8 +1217,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, if (_textiowrapper_fix_encoder_state(self) < 0) { goto error; } - - self->state = state; + self->ok = 1; return 0; From a51823a6ece769f9c3af757b270f34755b401968 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 20 Feb 2023 23:05:51 +0100 Subject: [PATCH 19/54] Experimental: add explicit finalizers to all types Also remove calls to _PyIOBase_finalize from dealloc funcs --- Modules/_io/_iomodule.h | 1 + Modules/_io/bufferedio.c | 7 +++++-- Modules/_io/bytesio.c | 2 ++ Modules/_io/fileio.c | 3 +-- Modules/_io/iobase.c | 31 +------------------------------ Modules/_io/stringio.c | 1 + Modules/_io/textio.c | 7 ++++--- Modules/_io/winconsoleio.c | 3 +-- 8 files changed, 16 insertions(+), 39 deletions(-) diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index e90bfd9e4d7ee1..2cc5e90a712455 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -135,6 +135,7 @@ extern Py_off_t PyNumber_AsOff_t(PyObject *item, PyObject *err); /* IO module structure */ extern PyModuleDef _PyIO_Module; +extern void iobase_finalize(PyObject *); typedef struct { PyObject *locale_module; diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 36babd3055100d..d973de437804b1 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -373,8 +373,6 @@ buffered_dealloc(buffered *self) { PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) - return; _PyObject_GC_UNTRACK(self); self->ok = 0; if (self->weakreflist != NULL) @@ -2362,6 +2360,7 @@ static PyType_Slot bufferediobase_slots[] = { {Py_tp_doc, (void *)bufferediobase_doc}, {Py_tp_methods, bufferediobase_methods}, {Py_tp_traverse, bufferediobase_traverse}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -2423,6 +2422,7 @@ static PyType_Slot bufferedreader_slots[] = { {Py_tp_members, bufferedreader_members}, {Py_tp_getset, bufferedreader_getset}, {Py_tp_init, _io_BufferedReader___init__}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -2479,6 +2479,7 @@ static PyType_Slot bufferedwriter_slots[] = { {Py_tp_members, bufferedwriter_members}, {Py_tp_getset, bufferedwriter_getset}, {Py_tp_init, _io_BufferedWriter___init__}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -2529,6 +2530,7 @@ static PyType_Slot bufferedrwpair_slots[] = { {Py_tp_members, bufferedrwpair_members}, {Py_tp_getset, bufferedrwpair_getset}, {Py_tp_init, _io_BufferedRWPair___init__}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -2595,6 +2597,7 @@ static PyType_Slot bufferedrandom_slots[] = { {Py_tp_members, bufferedrandom_members}, {Py_tp_getset, bufferedrandom_getset}, {Py_tp_init, _io_BufferedRandom___init__}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 6a7d9fad8a2a83..f2824615babfe0 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -1043,6 +1043,7 @@ static PyType_Slot bytesio_slots[] = { {Py_tp_getset, bytesio_getsetlist}, {Py_tp_init, _io_BytesIO___init__}, {Py_tp_new, bytesio_new}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -1112,6 +1113,7 @@ bytesiobuf_dealloc(bytesiobuf *self) static PyType_Slot bytesiobuf_slots[] = { {Py_tp_dealloc, bytesiobuf_dealloc}, {Py_tp_traverse, bytesiobuf_traverse}, + {Py_tp_finalize, iobase_finalize}, // Buffer protocol {Py_bf_getbuffer, bytesiobuf_getbuffer}, diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index b0a5d42c0d9627..fdf9693d1de592 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -526,8 +526,6 @@ fileio_dealloc(fileio *self) { PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) - return; _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); @@ -1211,6 +1209,7 @@ static PyType_Slot fileio_slots[] = { {Py_tp_getset, fileio_getsetlist}, {Py_tp_init, _io_FileIO___init__}, {Py_tp_new, fileio_new}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index de79f6c5b545d6..edb111a0b5730f 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -248,7 +248,7 @@ _io__IOBase_close_impl(PyObject *self) /* Finalization and garbage collection support */ -static void +void iobase_finalize(PyObject *self) { PyObject *res; @@ -300,22 +300,6 @@ iobase_finalize(PyObject *self) PyErr_Restore(error_type, error_value, error_traceback); } -int -_PyIOBase_finalize(PyObject *self) -{ - int is_zombie; - - /* If _PyIOBase_finalize() is called from a destructor, we need to - resurrect the object as calling close() can invoke arbitrary code. */ - is_zombie = (Py_REFCNT(self) == 0); - if (is_zombie) - return PyObject_CallFinalizerFromDealloc(self); - else { - PyObject_CallFinalizer(self); - return 0; - } -} - static int iobase_traverse(iobase *self, visitproc visit, void *arg) { @@ -336,19 +320,6 @@ iobase_clear(iobase *self) static void iobase_dealloc(iobase *self) { - /* NOTE: since IOBaseObject has its own dict, Python-defined attributes - are still available here for close() to use. - However, if the derived class declares a __slots__, those slots are - already gone. - */ - if (_PyIOBase_finalize((PyObject *) self) < 0) { - /* When called from a heap type's dealloc, the type will be - decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */ - if (_PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) { - Py_INCREF(Py_TYPE(self)); - } - return; - } PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 1cd8e01b3ed466..5b0a4b82360817 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -1022,6 +1022,7 @@ static PyType_Slot stringio_slots[] = { {Py_tp_getset, stringio_getset}, {Py_tp_init, _io_StringIO___init__}, {Py_tp_new, stringio_new}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 9e74f892990a4f..b147cbb0e08451 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -169,6 +169,7 @@ static PyType_Slot textiobase_slots[] = { {Py_tp_methods, textiobase_methods}, {Py_tp_getset, textiobase_getset}, {Py_tp_traverse, textiobase_traverse}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -873,7 +874,7 @@ _textiowrapper_set_decoder(textio *self, PyObject *codec_info, return -1; if (self->readuniversal) { - _PyIO_State *state = self->state; + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); PyObject *incrementalDecoder = PyObject_CallFunctionObjArgs( (PyObject *)state->PyIncrementalNewlineDecoder_Type, self->decoder, self->readtranslate ? Py_True : Py_False, NULL); @@ -1397,8 +1398,6 @@ textiowrapper_dealloc(textio *self) { PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) - return; self->ok = 0; _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) @@ -3182,6 +3181,7 @@ static PyType_Slot nldecoder_slots[] = { {Py_tp_traverse, incrementalnewlinedecoder_traverse}, {Py_tp_clear, incrementalnewlinedecoder_clear}, {Py_tp_init, _io_IncrementalNewlineDecoder___init__}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -3249,6 +3249,7 @@ PyType_Slot textiowrapper_slots[] = { {Py_tp_members, textiowrapper_members}, {Py_tp_getset, textiowrapper_getset}, {Py_tp_init, _io_TextIOWrapper___init__}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 4e4343a63480a8..a63902b58d4759 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -434,8 +434,6 @@ winconsoleio_dealloc(winconsoleio *self) { PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) - return; _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); @@ -1153,6 +1151,7 @@ static PyType_Slot winconsoleio_slots[] = { {Py_tp_getset, winconsoleio_getsetlist}, {Py_tp_init, _io__WindowsConsoleIO___init__}, {Py_tp_new, winconsoleio_new}, + {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; From 0cdd1eae3d33dc0fcf2ee25c395a81b262876737 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 20 Feb 2023 23:46:52 +0100 Subject: [PATCH 20/54] Fix check readable/writable/seekable methods --- .../pycore_global_objects_fini_generated.h | 3 + Include/internal/pycore_global_strings.h | 3 + .../internal/pycore_runtime_init_generated.h | 3 + .../internal/pycore_unicodeobject_generated.h | 6 + Modules/_io/_iomodule.h | 13 +- Modules/_io/bufferedio.c | 23 +-- Modules/_io/clinic/iobase.c.h | 134 +++++++++++++++++- Modules/_io/iobase.c | 59 ++++++-- 8 files changed, 217 insertions(+), 27 deletions(-) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index dc5cd58d853534..829f7c44a94b37 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -742,6 +742,9 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_asyncio_future_blocking)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_blksize)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_bootstrap)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_checkReadable)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_checkSeekable)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_checkWritable)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_check_retval_)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_dealloc_warn)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_feature_version)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 8b23aa15479301..2e16c9edfbbdac 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -228,6 +228,9 @@ struct _Py_global_strings { STRUCT_FOR_ID(_asyncio_future_blocking) STRUCT_FOR_ID(_blksize) STRUCT_FOR_ID(_bootstrap) + STRUCT_FOR_ID(_checkReadable) + STRUCT_FOR_ID(_checkSeekable) + STRUCT_FOR_ID(_checkWritable) STRUCT_FOR_ID(_check_retval_) STRUCT_FOR_ID(_dealloc_warn) STRUCT_FOR_ID(_feature_version) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 471efadb13bb4f..3fc14481c95c44 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -734,6 +734,9 @@ extern "C" { INIT_ID(_asyncio_future_blocking), \ INIT_ID(_blksize), \ INIT_ID(_bootstrap), \ + INIT_ID(_checkReadable), \ + INIT_ID(_checkSeekable), \ + INIT_ID(_checkWritable), \ INIT_ID(_check_retval_), \ INIT_ID(_dealloc_warn), \ INIT_ID(_feature_version), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index b47d240e492ff9..792b7317e09b38 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -362,6 +362,12 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(_bootstrap); PyUnicode_InternInPlace(&string); + string = &_Py_ID(_checkReadable); + PyUnicode_InternInPlace(&string); + string = &_Py_ID(_checkSeekable); + PyUnicode_InternInPlace(&string); + string = &_Py_ID(_checkWritable); + PyUnicode_InternInPlace(&string); string = &_Py_ID(_check_retval_); PyUnicode_InternInPlace(&string); string = &_Py_ID(_dealloc_warn); diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 2cc5e90a712455..dd668ceeff69ad 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -26,14 +26,19 @@ extern PyType_Spec textiowrapper_spec; extern PyType_Spec winconsoleio_spec; #endif +#define _CHECK(op, id) (PyObject_CallMethodOneArg(op, id, Py_True)) +#define CHECK_READABLE(op) (_CHECK(op, &_Py_ID(_checkReadable))) +#define CHECK_SEEKABLE(op) (_CHECK(op, &_Py_ID(_checkSeekable))) +#define CHECK_WRITABLE(op) (_CHECK(op, &_Py_ID(_checkWritable))) + /* These functions are used as METH_NOARGS methods, are normally called * with args=NULL, and return a new reference. * BUT when args=Py_True is passed, they return a borrowed reference. */ -extern PyObject* _PyIOBase_check_readable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_writable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_seekable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_closed(PyObject *self, PyObject *args); +extern PyObject *_PyIOBase_check_readable(PyObject *self, PyObject *args); +extern PyObject *_PyIOBase_check_writable(PyObject *self, PyObject *args); +extern PyObject *_PyIOBase_check_seekable(PyObject *self, PyObject *args); +extern PyObject *_PyIOBase_check_closed(PyObject *self, PyObject *args); /* Helper for finalization. This function will revive an object ready to be deallocated and try to diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index d973de437804b1..d79512cf869188 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1227,7 +1227,7 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) CHECK_CLOSED(self, "seek of closed file") - if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL) + if (CHECK_SEEKABLE(self->raw) == NULL) return NULL; target = PyNumber_AsOff_t(targetobj, PyExc_ValueError); @@ -1426,8 +1426,9 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (_PyIOBase_check_readable(raw, Py_True) == NULL) + if (CHECK_READABLE(raw) == NULL) { return -1; + } Py_XSETREF(self->raw, Py_NewRef(raw)); self->buffer_size = buffer_size; @@ -1782,8 +1783,9 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (_PyIOBase_check_writable(raw, Py_True) == NULL) + if (CHECK_WRITABLE(raw) == NULL) { return -1; + } Py_INCREF(raw); Py_XSETREF(self->raw, raw); @@ -2101,10 +2103,12 @@ _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, PyObject *writer, Py_ssize_t buffer_size) /*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/ { - if (_PyIOBase_check_readable(reader, Py_True) == NULL) + if (CHECK_READABLE(reader) == NULL) { return -1; - if (_PyIOBase_check_writable(writer, Py_True) == NULL) + } + if (CHECK_WRITABLE(writer) == NULL) { return -1; + } _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); self->reader = (buffered *) PyObject_CallFunction( @@ -2298,12 +2302,15 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (_PyIOBase_check_seekable(raw, Py_True) == NULL) + if (CHECK_SEEKABLE(raw) == NULL) { return -1; - if (_PyIOBase_check_readable(raw, Py_True) == NULL) + } + if (CHECK_READABLE(raw) == NULL) { return -1; - if (_PyIOBase_check_writable(raw, Py_True) == NULL) + } + if (CHECK_WRITABLE(raw) == NULL) { return -1; + } Py_INCREF(raw); Py_XSETREF(self->raw, raw); diff --git a/Modules/_io/clinic/iobase.c.h b/Modules/_io/clinic/iobase.c.h index d3d537f6a1a0ef..c9ff825338f3e7 100644 --- a/Modules/_io/clinic/iobase.c.h +++ b/Modules/_io/clinic/iobase.c.h @@ -87,6 +87,50 @@ _io__IOBase_seekable(PyObject *self, PyObject *Py_UNUSED(ignored)) return _io__IOBase_seekable_impl(self); } +PyDoc_STRVAR(_io__IOBase__checkSeekable__doc__, +"_checkSeekable($self, /, *args)\n" +"--\n" +"\n"); + +#define _IO__IOBASE__CHECKSEEKABLE_METHODDEF \ + {"_checkSeekable", _PyCFunction_CAST(_io__IOBase__checkSeekable), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__IOBase__checkSeekable__doc__}, + +static PyObject * +_io__IOBase__checkSeekable_impl(PyObject *self, PyTypeObject *cls, + PyObject *args); + +static PyObject * +_io__IOBase__checkSeekable(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_checkSeekable", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *__clinic_args = NULL; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + __clinic_args = args[0]; + return_value = _io__IOBase__checkSeekable_impl(self, cls, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(_io__IOBase_readable__doc__, "readable($self, /)\n" "--\n" @@ -107,6 +151,50 @@ _io__IOBase_readable(PyObject *self, PyObject *Py_UNUSED(ignored)) return _io__IOBase_readable_impl(self); } +PyDoc_STRVAR(_io__IOBase__checkReadable__doc__, +"_checkReadable($self, /, *args)\n" +"--\n" +"\n"); + +#define _IO__IOBASE__CHECKREADABLE_METHODDEF \ + {"_checkReadable", _PyCFunction_CAST(_io__IOBase__checkReadable), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__IOBase__checkReadable__doc__}, + +static PyObject * +_io__IOBase__checkReadable_impl(PyObject *self, PyTypeObject *cls, + PyObject *args); + +static PyObject * +_io__IOBase__checkReadable(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_checkReadable", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *__clinic_args = NULL; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + __clinic_args = args[0]; + return_value = _io__IOBase__checkReadable_impl(self, cls, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(_io__IOBase_writable__doc__, "writable($self, /)\n" "--\n" @@ -127,6 +215,50 @@ _io__IOBase_writable(PyObject *self, PyObject *Py_UNUSED(ignored)) return _io__IOBase_writable_impl(self); } +PyDoc_STRVAR(_io__IOBase__checkWritable__doc__, +"_checkWritable($self, /, *args)\n" +"--\n" +"\n"); + +#define _IO__IOBASE__CHECKWRITABLE_METHODDEF \ + {"_checkWritable", _PyCFunction_CAST(_io__IOBase__checkWritable), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__IOBase__checkWritable__doc__}, + +static PyObject * +_io__IOBase__checkWritable_impl(PyObject *self, PyTypeObject *cls, + PyObject *args); + +static PyObject * +_io__IOBase__checkWritable(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) + #else + # define KWTUPLE NULL + #endif + + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "_checkWritable", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *__clinic_args = NULL; + + args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); + if (!args) { + goto exit; + } + __clinic_args = args[0]; + return_value = _io__IOBase__checkWritable_impl(self, cls, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(_io__IOBase_fileno__doc__, "fileno($self, /)\n" "--\n" @@ -320,4 +452,4 @@ _io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored)) { return _io__RawIOBase_readall_impl(self); } -/*[clinic end generated code: output=98f212f95ac26d74 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cc302d8dc238cf37 input=a9049054013a1b77]*/ diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index edb111a0b5730f..444c1dbbd7bdcb 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -347,15 +347,26 @@ _io__IOBase_seekable_impl(PyObject *self) Py_RETURN_FALSE; } -PyObject * -_PyIOBase_check_seekable(PyObject *self, PyObject *args) +/*[clinic input] +_io._IOBase._checkSeekable + + cls: defining_class + / + *args: object + +[clinic start generated code]*/ + +static PyObject * +_io__IOBase__checkSeekable_impl(PyObject *self, PyTypeObject *cls, + PyObject *args) +/*[clinic end generated code: output=f9449595c526a9ed input=6cf1584801d4b564]*/ { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(seekable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + _PyIO_State *state = get_io_state_by_cls(cls); iobase_unsupported(state, "File or stream is not seekable."); return NULL; } @@ -380,16 +391,26 @@ _io__IOBase_readable_impl(PyObject *self) Py_RETURN_FALSE; } -/* May be called with any object */ -PyObject * -_PyIOBase_check_readable(PyObject *self, PyObject *args) +/*[clinic input] +_io._IOBase._checkReadable + + cls: defining_class + / + *args: object + +[clinic start generated code]*/ + +static PyObject * +_io__IOBase__checkReadable_impl(PyObject *self, PyTypeObject *cls, + PyObject *args) +/*[clinic end generated code: output=2eefd0c6015d18d3 input=cb9e598f66479243]*/ { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(readable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + _PyIO_State *state = get_io_state_by_cls(cls); iobase_unsupported(state, "File or stream is not readable."); return NULL; } @@ -414,16 +435,26 @@ _io__IOBase_writable_impl(PyObject *self) Py_RETURN_FALSE; } -/* May be called with any object */ -PyObject * -_PyIOBase_check_writable(PyObject *self, PyObject *args) +/*[clinic input] +_io._IOBase._checkWritable + + cls: defining_class + / + *args: object + +[clinic start generated code]*/ + +static PyObject * +_io__IOBase__checkWritable_impl(PyObject *self, PyTypeObject *cls, + PyObject *args) +/*[clinic end generated code: output=db0ec8af34f05a01 input=a385662e0b185943]*/ { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(writable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + _PyIO_State *state = get_io_state_by_cls(cls); iobase_unsupported(state, "File or stream is not writable."); return NULL; } @@ -783,9 +814,9 @@ static PyMethodDef iobase_methods[] = { _IO__IOBASE_WRITABLE_METHODDEF {"_checkClosed", _PyIOBase_check_closed, METH_NOARGS}, - {"_checkSeekable", _PyIOBase_check_seekable, METH_NOARGS}, - {"_checkReadable", _PyIOBase_check_readable, METH_NOARGS}, - {"_checkWritable", _PyIOBase_check_writable, METH_NOARGS}, + _IO__IOBASE__CHECKSEEKABLE_METHODDEF + _IO__IOBASE__CHECKREADABLE_METHODDEF + _IO__IOBASE__CHECKWRITABLE_METHODDEF _IO__IOBASE_FILENO_METHODDEF _IO__IOBASE_ISATTY_METHODDEF From 3a1ed0bda6c41d1e2e16a63eae536d33783ae566 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 20 Feb 2023 23:50:43 +0100 Subject: [PATCH 21/54] Fix _textiowrapper_decode --- Modules/_io/textio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index b147cbb0e08451..4a43c06136ba6e 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -887,11 +887,11 @@ _textiowrapper_set_decoder(textio *self, PyObject *codec_info, } static PyObject* -_textiowrapper_decode(PyObject *decoder, PyObject *bytes, int eof) +_textiowrapper_decode(_PyIO_State *state, PyObject *decoder, PyObject *bytes, + int eof) { PyObject *chars; - _PyIO_State *state = find_io_state_by_def(Py_TYPE(decoder)); if (Py_IS_TYPE(decoder, state->PyIncrementalNewlineDecoder_Type)) chars = _PyIncrementalNewlineDecoder_decode(decoder, bytes, eof); else @@ -1846,7 +1846,8 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint) nbytes = input_chunk_buf.len; eof = (nbytes == 0); - decoded_chars = _textiowrapper_decode(self->decoder, input_chunk, eof); + decoded_chars = _textiowrapper_decode(self->state, self->decoder, + input_chunk, eof); PyBuffer_Release(&input_chunk_buf); if (decoded_chars == NULL) goto fail; From 039b757170053597bbac3e5935d95e61157042ab Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 20 Feb 2023 23:59:32 +0100 Subject: [PATCH 22/54] Revert "Experimental: add explicit finalizers to all types" This reverts commit a51823a6ece769f9c3af757b270f34755b401968. --- Modules/_io/_iomodule.h | 1 - Modules/_io/bufferedio.c | 7 ++----- Modules/_io/bytesio.c | 2 -- Modules/_io/fileio.c | 3 ++- Modules/_io/iobase.c | 31 ++++++++++++++++++++++++++++++- Modules/_io/stringio.c | 1 - Modules/_io/textio.c | 7 +++---- Modules/_io/winconsoleio.c | 3 ++- 8 files changed, 39 insertions(+), 16 deletions(-) diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index dd668ceeff69ad..e6addc12450d4c 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -140,7 +140,6 @@ extern Py_off_t PyNumber_AsOff_t(PyObject *item, PyObject *err); /* IO module structure */ extern PyModuleDef _PyIO_Module; -extern void iobase_finalize(PyObject *); typedef struct { PyObject *locale_module; diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index d79512cf869188..9a249634c6dfc7 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -373,6 +373,8 @@ buffered_dealloc(buffered *self) { PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; + if (_PyIOBase_finalize((PyObject *) self) < 0) + return; _PyObject_GC_UNTRACK(self); self->ok = 0; if (self->weakreflist != NULL) @@ -2367,7 +2369,6 @@ static PyType_Slot bufferediobase_slots[] = { {Py_tp_doc, (void *)bufferediobase_doc}, {Py_tp_methods, bufferediobase_methods}, {Py_tp_traverse, bufferediobase_traverse}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -2429,7 +2430,6 @@ static PyType_Slot bufferedreader_slots[] = { {Py_tp_members, bufferedreader_members}, {Py_tp_getset, bufferedreader_getset}, {Py_tp_init, _io_BufferedReader___init__}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -2486,7 +2486,6 @@ static PyType_Slot bufferedwriter_slots[] = { {Py_tp_members, bufferedwriter_members}, {Py_tp_getset, bufferedwriter_getset}, {Py_tp_init, _io_BufferedWriter___init__}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -2537,7 +2536,6 @@ static PyType_Slot bufferedrwpair_slots[] = { {Py_tp_members, bufferedrwpair_members}, {Py_tp_getset, bufferedrwpair_getset}, {Py_tp_init, _io_BufferedRWPair___init__}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -2604,7 +2602,6 @@ static PyType_Slot bufferedrandom_slots[] = { {Py_tp_members, bufferedrandom_members}, {Py_tp_getset, bufferedrandom_getset}, {Py_tp_init, _io_BufferedRandom___init__}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index f2824615babfe0..6a7d9fad8a2a83 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -1043,7 +1043,6 @@ static PyType_Slot bytesio_slots[] = { {Py_tp_getset, bytesio_getsetlist}, {Py_tp_init, _io_BytesIO___init__}, {Py_tp_new, bytesio_new}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -1113,7 +1112,6 @@ bytesiobuf_dealloc(bytesiobuf *self) static PyType_Slot bytesiobuf_slots[] = { {Py_tp_dealloc, bytesiobuf_dealloc}, {Py_tp_traverse, bytesiobuf_traverse}, - {Py_tp_finalize, iobase_finalize}, // Buffer protocol {Py_bf_getbuffer, bytesiobuf_getbuffer}, diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index fdf9693d1de592..b0a5d42c0d9627 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -526,6 +526,8 @@ fileio_dealloc(fileio *self) { PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; + if (_PyIOBase_finalize((PyObject *) self) < 0) + return; _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); @@ -1209,7 +1211,6 @@ static PyType_Slot fileio_slots[] = { {Py_tp_getset, fileio_getsetlist}, {Py_tp_init, _io_FileIO___init__}, {Py_tp_new, fileio_new}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 444c1dbbd7bdcb..febe4c412d9c70 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -248,7 +248,7 @@ _io__IOBase_close_impl(PyObject *self) /* Finalization and garbage collection support */ -void +static void iobase_finalize(PyObject *self) { PyObject *res; @@ -300,6 +300,22 @@ iobase_finalize(PyObject *self) PyErr_Restore(error_type, error_value, error_traceback); } +int +_PyIOBase_finalize(PyObject *self) +{ + int is_zombie; + + /* If _PyIOBase_finalize() is called from a destructor, we need to + resurrect the object as calling close() can invoke arbitrary code. */ + is_zombie = (Py_REFCNT(self) == 0); + if (is_zombie) + return PyObject_CallFinalizerFromDealloc(self); + else { + PyObject_CallFinalizer(self); + return 0; + } +} + static int iobase_traverse(iobase *self, visitproc visit, void *arg) { @@ -320,6 +336,19 @@ iobase_clear(iobase *self) static void iobase_dealloc(iobase *self) { + /* NOTE: since IOBaseObject has its own dict, Python-defined attributes + are still available here for close() to use. + However, if the derived class declares a __slots__, those slots are + already gone. + */ + if (_PyIOBase_finalize((PyObject *) self) < 0) { + /* When called from a heap type's dealloc, the type will be + decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */ + if (_PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) { + Py_INCREF(Py_TYPE(self)); + } + return; + } PyTypeObject *tp = Py_TYPE(self); _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 5b0a4b82360817..1cd8e01b3ed466 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -1022,7 +1022,6 @@ static PyType_Slot stringio_slots[] = { {Py_tp_getset, stringio_getset}, {Py_tp_init, _io_StringIO___init__}, {Py_tp_new, stringio_new}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 4a43c06136ba6e..aaec54cc3f9766 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -169,7 +169,6 @@ static PyType_Slot textiobase_slots[] = { {Py_tp_methods, textiobase_methods}, {Py_tp_getset, textiobase_getset}, {Py_tp_traverse, textiobase_traverse}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -874,7 +873,7 @@ _textiowrapper_set_decoder(textio *self, PyObject *codec_info, return -1; if (self->readuniversal) { - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + _PyIO_State *state = self->state; PyObject *incrementalDecoder = PyObject_CallFunctionObjArgs( (PyObject *)state->PyIncrementalNewlineDecoder_Type, self->decoder, self->readtranslate ? Py_True : Py_False, NULL); @@ -1398,6 +1397,8 @@ textiowrapper_dealloc(textio *self) { PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; + if (_PyIOBase_finalize((PyObject *) self) < 0) + return; self->ok = 0; _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) @@ -3182,7 +3183,6 @@ static PyType_Slot nldecoder_slots[] = { {Py_tp_traverse, incrementalnewlinedecoder_traverse}, {Py_tp_clear, incrementalnewlinedecoder_clear}, {Py_tp_init, _io_IncrementalNewlineDecoder___init__}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; @@ -3250,7 +3250,6 @@ PyType_Slot textiowrapper_slots[] = { {Py_tp_members, textiowrapper_members}, {Py_tp_getset, textiowrapper_getset}, {Py_tp_init, _io_TextIOWrapper___init__}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index a63902b58d4759..4e4343a63480a8 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -434,6 +434,8 @@ winconsoleio_dealloc(winconsoleio *self) { PyTypeObject *tp = Py_TYPE(self); self->finalizing = 1; + if (_PyIOBase_finalize((PyObject *) self) < 0) + return; _PyObject_GC_UNTRACK(self); if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); @@ -1151,7 +1153,6 @@ static PyType_Slot winconsoleio_slots[] = { {Py_tp_getset, winconsoleio_getsetlist}, {Py_tp_init, _io__WindowsConsoleIO___init__}, {Py_tp_new, winconsoleio_new}, - {Py_tp_finalize, iobase_finalize}, {0, NULL}, }; From 17eb640c5406bca6396fce5e69d0eb50b1f100f6 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 21 Feb 2023 00:05:37 +0100 Subject: [PATCH 23/54] Purge old exports --- Modules/_io/_iomodule.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index e6addc12450d4c..c07df4f2cd7668 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -31,13 +31,6 @@ extern PyType_Spec winconsoleio_spec; #define CHECK_SEEKABLE(op) (_CHECK(op, &_Py_ID(_checkSeekable))) #define CHECK_WRITABLE(op) (_CHECK(op, &_Py_ID(_checkWritable))) -/* These functions are used as METH_NOARGS methods, are normally called - * with args=NULL, and return a new reference. - * BUT when args=Py_True is passed, they return a borrowed reference. - */ -extern PyObject *_PyIOBase_check_readable(PyObject *self, PyObject *args); -extern PyObject *_PyIOBase_check_writable(PyObject *self, PyObject *args); -extern PyObject *_PyIOBase_check_seekable(PyObject *self, PyObject *args); extern PyObject *_PyIOBase_check_closed(PyObject *self, PyObject *args); /* Helper for finalization. From 00d5abb525e03e12cb7a2421104a14eddd1a79a2 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 21 Feb 2023 12:11:42 +0100 Subject: [PATCH 24/54] Revert "Fix check readable/writable/seekable methods" This reverts commit 0cdd1eae3d33dc0fcf2ee25c395a81b262876737. --- .../pycore_global_objects_fini_generated.h | 3 - Include/internal/pycore_global_strings.h | 3 - .../internal/pycore_runtime_init_generated.h | 3 - .../internal/pycore_unicodeobject_generated.h | 6 - Modules/_io/_iomodule.h | 14 +- Modules/_io/bufferedio.c | 23 ++- Modules/_io/clinic/iobase.c.h | 134 +----------------- Modules/_io/iobase.c | 59 ++------ 8 files changed, 31 insertions(+), 214 deletions(-) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 829f7c44a94b37..dc5cd58d853534 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -742,9 +742,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_asyncio_future_blocking)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_blksize)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_bootstrap)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_checkReadable)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_checkSeekable)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_checkWritable)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_check_retval_)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_dealloc_warn)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_feature_version)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 2e16c9edfbbdac..8b23aa15479301 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -228,9 +228,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(_asyncio_future_blocking) STRUCT_FOR_ID(_blksize) STRUCT_FOR_ID(_bootstrap) - STRUCT_FOR_ID(_checkReadable) - STRUCT_FOR_ID(_checkSeekable) - STRUCT_FOR_ID(_checkWritable) STRUCT_FOR_ID(_check_retval_) STRUCT_FOR_ID(_dealloc_warn) STRUCT_FOR_ID(_feature_version) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 3fc14481c95c44..471efadb13bb4f 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -734,9 +734,6 @@ extern "C" { INIT_ID(_asyncio_future_blocking), \ INIT_ID(_blksize), \ INIT_ID(_bootstrap), \ - INIT_ID(_checkReadable), \ - INIT_ID(_checkSeekable), \ - INIT_ID(_checkWritable), \ INIT_ID(_check_retval_), \ INIT_ID(_dealloc_warn), \ INIT_ID(_feature_version), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 792b7317e09b38..b47d240e492ff9 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -362,12 +362,6 @@ _PyUnicode_InitStaticStrings(void) { PyUnicode_InternInPlace(&string); string = &_Py_ID(_bootstrap); PyUnicode_InternInPlace(&string); - string = &_Py_ID(_checkReadable); - PyUnicode_InternInPlace(&string); - string = &_Py_ID(_checkSeekable); - PyUnicode_InternInPlace(&string); - string = &_Py_ID(_checkWritable); - PyUnicode_InternInPlace(&string); string = &_Py_ID(_check_retval_); PyUnicode_InternInPlace(&string); string = &_Py_ID(_dealloc_warn); diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index c07df4f2cd7668..e90bfd9e4d7ee1 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -26,12 +26,14 @@ extern PyType_Spec textiowrapper_spec; extern PyType_Spec winconsoleio_spec; #endif -#define _CHECK(op, id) (PyObject_CallMethodOneArg(op, id, Py_True)) -#define CHECK_READABLE(op) (_CHECK(op, &_Py_ID(_checkReadable))) -#define CHECK_SEEKABLE(op) (_CHECK(op, &_Py_ID(_checkSeekable))) -#define CHECK_WRITABLE(op) (_CHECK(op, &_Py_ID(_checkWritable))) - -extern PyObject *_PyIOBase_check_closed(PyObject *self, PyObject *args); +/* These functions are used as METH_NOARGS methods, are normally called + * with args=NULL, and return a new reference. + * BUT when args=Py_True is passed, they return a borrowed reference. + */ +extern PyObject* _PyIOBase_check_readable(PyObject *self, PyObject *args); +extern PyObject* _PyIOBase_check_writable(PyObject *self, PyObject *args); +extern PyObject* _PyIOBase_check_seekable(PyObject *self, PyObject *args); +extern PyObject* _PyIOBase_check_closed(PyObject *self, PyObject *args); /* Helper for finalization. This function will revive an object ready to be deallocated and try to diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 9a249634c6dfc7..36babd3055100d 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1229,7 +1229,7 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) CHECK_CLOSED(self, "seek of closed file") - if (CHECK_SEEKABLE(self->raw) == NULL) + if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL) return NULL; target = PyNumber_AsOff_t(targetobj, PyExc_ValueError); @@ -1428,9 +1428,8 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (CHECK_READABLE(raw) == NULL) { + if (_PyIOBase_check_readable(raw, Py_True) == NULL) return -1; - } Py_XSETREF(self->raw, Py_NewRef(raw)); self->buffer_size = buffer_size; @@ -1785,9 +1784,8 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (CHECK_WRITABLE(raw) == NULL) { + if (_PyIOBase_check_writable(raw, Py_True) == NULL) return -1; - } Py_INCREF(raw); Py_XSETREF(self->raw, raw); @@ -2105,12 +2103,10 @@ _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, PyObject *writer, Py_ssize_t buffer_size) /*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/ { - if (CHECK_READABLE(reader) == NULL) { + if (_PyIOBase_check_readable(reader, Py_True) == NULL) return -1; - } - if (CHECK_WRITABLE(writer) == NULL) { + 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( @@ -2304,15 +2300,12 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (CHECK_SEEKABLE(raw) == NULL) { + if (_PyIOBase_check_seekable(raw, Py_True) == NULL) return -1; - } - if (CHECK_READABLE(raw) == NULL) { + if (_PyIOBase_check_readable(raw, Py_True) == NULL) return -1; - } - if (CHECK_WRITABLE(raw) == NULL) { + if (_PyIOBase_check_writable(raw, Py_True) == NULL) return -1; - } Py_INCREF(raw); Py_XSETREF(self->raw, raw); diff --git a/Modules/_io/clinic/iobase.c.h b/Modules/_io/clinic/iobase.c.h index c9ff825338f3e7..d3d537f6a1a0ef 100644 --- a/Modules/_io/clinic/iobase.c.h +++ b/Modules/_io/clinic/iobase.c.h @@ -87,50 +87,6 @@ _io__IOBase_seekable(PyObject *self, PyObject *Py_UNUSED(ignored)) return _io__IOBase_seekable_impl(self); } -PyDoc_STRVAR(_io__IOBase__checkSeekable__doc__, -"_checkSeekable($self, /, *args)\n" -"--\n" -"\n"); - -#define _IO__IOBASE__CHECKSEEKABLE_METHODDEF \ - {"_checkSeekable", _PyCFunction_CAST(_io__IOBase__checkSeekable), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__IOBase__checkSeekable__doc__}, - -static PyObject * -_io__IOBase__checkSeekable_impl(PyObject *self, PyTypeObject *cls, - PyObject *args); - -static PyObject * -_io__IOBase__checkSeekable(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) - #else - # define KWTUPLE NULL - #endif - - static const char * const _keywords[] = { NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_checkSeekable", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *__clinic_args = NULL; - - args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - __clinic_args = args[0]; - return_value = _io__IOBase__checkSeekable_impl(self, cls, __clinic_args); - -exit: - Py_XDECREF(__clinic_args); - return return_value; -} - PyDoc_STRVAR(_io__IOBase_readable__doc__, "readable($self, /)\n" "--\n" @@ -151,50 +107,6 @@ _io__IOBase_readable(PyObject *self, PyObject *Py_UNUSED(ignored)) return _io__IOBase_readable_impl(self); } -PyDoc_STRVAR(_io__IOBase__checkReadable__doc__, -"_checkReadable($self, /, *args)\n" -"--\n" -"\n"); - -#define _IO__IOBASE__CHECKREADABLE_METHODDEF \ - {"_checkReadable", _PyCFunction_CAST(_io__IOBase__checkReadable), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__IOBase__checkReadable__doc__}, - -static PyObject * -_io__IOBase__checkReadable_impl(PyObject *self, PyTypeObject *cls, - PyObject *args); - -static PyObject * -_io__IOBase__checkReadable(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) - #else - # define KWTUPLE NULL - #endif - - static const char * const _keywords[] = { NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_checkReadable", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *__clinic_args = NULL; - - args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - __clinic_args = args[0]; - return_value = _io__IOBase__checkReadable_impl(self, cls, __clinic_args); - -exit: - Py_XDECREF(__clinic_args); - return return_value; -} - PyDoc_STRVAR(_io__IOBase_writable__doc__, "writable($self, /)\n" "--\n" @@ -215,50 +127,6 @@ _io__IOBase_writable(PyObject *self, PyObject *Py_UNUSED(ignored)) return _io__IOBase_writable_impl(self); } -PyDoc_STRVAR(_io__IOBase__checkWritable__doc__, -"_checkWritable($self, /, *args)\n" -"--\n" -"\n"); - -#define _IO__IOBASE__CHECKWRITABLE_METHODDEF \ - {"_checkWritable", _PyCFunction_CAST(_io__IOBase__checkWritable), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__IOBase__checkWritable__doc__}, - -static PyObject * -_io__IOBase__checkWritable_impl(PyObject *self, PyTypeObject *cls, - PyObject *args); - -static PyObject * -_io__IOBase__checkWritable(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty) - #else - # define KWTUPLE NULL - #endif - - static const char * const _keywords[] = { NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "_checkWritable", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *__clinic_args = NULL; - - args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf); - if (!args) { - goto exit; - } - __clinic_args = args[0]; - return_value = _io__IOBase__checkWritable_impl(self, cls, __clinic_args); - -exit: - Py_XDECREF(__clinic_args); - return return_value; -} - PyDoc_STRVAR(_io__IOBase_fileno__doc__, "fileno($self, /)\n" "--\n" @@ -452,4 +320,4 @@ _io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored)) { return _io__RawIOBase_readall_impl(self); } -/*[clinic end generated code: output=cc302d8dc238cf37 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=98f212f95ac26d74 input=a9049054013a1b77]*/ diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index febe4c412d9c70..de79f6c5b545d6 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -376,26 +376,15 @@ _io__IOBase_seekable_impl(PyObject *self) Py_RETURN_FALSE; } -/*[clinic input] -_io._IOBase._checkSeekable - - cls: defining_class - / - *args: object - -[clinic start generated code]*/ - -static PyObject * -_io__IOBase__checkSeekable_impl(PyObject *self, PyTypeObject *cls, - PyObject *args) -/*[clinic end generated code: output=f9449595c526a9ed input=6cf1584801d4b564]*/ +PyObject * +_PyIOBase_check_seekable(PyObject *self, PyObject *args) { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(seekable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - _PyIO_State *state = get_io_state_by_cls(cls); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); iobase_unsupported(state, "File or stream is not seekable."); return NULL; } @@ -420,26 +409,16 @@ _io__IOBase_readable_impl(PyObject *self) Py_RETURN_FALSE; } -/*[clinic input] -_io._IOBase._checkReadable - - cls: defining_class - / - *args: object - -[clinic start generated code]*/ - -static PyObject * -_io__IOBase__checkReadable_impl(PyObject *self, PyTypeObject *cls, - PyObject *args) -/*[clinic end generated code: output=2eefd0c6015d18d3 input=cb9e598f66479243]*/ +/* May be called with any object */ +PyObject * +_PyIOBase_check_readable(PyObject *self, PyObject *args) { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(readable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - _PyIO_State *state = get_io_state_by_cls(cls); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); iobase_unsupported(state, "File or stream is not readable."); return NULL; } @@ -464,26 +443,16 @@ _io__IOBase_writable_impl(PyObject *self) Py_RETURN_FALSE; } -/*[clinic input] -_io._IOBase._checkWritable - - cls: defining_class - / - *args: object - -[clinic start generated code]*/ - -static PyObject * -_io__IOBase__checkWritable_impl(PyObject *self, PyTypeObject *cls, - PyObject *args) -/*[clinic end generated code: output=db0ec8af34f05a01 input=a385662e0b185943]*/ +/* May be called with any object */ +PyObject * +_PyIOBase_check_writable(PyObject *self, PyObject *args) { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(writable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - _PyIO_State *state = get_io_state_by_cls(cls); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); iobase_unsupported(state, "File or stream is not writable."); return NULL; } @@ -843,9 +812,9 @@ static PyMethodDef iobase_methods[] = { _IO__IOBASE_WRITABLE_METHODDEF {"_checkClosed", _PyIOBase_check_closed, METH_NOARGS}, - _IO__IOBASE__CHECKSEEKABLE_METHODDEF - _IO__IOBASE__CHECKREADABLE_METHODDEF - _IO__IOBASE__CHECKWRITABLE_METHODDEF + {"_checkSeekable", _PyIOBase_check_seekable, METH_NOARGS}, + {"_checkReadable", _PyIOBase_check_readable, METH_NOARGS}, + {"_checkWritable", _PyIOBase_check_writable, METH_NOARGS}, _IO__IOBASE_FILENO_METHODDEF _IO__IOBASE_ISATTY_METHODDEF From fe8c256260bd5828db0687b38807e778feb677cb Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 23 Feb 2023 13:26:10 +0100 Subject: [PATCH 25/54] Pass state to _check* functions Also remove them as private methods on the private iobase type --- Lib/test/test_io.py | 7 +++++-- Modules/_io/_iomodule.h | 18 +++++++++--------- Modules/_io/bufferedio.c | 25 +++++++++++++------------ Modules/_io/iobase.c | 14 +++----------- 4 files changed, 30 insertions(+), 34 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 9bcc92a40c61df..cc16804fe21829 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -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" diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index e90bfd9e4d7ee1..bf34aa58c95bf7 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -26,15 +26,6 @@ extern PyType_Spec textiowrapper_spec; extern PyType_Spec winconsoleio_spec; #endif -/* These functions are used as METH_NOARGS methods, are normally called - * with args=NULL, and return a new reference. - * BUT when args=Py_True is passed, they return a borrowed reference. - */ -extern PyObject* _PyIOBase_check_readable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_writable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_seekable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_closed(PyObject *self, PyObject *args); - /* Helper for finalization. This function will revive an object ready to be deallocated and try to close() it. It returns 0 if the object can be destroyed, or -1 if it @@ -185,6 +176,15 @@ find_io_state_by_def(PyTypeObject *type) return get_io_state(mod); } +/* These functions are used as METH_NOARGS methods, are normally called + * with args=NULL, and return a new reference. + * BUT when args=Py_True is passed, they return a borrowed reference. + */ +extern PyObject* _PyIOBase_check_readable(_PyIO_State *state, PyObject *self, PyObject *args); +extern PyObject* _PyIOBase_check_writable(_PyIO_State *state, PyObject *self, PyObject *args); +extern PyObject* _PyIOBase_check_seekable(_PyIO_State *state, PyObject *self, PyObject *args); +extern PyObject* _PyIOBase_check_closed(PyObject *self, PyObject *args); + #ifdef MS_WINDOWS extern char _PyIO_get_console_type(PyObject *); #endif diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 36babd3055100d..18a0854c96adab 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1229,7 +1229,8 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) CHECK_CLOSED(self, "seek of closed file") - if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL) + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + if (_PyIOBase_check_seekable(state, self->raw, Py_True) == NULL) return NULL; target = PyNumber_AsOff_t(targetobj, PyExc_ValueError); @@ -1428,7 +1429,8 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (_PyIOBase_check_readable(raw, Py_True) == NULL) + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) return -1; Py_XSETREF(self->raw, Py_NewRef(raw)); @@ -1440,7 +1442,6 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, return -1; _bufferedreader_reset_buf(self); - _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) @@ -1784,7 +1785,8 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (_PyIOBase_check_writable(raw, Py_True) == NULL) + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) return -1; Py_INCREF(raw); @@ -1798,7 +1800,6 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, _bufferedwriter_reset_buf(self); self->pos = 0; - _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) @@ -2103,12 +2104,12 @@ _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, PyObject *writer, Py_ssize_t buffer_size) /*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/ { - if (_PyIOBase_check_readable(reader, Py_True) == NULL) + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + if (_PyIOBase_check_readable(state, reader, Py_True) == NULL) return -1; - if (_PyIOBase_check_writable(writer, Py_True) == NULL) + if (_PyIOBase_check_writable(state, writer, Py_True) == NULL) return -1; - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); self->reader = (buffered *) PyObject_CallFunction( (PyObject *)state->PyBufferedReader_Type, "On", reader, buffer_size); @@ -2300,11 +2301,12 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, self->ok = 0; self->detached = 0; - if (_PyIOBase_check_seekable(raw, Py_True) == NULL) + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + if (_PyIOBase_check_seekable(state, raw, Py_True) == NULL) return -1; - if (_PyIOBase_check_readable(raw, Py_True) == NULL) + if (_PyIOBase_check_readable(state, raw, Py_True) == NULL) return -1; - if (_PyIOBase_check_writable(raw, Py_True) == NULL) + if (_PyIOBase_check_writable(state, raw, Py_True) == NULL) return -1; Py_INCREF(raw); @@ -2319,7 +2321,6 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, _bufferedwriter_reset_buf(self); self->pos = 0; - _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)); diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index de79f6c5b545d6..4849b4e3d70340 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -377,14 +377,13 @@ _io__IOBase_seekable_impl(PyObject *self) } PyObject * -_PyIOBase_check_seekable(PyObject *self, PyObject *args) +_PyIOBase_check_seekable(_PyIO_State *state, PyObject *self, PyObject *args) { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(seekable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); iobase_unsupported(state, "File or stream is not seekable."); return NULL; } @@ -411,14 +410,13 @@ _io__IOBase_readable_impl(PyObject *self) /* May be called with any object */ PyObject * -_PyIOBase_check_readable(PyObject *self, PyObject *args) +_PyIOBase_check_readable(_PyIO_State *state, PyObject *self, PyObject *args) { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(readable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); iobase_unsupported(state, "File or stream is not readable."); return NULL; } @@ -445,14 +443,13 @@ _io__IOBase_writable_impl(PyObject *self) /* May be called with any object */ PyObject * -_PyIOBase_check_writable(PyObject *self, PyObject *args) +_PyIOBase_check_writable(_PyIO_State *state, PyObject *self, PyObject *args) { PyObject *res = PyObject_CallMethodNoArgs(self, &_Py_ID(writable)); if (res == NULL) return NULL; if (res != Py_True) { Py_CLEAR(res); - _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); iobase_unsupported(state, "File or stream is not writable."); return NULL; } @@ -811,11 +808,6 @@ static PyMethodDef iobase_methods[] = { _IO__IOBASE_READABLE_METHODDEF _IO__IOBASE_WRITABLE_METHODDEF - {"_checkClosed", _PyIOBase_check_closed, METH_NOARGS}, - {"_checkSeekable", _PyIOBase_check_seekable, METH_NOARGS}, - {"_checkReadable", _PyIOBase_check_readable, METH_NOARGS}, - {"_checkWritable", _PyIOBase_check_writable, METH_NOARGS}, - _IO__IOBASE_FILENO_METHODDEF _IO__IOBASE_ISATTY_METHODDEF From d0a0d542b8d76e08b177b68a031f7cd4f7673d63 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 23 Feb 2023 21:17:11 +0100 Subject: [PATCH 26/54] Windows fix (first of many) --- Modules/_io/winconsoleio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 4e4343a63480a8..a992a5effe3ef2 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -154,8 +154,6 @@ typedef struct { wchar_t wbuf; } winconsoleio; -PyTypeObject PyWindowsConsoleIO_Type; - int _PyWindowsConsoleIO_closed(PyObject *self) { @@ -265,7 +263,8 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj, int fd_is_own = 0; HANDLE handle = NULL; - assert(PyObject_TypeCheck(self, (PyTypeObject *)&PyWindowsConsoleIO_Type)); + _PyIO_State *state = find_io_state_by_def(Py_TYPE(self)); + assert(PyObject_TypeCheck(self, state->PyWindowsConsoleIO_Type)); if (self->fd >= 0) { if (self->closefd) { /* Have to close the existing file first. */ From 6a813b48c1f4a637c6f3f2dd5a4124549501a399 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Tue, 14 Mar 2023 10:01:20 +0000 Subject: [PATCH 27/54] fix conflict --- Modules/_io/_iomodule.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 490e15c03b896d..219298387d186a 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -642,19 +642,10 @@ iomodule_exec(PyObject *m) { _PyIO_State *state = get_io_state(m); -<<<<<<< HEAD /* DEFAULT_BUFFER_SIZE */ if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0) { return -1; } -======= - // PyRawIOBase_Type(PyIOBase_Type) subclasses - &_PyBytesIOBuffer_Type, -#ifdef HAVE_WINDOWS_CONSOLE_IO - &PyWindowsConsoleIO_Type, -#endif -}; ->>>>>>> 3d872a74c8c16d4a077c2223f678b1f8f7e0e988 /* UnsupportedOperation inherits from ValueError and OSError */ state->unsupported_operation = PyObject_CallFunction( From 0689f21608ce47d023bad0cd2b53c0998a7252e9 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Tue, 14 Mar 2023 10:11:10 +0000 Subject: [PATCH 28/54] remove duplicate declarations --- Modules/_io/_iomodule.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 2fc2b66117291b..480913e4fd9d81 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -26,15 +26,6 @@ extern PyType_Spec textiowrapper_spec; extern PyType_Spec winconsoleio_spec; #endif /* HAVE_WINDOWS_CONSOLE_IO */ -/* These functions are used as METH_NOARGS methods, are normally called - * with args=NULL, and return a new reference. - * BUT when args=Py_True is passed, they return a borrowed reference. - */ -extern PyObject* _PyIOBase_check_readable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_writable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_seekable(PyObject *self, PyObject *args); -extern PyObject* _PyIOBase_check_closed(PyObject *self, PyObject *args); - /* Helper for finalization. This function will revive an object ready to be deallocated and try to close() it. It returns 0 if the object can be destroyed, or -1 if it From 5e19c48cb115f7d3a175a2df10df47fcffa44547 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Tue, 14 Mar 2023 10:24:28 +0000 Subject: [PATCH 29/54] add missing methods --- Modules/_io/iobase.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 85409c93bfc055..41e9562767b2e9 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -204,6 +204,27 @@ _PyIOBase_check_closed(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject * +iobase_check_seekable(PyObject *self, PyObject *args) +{ + _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 = 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 = find_io_state_by_def(Py_TYPE(self)); + return _PyIOBase_check_writable(state, self, args); +} + /* 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. */ @@ -806,6 +827,11 @@ static PyMethodDef iobase_methods[] = { _IO__IOBASE_READABLE_METHODDEF _IO__IOBASE_WRITABLE_METHODDEF + {"_checkClosed", _PyIOBase_check_closed, METH_NOARGS}, + {"_checkSeekable", iobase_check_seekable, METH_NOARGS}, + {"_checkReadable", iobase_check_readable, METH_NOARGS}, + {"_checkWritable", iobase_check_writable, METH_NOARGS}, + _IO__IOBASE_FILENO_METHODDEF _IO__IOBASE_ISATTY_METHODDEF From 6099d5b9b8d2ccf0e9ddf7ffeeece69a79fbe036 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Tue, 14 Mar 2023 10:48:31 +0000 Subject: [PATCH 30/54] fix pickling --- Modules/_io/iobase.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 41e9562767b2e9..aaf1f6f2dac635 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -225,6 +225,13 @@ iobase_check_writable(PyObject *self, PyObject *args) return _PyIOBase_check_writable(state, self, args); } +static PyObject * +iobase_reduce(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. */ @@ -842,6 +849,9 @@ static PyMethodDef iobase_methods[] = { _IO__IOBASE_READLINES_METHODDEF _IO__IOBASE_WRITELINES_METHODDEF + {"__reduce__", iobase_reduce, METH_VARARGS}, + {"__reduce_ex__", iobase_reduce, METH_VARARGS}, + {NULL, NULL} }; From 18de9128d6d58636164b814ea1d1a1d8ec6db1a5 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 14 Mar 2023 12:03:02 +0100 Subject: [PATCH 31/54] Add NEWS --- .../next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst diff --git a/Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst b/Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst new file mode 100644 index 00000000000000..2232ea49382d13 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst @@ -0,0 +1,2 @@ +Isolate the :mod:`io` extension module by applying :pep:`687`. Patch by +Kumar Aditya and Erlend E. Aasland. From c363eb80e97a45c443458365ba18fff31cacbb26 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Tue, 14 Mar 2023 11:19:29 +0000 Subject: [PATCH 32/54] fix windows console check --- Modules/_io/_iomodule.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 480913e4fd9d81..15bfaa3ca7eb7d 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -147,7 +147,7 @@ typedef struct { PyTypeObject *PyStringIO_Type; PyTypeObject *PyTextIOBase_Type; PyTypeObject *PyTextIOWrapper_Type; -#ifdef MS_WINDOWS +#ifdef HAVE_WINDOWS_CONSOLE_IO PyTypeObject *PyWindowsConsoleIO_Type; #endif } _PyIO_State; From 73d581c4b6c5e53a5b9c0a8941051bfa6e879dc9 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Tue, 14 Mar 2023 11:28:42 +0000 Subject: [PATCH 33/54] remove locale --- Modules/_io/_iomodule.c | 2 -- Modules/_io/_iomodule.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 219298387d186a..bae0dbe0fe8837 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -564,7 +564,6 @@ static int iomodule_traverse(PyObject *mod, visitproc visit, void *arg) { _PyIO_State *state = get_io_state(mod); - Py_VISIT(state->locale_module); Py_VISIT(state->unsupported_operation); Py_VISIT(state->PyBufferedIOBase_Type); @@ -592,7 +591,6 @@ static int iomodule_clear(PyObject *mod) { _PyIO_State *state = get_io_state(mod); - Py_CLEAR(state->locale_module); Py_CLEAR(state->unsupported_operation); Py_CLEAR(state->PyBufferedIOBase_Type); diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 15bfaa3ca7eb7d..cac7b2514c210c 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -128,8 +128,6 @@ extern Py_off_t PyNumber_AsOff_t(PyObject *item, PyObject *err); extern PyModuleDef _PyIO_Module; typedef struct { - PyObject *locale_module; - PyObject *unsupported_operation; /* Types */ From eaf585e18d45c00df3c462c9017bc79f079a7402 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Wed, 15 Mar 2023 07:32:39 +0000 Subject: [PATCH 34/54] fix all windows checks --- Modules/_io/_iomodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index bae0dbe0fe8837..b10997a11f7282 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -580,7 +580,7 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) Py_VISIT(state->PyStringIO_Type); Py_VISIT(state->PyTextIOBase_Type); Py_VISIT(state->PyTextIOWrapper_Type); -#ifdef MS_WINDOWS +#ifdef HAVE_WINDOWS_CONSOLE_IO Py_VISIT(state->PyWindowsConsoleIO_Type); #endif return 0; @@ -607,7 +607,7 @@ iomodule_clear(PyObject *mod) Py_CLEAR(state->PyStringIO_Type); Py_CLEAR(state->PyTextIOBase_Type); Py_CLEAR(state->PyTextIOWrapper_Type); -#ifdef MS_WINDOWS +#ifdef HAVE_WINDOWS_CONSOLE_IO Py_CLEAR(state->PyWindowsConsoleIO_Type); #endif return 0; From 8d5b6a1a2aaf4a10f4505432177b0c4c9bb7d520 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 22 Mar 2023 13:01:55 +0100 Subject: [PATCH 35/54] Fix merge --- Python/pylifecycle.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 7d98203a681f73..9cc5fa1b98931f 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -695,11 +695,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; From e12eb85a1267c4b314ef5cded4497864ae0655e9 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Tue, 4 Apr 2023 16:16:31 +0530 Subject: [PATCH 36/54] use _PyType_GetModuleState --- Modules/_io/_iomodule.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index cac7b2514c210c..c78bb153968c4f 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -5,6 +5,7 @@ #include "exports.h" #include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_typeobject.h" // _PyType_GetModuleState() #include "structmember.h" /* Type specs */ @@ -161,7 +162,7 @@ get_io_state(PyObject *module) static inline _PyIO_State * get_io_state_by_cls(PyTypeObject *cls) { - void *state = PyType_GetModuleState(cls); + void *state = _PyType_GetModuleState(cls); assert(state != NULL); return (_PyIO_State *)state; } From 408c3b27ac315a95aaf417726dbbf03c991b471e Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 18 Apr 2023 22:33:20 -0600 Subject: [PATCH 37/54] WIP --- Modules/_io/bufferedio.c | 27 +++++++++++++-------------- Modules/_io/bytesio.c | 10 +++++++++- Modules/_io/fileio.c | 2 +- Modules/_io/stringio.c | 11 +++++++---- Modules/_io/textio.c | 2 +- 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index e935b73a42f301..2f658b9b5a26cd 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -368,6 +368,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) { @@ -379,7 +388,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; @@ -388,7 +396,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); } @@ -412,15 +420,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). */ @@ -2128,6 +2127,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; } @@ -2147,9 +2148,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); } diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 6a7d9fad8a2a83..3fddfc2ed0bc9c 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -1090,6 +1090,13 @@ bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view) b->exports--; } +static int +bytesiobuf_clear(bytesiobuf *self) +{ + Py_CLEAR(self->source); + return 0; +} + static int bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg) { @@ -1104,7 +1111,7 @@ bytesiobuf_dealloc(bytesiobuf *self) PyTypeObject *tp = Py_TYPE(self); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(self); - Py_CLEAR(self->source); + (void)bytesiobuf_clear(self); tp->tp_free(self); Py_DECREF(tp); } @@ -1112,6 +1119,7 @@ bytesiobuf_dealloc(bytesiobuf *self) static PyType_Slot bytesiobuf_slots[] = { {Py_tp_dealloc, bytesiobuf_dealloc}, {Py_tp_traverse, bytesiobuf_traverse}, + {Py_tp_clear, bytesiobuf_clear}, // Buffer protocol {Py_bf_getbuffer, bytesiobuf_getbuffer}, diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 44a04fa599af6b..1a286b29e526ff 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -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); } diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 1cd8e01b3ed466..c741f31cbdea98 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -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); } diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 303e86f832c9fb..a50f8f69bec348 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -1403,7 +1403,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); } From 22b73a18d85b88aef0a987c1fe5ec39809ae9b46 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Fri, 28 Apr 2023 08:58:32 +0200 Subject: [PATCH 38/54] Visit and clear bytesio buf --- Modules/_io/bytesio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 3fddfc2ed0bc9c..80773058693259 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -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; } From 21470e61410afafe9aa03f1fc35839c6fb1c6fba Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 6 May 2023 21:55:45 +0200 Subject: [PATCH 39/54] Update NEWS --- .../next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst b/Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst index 2232ea49382d13..4a73bbf32b370e 100644 --- a/Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst +++ b/Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst @@ -1,2 +1,2 @@ Isolate the :mod:`io` extension module by applying :pep:`687`. Patch by -Kumar Aditya and Erlend E. Aasland. +Kumar Aditya, Victor Stinner, and Erlend E. Aasland. From ce82d88c0152266d14f8ecf5dd6d8305cf969a56 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 6 May 2023 21:57:27 +0200 Subject: [PATCH 40/54] Minimise diff a little bit --- Modules/_io/_iomodule.c | 8 ++++---- Modules/_io/_iomodule.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index ece26b113cf94d..cae599c79fc214 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -567,6 +567,8 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) _PyIO_State *state = get_io_state(mod); Py_VISIT(state->unsupported_operation); + Py_VISIT(state->PyIncrementalNewlineDecoder_Type); + Py_VISIT(state->PyRawIOBase_Type); Py_VISIT(state->PyBufferedIOBase_Type); Py_VISIT(state->PyBufferedRWPair_Type); Py_VISIT(state->PyBufferedRandom_Type); @@ -576,8 +578,6 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) Py_VISIT(state->PyBytesIO_Type); Py_VISIT(state->PyFileIO_Type); Py_VISIT(state->PyIOBase_Type); - Py_VISIT(state->PyIncrementalNewlineDecoder_Type); - Py_VISIT(state->PyRawIOBase_Type); Py_VISIT(state->PyStringIO_Type); Py_VISIT(state->PyTextIOBase_Type); Py_VISIT(state->PyTextIOWrapper_Type); @@ -594,6 +594,8 @@ iomodule_clear(PyObject *mod) _PyIO_State *state = get_io_state(mod); Py_CLEAR(state->unsupported_operation); + Py_CLEAR(state->PyIncrementalNewlineDecoder_Type); + Py_CLEAR(state->PyRawIOBase_Type); Py_CLEAR(state->PyBufferedIOBase_Type); Py_CLEAR(state->PyBufferedRWPair_Type); Py_CLEAR(state->PyBufferedRandom_Type); @@ -603,8 +605,6 @@ iomodule_clear(PyObject *mod) Py_CLEAR(state->PyBytesIO_Type); Py_CLEAR(state->PyFileIO_Type); Py_CLEAR(state->PyIOBase_Type); - Py_CLEAR(state->PyIncrementalNewlineDecoder_Type); - Py_CLEAR(state->PyRawIOBase_Type); Py_CLEAR(state->PyStringIO_Type); Py_CLEAR(state->PyTextIOBase_Type); Py_CLEAR(state->PyTextIOWrapper_Type); diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index c78bb153968c4f..3cab2fee3903c1 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -132,6 +132,8 @@ typedef struct { PyObject *unsupported_operation; /* Types */ + PyTypeObject *PyIncrementalNewlineDecoder_Type; + PyTypeObject *PyRawIOBase_Type; PyTypeObject *PyBufferedIOBase_Type; PyTypeObject *PyBufferedRWPair_Type; PyTypeObject *PyBufferedRandom_Type; @@ -141,8 +143,6 @@ typedef struct { PyTypeObject *PyBytesIO_Type; PyTypeObject *PyFileIO_Type; PyTypeObject *PyIOBase_Type; - PyTypeObject *PyIncrementalNewlineDecoder_Type; - PyTypeObject *PyRawIOBase_Type; PyTypeObject *PyStringIO_Type; PyTypeObject *PyTextIOBase_Type; PyTypeObject *PyTextIOWrapper_Type; From 3a9f5823dd1db02175d9b101a5527b05f9308ff2 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 6 May 2023 21:58:39 +0200 Subject: [PATCH 41/54] Add Py_mod_multiple_interpreters mod slot --- Modules/_io/_iomodule.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index cae599c79fc214..45f676eda79ce3 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -719,6 +719,7 @@ do { \ 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, From 13700b5903ae46dc37be2a56fa0a49d020cc05f8 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 6 May 2023 23:41:28 +0200 Subject: [PATCH 42/54] Fix pickling --- Modules/_io/_iomodule.h | 2 ++ Modules/_io/bufferedio.c | 8 ++++++++ Modules/_io/fileio.c | 2 ++ Modules/_io/iobase.c | 8 +++----- Modules/_io/textio.c | 3 +++ 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 3cab2fee3903c1..2ed4568b7733c3 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -184,6 +184,8 @@ extern PyObject* _PyIOBase_check_writable(_PyIO_State *state, PyObject *self, Py extern PyObject* _PyIOBase_check_seekable(_PyIO_State *state, PyObject *self, PyObject *args); extern PyObject* _PyIOBase_check_closed(PyObject *self, PyObject *args); +extern PyObject *cannot_pickle(PyObject *self, PyObject *args); + #ifdef HAVE_WINDOWS_CONSOLE_IO extern char _PyIO_get_console_type(PyObject *); #endif diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 040f33828ccaec..d0a680a00718b6 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -2390,6 +2390,9 @@ static PyMethodDef bufferedreader_methods[] = { {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, _IO__BUFFERED_TRUNCATE_METHODDEF {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, + + {"__reduce__", cannot_pickle, METH_VARARGS}, + {"__reduce_ex__", cannot_pickle, METH_VARARGS}, {NULL, NULL} }; @@ -2447,6 +2450,8 @@ static PyMethodDef bufferedwriter_methods[] = { _IO__BUFFERED_SEEK_METHODDEF {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, + {"__reduce__", cannot_pickle, METH_VARARGS}, + {"__reduce_ex__", cannot_pickle, METH_VARARGS}, {NULL, NULL} }; @@ -2562,6 +2567,9 @@ static PyMethodDef bufferedrandom_methods[] = { _IO__BUFFERED_PEEK_METHODDEF _IO_BUFFEREDWRITER_WRITE_METHODDEF {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, + + {"__reduce__", cannot_pickle, METH_VARARGS}, + {"__reduce_ex__", cannot_pickle, METH_VARARGS}, {NULL, NULL} }; diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 8dd5e61b245028..45a99ca42f797a 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -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__", cannot_pickle, METH_VARARGS}, + {"__reduce_ex__", cannot_pickle, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index aaf1f6f2dac635..3c24765d2f678f 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -225,8 +225,9 @@ iobase_check_writable(PyObject *self, PyObject *args) return _PyIOBase_check_writable(state, self, args); } -static PyObject * -iobase_reduce(PyObject *self, PyObject *args) { +PyObject * +cannot_pickle(PyObject *self, PyObject *args) +{ PyErr_Format(PyExc_TypeError, "cannot pickle '%.100s' instances", _PyType_Name(Py_TYPE(self))); return NULL; @@ -849,9 +850,6 @@ static PyMethodDef iobase_methods[] = { _IO__IOBASE_READLINES_METHODDEF _IO__IOBASE_WRITELINES_METHODDEF - {"__reduce__", iobase_reduce, METH_VARARGS}, - {"__reduce_ex__", iobase_reduce, METH_VARARGS}, - {NULL, NULL} }; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index b772a511e9a83a..183e185166dbf2 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -3216,6 +3216,9 @@ static PyMethodDef textiowrapper_methods[] = { _IO_TEXTIOWRAPPER_SEEK_METHODDEF _IO_TEXTIOWRAPPER_TELL_METHODDEF _IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF + + {"__reduce__", cannot_pickle, METH_VARARGS}, + {"__reduce_ex__", cannot_pickle, METH_VARARGS}, {NULL, NULL} }; From e8d0b57da8f9ae55bf0f14500c55e5c4cccc13a4 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sat, 6 May 2023 23:53:48 +0200 Subject: [PATCH 43/54] Make cannot-pickle function less smelly --- Modules/_io/_iomodule.h | 2 +- Modules/_io/bufferedio.c | 12 ++++++------ Modules/_io/fileio.c | 4 ++-- Modules/_io/iobase.c | 2 +- Modules/_io/textio.c | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index 2ed4568b7733c3..fb2bb08871a5b9 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -184,7 +184,7 @@ extern PyObject* _PyIOBase_check_writable(_PyIO_State *state, PyObject *self, Py extern PyObject* _PyIOBase_check_seekable(_PyIO_State *state, PyObject *self, PyObject *args); extern PyObject* _PyIOBase_check_closed(PyObject *self, PyObject *args); -extern PyObject *cannot_pickle(PyObject *self, PyObject *args); +extern PyObject *_PyIOBase_cannot_pickle(PyObject *self, PyObject *args); #ifdef HAVE_WINDOWS_CONSOLE_IO extern char _PyIO_get_console_type(PyObject *); diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index d0a680a00718b6..041a30a8f3278c 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -2391,8 +2391,8 @@ static PyMethodDef bufferedreader_methods[] = { _IO__BUFFERED_TRUNCATE_METHODDEF {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, - {"__reduce__", cannot_pickle, METH_VARARGS}, - {"__reduce_ex__", cannot_pickle, METH_VARARGS}, + {"__reduce__", _PyIOBase_cannot_pickle, METH_VARARGS}, + {"__reduce_ex__", _PyIOBase_cannot_pickle, METH_VARARGS}, {NULL, NULL} }; @@ -2450,8 +2450,8 @@ static PyMethodDef bufferedwriter_methods[] = { _IO__BUFFERED_SEEK_METHODDEF {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, - {"__reduce__", cannot_pickle, METH_VARARGS}, - {"__reduce_ex__", cannot_pickle, METH_VARARGS}, + {"__reduce__", _PyIOBase_cannot_pickle, METH_VARARGS}, + {"__reduce_ex__", _PyIOBase_cannot_pickle, METH_VARARGS}, {NULL, NULL} }; @@ -2568,8 +2568,8 @@ static PyMethodDef bufferedrandom_methods[] = { _IO_BUFFEREDWRITER_WRITE_METHODDEF {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, - {"__reduce__", cannot_pickle, METH_VARARGS}, - {"__reduce_ex__", cannot_pickle, METH_VARARGS}, + {"__reduce__", _PyIOBase_cannot_pickle, METH_VARARGS}, + {"__reduce_ex__", _PyIOBase_cannot_pickle, METH_VARARGS}, {NULL, NULL} }; diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 45a99ca42f797a..8fc2e3ae256788 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -1166,8 +1166,8 @@ static PyMethodDef fileio_methods[] = { _IO_FILEIO_FILENO_METHODDEF _IO_FILEIO_ISATTY_METHODDEF {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL}, - {"__reduce__", cannot_pickle, METH_VARARGS}, - {"__reduce_ex__", cannot_pickle, METH_VARARGS}, + {"__reduce__", _PyIOBase_cannot_pickle, METH_VARARGS}, + {"__reduce_ex__", _PyIOBase_cannot_pickle, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 3c24765d2f678f..c9bfaef2fa8083 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -226,7 +226,7 @@ iobase_check_writable(PyObject *self, PyObject *args) } PyObject * -cannot_pickle(PyObject *self, PyObject *args) +_PyIOBase_cannot_pickle(PyObject *self, PyObject *args) { PyErr_Format(PyExc_TypeError, "cannot pickle '%.100s' instances", _PyType_Name(Py_TYPE(self))); diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 183e185166dbf2..54863c87f8d0aa 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -3217,8 +3217,8 @@ static PyMethodDef textiowrapper_methods[] = { _IO_TEXTIOWRAPPER_TELL_METHODDEF _IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF - {"__reduce__", cannot_pickle, METH_VARARGS}, - {"__reduce_ex__", cannot_pickle, METH_VARARGS}, + {"__reduce__", _PyIOBase_cannot_pickle, METH_VARARGS}, + {"__reduce_ex__", _PyIOBase_cannot_pickle, METH_VARARGS}, {NULL, NULL} }; From f1a5de0f63349133e7bfae6a71df41b23ef449dd Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 7 May 2023 12:25:00 +0200 Subject: [PATCH 44/54] Style nit --- Modules/_io/_iomodule.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 57ea0579f46436..945fdaf0c5eadc 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -724,7 +724,9 @@ 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 = { +}; + +struct PyModuleDef _PyIO_Module = { .m_base = PyModuleDef_HEAD_INIT, .m_name = "io", .m_doc = module_doc, From 10788579438f9be610a7e103f0c268d556c4ca42 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 10 May 2023 12:27:37 +0200 Subject: [PATCH 45/54] Reduce diff --- Modules/_io/_iomodule.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index a90105f441d832..1034ee8d90c918 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -676,11 +676,9 @@ do { \ } \ } while (0) - // Concrete classes + // Base classes ADD_TYPE(m, state->PyIncrementalNewlineDecoder_Type, &nldecoder_spec, NULL); ADD_TYPE(m, state->PyBytesIOBuffer_Type, &bytesiobuf_spec, NULL); - - // Base classes ADD_TYPE(m, state->PyIOBase_Type, &iobase_spec, NULL); // PyIOBase_Type subclasses From 3dad38886193b929d66ce4f7b083d5a97344431b Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 10 May 2023 12:29:43 +0200 Subject: [PATCH 46/54] Remove duplicate ADD_TYPE(PyBytesIOBuffer_Type...) --- Modules/_io/_iomodule.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 1034ee8d90c918..9eec197474d047 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -702,8 +702,6 @@ do { \ // PyRawIOBase_Type(PyIOBase_Type) subclasses ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, state->PyRawIOBase_Type); - // XXX: should PyBytesIOBuffer_Type be subclass of PyRawIOBase_Type? - ADD_TYPE(m, state->PyBytesIOBuffer_Type, &bytesiobuf_spec, NULL); #ifdef HAVE_WINDOWS_CONSOLE_IO ADD_TYPE(m, state->PyWindowsConsoleIO_Type, &winconsoleio_spec, From 8df2633ae2566bfc84560cd2304ab3c50c0a6f5d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 10 May 2023 13:04:15 +0200 Subject: [PATCH 47/54] Remove unneeded stylic change --- Modules/_io/_iomodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 01c6f85e97fbe4..235a39be0a7d86 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -640,9 +640,8 @@ iomodule_exec(PyObject *m) _PyIO_State *state = get_io_state(m); /* DEFAULT_BUFFER_SIZE */ - if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0) { + if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0) return -1; - } /* UnsupportedOperation inherits from ValueError and OSError */ state->unsupported_operation = PyObject_CallFunction( From 150587201d306c39eccdecbea5cb2074c24b7153 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 10 May 2023 13:05:36 +0200 Subject: [PATCH 48/54] Reduce diff further --- Modules/_io/_iomodule.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 235a39be0a7d86..1d23445d6656e1 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -634,6 +634,18 @@ static PyMethodDef module_methods[] = { {NULL, NULL} }; +#define ADD_TYPE(module, type, spec, base) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \ + (PyObject *)base); \ + if (type == NULL) { \ + return -1; \ + } \ + if (PyModule_AddType(module, type) < 0) { \ + return -1; \ + } \ +} while (0) + static int iomodule_exec(PyObject *m) { @@ -661,18 +673,6 @@ iomodule_exec(PyObject *m) return -1; } -#define ADD_TYPE(module, type, spec, base) \ -do { \ - type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \ - (PyObject *)base); \ - if (type == NULL) { \ - return -1; \ - } \ - if (PyModule_AddType(module, type) < 0) { \ - return -1; \ - } \ -} while (0) - // Base classes ADD_TYPE(m, state->PyIncrementalNewlineDecoder_Type, &nldecoder_spec, NULL); ADD_TYPE(m, state->PyBytesIOBuffer_Type, &bytesiobuf_spec, NULL); From 6d55da9189cf27aa8e527428408740a81ccc75b6 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Fri, 12 May 2023 11:08:35 +0530 Subject: [PATCH 49/54] fixes by Victor --- Modules/_io/bufferedio.c | 1 - Modules/_io/textio.c | 1 - 2 files changed, 2 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 00698883c7697c..622088628a1d42 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -2450,7 +2450,6 @@ static PyMethodDef bufferediobase_methods[] = { }; static PyType_Slot bufferediobase_slots[] = { - {Py_tp_dealloc, bufferediobase_dealloc}, {Py_tp_doc, (void *)bufferediobase_doc}, {Py_tp_methods, bufferediobase_methods}, {Py_tp_traverse, bufferediobase_traverse}, diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index ad8e7c74df3ca9..b6d1113f98f42e 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -196,7 +196,6 @@ static PyGetSetDef textiobase_getset[] = { }; static PyType_Slot textiobase_slots[] = { - {Py_tp_dealloc, textiobase_dealloc}, {Py_tp_doc, (void *)textiobase_doc}, {Py_tp_methods, textiobase_methods}, {Py_tp_getset, textiobase_getset}, From 80af518c8ccaa10b7abc39bdbe79664a75f7f788 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Fri, 12 May 2023 12:08:21 +0530 Subject: [PATCH 50/54] remove unused functions --- Modules/_io/bufferedio.c | 9 --------- Modules/_io/textio.c | 9 --------- 2 files changed, 18 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 622088628a1d42..471f849e1770f5 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -2423,15 +2423,6 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, #include "clinic/bufferedio.c.h" #undef clinic_state -static void -bufferediobase_dealloc(PyObject *self) -{ - PyTypeObject *tp = Py_TYPE(self); - _PyObject_GC_UNTRACK(self); - tp->tp_free(self); - Py_DECREF(tp); -} - static int bufferediobase_traverse(PyObject *self, visitproc visit, void *arg) { diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index b6d1113f98f42e..be0ba52c0b7308 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -171,15 +171,6 @@ textiobase_traverse(PyObject *self, visitproc visit, void *arg) return 0; } -static void -textiobase_dealloc(PyObject *self) -{ - PyTypeObject *tp = Py_TYPE(self); - _PyObject_GC_UNTRACK(self); - tp->tp_free((PyObject *)self); - Py_DECREF(tp); -} - static PyMethodDef textiobase_methods[] = { _IO__TEXTIOBASE_DETACH_METHODDEF _IO__TEXTIOBASE_READ_METHODDEF From 02dbef74471fa0767545df9277032e1eac833788 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Fri, 12 May 2023 12:14:39 +0530 Subject: [PATCH 51/54] use defining_class --- Modules/_io/bufferedio.c | 6 +++--- Modules/_io/iobase.c | 4 ++-- Modules/_io/textio.c | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 471f849e1770f5..d5cc047bd8d563 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -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 = find_io_state_by_def(Py_TYPE(self)); + _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 = find_io_state_by_def(Py_TYPE(self)); + _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 = find_io_state_by_def(Py_TYPE(self)); + _PyIO_State *state = get_io_state_by_cls(cls); return bufferediobase_unsupported(state, "write"); } diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 6ce34a1cbff857..0129ae5f62a7ef 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -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 = find_io_state_by_def(Py_TYPE(self)); + _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 = find_io_state_by_def(Py_TYPE(self)); + _PyIO_State *state = get_io_state_by_cls(cls); return iobase_unsupported(state, "truncate"); } diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index be0ba52c0b7308..81dd3bed005a61 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -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 = find_io_state_by_def(Py_TYPE(self)); + _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 = find_io_state_by_def(Py_TYPE(self)); + _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 = find_io_state_by_def(Py_TYPE(self)); + _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 = find_io_state_by_def(Py_TYPE(self)); + _PyIO_State *state = get_io_state_by_cls(cls); return _unsupported(state, "write"); } From 8518ec5f5f673dce443dc7671e911640ab32034a Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Fri, 12 May 2023 12:17:00 +0530 Subject: [PATCH 52/54] remove rawiobase_dealloc --- Modules/_io/iobase.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 0129ae5f62a7ef..7a1f4643b72997 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -1034,15 +1034,6 @@ rawiobase_write(PyObject *self, PyObject *args) return NULL; } -static void -rawiobase_dealloc(PyObject *self) -{ - PyTypeObject *tp = Py_TYPE(self); - _PyObject_GC_UNTRACK(self); - tp->tp_free(self); - Py_DECREF(tp); -} - static int rawiobase_traverse(PyObject *self, visitproc visit, void *arg) { @@ -1059,7 +1050,6 @@ static PyMethodDef rawiobase_methods[] = { }; static PyType_Slot rawiobase_slots[] = { - {Py_tp_dealloc, rawiobase_dealloc}, {Py_tp_doc, (void *)rawiobase_doc}, {Py_tp_methods, rawiobase_methods}, {Py_tp_traverse, rawiobase_traverse}, From c5a430565ca7f88877fa36895129f95d4d0ec67d Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Fri, 12 May 2023 13:10:52 +0530 Subject: [PATCH 53/54] fix merge --- Modules/_io/_iomodule.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index a783a5bdb8a886..7b06c1bee5a832 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -577,7 +577,6 @@ iomodule_traverse(PyObject *mod, visitproc visit, void *arg) { Py_VISIT(state->PyBytesIOBuffer_Type); Py_VISIT(state->PyBytesIO_Type); Py_VISIT(state->PyFileIO_Type); - Py_VISIT(state->PyIOBase_Type); Py_VISIT(state->PyStringIO_Type); Py_VISIT(state->PyTextIOBase_Type); Py_VISIT(state->PyTextIOWrapper_Type); @@ -604,7 +603,6 @@ iomodule_clear(PyObject *mod) { Py_CLEAR(state->PyBytesIOBuffer_Type); Py_CLEAR(state->PyBytesIO_Type); Py_CLEAR(state->PyFileIO_Type); - Py_CLEAR(state->PyIOBase_Type); Py_CLEAR(state->PyStringIO_Type); Py_CLEAR(state->PyTextIOBase_Type); Py_CLEAR(state->PyTextIOWrapper_Type); @@ -676,7 +674,6 @@ iomodule_exec(PyObject *m) } // 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); From ab1baf442949297b21a7d628bb214d0effdfd0b7 Mon Sep 17 00:00:00 2001 From: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Date: Fri, 12 May 2023 13:17:06 +0530 Subject: [PATCH 54/54] fix merge --- Modules/_io/_iomodule.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h index d1af6a5cdc131f..afd638a120ba08 100644 --- a/Modules/_io/_iomodule.h +++ b/Modules/_io/_iomodule.h @@ -158,7 +158,6 @@ struct _io_state { PyTypeObject *PyBytesIOBuffer_Type; PyTypeObject *PyBytesIO_Type; PyTypeObject *PyFileIO_Type; - PyTypeObject *PyIOBase_Type; PyTypeObject *PyStringIO_Type; PyTypeObject *PyTextIOBase_Type; PyTypeObject *PyTextIOWrapper_Type; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy