bpo-41262: Convert memoryview to Argument Clinic. (GH-21421)

diff --git a/Objects/clinic/memoryobject.c.h b/Objects/clinic/memoryobject.c.h
index 8227f0e..4a682f6 100644
--- a/Objects/clinic/memoryobject.c.h
+++ b/Objects/clinic/memoryobject.c.h
@@ -2,6 +2,198 @@
 preserve
 [clinic start generated code]*/
 
+PyDoc_STRVAR(memoryview__doc__,
+"memoryview(object)\n"
+"--\n"
+"\n"
+"Create a new memoryview object which references the given object.");
+
+static PyObject *
+memoryview_impl(PyTypeObject *type, PyObject *object);
+
+static PyObject *
+memoryview(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"object", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "memoryview", 0};
+    PyObject *argsbuf[1];
+    PyObject * const *fastargs;
+    Py_ssize_t nargs = PyTuple_GET_SIZE(args);
+    PyObject *object;
+
+    fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf);
+    if (!fastargs) {
+        goto exit;
+    }
+    object = fastargs[0];
+    return_value = memoryview_impl(type, object);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(memoryview_release__doc__,
+"release($self, /)\n"
+"--\n"
+"\n"
+"Release the underlying buffer exposed by the memoryview object.");
+
+#define MEMORYVIEW_RELEASE_METHODDEF    \
+    {"release", (PyCFunction)memoryview_release, METH_NOARGS, memoryview_release__doc__},
+
+static PyObject *
+memoryview_release_impl(PyMemoryViewObject *self);
+
+static PyObject *
+memoryview_release(PyMemoryViewObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return memoryview_release_impl(self);
+}
+
+PyDoc_STRVAR(memoryview_cast__doc__,
+"cast($self, /, format, shape=<unrepresentable>)\n"
+"--\n"
+"\n"
+"Cast a memoryview to a new format or shape.");
+
+#define MEMORYVIEW_CAST_METHODDEF    \
+    {"cast", (PyCFunction)(void(*)(void))memoryview_cast, METH_FASTCALL|METH_KEYWORDS, memoryview_cast__doc__},
+
+static PyObject *
+memoryview_cast_impl(PyMemoryViewObject *self, PyObject *format,
+                     PyObject *shape);
+
+static PyObject *
+memoryview_cast(PyMemoryViewObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"format", "shape", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "cast", 0};
+    PyObject *argsbuf[2];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
+    PyObject *format;
+    PyObject *shape = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!PyUnicode_Check(args[0])) {
+        _PyArg_BadArgument("cast", "argument 'format'", "str", args[0]);
+        goto exit;
+    }
+    if (PyUnicode_READY(args[0]) == -1) {
+        goto exit;
+    }
+    format = args[0];
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    shape = args[1];
+skip_optional_pos:
+    return_value = memoryview_cast_impl(self, format, shape);
+
+exit:
+    return return_value;
+}
+
+PyDoc_STRVAR(memoryview_toreadonly__doc__,
+"toreadonly($self, /)\n"
+"--\n"
+"\n"
+"Return a readonly version of the memoryview.");
+
+#define MEMORYVIEW_TOREADONLY_METHODDEF    \
+    {"toreadonly", (PyCFunction)memoryview_toreadonly, METH_NOARGS, memoryview_toreadonly__doc__},
+
+static PyObject *
+memoryview_toreadonly_impl(PyMemoryViewObject *self);
+
+static PyObject *
+memoryview_toreadonly(PyMemoryViewObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return memoryview_toreadonly_impl(self);
+}
+
+PyDoc_STRVAR(memoryview_tolist__doc__,
+"tolist($self, /)\n"
+"--\n"
+"\n"
+"Return the data in the buffer as a list of elements.");
+
+#define MEMORYVIEW_TOLIST_METHODDEF    \
+    {"tolist", (PyCFunction)memoryview_tolist, METH_NOARGS, memoryview_tolist__doc__},
+
+static PyObject *
+memoryview_tolist_impl(PyMemoryViewObject *self);
+
+static PyObject *
+memoryview_tolist(PyMemoryViewObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return memoryview_tolist_impl(self);
+}
+
+PyDoc_STRVAR(memoryview_tobytes__doc__,
+"tobytes($self, /, order=\'C\')\n"
+"--\n"
+"\n"
+"Return the data in the buffer as a byte string.\n"
+"\n"
+"Order can be {\'C\', \'F\', \'A\'}. When order is \'C\' or \'F\', the data of the\n"
+"original array is converted to C or Fortran order. For contiguous views,\n"
+"\'A\' returns an exact copy of the physical memory. In particular, in-memory\n"
+"Fortran order is preserved. For non-contiguous views, the data is converted\n"
+"to C first. order=None is the same as order=\'C\'.");
+
+#define MEMORYVIEW_TOBYTES_METHODDEF    \
+    {"tobytes", (PyCFunction)(void(*)(void))memoryview_tobytes, METH_FASTCALL|METH_KEYWORDS, memoryview_tobytes__doc__},
+
+static PyObject *
+memoryview_tobytes_impl(PyMemoryViewObject *self, const char *order);
+
+static PyObject *
+memoryview_tobytes(PyMemoryViewObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+    PyObject *return_value = NULL;
+    static const char * const _keywords[] = {"order", NULL};
+    static _PyArg_Parser _parser = {NULL, _keywords, "tobytes", 0};
+    PyObject *argsbuf[1];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+    const char *order = NULL;
+
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    if (args[0] == Py_None) {
+        order = NULL;
+    }
+    else if (PyUnicode_Check(args[0])) {
+        Py_ssize_t order_length;
+        order = PyUnicode_AsUTF8AndSize(args[0], &order_length);
+        if (order == NULL) {
+            goto exit;
+        }
+        if (strlen(order) != (size_t)order_length) {
+            PyErr_SetString(PyExc_ValueError, "embedded null character");
+            goto exit;
+        }
+    }
+    else {
+        _PyArg_BadArgument("tobytes", "argument 'order'", "str or None", args[0]);
+        goto exit;
+    }
+skip_optional_pos:
+    return_value = memoryview_tobytes_impl(self, order);
+
+exit:
+    return return_value;
+}
+
 PyDoc_STRVAR(memoryview_hex__doc__,
 "hex($self, /, sep=<unrepresentable>, bytes_per_sep=1)\n"
 "--\n"
@@ -66,4 +258,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=91106ef704134b19 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=1b879bb934d18c66 input=a9049054013a1b77]*/
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index e3d3bd6a..13d883a 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -238,12 +238,6 @@
 #define REQ_FORMAT(flags) (flags&PyBUF_FORMAT)
 
 
