accept None as the same as having passed no argument in file types #7349

This is for consistency with imitation file objects like StringIO and BytesIO.

This commit also adds a few tests, where they were lacking for concerned
methods.
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c
index 7b43022..a2a6430 100644
--- a/Modules/_io/_iomodule.c
+++ b/Modules/_io/_iomodule.c
@@ -573,6 +573,29 @@
 }
 
 
+/* Basically the "n" format code with the ability to turn None into -1. */
+int 
+_PyIO_ConvertSsize_t(PyObject *obj, void *result) {
+    Py_ssize_t limit;
+    if (obj == Py_None) {
+        limit = -1;
+    }
+    else if (PyNumber_Check(obj)) {
+        limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
+        if (limit == -1 && PyErr_Occurred())
+            return 0;
+    }
+    else {
+        PyErr_Format(PyExc_TypeError,
+                     "integer argument expected, got '%.200s'",
+                     Py_TYPE(obj)->tp_name);
+        return 0;
+    }
+    *((Py_ssize_t *)result) = limit;
+    return 1;
+}
+
+
 /*
  * Module definition
  */
diff --git a/Modules/_io/_iomodule.h b/Modules/_io/_iomodule.h
index 790d919..0fa5391 100644
--- a/Modules/_io/_iomodule.h
+++ b/Modules/_io/_iomodule.h
@@ -19,6 +19,9 @@
 extern PyTypeObject PyTextIOWrapper_Type;
 extern PyTypeObject PyIncrementalNewlineDecoder_Type;
 
+
+extern int _PyIO_ConvertSsize_t(PyObject *, void *);
+
 /* 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.
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c
index 3ab7906..ba937ed 100644
--- a/Modules/_io/bufferedio.c
+++ b/Modules/_io/bufferedio.c
@@ -720,7 +720,7 @@
     PyObject *res;
 
     CHECK_INITIALIZED(self)
-    if (!PyArg_ParseTuple(args, "|n:read", &n)) {
+    if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) {
         return NULL;
     }
     if (n < -1) {
@@ -950,25 +950,11 @@
 static PyObject *
 buffered_readline(buffered *self, PyObject *args)
 {
-    PyObject *limitobj = NULL;
     Py_ssize_t limit = -1;
 
     CHECK_INITIALIZED(self)
-
-    if (!PyArg_ParseTuple(args, "|O:readline", &limitobj)) {
+    if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit))
         return NULL;
-    }
-    if (limitobj) {
-        if (!PyNumber_Check(limitobj)) {
-            PyErr_Format(PyExc_TypeError,
-                         "integer argument expected, got '%.200s'",
-                         Py_TYPE(limitobj)->tp_name);
-            return NULL;
-        }
-        limit = PyNumber_AsSsize_t(limitobj, PyExc_OverflowError);
-        if (limit == -1 && PyErr_Occurred())
-            return NULL;
-    }
     return _buffered_readline(self, limit);
 }
 
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index e98de9e..164fe5b 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -599,7 +599,7 @@
 	if (!self->readable)
 		return err_mode("reading");
 
-	if (!PyArg_ParseTuple(args, "|n", &size))
+	if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size))
 		return NULL;
 
         if (size < 0) {
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index 38080f7..bd6cd5f 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -455,7 +455,7 @@
     PyObject *buffer, *result;
     Py_ssize_t old_size = -1;
 
-    if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
+    if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit)) {
         return NULL;
     }
 
@@ -579,14 +579,9 @@
     Py_ssize_t hint = -1, length = 0;
     PyObject *hintobj = Py_None, *result;
 
-    if (!PyArg_ParseTuple(args, "|O:readlines", &hintobj)) {
+    if (!PyArg_ParseTuple(args, "|O&:readlines", &_PyIO_ConvertSsize_t, &hint)) {
         return NULL;
     }
-    if (hintobj != Py_None) {
-        hint = PyNumber_AsSsize_t(hintobj, PyExc_ValueError);
-        if (hint == -1 && PyErr_Occurred())
-            return NULL;
-    }
 
     result = PyList_New(0);
     if (result == NULL)
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 2f99a60..91fecae 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -1455,7 +1455,7 @@
 
     CHECK_INITIALIZED(self);
 
-    if (!PyArg_ParseTuple(args, "|n:read", &n))
+    if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n))
         return NULL;
 
     CHECK_CLOSED(self);