[Python-checkins] gh-101819: Refactor _io in preparation for module isolation (#104334)

erlend-aasland webhook-mailer at python.org
Tue May 9 19:09:16 EDT 2023


https://github.com/python/cpython/commit/235b82721dbbe2bc5bf1f45a74e22b7185e5783e
commit: 235b82721dbbe2bc5bf1f45a74e22b7185e5783e
branch: main
author: Erlend E. Aasland <erlend.aasland at protonmail.com>
committer: erlend-aasland <erlend.aasland at protonmail.com>
date: 2023-05-09T23:09:03Z
summary:

gh-101819: Refactor _io in preparation for module isolation (#104334)

- Replace query with parameter in bufferediobase_unsupported()
- Replace query with parameter in iobase_unsupported()
- Hide delegate: Add method wrapper for _PyIOBase_check_seekable
- Hide delegate: Add method wraper for _PyIOBase_check_readable
- Hide delegate: Add method wraper for _PyIOBase_check_writable
- Replace query with parameter in _PyIOBase_check_seekable()
- Replace query with parameter in _PyIOBase_check_readable()
- Replace query with parameter in _PyIOBase_check_writable()

files:
M Modules/_io/_iomodule.h
M Modules/_io/bufferedio.c
M Modules/_io/iobase.c

diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h
index 1bf301c9cf0a..b3873ddf7e08 100644
--- a/Modules/_io/_iomodule.h
+++ b/Modules/_io/_iomodule.h
@@ -34,9 +34,13 @@ extern PyType_Spec winconsoleio_spec;
  * 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);
+typedef struct _io_state _PyIO_State;  // Forward decl.
+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);
 
 /* Helper for finalization.
@@ -140,7 +144,7 @@ extern Py_off_t PyNumber_AsOff_t(PyObject *item, PyObject *err);
 
 extern PyModuleDef _PyIO_Module;
 
-typedef struct {
+struct _io_state {
     int initialized;
     PyObject *unsupported_operation;
 
@@ -161,7 +165,7 @@ typedef struct {
 #ifdef MS_WINDOWS
     PyTypeObject *PyWindowsConsoleIO_Type;
 #endif
-} _PyIO_State;
+};
 
 #define IO_MOD_STATE(mod) ((_PyIO_State *)PyModule_GetState(mod))
 #define IO_STATE() _PyIO_get_module_state()
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index 723d16b47fef..172fafe6db8a 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -106,11 +106,9 @@ _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;
 }
 
@@ -127,7 +125,8 @@ static PyObject *
 _io__BufferedIOBase_detach_impl(PyObject *self)
 /*[clinic end generated code: output=754977c8d10ed88c input=822427fb58fe4169]*/
 {
-    return bufferediobase_unsupported("detach");
+    _PyIO_State *state = IO_STATE();
+    return bufferediobase_unsupported(state, "detach");
 }
 
 PyDoc_STRVAR(bufferediobase_read_doc,
@@ -151,7 +150,8 @@ PyDoc_STRVAR(bufferediobase_read_doc,
 static PyObject *
 bufferediobase_read(PyObject *self, PyObject *args)
 {
-    return bufferediobase_unsupported("read");
+    _PyIO_State *state = IO_STATE();
+    return bufferediobase_unsupported(state, "read");
 }
 
 PyDoc_STRVAR(bufferediobase_read1_doc,
@@ -164,7 +164,8 @@ PyDoc_STRVAR(bufferediobase_read1_doc,
 static PyObject *
 bufferediobase_read1(PyObject *self, PyObject *args)
 {
-    return bufferediobase_unsupported("read1");
+    _PyIO_State *state = IO_STATE();
+    return bufferediobase_unsupported(state, "read1");
 }
 
 PyDoc_STRVAR(bufferediobase_write_doc,
@@ -179,7 +180,8 @@ PyDoc_STRVAR(bufferediobase_write_doc,
 static PyObject *
 bufferediobase_write(PyObject *self, PyObject *args)
 {
-    return bufferediobase_unsupported("write");
+    _PyIO_State *state = IO_STATE();
+    return bufferediobase_unsupported(state, "write");
 }
 
 
@@ -1222,8 +1224,10 @@ _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);
     if (target == -1 && PyErr_Occurred())
@@ -1298,7 +1302,8 @@ _io__Buffered_truncate_impl(buffered *self, PyObject *pos)
     CHECK_INITIALIZED(self)
     CHECK_CLOSED(self, "truncate of closed file")
     if (!self->writable) {
-        return bufferediobase_unsupported("truncate");
+        _PyIO_State *state = IO_STATE();
+        return bufferediobase_unsupported(state, "truncate");
     }
     if (!ENTER_BUFFERED(self))
         return NULL;
@@ -1419,8 +1424,10 @@ _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));
     self->buffer_size = buffer_size;
@@ -1431,7 +1438,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)
@@ -1774,8 +1780,10 @@ _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);
     Py_XSETREF(self->raw, raw);
@@ -1788,7 +1796,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)
@@ -2092,12 +2099,14 @@ _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);
@@ -2290,12 +2299,16 @@ _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);
     Py_XSETREF(self->raw, raw);
@@ -2309,7 +2322,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 682ed000eb1f..ca13866c33fb 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 = IO_STATE();
+    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 = IO_STATE();
+    return iobase_unsupported(state, "truncate");
 }
 
 static int
@@ -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 = IO_STATE();
+    return _PyIOBase_check_seekable(state, self, args);
+}
+
+static PyObject *
+iobase_check_readable(PyObject *self, PyObject *args)
+{
+    _PyIO_State *state = IO_STATE();
+    return _PyIOBase_check_readable(state, self, args);
+}
+
+static PyObject *
+iobase_check_writable(PyObject *self, PyObject *args)
+{
+    _PyIO_State *state = IO_STATE();
+    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. */
@@ -372,14 +393,14 @@ _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);
-        iobase_unsupported("File or stream is not seekable.");
+        iobase_unsupported(state, "File or stream is not seekable.");
         return NULL;
     }
     if (args == Py_True) {
@@ -405,14 +426,14 @@ _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);
-        iobase_unsupported("File or stream is not readable.");
+        iobase_unsupported(state, "File or stream is not readable.");
         return NULL;
     }
     if (args == Py_True) {
@@ -438,14 +459,14 @@ _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);
-        iobase_unsupported("File or stream is not writable.");
+        iobase_unsupported(state, "File or stream is not writable.");
         return NULL;
     }
     if (args == Py_True) {
@@ -487,7 +508,8 @@ static PyObject *
 _io__IOBase_fileno_impl(PyObject *self)
 /*[clinic end generated code: output=7cc0973f0f5f3b73 input=4e37028947dc1cc8]*/
 {
-    return iobase_unsupported("fileno");
+    _PyIO_State *state = IO_STATE();
+    return iobase_unsupported(state, "fileno");
 }
 
 /*[clinic input]
@@ -798,9 +820,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},
+    {"_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



More information about the Python-checkins mailing list