-PyDoc_STRVAR(memory_doc,
-"memoryview(object)\n--\n\
-\n\
-Create a new memoryview object which references the given object.");
-
-
 /**************************************************************************/
 /*                       Copy memoryview buffers                          */
 /**************************************************************************/
@@ -961,18 +955,20 @@
 }
 
 
+/*[clinic input]
+@classmethod
+memoryview.__new__
+
+    object: object
+
+Create a new memoryview object which references the given object.
+[clinic start generated code]*/
+
 static PyObject *
-memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
+memoryview_impl(PyTypeObject *type, PyObject *object)
+/*[clinic end generated code: output=7de78e184ed66db8 input=f04429eb0bdf8c6e]*/
 {
-    PyObject *obj;
-    static char *kwlist[] = {"object", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist,
-                                     &obj)) {
-        return NULL;
-    }
-
-    return PyMemoryView_FromObject(obj);
+    return PyMemoryView_FromObject(object);
 }
 
 
@@ -1062,8 +1058,15 @@
     return -1;
 }
 
+/*[clinic input]
+memoryview.release
+
+Release the underlying buffer exposed by the memoryview object.
+[clinic start generated code]*/
+
 static PyObject *
-memory_release(PyMemoryViewObject *self, PyObject *noargs)
+memoryview_release_impl(PyMemoryViewObject *self)
+/*[clinic end generated code: output=d0b7e3ba95b7fcb9 input=bc71d1d51f4a52f0]*/
 {
     if (_memory_release(self) < 0)
         return NULL;
@@ -1108,7 +1111,7 @@
 static PyObject *
 memory_exit(PyObject *self, PyObject *args)
 {
-    return memory_release((PyMemoryViewObject *)self, NULL);
+    return memoryview_release_impl((PyMemoryViewObject *)self);
 }
 
 
@@ -1352,26 +1355,25 @@
    All casts must result in views that will have the exact byte
    size of the original input. Otherwise, an error is raised.
 */
+/*[clinic input]
+memoryview.cast
+
+    format: unicode
+    shape: object = NULL
+
+Cast a memoryview to a new format or shape.
+[clinic start generated code]*/
+
 static PyObject *
-memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
+memoryview_cast_impl(PyMemoryViewObject *self, PyObject *format,
+                     PyObject *shape)
+/*[clinic end generated code: output=bae520b3a389cbab input=138936cc9041b1a3]*/
 {
-    static char *kwlist[] = {"format", "shape", NULL};
     PyMemoryViewObject *mv = NULL;
-    PyObject *shape = NULL;
-    PyObject *format;
     Py_ssize_t ndim = 1;
 
     CHECK_RELEASED(self);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
-                                     &format, &shape)) {
-        return NULL;
-    }
-    if (!PyUnicode_Check(format)) {
-        PyErr_SetString(PyExc_TypeError,
-            "memoryview: format argument must be a string");
-        return NULL;
-    }
     if (!MV_C_CONTIGUOUS(self->flags)) {
         PyErr_SetString(PyExc_TypeError,
             "memoryview: casts are restricted to C-contiguous views");
@@ -1415,8 +1417,15 @@
     return NULL;
 }
 
