bpo-30534: Fixed error messages when pass keyword arguments (#1901)

to functions implemented in C that don't support this.

Also unified error messages for functions that don't take positional or keyword
arguments.
diff --git a/Objects/call.c b/Objects/call.c
index 4c74eab..6c8a640 100644
--- a/Objects/call.c
+++ b/Objects/call.c
@@ -466,6 +466,10 @@
     switch (flags)
     {
     case METH_NOARGS:
+        if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
+            goto no_keyword_error;
+        }
+
         if (nargs != 0) {
             PyErr_Format(PyExc_TypeError,
                 "%.200s() takes no arguments (%zd given)",
@@ -473,14 +477,14 @@
             goto exit;
         }
 
-        if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
-            goto no_keyword_error;
-        }
-
         result = (*meth) (self, NULL);
         break;
 
     case METH_O:
+        if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
+            goto no_keyword_error;
+        }
+
         if (nargs != 1) {
             PyErr_Format(PyExc_TypeError,
                 "%.200s() takes exactly one argument (%zd given)",
@@ -488,16 +492,11 @@
             goto exit;
         }
 
-        if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
-            goto no_keyword_error;
-        }
-
         result = (*meth) (self, args[0]);
         break;
 
     case METH_VARARGS:
-        if (!(flags & METH_KEYWORDS)
-                && kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
+        if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
             goto no_keyword_error;
         }
         /* fall through next case */
@@ -592,7 +591,7 @@
 
     PyCFunction meth = method->ml_meth;
     int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
-    Py_ssize_t nkwargs = kwnames == NULL ? 0 : PyTuple_Size(kwnames);
+    Py_ssize_t nkwargs = kwnames == NULL ? 0 : PyTuple_GET_SIZE(kwnames);
     PyObject *result = NULL;
 
     if (Py_EnterRecursiveCall(" while calling a Python object")) {
@@ -602,6 +601,10 @@
     switch (flags)
     {
     case METH_NOARGS:
+        if (nkwargs) {
+            goto no_keyword_error;
+        }
+
         if (nargs != 0) {
             PyErr_Format(PyExc_TypeError,
                 "%.200s() takes no arguments (%zd given)",
@@ -609,14 +612,14 @@
             goto exit;
         }
 
-        if (nkwargs) {
-            goto no_keyword_error;
-        }
-
         result = (*meth) (self, NULL);
         break;
 
     case METH_O:
+        if (nkwargs) {
+            goto no_keyword_error;
+        }
+
         if (nargs != 1) {
             PyErr_Format(PyExc_TypeError,
                 "%.200s() takes exactly one argument (%zd given)",
@@ -624,10 +627,6 @@
             goto exit;
         }
 
-        if (nkwargs) {
-            goto no_keyword_error;
-        }
-
         result = (*meth) (self, args[0]);
         break;
 
@@ -637,16 +636,17 @@
         break;
 
     case METH_VARARGS:
+        if (nkwargs) {
+            goto no_keyword_error;
+        }
+        /* fall through next case */
+
     case METH_VARARGS | METH_KEYWORDS:
     {
         /* Slow-path: create a temporary tuple for positional arguments
            and a temporary dict for keyword arguments */
         PyObject *argtuple;
 
-        if (!(flags & METH_KEYWORDS) && nkwargs) {
-            goto no_keyword_error;
-        }
-
         argtuple = _PyStack_AsTuple(args, nargs);
         if (argtuple == NULL) {
             goto exit;
@@ -717,6 +717,7 @@
 cfunction_call_varargs(PyObject *func, PyObject *args, PyObject *kwargs)
 {
     assert(!PyErr_Occurred());
+    assert(kwargs == NULL || PyDict_Check(kwargs));
 
     PyCFunction meth = PyCFunction_GET_FUNCTION(func);
     PyObject *self = PyCFunction_GET_SELF(func);
@@ -732,7 +733,7 @@
         Py_LeaveRecursiveCall();
     }
     else {
-        if (kwargs != NULL && PyDict_Size(kwargs) != 0) {
+        if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
             PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
                          ((PyCFunctionObject*)func)->m_ml->ml_name);
             return NULL;
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 1d11605..c20ca9b 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -1176,7 +1176,7 @@
 
     if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
         PyErr_Format(PyExc_TypeError,
-                     "wrapper %s doesn't take keyword arguments",
+                     "wrapper %s() takes no keyword arguments",
                      wp->descr->d_base->name);
         return NULL;
     }