+/*[clinic input]
+memoryview.toreadonly
+
+Return a readonly version of the memoryview.
+[clinic start generated code]*/
+
 static PyObject *
-memory_toreadonly(PyMemoryViewObject *self, PyObject *noargs)
+memoryview_toreadonly_impl(PyMemoryViewObject *self)
+/*[clinic end generated code: output=2c7e056f04c99e62 input=dc06d20f19ba236f]*/
 {
     CHECK_RELEASED(self);
     /* Even if self is already readonly, we still need to create a new
@@ -2109,13 +2118,20 @@
 
 /* Return a list representation of the memoryview. Currently only buffers
    with native format strings are supported. */
+/*[clinic input]
+memoryview.tolist
+
+Return the data in the buffer as a list of elements.
+[clinic start generated code]*/
+
 static PyObject *
-memory_tolist(PyMemoryViewObject *mv, PyObject *noargs)
+memoryview_tolist_impl(PyMemoryViewObject *self)
+/*[clinic end generated code: output=a6cda89214fd5a1b input=21e7d0c1860b211a]*/
 {
-    const Py_buffer *view = &(mv->view);
+    const Py_buffer *view = &self->view;
     const char *fmt;
 
-    CHECK_RELEASED(mv);
+    CHECK_RELEASED(self);
 
     fmt = adjust_fmt(view);
     if (fmt == NULL)
@@ -2135,21 +2151,30 @@
     }
 }
 
+/*[clinic input]
+memoryview.tobytes
+
+    order: str(accept={str, NoneType}, c_default="NULL") = 'C'
+
+Return the data in the buffer as a byte string.
+
+Order can be {'C', 'F', 'A'}. When order is 'C' or 'F', the data of the
+original array is converted to C or Fortran order. For contiguous views,
+'A' returns an exact copy of the physical memory. In particular, in-memory
+Fortran order is preserved. For non-contiguous views, the data is converted
+to C first. order=None is the same as order='C'.
+[clinic start generated code]*/
+
 static PyObject *
-memory_tobytes(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
+memoryview_tobytes_impl(PyMemoryViewObject *self, const char *order)
+/*[clinic end generated code: output=1288b62560a32a23 input=0efa3ddaeda573a8]*/
 {
-    static char *kwlist[] = {"order", NULL};
     Py_buffer *src = VIEW_ADDR(self);
-    char *order = NULL;
     char ord = 'C';
     PyObject *bytes;
 
     CHECK_RELEASED(self);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|z", kwlist, &order)) {
-        return NULL;
-    }
-
     if (order) {
         if (strcmp(order, "F") == 0) {
             ord = 'F';
@@ -3122,38 +3147,14 @@
     {NULL, NULL, NULL, NULL},
 };
 
-PyDoc_STRVAR(memory_release_doc,
-"release($self, /)\n--\n\
-\n\
-Release the underlying buffer exposed by the memoryview object.");
-PyDoc_STRVAR(memory_tobytes_doc,
-"tobytes($self, /, order=None)\n--\n\
-\n\
-Return the data in the buffer as a byte string. Order can be {'C', 'F', 'A'}.\n\
-When order is 'C' or 'F', the data of the original array is converted to C or\n\
-Fortran order. For contiguous views, 'A' returns an exact copy of the physical\n\
-memory. In particular, in-memory Fortran order is preserved. For non-contiguous\n\
-views, the data is converted to C first. order=None is the same as order='C'.");
-PyDoc_STRVAR(memory_tolist_doc,
-"tolist($self, /)\n--\n\
-\n\
-Return the data in the buffer as a list of elements.");
-PyDoc_STRVAR(memory_cast_doc,
-"cast($self, /, format, *, shape)\n--\n\
-\n\
-Cast a memoryview to a new format or shape.");
-PyDoc_STRVAR(memory_toreadonly_doc,
-"toreadonly($self, /)\n--\n\
-\n\
-Return a readonly version of the memoryview.");
 
 static PyMethodDef memory_methods[] = {
-    {"release",     (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
-    {"tobytes",     (PyCFunction)(void(*)(void))memory_tobytes, METH_VARARGS|METH_KEYWORDS, memory_tobytes_doc},
+    MEMORYVIEW_RELEASE_METHODDEF
+    MEMORYVIEW_TOBYTES_METHODDEF
     MEMORYVIEW_HEX_METHODDEF
-    {"tolist",      (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
-    {"cast",        (PyCFunction)(void(*)(void))memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
-    {"toreadonly",  (PyCFunction)memory_toreadonly, METH_NOARGS, memory_toreadonly_doc},
+    MEMORYVIEW_TOLIST_METHODDEF
+    MEMORYVIEW_CAST_METHODDEF
+    MEMORYVIEW_TOREADONLY_METHODDEF
     {"__enter__",   memory_enter, METH_NOARGS, NULL},
     {"__exit__",    memory_exit, METH_VARARGS, NULL},
     {NULL,          NULL}
@@ -3181,7 +3182,7 @@
     0,                                        /* tp_setattro */
     &memory_as_buffer,                        /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,  /* tp_flags */
-    memory_doc,                               /* tp_doc */
+    memoryview__doc__,                        /* tp_doc */
     (traverseproc)memory_traverse,            /* tp_traverse */
     (inquiry)memory_clear,                    /* tp_clear */
     memory_richcompare,                       /* tp_richcompare */
@@ -3198,5 +3199,5 @@
     0,                                        /* tp_dictoffset */
     0,                                        /* tp_init */
     0,                                        /* tp_alloc */
-    memory_new,                               /* tp_new */
+    memoryview,                               /* tp_new */
 };