[Python-checkins] cpython: Issue #27574: Decreased an overhead of parsing keyword arguments in functions

serhiy.storchaka python-checkins at python.org
Sun Aug 14 03:53:16 EDT 2016


https://hg.python.org/cpython/rev/e527715bd0b3
changeset:   102650:e527715bd0b3
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Sun Aug 14 10:52:18 2016 +0300
summary:
  Issue #27574: Decreased an overhead of parsing keyword arguments in functions
implemented with using Argument Clinic.

files:
  Doc/whatsnew/3.6.rst                        |    7 +
  Include/modsupport.h                        |   23 +
  Misc/NEWS                                   |    3 +
  Modules/_io/clinic/_iomodule.c.h            |    7 +-
  Modules/_io/clinic/bufferedio.c.h           |   17 +-
  Modules/_io/clinic/bytesio.c.h              |    7 +-
  Modules/_io/clinic/fileio.c.h               |    7 +-
  Modules/_io/clinic/stringio.c.h             |    7 +-
  Modules/_io/clinic/textio.c.h               |   17 +-
  Modules/cjkcodecs/clinic/multibytecodec.c.h |   22 +-
  Modules/clinic/_bz2module.c.h               |    7 +-
  Modules/clinic/_codecsmodule.c.h            |   12 +-
  Modules/clinic/_datetimemodule.c.h          |    7 +-
  Modules/clinic/_elementtree.c.h             |   42 +-
  Modules/clinic/_lzmamodule.c.h              |   12 +-
  Modules/clinic/_pickle.c.h                  |   32 +-
  Modules/clinic/_sre.c.h                     |   77 +-
  Modules/clinic/_ssl.c.h                     |   42 +-
  Modules/clinic/_winapi.c.h                  |   17 +-
  Modules/clinic/binascii.c.h                 |   17 +-
  Modules/clinic/cmathmodule.c.h              |    7 +-
  Modules/clinic/grpmodule.c.h                |   12 +-
  Modules/clinic/md5module.c.h                |    7 +-
  Modules/clinic/posixmodule.c.h              |  312 ++++--
  Modules/clinic/pyexpat.c.h                  |    7 +-
  Modules/clinic/sha1module.c.h               |    7 +-
  Modules/clinic/sha256module.c.h             |   12 +-
  Modules/clinic/sha512module.c.h             |   12 +-
  Modules/clinic/zlibmodule.c.h               |   17 +-
  Objects/clinic/bytearrayobject.c.h          |   22 +-
  Objects/clinic/bytesobject.c.h              |   22 +-
  PC/clinic/winreg.c.h                        |   27 +-
  Python/clinic/bltinmodule.c.h               |    7 +-
  Python/getargs.c                            |  449 +++++++++-
  Python/pylifecycle.c                        |    1 +
  Tools/clinic/clinic.py                      |   14 +-
  36 files changed, 963 insertions(+), 354 deletions(-)


diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -579,6 +579,13 @@
   deserializing many small objects (Contributed by Victor Stinner in
   :issue:`27056`).
 
+- Passing :term:`keyword arguments <keyword argument>` to a function has an
+  overhead in comparison with passing :term:`positional arguments
+  <positional argument>`.  Now in extension functions implemented with using
+  Argument Clinic this overhead is significantly decreased.
+  (Contributed by Serhiy Storchaka in :issue:`27574`).
+
+
 Build and C API Changes
 =======================
 
diff --git a/Include/modsupport.h b/Include/modsupport.h
--- a/Include/modsupport.h
+++ b/Include/modsupport.h
@@ -44,6 +44,29 @@
 #endif
 PyAPI_FUNC(PyObject *) Py_VaBuildValue(const char *, va_list);
 
+#ifndef Py_LIMITED_API
+typedef struct _PyArg_Parser {
+    const char *format;
+    const char * const *keywords;
+    const char *fname;
+    const char *custom_msg;
+    int pos;            /* number of positional-only arguments */
+    int min;            /* minimal number of arguments */
+    int max;            /* maximal number of positional arguments */
+    PyObject *kwtuple;  /* tuple of keyword parameter names */
+    struct _PyArg_Parser *next;
+} _PyArg_Parser;
+#ifdef PY_SSIZE_T_CLEAN
+#define _PyArg_ParseTupleAndKeywordsFast  _PyArg_ParseTupleAndKeywordsFast_SizeT
+#define _PyArg_VaParseTupleAndKeywordsFast  _PyArg_VaParseTupleAndKeywordsFast_SizeT
+#endif
+PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *,
+                                                 struct _PyArg_Parser *, ...);
+PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
+                                                   struct _PyArg_Parser *, va_list);
+void _PyArg_Fini(void);
+#endif
+
 PyAPI_FUNC(int) PyModule_AddObject(PyObject *, const char *, PyObject *);
 PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);
 PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char *);
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #27574: Decreased an overhead of parsing keyword arguments in functions
+  implemented with using Argument Clinic.
+
 - Issue #22557: Now importing already imported modules is up to 2.5 times faster.
 
 - Issue #17596: Include <wincrypt.h> to help with Min GW building.
diff --git a/Modules/_io/clinic/_iomodule.c.h b/Modules/_io/clinic/_iomodule.c.h
--- a/Modules/_io/clinic/_iomodule.c.h
+++ b/Modules/_io/clinic/_iomodule.c.h
@@ -138,7 +138,8 @@
 _io_open(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"file", "mode", "buffering", "encoding", "errors", "newline", "closefd", "opener", NULL};
+    static const char * const _keywords[] = {"file", "mode", "buffering", "encoding", "errors", "newline", "closefd", "opener", NULL};
+    static _PyArg_Parser _parser = {"O|sizzziO:open", _keywords, 0};
     PyObject *file;
     const char *mode = "r";
     int buffering = -1;
@@ -148,7 +149,7 @@
     int closefd = 1;
     PyObject *opener = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|sizzziO:open", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &file, &mode, &buffering, &encoding, &errors, &newline, &closefd, &opener)) {
         goto exit;
     }
@@ -157,4 +158,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=ae2facf262cf464e input=a9049054013a1b77]*/
+/*[clinic end generated code: output=14769629391a3130 input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h
--- a/Modules/_io/clinic/bufferedio.c.h
+++ b/Modules/_io/clinic/bufferedio.c.h
@@ -324,11 +324,12 @@
 _io_BufferedReader___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"raw", "buffer_size", NULL};
+    static const char * const _keywords[] = {"raw", "buffer_size", NULL};
+    static _PyArg_Parser _parser = {"O|n:BufferedReader", _keywords, 0};
     PyObject *raw;
     Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|n:BufferedReader", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &raw, &buffer_size)) {
         goto exit;
     }
@@ -356,11 +357,12 @@
 _io_BufferedWriter___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"raw", "buffer_size", NULL};
+    static const char * const _keywords[] = {"raw", "buffer_size", NULL};
+    static _PyArg_Parser _parser = {"O|n:BufferedWriter", _keywords, 0};
     PyObject *raw;
     Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|n:BufferedWriter", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &raw, &buffer_size)) {
         goto exit;
     }
@@ -459,11 +461,12 @@
 _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"raw", "buffer_size", NULL};
+    static const char * const _keywords[] = {"raw", "buffer_size", NULL};
+    static _PyArg_Parser _parser = {"O|n:BufferedRandom", _keywords, 0};
     PyObject *raw;
     Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|n:BufferedRandom", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &raw, &buffer_size)) {
         goto exit;
     }
@@ -472,4 +475,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=4f6196c756b880c8 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=a956f394ecde4cf9 input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/bytesio.c.h b/Modules/_io/clinic/bytesio.c.h
--- a/Modules/_io/clinic/bytesio.c.h
+++ b/Modules/_io/clinic/bytesio.c.h
@@ -415,10 +415,11 @@
 _io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"initial_bytes", NULL};
+    static const char * const _keywords[] = {"initial_bytes", NULL};
+    static _PyArg_Parser _parser = {"|O:BytesIO", _keywords, 0};
     PyObject *initvalue = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:BytesIO", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &initvalue)) {
         goto exit;
     }
@@ -427,4 +428,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=3fdb62f3e3b0544d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=6382e8eb578eea64 input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/fileio.c.h b/Modules/_io/clinic/fileio.c.h
--- a/Modules/_io/clinic/fileio.c.h
+++ b/Modules/_io/clinic/fileio.c.h
@@ -49,13 +49,14 @@
 _io_FileIO___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"file", "mode", "closefd", "opener", NULL};
+    static const char * const _keywords[] = {"file", "mode", "closefd", "opener", NULL};
+    static _PyArg_Parser _parser = {"O|siO:FileIO", _keywords, 0};
     PyObject *nameobj;
     const char *mode = "r";
     int closefd = 1;
     PyObject *opener = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|siO:FileIO", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &nameobj, &mode, &closefd, &opener)) {
         goto exit;
     }
@@ -372,4 +373,4 @@
 #ifndef _IO_FILEIO_TRUNCATE_METHODDEF
     #define _IO_FILEIO_TRUNCATE_METHODDEF
 #endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */
-/*[clinic end generated code: output=bf4b4bd6b976346d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=51924bc0ee11d58e input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/stringio.c.h b/Modules/_io/clinic/stringio.c.h
--- a/Modules/_io/clinic/stringio.c.h
+++ b/Modules/_io/clinic/stringio.c.h
@@ -221,11 +221,12 @@
 _io_StringIO___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"initial_value", "newline", NULL};
+    static const char * const _keywords[] = {"initial_value", "newline", NULL};
+    static _PyArg_Parser _parser = {"|OO:StringIO", _keywords, 0};
     PyObject *value = NULL;
     PyObject *newline_obj = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:StringIO", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &value, &newline_obj)) {
         goto exit;
     }
@@ -288,4 +289,4 @@
 {
     return _io_StringIO_seekable_impl(self);
 }
-/*[clinic end generated code: output=0513219581cbe952 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5dd5c2a213e75405 input=a9049054013a1b77]*/
diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h
--- a/Modules/_io/clinic/textio.c.h
+++ b/Modules/_io/clinic/textio.c.h
@@ -24,12 +24,13 @@
 _io_IncrementalNewlineDecoder___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"decoder", "translate", "errors", NULL};
+    static const char * const _keywords[] = {"decoder", "translate", "errors", NULL};
+    static _PyArg_Parser _parser = {"Oi|O:IncrementalNewlineDecoder", _keywords, 0};
     PyObject *decoder;
     int translate;
     PyObject *errors = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|O:IncrementalNewlineDecoder", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &decoder, &translate, &errors)) {
         goto exit;
     }
@@ -55,11 +56,12 @@
 _io_IncrementalNewlineDecoder_decode(nldecoder_object *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"input", "final", NULL};
+    static const char * const _keywords[] = {"input", "final", NULL};
+    static _PyArg_Parser _parser = {"O|i:decode", _keywords, 0};
     PyObject *input;
     int final = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:decode", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &input, &final)) {
         goto exit;
     }
@@ -155,7 +157,8 @@
 _io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"buffer", "encoding", "errors", "newline", "line_buffering", "write_through", NULL};
+    static const char * const _keywords[] = {"buffer", "encoding", "errors", "newline", "line_buffering", "write_through", NULL};
+    static _PyArg_Parser _parser = {"O|zzzii:TextIOWrapper", _keywords, 0};
     PyObject *buffer;
     const char *encoding = NULL;
     const char *errors = NULL;
@@ -163,7 +166,7 @@
     int line_buffering = 0;
     int write_through = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|zzzii:TextIOWrapper", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &buffer, &encoding, &errors, &newline, &line_buffering, &write_through)) {
         goto exit;
     }
@@ -461,4 +464,4 @@
 {
     return _io_TextIOWrapper_close_impl(self);
 }
-/*[clinic end generated code: output=31a39bbbe07ae4e7 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=7ec624a9bf6393f5 input=a9049054013a1b77]*/
diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h
--- a/Modules/cjkcodecs/clinic/multibytecodec.c.h
+++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h
@@ -25,11 +25,12 @@
 _multibytecodec_MultibyteCodec_encode(MultibyteCodecObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"input", "errors", NULL};
+    static const char * const _keywords[] = {"input", "errors", NULL};
+    static _PyArg_Parser _parser = {"O|z:encode", _keywords, 0};
     PyObject *input;
     const char *errors = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|z:encode", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &input, &errors)) {
         goto exit;
     }
@@ -62,11 +63,12 @@
 _multibytecodec_MultibyteCodec_decode(MultibyteCodecObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"input", "errors", NULL};
+    static const char * const _keywords[] = {"input", "errors", NULL};
+    static _PyArg_Parser _parser = {"y*|z:decode", _keywords, 0};
     Py_buffer input = {NULL, NULL};
     const char *errors = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|z:decode", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &input, &errors)) {
         goto exit;
     }
@@ -98,11 +100,12 @@
 _multibytecodec_MultibyteIncrementalEncoder_encode(MultibyteIncrementalEncoderObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"input", "final", NULL};
+    static const char * const _keywords[] = {"input", "final", NULL};
+    static _PyArg_Parser _parser = {"O|i:encode", _keywords, 0};
     PyObject *input;
     int final = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:encode", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &input, &final)) {
         goto exit;
     }
@@ -146,11 +149,12 @@
 _multibytecodec_MultibyteIncrementalDecoder_decode(MultibyteIncrementalDecoderObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"input", "final", NULL};
+    static const char * const _keywords[] = {"input", "final", NULL};
+    static _PyArg_Parser _parser = {"y*|i:decode", _keywords, 0};
     Py_buffer input = {NULL, NULL};
     int final = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|i:decode", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &input, &final)) {
         goto exit;
     }
@@ -326,4 +330,4 @@
 
 #define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF    \
     {"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__},
-/*[clinic end generated code: output=f837bc56b2fa2a4e input=a9049054013a1b77]*/
+/*[clinic end generated code: output=8e86fa162c85230b input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_bz2module.c.h b/Modules/clinic/_bz2module.c.h
--- a/Modules/clinic/_bz2module.c.h
+++ b/Modules/clinic/_bz2module.c.h
@@ -125,11 +125,12 @@
 _bz2_BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"data", "max_length", NULL};
+    static const char * const _keywords[] = {"data", "max_length", NULL};
+    static _PyArg_Parser _parser = {"y*|n:decompress", _keywords, 0};
     Py_buffer data = {NULL, NULL};
     Py_ssize_t max_length = -1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|n:decompress", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &data, &max_length)) {
         goto exit;
     }
@@ -173,4 +174,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=71be22f38224fe84 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=40e5ef049f9e719b input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h
--- a/Modules/clinic/_codecsmodule.c.h
+++ b/Modules/clinic/_codecsmodule.c.h
@@ -65,12 +65,13 @@
 _codecs_encode(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"obj", "encoding", "errors", NULL};
+    static const char * const _keywords[] = {"obj", "encoding", "errors", NULL};
+    static _PyArg_Parser _parser = {"O|ss:encode", _keywords, 0};
     PyObject *obj;
     const char *encoding = NULL;
     const char *errors = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ss:encode", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &obj, &encoding, &errors)) {
         goto exit;
     }
@@ -103,12 +104,13 @@
 _codecs_decode(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"obj", "encoding", "errors", NULL};
+    static const char * const _keywords[] = {"obj", "encoding", "errors", NULL};
+    static _PyArg_Parser _parser = {"O|ss:decode", _keywords, 0};
     PyObject *obj;
     const char *encoding = NULL;
     const char *errors = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ss:decode", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &obj, &encoding, &errors)) {
         goto exit;
     }
@@ -1455,4 +1457,4 @@
 #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF
     #define _CODECS_CODE_PAGE_ENCODE_METHODDEF
 #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */
-/*[clinic end generated code: output=6e89ff4423c12a9b input=a9049054013a1b77]*/
+/*[clinic end generated code: output=0221e4eece62c905 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_datetimemodule.c.h b/Modules/clinic/_datetimemodule.c.h
--- a/Modules/clinic/_datetimemodule.c.h
+++ b/Modules/clinic/_datetimemodule.c.h
@@ -23,10 +23,11 @@
 datetime_datetime_now(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"tz", NULL};
+    static const char * const _keywords[] = {"tz", NULL};
+    static _PyArg_Parser _parser = {"|O:now", _keywords, 0};
     PyObject *tz = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:now", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &tz)) {
         goto exit;
     }
@@ -35,4 +36,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=a82e6bd057a5dab9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=61f85af5637df8b5 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h
--- a/Modules/clinic/_elementtree.c.h
+++ b/Modules/clinic/_elementtree.c.h
@@ -146,11 +146,12 @@
 _elementtree_Element_find(ElementObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "namespaces", NULL};
+    static const char * const _keywords[] = {"path", "namespaces", NULL};
+    static _PyArg_Parser _parser = {"O|O:find", _keywords, 0};
     PyObject *path;
     PyObject *namespaces = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:find", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &path, &namespaces)) {
         goto exit;
     }
@@ -177,12 +178,13 @@
 _elementtree_Element_findtext(ElementObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "default", "namespaces", NULL};
+    static const char * const _keywords[] = {"path", "default", "namespaces", NULL};
+    static _PyArg_Parser _parser = {"O|OO:findtext", _keywords, 0};
     PyObject *path;
     PyObject *default_value = Py_None;
     PyObject *namespaces = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO:findtext", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &path, &default_value, &namespaces)) {
         goto exit;
     }
@@ -208,11 +210,12 @@
 _elementtree_Element_findall(ElementObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "namespaces", NULL};
+    static const char * const _keywords[] = {"path", "namespaces", NULL};
+    static _PyArg_Parser _parser = {"O|O:findall", _keywords, 0};
     PyObject *path;
     PyObject *namespaces = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:findall", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &path, &namespaces)) {
         goto exit;
     }
@@ -238,11 +241,12 @@
 _elementtree_Element_iterfind(ElementObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "namespaces", NULL};
+    static const char * const _keywords[] = {"path", "namespaces", NULL};
+    static _PyArg_Parser _parser = {"O|O:iterfind", _keywords, 0};
     PyObject *path;
     PyObject *namespaces = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:iterfind", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &path, &namespaces)) {
         goto exit;
     }
@@ -268,11 +272,12 @@
 _elementtree_Element_get(ElementObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"key", "default", NULL};
+    static const char * const _keywords[] = {"key", "default", NULL};
+    static _PyArg_Parser _parser = {"O|O:get", _keywords, 0};
     PyObject *key;
     PyObject *default_value = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &key, &default_value)) {
         goto exit;
     }
@@ -314,10 +319,11 @@
 _elementtree_Element_iter(ElementObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"tag", NULL};
+    static const char * const _keywords[] = {"tag", NULL};
+    static _PyArg_Parser _parser = {"|O:iter", _keywords, 0};
     PyObject *tag = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:iter", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &tag)) {
         goto exit;
     }
@@ -501,10 +507,11 @@
 _elementtree_TreeBuilder___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"element_factory", NULL};
+    static const char * const _keywords[] = {"element_factory", NULL};
+    static _PyArg_Parser _parser = {"|O:TreeBuilder", _keywords, 0};
     PyObject *element_factory = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:TreeBuilder", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &element_factory)) {
         goto exit;
     }
@@ -585,12 +592,13 @@
 _elementtree_XMLParser___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"html", "target", "encoding", NULL};
+    static const char * const _keywords[] = {"html", "target", "encoding", NULL};
+    static _PyArg_Parser _parser = {"|OOz:XMLParser", _keywords, 0};
     PyObject *html = NULL;
     PyObject *target = NULL;
     const char *encoding = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOz:XMLParser", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &html, &target, &encoding)) {
         goto exit;
     }
@@ -694,4 +702,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=491eb5718c1ae64b input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4c5e94c28a009ce6 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_lzmamodule.c.h b/Modules/clinic/_lzmamodule.c.h
--- a/Modules/clinic/_lzmamodule.c.h
+++ b/Modules/clinic/_lzmamodule.c.h
@@ -91,11 +91,12 @@
 _lzma_LZMADecompressor_decompress(Decompressor *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"data", "max_length", NULL};
+    static const char * const _keywords[] = {"data", "max_length", NULL};
+    static _PyArg_Parser _parser = {"y*|n:decompress", _keywords, 0};
     Py_buffer data = {NULL, NULL};
     Py_ssize_t max_length = -1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|n:decompress", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &data, &max_length)) {
         goto exit;
     }
@@ -141,12 +142,13 @@
 _lzma_LZMADecompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"format", "memlimit", "filters", NULL};
+    static const char * const _keywords[] = {"format", "memlimit", "filters", NULL};
+    static _PyArg_Parser _parser = {"|iOO:LZMADecompressor", _keywords, 0};
     int format = FORMAT_AUTO;
     PyObject *memlimit = Py_None;
     PyObject *filters = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOO:LZMADecompressor", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &format, &memlimit, &filters)) {
         goto exit;
     }
@@ -254,4 +256,4 @@
 
     return return_value;
 }
-/*[clinic end generated code: output=25bf57a0845d147a input=a9049054013a1b77]*/
+/*[clinic end generated code: output=9434583fe111c771 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_pickle.c.h b/Modules/clinic/_pickle.c.h
--- a/Modules/clinic/_pickle.c.h
+++ b/Modules/clinic/_pickle.c.h
@@ -93,12 +93,13 @@
 _pickle_Pickler___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"file", "protocol", "fix_imports", NULL};
+    static const char * const _keywords[] = {"file", "protocol", "fix_imports", NULL};
+    static _PyArg_Parser _parser = {"O|Op:Pickler", _keywords, 0};
     PyObject *file;
     PyObject *protocol = NULL;
     int fix_imports = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Op:Pickler", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &file, &protocol, &fix_imports)) {
         goto exit;
     }
@@ -285,13 +286,14 @@
 _pickle_Unpickler___init__(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     int return_value = -1;
-    static char *_keywords[] = {"file", "fix_imports", "encoding", "errors", NULL};
+    static const char * const _keywords[] = {"file", "fix_imports", "encoding", "errors", NULL};
+    static _PyArg_Parser _parser = {"O|$pss:Unpickler", _keywords, 0};
     PyObject *file;
     int fix_imports = 1;
     const char *encoding = "ASCII";
     const char *errors = "strict";
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|$pss:Unpickler", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &file, &fix_imports, &encoding, &errors)) {
         goto exit;
     }
@@ -392,13 +394,14 @@
 _pickle_dump(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"obj", "file", "protocol", "fix_imports", NULL};
+    static const char * const _keywords[] = {"obj", "file", "protocol", "fix_imports", NULL};
+    static _PyArg_Parser _parser = {"OO|O$p:dump", _keywords, 0};
     PyObject *obj;
     PyObject *file;
     PyObject *protocol = NULL;
     int fix_imports = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O$p:dump", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &obj, &file, &protocol, &fix_imports)) {
         goto exit;
     }
@@ -437,12 +440,13 @@
 _pickle_dumps(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"obj", "protocol", "fix_imports", NULL};
+    static const char * const _keywords[] = {"obj", "protocol", "fix_imports", NULL};
+    static _PyArg_Parser _parser = {"O|O$p:dumps", _keywords, 0};
     PyObject *obj;
     PyObject *protocol = NULL;
     int fix_imports = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O$p:dumps", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &obj, &protocol, &fix_imports)) {
         goto exit;
     }
@@ -492,13 +496,14 @@
 _pickle_load(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"file", "fix_imports", "encoding", "errors", NULL};
+    static const char * const _keywords[] = {"file", "fix_imports", "encoding", "errors", NULL};
+    static _PyArg_Parser _parser = {"O|$pss:load", _keywords, 0};
     PyObject *file;
     int fix_imports = 1;
     const char *encoding = "ASCII";
     const char *errors = "strict";
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|$pss:load", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &file, &fix_imports, &encoding, &errors)) {
         goto exit;
     }
@@ -539,13 +544,14 @@
 _pickle_loads(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"data", "fix_imports", "encoding", "errors", NULL};
+    static const char * const _keywords[] = {"data", "fix_imports", "encoding", "errors", NULL};
+    static _PyArg_Parser _parser = {"O|$pss:loads", _keywords, 0};
     PyObject *data;
     int fix_imports = 1;
     const char *encoding = "ASCII";
     const char *errors = "strict";
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|$pss:loads", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &data, &fix_imports, &encoding, &errors)) {
         goto exit;
     }
@@ -554,4 +560,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=5c5f9149df292ce4 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=50f9127109673c98 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_sre.c.h b/Modules/clinic/_sre.c.h
--- a/Modules/clinic/_sre.c.h
+++ b/Modules/clinic/_sre.c.h
@@ -80,13 +80,14 @@
 _sre_SRE_Pattern_match(PatternObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", "pos", "endpos", "pattern", NULL};
+    static const char * const _keywords[] = {"string", "pos", "endpos", "pattern", NULL};
+    static _PyArg_Parser _parser = {"|Onn$O:match", _keywords, 0};
     PyObject *string = NULL;
     Py_ssize_t pos = 0;
     Py_ssize_t endpos = PY_SSIZE_T_MAX;
     PyObject *pattern = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Onn$O:match", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string, &pos, &endpos, &pattern)) {
         goto exit;
     }
@@ -115,13 +116,14 @@
 _sre_SRE_Pattern_fullmatch(PatternObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", "pos", "endpos", "pattern", NULL};
+    static const char * const _keywords[] = {"string", "pos", "endpos", "pattern", NULL};
+    static _PyArg_Parser _parser = {"|Onn$O:fullmatch", _keywords, 0};
     PyObject *string = NULL;
     Py_ssize_t pos = 0;
     Py_ssize_t endpos = PY_SSIZE_T_MAX;
     PyObject *pattern = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Onn$O:fullmatch", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string, &pos, &endpos, &pattern)) {
         goto exit;
     }
@@ -152,13 +154,14 @@
 _sre_SRE_Pattern_search(PatternObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", "pos", "endpos", "pattern", NULL};
+    static const char * const _keywords[] = {"string", "pos", "endpos", "pattern", NULL};
+    static _PyArg_Parser _parser = {"|Onn$O:search", _keywords, 0};
     PyObject *string = NULL;
     Py_ssize_t pos = 0;
     Py_ssize_t endpos = PY_SSIZE_T_MAX;
     PyObject *pattern = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Onn$O:search", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string, &pos, &endpos, &pattern)) {
         goto exit;
     }
@@ -187,13 +190,14 @@
 _sre_SRE_Pattern_findall(PatternObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", "pos", "endpos", "source", NULL};
+    static const char * const _keywords[] = {"string", "pos", "endpos", "source", NULL};
+    static _PyArg_Parser _parser = {"|Onn$O:findall", _keywords, 0};
     PyObject *string = NULL;
     Py_ssize_t pos = 0;
     Py_ssize_t endpos = PY_SSIZE_T_MAX;
     PyObject *source = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Onn$O:findall", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string, &pos, &endpos, &source)) {
         goto exit;
     }
@@ -222,12 +226,13 @@
 _sre_SRE_Pattern_finditer(PatternObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", "pos", "endpos", NULL};
+    static const char * const _keywords[] = {"string", "pos", "endpos", NULL};
+    static _PyArg_Parser _parser = {"O|nn:finditer", _keywords, 0};
     PyObject *string;
     Py_ssize_t pos = 0;
     Py_ssize_t endpos = PY_SSIZE_T_MAX;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|nn:finditer", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string, &pos, &endpos)) {
         goto exit;
     }
@@ -253,12 +258,13 @@
 _sre_SRE_Pattern_scanner(PatternObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", "pos", "endpos", NULL};
+    static const char * const _keywords[] = {"string", "pos", "endpos", NULL};
+    static _PyArg_Parser _parser = {"O|nn:scanner", _keywords, 0};
     PyObject *string;
     Py_ssize_t pos = 0;
     Py_ssize_t endpos = PY_SSIZE_T_MAX;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|nn:scanner", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string, &pos, &endpos)) {
         goto exit;
     }
@@ -285,12 +291,13 @@
 _sre_SRE_Pattern_split(PatternObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", "maxsplit", "source", NULL};
+    static const char * const _keywords[] = {"string", "maxsplit", "source", NULL};
+    static _PyArg_Parser _parser = {"|On$O:split", _keywords, 0};
     PyObject *string = NULL;
     Py_ssize_t maxsplit = 0;
     PyObject *source = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On$O:split", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string, &maxsplit, &source)) {
         goto exit;
     }
@@ -317,12 +324,13 @@
 _sre_SRE_Pattern_sub(PatternObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"repl", "string", "count", NULL};
+    static const char * const _keywords[] = {"repl", "string", "count", NULL};
+    static _PyArg_Parser _parser = {"OO|n:sub", _keywords, 0};
     PyObject *repl;
     PyObject *string;
     Py_ssize_t count = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|n:sub", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &repl, &string, &count)) {
         goto exit;
     }
@@ -349,12 +357,13 @@
 _sre_SRE_Pattern_subn(PatternObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"repl", "string", "count", NULL};
+    static const char * const _keywords[] = {"repl", "string", "count", NULL};
+    static _PyArg_Parser _parser = {"OO|n:subn", _keywords, 0};
     PyObject *repl;
     PyObject *string;
     Py_ssize_t count = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|n:subn", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &repl, &string, &count)) {
         goto exit;
     }
@@ -396,10 +405,11 @@
 _sre_SRE_Pattern___deepcopy__(PatternObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"memo", NULL};
+    static const char * const _keywords[] = {"memo", NULL};
+    static _PyArg_Parser _parser = {"O:__deepcopy__", _keywords, 0};
     PyObject *memo;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:__deepcopy__", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &memo)) {
         goto exit;
     }
@@ -427,7 +437,8 @@
 _sre_compile(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"pattern", "flags", "code", "groups", "groupindex", "indexgroup", NULL};
+    static const char * const _keywords[] = {"pattern", "flags", "code", "groups", "groupindex", "indexgroup", NULL};
+    static _PyArg_Parser _parser = {"OiO!nOO:compile", _keywords, 0};
     PyObject *pattern;
     int flags;
     PyObject *code;
@@ -435,7 +446,7 @@
     PyObject *groupindex;
     PyObject *indexgroup;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiO!nOO:compile", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &pattern, &flags, &PyList_Type, &code, &groups, &groupindex, &indexgroup)) {
         goto exit;
     }
@@ -461,10 +472,11 @@
 _sre_SRE_Match_expand(MatchObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"template", NULL};
+    static const char * const _keywords[] = {"template", NULL};
+    static _PyArg_Parser _parser = {"O:expand", _keywords, 0};
     PyObject *template;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:expand", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &template)) {
         goto exit;
     }
@@ -493,10 +505,11 @@
 _sre_SRE_Match_groups(MatchObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"default", NULL};
+    static const char * const _keywords[] = {"default", NULL};
+    static _PyArg_Parser _parser = {"|O:groups", _keywords, 0};
     PyObject *default_value = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:groups", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &default_value)) {
         goto exit;
     }
@@ -525,10 +538,11 @@
 _sre_SRE_Match_groupdict(MatchObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"default", NULL};
+    static const char * const _keywords[] = {"default", NULL};
+    static _PyArg_Parser _parser = {"|O:groupdict", _keywords, 0};
     PyObject *default_value = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:groupdict", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &default_value)) {
         goto exit;
     }
@@ -667,10 +681,11 @@
 _sre_SRE_Match___deepcopy__(MatchObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"memo", NULL};
+    static const char * const _keywords[] = {"memo", NULL};
+    static _PyArg_Parser _parser = {"O:__deepcopy__", _keywords, 0};
     PyObject *memo;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:__deepcopy__", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &memo)) {
         goto exit;
     }
@@ -713,4 +728,4 @@
 {
     return _sre_SRE_Scanner_search_impl(self);
 }
-/*[clinic end generated code: output=af9455cb54b2a907 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=2cbc2b1482738e54 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h
--- a/Modules/clinic/_ssl.c.h
+++ b/Modules/clinic/_ssl.c.h
@@ -458,12 +458,13 @@
 _ssl__SSLContext_load_cert_chain(PySSLContext *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"certfile", "keyfile", "password", NULL};
+    static const char * const _keywords[] = {"certfile", "keyfile", "password", NULL};
+    static _PyArg_Parser _parser = {"O|OO:load_cert_chain", _keywords, 0};
     PyObject *certfile;
     PyObject *keyfile = NULL;
     PyObject *password = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO:load_cert_chain", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &certfile, &keyfile, &password)) {
         goto exit;
     }
@@ -491,12 +492,13 @@
 _ssl__SSLContext_load_verify_locations(PySSLContext *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"cafile", "capath", "cadata", NULL};
+    static const char * const _keywords[] = {"cafile", "capath", "cadata", NULL};
+    static _PyArg_Parser _parser = {"|OOO:load_verify_locations", _keywords, 0};
     PyObject *cafile = NULL;
     PyObject *capath = NULL;
     PyObject *cadata = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:load_verify_locations", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &cafile, &capath, &cadata)) {
         goto exit;
     }
@@ -530,12 +532,13 @@
 _ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"sock", "server_side", "server_hostname", NULL};
+    static const char * const _keywords[] = {"sock", "server_side", "server_hostname", NULL};
+    static _PyArg_Parser _parser = {"O!i|O:_wrap_socket", _keywords, 0};
     PyObject *sock;
     int server_side;
     PyObject *hostname_obj = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!i|O:_wrap_socket", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         PySocketModule.Sock_Type, &sock, &server_side, &hostname_obj)) {
         goto exit;
     }
@@ -563,13 +566,14 @@
 _ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"incoming", "outgoing", "server_side", "server_hostname", NULL};
+    static const char * const _keywords[] = {"incoming", "outgoing", "server_side", "server_hostname", NULL};
+    static _PyArg_Parser _parser = {"O!O!i|O:_wrap_bio", _keywords, 0};
     PySSLMemoryBIO *incoming;
     PySSLMemoryBIO *outgoing;
     int server_side;
     PyObject *hostname_obj = Py_None;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O!i|O:_wrap_bio", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &PySSLMemoryBIO_Type, &incoming, &PySSLMemoryBIO_Type, &outgoing, &server_side, &hostname_obj)) {
         goto exit;
     }
@@ -684,10 +688,11 @@
 _ssl__SSLContext_get_ca_certs(PySSLContext *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"binary_form", NULL};
+    static const char * const _keywords[] = {"binary_form", NULL};
+    static _PyArg_Parser _parser = {"|p:get_ca_certs", _keywords, 0};
     int binary_form = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|p:get_ca_certs", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &binary_form)) {
         goto exit;
     }
@@ -994,11 +999,12 @@
 _ssl_txt2obj(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"txt", "name", NULL};
+    static const char * const _keywords[] = {"txt", "name", NULL};
+    static _PyArg_Parser _parser = {"s|p:txt2obj", _keywords, 0};
     const char *txt;
     int name = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|p:txt2obj", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &txt, &name)) {
         goto exit;
     }
@@ -1059,10 +1065,11 @@
 _ssl_enum_certificates(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"store_name", NULL};
+    static const char * const _keywords[] = {"store_name", NULL};
+    static _PyArg_Parser _parser = {"s:enum_certificates", _keywords, 0};
     const char *store_name;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:enum_certificates", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &store_name)) {
         goto exit;
     }
@@ -1097,10 +1104,11 @@
 _ssl_enum_crls(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"store_name", NULL};
+    static const char * const _keywords[] = {"store_name", NULL};
+    static _PyArg_Parser _parser = {"s:enum_crls", _keywords, 0};
     const char *store_name;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:enum_crls", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &store_name)) {
         goto exit;
     }
@@ -1135,4 +1143,4 @@
 #ifndef _SSL_ENUM_CRLS_METHODDEF
     #define _SSL_ENUM_CRLS_METHODDEF
 #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */
-/*[clinic end generated code: output=02444732c19722b3 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=6057f95343369849 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h
--- a/Modules/clinic/_winapi.c.h
+++ b/Modules/clinic/_winapi.c.h
@@ -105,11 +105,12 @@
 _winapi_ConnectNamedPipe(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"handle", "overlapped", NULL};
+    static const char * const _keywords[] = {"handle", "overlapped", NULL};
+    static _PyArg_Parser _parser = {"" F_HANDLE "|i:ConnectNamedPipe", _keywords, 0};
     HANDLE handle;
     int use_overlapped = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "" F_HANDLE "|i:ConnectNamedPipe", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &handle, &use_overlapped)) {
         goto exit;
     }
@@ -679,12 +680,13 @@
 _winapi_ReadFile(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"handle", "size", "overlapped", NULL};
+    static const char * const _keywords[] = {"handle", "size", "overlapped", NULL};
+    static _PyArg_Parser _parser = {"" F_HANDLE "i|i:ReadFile", _keywords, 0};
     HANDLE handle;
     int size;
     int use_overlapped = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "" F_HANDLE "i|i:ReadFile", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &handle, &size, &use_overlapped)) {
         goto exit;
     }
@@ -872,12 +874,13 @@
 _winapi_WriteFile(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"handle", "buffer", "overlapped", NULL};
+    static const char * const _keywords[] = {"handle", "buffer", "overlapped", NULL};
+    static _PyArg_Parser _parser = {"" F_HANDLE "O|i:WriteFile", _keywords, 0};
     HANDLE handle;
     PyObject *buffer;
     int use_overlapped = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "" F_HANDLE "O|i:WriteFile", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &handle, &buffer, &use_overlapped)) {
         goto exit;
     }
@@ -886,4 +889,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=8032f3371c14749e input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4bfccfb32ab726e8 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h
--- a/Modules/clinic/binascii.c.h
+++ b/Modules/clinic/binascii.c.h
@@ -112,11 +112,12 @@
 binascii_b2a_base64(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"data", "newline", NULL};
+    static const char * const _keywords[] = {"data", "newline", NULL};
+    static _PyArg_Parser _parser = {"y*|$i:b2a_base64", _keywords, 0};
     Py_buffer data = {NULL, NULL};
     int newline = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|$i:b2a_base64", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &data, &newline)) {
         goto exit;
     }
@@ -488,11 +489,12 @@
 binascii_a2b_qp(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"data", "header", NULL};
+    static const char * const _keywords[] = {"data", "header", NULL};
+    static _PyArg_Parser _parser = {"O&|i:a2b_qp", _keywords, 0};
     Py_buffer data = {NULL, NULL};
     int header = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i:a2b_qp", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         ascii_buffer_converter, &data, &header)) {
         goto exit;
     }
@@ -527,13 +529,14 @@
 binascii_b2a_qp(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"data", "quotetabs", "istext", "header", NULL};
+    static const char * const _keywords[] = {"data", "quotetabs", "istext", "header", NULL};
+    static _PyArg_Parser _parser = {"y*|iii:b2a_qp", _keywords, 0};
     Py_buffer data = {NULL, NULL};
     int quotetabs = 0;
     int istext = 1;
     int header = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|iii:b2a_qp", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &data, &quotetabs, &istext, &header)) {
         goto exit;
     }
@@ -547,4 +550,4 @@
 
     return return_value;
 }
-/*[clinic end generated code: output=d91d1058dc0590e1 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=12611b05d8bf4a9c input=a9049054013a1b77]*/
diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h
--- a/Modules/clinic/cmathmodule.c.h
+++ b/Modules/clinic/cmathmodule.c.h
@@ -861,14 +861,15 @@
 cmath_isclose(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL};
+    static const char * const _keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL};
+    static _PyArg_Parser _parser = {"DD|$dd:isclose", _keywords, 0};
     Py_complex a;
     Py_complex b;
     double rel_tol = 1e-09;
     double abs_tol = 0.0;
     int _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "DD|$dd:isclose", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &a, &b, &rel_tol, &abs_tol)) {
         goto exit;
     }
@@ -881,4 +882,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=0f49dd11b50175bc input=a9049054013a1b77]*/
+/*[clinic end generated code: output=aa2e77ca9fc26928 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/grpmodule.c.h b/Modules/clinic/grpmodule.c.h
--- a/Modules/clinic/grpmodule.c.h
+++ b/Modules/clinic/grpmodule.c.h
@@ -20,10 +20,11 @@
 grp_getgrgid(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"id", NULL};
+    static const char * const _keywords[] = {"id", NULL};
+    static _PyArg_Parser _parser = {"O:getgrgid", _keywords, 0};
     PyObject *id;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:getgrgid", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &id)) {
         goto exit;
     }
@@ -51,10 +52,11 @@
 grp_getgrnam(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"name", NULL};
+    static const char * const _keywords[] = {"name", NULL};
+    static _PyArg_Parser _parser = {"U:getgrnam", _keywords, 0};
     PyObject *name;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U:getgrnam", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &name)) {
         goto exit;
     }
@@ -84,4 +86,4 @@
 {
     return grp_getgrall_impl(module);
 }
-/*[clinic end generated code: output=8b7502970a29e7f1 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=c06081097b7fffe7 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/md5module.c.h b/Modules/clinic/md5module.c.h
--- a/Modules/clinic/md5module.c.h
+++ b/Modules/clinic/md5module.c.h
@@ -81,10 +81,11 @@
 _md5_md5(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {"|O:md5", _keywords, 0};
     PyObject *string = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:md5", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string)) {
         goto exit;
     }
@@ -93,4 +94,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=8f640a98761daffe input=a9049054013a1b77]*/
+/*[clinic end generated code: output=f86fc2f3f21831e2 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h
--- a/Modules/clinic/posixmodule.c.h
+++ b/Modules/clinic/posixmodule.c.h
@@ -36,12 +36,13 @@
 os_stat(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "dir_fd", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"path", "dir_fd", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"O&|$O&p:stat", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("stat", "path", 0, 1);
     int dir_fd = DEFAULT_DIR_FD;
     int follow_symlinks = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&p:stat", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, FSTATAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) {
         goto exit;
     }
@@ -73,11 +74,12 @@
 os_lstat(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "dir_fd", NULL};
+    static const char * const _keywords[] = {"path", "dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&|$O&:lstat", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0);
     int dir_fd = DEFAULT_DIR_FD;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:lstat", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, FSTATAT_DIR_FD_CONVERTER, &dir_fd)) {
         goto exit;
     }
@@ -133,7 +135,8 @@
 os_access(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"O&i|$O&pp:access", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("access", "path", 0, 1);
     int mode;
     int dir_fd = DEFAULT_DIR_FD;
@@ -141,7 +144,7 @@
     int follow_symlinks = 1;
     int _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&pp:access", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &mode, FACCESSAT_DIR_FD_CONVERTER, &dir_fd, &effective_ids, &follow_symlinks)) {
         goto exit;
     }
@@ -239,10 +242,11 @@
 os_chdir(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", NULL};
+    static const char * const _keywords[] = {"path", NULL};
+    static _PyArg_Parser _parser = {"O&:chdir", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("chdir", "path", 0, PATH_HAVE_FCHDIR);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:chdir", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path)) {
         goto exit;
     }
@@ -276,10 +280,11 @@
 os_fchdir(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"fd", NULL};
+    static const char * const _keywords[] = {"fd", NULL};
+    static _PyArg_Parser _parser = {"O&:fchdir", _keywords, 0};
     int fd;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:fchdir", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         fildes_converter, &fd)) {
         goto exit;
     }
@@ -328,13 +333,14 @@
 os_chmod(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "mode", "dir_fd", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"path", "mode", "dir_fd", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"O&i|$O&p:chmod", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("chmod", "path", 0, PATH_HAVE_FCHMOD);
     int mode;
     int dir_fd = DEFAULT_DIR_FD;
     int follow_symlinks = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&p:chmod", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &mode, FCHMODAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) {
         goto exit;
     }
@@ -367,11 +373,12 @@
 os_fchmod(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"fd", "mode", NULL};
+    static const char * const _keywords[] = {"fd", "mode", NULL};
+    static _PyArg_Parser _parser = {"ii:fchmod", _keywords, 0};
     int fd;
     int mode;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:fchmod", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &fd, &mode)) {
         goto exit;
     }
@@ -404,11 +411,12 @@
 os_lchmod(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "mode", NULL};
+    static const char * const _keywords[] = {"path", "mode", NULL};
+    static _PyArg_Parser _parser = {"O&i:lchmod", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0);
     int mode;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i:lchmod", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &mode)) {
         goto exit;
     }
@@ -448,12 +456,13 @@
 os_chflags(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "flags", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"path", "flags", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"O&k|p:chflags", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0);
     unsigned long flags;
     int follow_symlinks = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&k|p:chflags", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &flags, &follow_symlinks)) {
         goto exit;
     }
@@ -489,11 +498,12 @@
 os_lchflags(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "flags", NULL};
+    static const char * const _keywords[] = {"path", "flags", NULL};
+    static _PyArg_Parser _parser = {"O&k:lchflags", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0);
     unsigned long flags;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&k:lchflags", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &flags)) {
         goto exit;
     }
@@ -526,10 +536,11 @@
 os_chroot(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", NULL};
+    static const char * const _keywords[] = {"path", NULL};
+    static _PyArg_Parser _parser = {"O&:chroot", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:chroot", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path)) {
         goto exit;
     }
@@ -562,10 +573,11 @@
 os_fsync(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"fd", NULL};
+    static const char * const _keywords[] = {"fd", NULL};
+    static _PyArg_Parser _parser = {"O&:fsync", _keywords, 0};
     int fd;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:fsync", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         fildes_converter, &fd)) {
         goto exit;
     }
@@ -617,10 +629,11 @@
 os_fdatasync(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"fd", NULL};
+    static const char * const _keywords[] = {"fd", NULL};
+    static _PyArg_Parser _parser = {"O&:fdatasync", _keywords, 0};
     int fd;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:fdatasync", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         fildes_converter, &fd)) {
         goto exit;
     }
@@ -675,14 +688,15 @@
 os_chown(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "uid", "gid", "dir_fd", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"path", "uid", "gid", "dir_fd", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"O&O&O&|$O&p:chown", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("chown", "path", 0, PATH_HAVE_FCHOWN);
     uid_t uid;
     gid_t gid;
     int dir_fd = DEFAULT_DIR_FD;
     int follow_symlinks = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&O&|$O&p:chown", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, _Py_Uid_Converter, &uid, _Py_Gid_Converter, &gid, FCHOWNAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) {
         goto exit;
     }
@@ -717,12 +731,13 @@
 os_fchown(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"fd", "uid", "gid", NULL};
+    static const char * const _keywords[] = {"fd", "uid", "gid", NULL};
+    static _PyArg_Parser _parser = {"iO&O&:fchown", _keywords, 0};
     int fd;
     uid_t uid;
     gid_t gid;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO&O&:fchown", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &fd, _Py_Uid_Converter, &uid, _Py_Gid_Converter, &gid)) {
         goto exit;
     }
@@ -755,12 +770,13 @@
 os_lchown(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "uid", "gid", NULL};
+    static const char * const _keywords[] = {"path", "uid", "gid", NULL};
+    static _PyArg_Parser _parser = {"O&O&O&:lchown", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0);
     uid_t uid;
     gid_t gid;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&O&:lchown", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, _Py_Uid_Converter, &uid, _Py_Gid_Converter, &gid)) {
         goto exit;
     }
@@ -841,14 +857,15 @@
 os_link(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"O&O&|$O&O&p:link", _keywords, 0};
     path_t src = PATH_T_INITIALIZE("link", "src", 0, 0);
     path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0);
     int src_dir_fd = DEFAULT_DIR_FD;
     int dst_dir_fd = DEFAULT_DIR_FD;
     int follow_symlinks = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$O&O&p:link", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &src, path_converter, &dst, dir_fd_converter, &src_dir_fd, dir_fd_converter, &dst_dir_fd, &follow_symlinks)) {
         goto exit;
     }
@@ -892,10 +909,11 @@
 os_listdir(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", NULL};
+    static const char * const _keywords[] = {"path", NULL};
+    static _PyArg_Parser _parser = {"|O&:listdir", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("listdir", "path", 1, PATH_HAVE_FDOPENDIR);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:listdir", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path)) {
         goto exit;
     }
@@ -1023,10 +1041,11 @@
 os__getvolumepathname(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", NULL};
+    static const char * const _keywords[] = {"path", NULL};
+    static _PyArg_Parser _parser = {"U:_getvolumepathname", _keywords, 0};
     PyObject *path;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U:_getvolumepathname", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &path)) {
         goto exit;
     }
@@ -1061,12 +1080,13 @@
 os_mkdir(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "mode", "dir_fd", NULL};
+    static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&|i$O&:mkdir", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0);
     int mode = 511;
     int dir_fd = DEFAULT_DIR_FD;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkdir", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &mode, MKDIRAT_DIR_FD_CONVERTER, &dir_fd)) {
         goto exit;
     }
@@ -1128,11 +1148,12 @@
 os_getpriority(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"which", "who", NULL};
+    static const char * const _keywords[] = {"which", "who", NULL};
+    static _PyArg_Parser _parser = {"ii:getpriority", _keywords, 0};
     int which;
     int who;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:getpriority", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &which, &who)) {
         goto exit;
     }
@@ -1162,12 +1183,13 @@
 os_setpriority(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"which", "who", "priority", NULL};
+    static const char * const _keywords[] = {"which", "who", "priority", NULL};
+    static _PyArg_Parser _parser = {"iii:setpriority", _keywords, 0};
     int which;
     int who;
     int priority;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iii:setpriority", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &which, &who, &priority)) {
         goto exit;
     }
@@ -1202,13 +1224,14 @@
 os_rename(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL};
+    static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&O&|$O&O&:rename", _keywords, 0};
     path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0);
     path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0);
     int src_dir_fd = DEFAULT_DIR_FD;
     int dst_dir_fd = DEFAULT_DIR_FD;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$O&O&:rename", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &src, path_converter, &dst, dir_fd_converter, &src_dir_fd, dir_fd_converter, &dst_dir_fd)) {
         goto exit;
     }
@@ -1246,13 +1269,14 @@
 os_replace(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL};
+    static const char * const _keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&O&|$O&O&:replace", _keywords, 0};
     path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0);
     path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0);
     int src_dir_fd = DEFAULT_DIR_FD;
     int dst_dir_fd = DEFAULT_DIR_FD;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$O&O&:replace", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &src, path_converter, &dst, dir_fd_converter, &src_dir_fd, dir_fd_converter, &dst_dir_fd)) {
         goto exit;
     }
@@ -1288,11 +1312,12 @@
 os_rmdir(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "dir_fd", NULL};
+    static const char * const _keywords[] = {"path", "dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&|$O&:rmdir", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0);
     int dir_fd = DEFAULT_DIR_FD;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:rmdir", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, UNLINKAT_DIR_FD_CONVERTER, &dir_fd)) {
         goto exit;
     }
@@ -1323,11 +1348,12 @@
 os_system(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"command", NULL};
+    static const char * const _keywords[] = {"command", NULL};
+    static _PyArg_Parser _parser = {"u:system", _keywords, 0};
     Py_UNICODE *command;
     long _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "u:system", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &command)) {
         goto exit;
     }
@@ -1361,11 +1387,12 @@
 os_system(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"command", NULL};
+    static const char * const _keywords[] = {"command", NULL};
+    static _PyArg_Parser _parser = {"O&:system", _keywords, 0};
     PyObject *command = NULL;
     long _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:system", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         PyUnicode_FSConverter, &command)) {
         goto exit;
     }
@@ -1432,11 +1459,12 @@
 os_unlink(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "dir_fd", NULL};
+    static const char * const _keywords[] = {"path", "dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&|$O&:unlink", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0);
     int dir_fd = DEFAULT_DIR_FD;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:unlink", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, UNLINKAT_DIR_FD_CONVERTER, &dir_fd)) {
         goto exit;
     }
@@ -1470,11 +1498,12 @@
 os_remove(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "dir_fd", NULL};
+    static const char * const _keywords[] = {"path", "dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&|$O&:remove", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0);
     int dir_fd = DEFAULT_DIR_FD;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:remove", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, UNLINKAT_DIR_FD_CONVERTER, &dir_fd)) {
         goto exit;
     }
@@ -1552,14 +1581,15 @@
 os_utime(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "times", "ns", "dir_fd", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"path", "times", "ns", "dir_fd", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"O&|O$OO&p:utime", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("utime", "path", 0, PATH_UTIME_HAVE_FD);
     PyObject *times = NULL;
     PyObject *ns = NULL;
     int dir_fd = DEFAULT_DIR_FD;
     int follow_symlinks = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|O$OO&p:utime", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &times, &ns, FUTIMENSAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) {
         goto exit;
     }
@@ -1588,10 +1618,11 @@
 os__exit(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"status", NULL};
+    static const char * const _keywords[] = {"status", NULL};
+    static _PyArg_Parser _parser = {"i:_exit", _keywords, 0};
     int status;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:_exit", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &status)) {
         goto exit;
     }
@@ -1667,12 +1698,13 @@
 os_execve(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "argv", "env", NULL};
+    static const char * const _keywords[] = {"path", "argv", "env", NULL};
+    static _PyArg_Parser _parser = {"O&OO:execve", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("execve", "path", 0, PATH_HAVE_FEXECVE);
     PyObject *argv;
     PyObject *env;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&OO:execve", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &argv, &env)) {
         goto exit;
     }
@@ -1845,10 +1877,11 @@
 os_sched_get_priority_max(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"policy", NULL};
+    static const char * const _keywords[] = {"policy", NULL};
+    static _PyArg_Parser _parser = {"i:sched_get_priority_max", _keywords, 0};
     int policy;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:sched_get_priority_max", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &policy)) {
         goto exit;
     }
@@ -1878,10 +1911,11 @@
 os_sched_get_priority_min(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"policy", NULL};
+    static const char * const _keywords[] = {"policy", NULL};
+    static _PyArg_Parser _parser = {"i:sched_get_priority_min", _keywords, 0};
     int policy;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:sched_get_priority_min", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &policy)) {
         goto exit;
     }
@@ -1944,10 +1978,11 @@
 os_sched_param(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"sched_priority", NULL};
+    static const char * const _keywords[] = {"sched_priority", NULL};
+    static _PyArg_Parser _parser = {"O:sched_param", _keywords, 0};
     PyObject *sched_priority;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:sched_param", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &sched_priority)) {
         goto exit;
     }
@@ -2372,10 +2407,11 @@
 os_getpgid(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"pid", NULL};
+    static const char * const _keywords[] = {"pid", NULL};
+    static _PyArg_Parser _parser = {"" _Py_PARSE_PID ":getpgid", _keywords, 0};
     pid_t pid;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "" _Py_PARSE_PID ":getpgid", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &pid)) {
         goto exit;
     }
@@ -2821,10 +2857,11 @@
 os_wait3(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"options", NULL};
+    static const char * const _keywords[] = {"options", NULL};
+    static _PyArg_Parser _parser = {"i:wait3", _keywords, 0};
     int options;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:wait3", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &options)) {
         goto exit;
     }
@@ -2857,11 +2894,12 @@
 os_wait4(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"pid", "options", NULL};
+    static const char * const _keywords[] = {"pid", "options", NULL};
+    static _PyArg_Parser _parser = {"" _Py_PARSE_PID "i:wait4", _keywords, 0};
     pid_t pid;
     int options;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "" _Py_PARSE_PID "i:wait4", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &pid, &options)) {
         goto exit;
     }
@@ -3048,13 +3086,14 @@
 os_symlink(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL};
+    static const char * const _keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&O&|p$O&:symlink", _keywords, 0};
     path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0);
     path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0);
     int target_is_directory = 0;
     int dir_fd = DEFAULT_DIR_FD;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|p$O&:symlink", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &src, path_converter, &dst, &target_is_directory, SYMLINKAT_DIR_FD_CONVERTER, &dir_fd)) {
         goto exit;
     }
@@ -3268,14 +3307,15 @@
 os_open(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "flags", "mode", "dir_fd", NULL};
+    static const char * const _keywords[] = {"path", "flags", "mode", "dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&i|i$O&:open", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("open", "path", 0, 0);
     int flags;
     int mode = 511;
     int dir_fd = DEFAULT_DIR_FD;
     int _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|i$O&:open", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &flags, &mode, OPENAT_DIR_FD_CONVERTER, &dir_fd)) {
         goto exit;
     }
@@ -3308,10 +3348,11 @@
 os_close(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"fd", NULL};
+    static const char * const _keywords[] = {"fd", NULL};
+    static _PyArg_Parser _parser = {"i:close", _keywords, 0};
     int fd;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:close", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &fd)) {
         goto exit;
     }
@@ -3398,12 +3439,13 @@
 os_dup2(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"fd", "fd2", "inheritable", NULL};
+    static const char * const _keywords[] = {"fd", "fd2", "inheritable", NULL};
+    static _PyArg_Parser _parser = {"ii|p:dup2", _keywords, 0};
     int fd;
     int fd2;
     int inheritable = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|p:dup2", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &fd, &fd2, &inheritable)) {
         goto exit;
     }
@@ -3662,10 +3704,11 @@
 os_fstat(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"fd", NULL};
+    static const char * const _keywords[] = {"fd", NULL};
+    static _PyArg_Parser _parser = {"i:fstat", _keywords, 0};
     int fd;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:fstat", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &fd)) {
         goto exit;
     }
@@ -3884,12 +3927,13 @@
 os_mkfifo(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "mode", "dir_fd", NULL};
+    static const char * const _keywords[] = {"path", "mode", "dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&|i$O&:mkfifo", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0);
     int mode = 438;
     int dir_fd = DEFAULT_DIR_FD;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkfifo", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &mode, MKFIFOAT_DIR_FD_CONVERTER, &dir_fd)) {
         goto exit;
     }
@@ -3935,13 +3979,14 @@
 os_mknod(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "mode", "device", "dir_fd", NULL};
+    static const char * const _keywords[] = {"path", "mode", "device", "dir_fd", NULL};
+    static _PyArg_Parser _parser = {"O&|iO&$O&:mknod", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0);
     int mode = 384;
     dev_t device = 0;
     int dir_fd = DEFAULT_DIR_FD;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|iO&$O&:mknod", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &mode, _Py_Dev_Converter, &device, MKNODAT_DIR_FD_CONVERTER, &dir_fd)) {
         goto exit;
     }
@@ -4120,11 +4165,12 @@
 os_truncate(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "length", NULL};
+    static const char * const _keywords[] = {"path", "length", NULL};
+    static _PyArg_Parser _parser = {"O&O&:truncate", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE);
     Py_off_t length;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, Py_off_t_converter, &length)) {
         goto exit;
     }
@@ -4410,11 +4456,12 @@
 os_WIFCONTINUED(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"status", NULL};
+    static const char * const _keywords[] = {"status", NULL};
+    static _PyArg_Parser _parser = {"i:WIFCONTINUED", _keywords, 0};
     int status;
     int _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WIFCONTINUED", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &status)) {
         goto exit;
     }
@@ -4448,11 +4495,12 @@
 os_WIFSTOPPED(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"status", NULL};
+    static const char * const _keywords[] = {"status", NULL};
+    static _PyArg_Parser _parser = {"i:WIFSTOPPED", _keywords, 0};
     int status;
     int _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WIFSTOPPED", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &status)) {
         goto exit;
     }
@@ -4486,11 +4534,12 @@
 os_WIFSIGNALED(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"status", NULL};
+    static const char * const _keywords[] = {"status", NULL};
+    static _PyArg_Parser _parser = {"i:WIFSIGNALED", _keywords, 0};
     int status;
     int _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WIFSIGNALED", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &status)) {
         goto exit;
     }
@@ -4524,11 +4573,12 @@
 os_WIFEXITED(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"status", NULL};
+    static const char * const _keywords[] = {"status", NULL};
+    static _PyArg_Parser _parser = {"i:WIFEXITED", _keywords, 0};
     int status;
     int _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WIFEXITED", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &status)) {
         goto exit;
     }
@@ -4562,11 +4612,12 @@
 os_WEXITSTATUS(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"status", NULL};
+    static const char * const _keywords[] = {"status", NULL};
+    static _PyArg_Parser _parser = {"i:WEXITSTATUS", _keywords, 0};
     int status;
     int _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WEXITSTATUS", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &status)) {
         goto exit;
     }
@@ -4600,11 +4651,12 @@
 os_WTERMSIG(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"status", NULL};
+    static const char * const _keywords[] = {"status", NULL};
+    static _PyArg_Parser _parser = {"i:WTERMSIG", _keywords, 0};
     int status;
     int _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WTERMSIG", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &status)) {
         goto exit;
     }
@@ -4638,11 +4690,12 @@
 os_WSTOPSIG(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"status", NULL};
+    static const char * const _keywords[] = {"status", NULL};
+    static _PyArg_Parser _parser = {"i:WSTOPSIG", _keywords, 0};
     int status;
     int _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WSTOPSIG", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &status)) {
         goto exit;
     }
@@ -4713,10 +4766,11 @@
 os_statvfs(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", NULL};
+    static const char * const _keywords[] = {"path", NULL};
+    static _PyArg_Parser _parser = {"O&:statvfs", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:statvfs", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path)) {
         goto exit;
     }
@@ -4749,10 +4803,11 @@
 os__getdiskusage(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", NULL};
+    static const char * const _keywords[] = {"path", NULL};
+    static _PyArg_Parser _parser = {"u:_getdiskusage", _keywords, 0};
     Py_UNICODE *path;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "u:_getdiskusage", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &path)) {
         goto exit;
     }
@@ -4826,12 +4881,13 @@
 os_pathconf(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "name", NULL};
+    static const char * const _keywords[] = {"path", "name", NULL};
+    static _PyArg_Parser _parser = {"O&O&:pathconf", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, PATH_HAVE_FPATHCONF);
     int name;
     long _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:pathconf", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, conv_path_confname, &name)) {
         goto exit;
     }
@@ -4983,10 +5039,11 @@
 os_device_encoding(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"fd", NULL};
+    static const char * const _keywords[] = {"fd", NULL};
+    static _PyArg_Parser _parser = {"i:device_encoding", _keywords, 0};
     int fd;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:device_encoding", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &fd)) {
         goto exit;
     }
@@ -5132,12 +5189,13 @@
 os_getxattr(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "attribute", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"O&O&|$p:getxattr", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 1);
     path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0);
     int follow_symlinks = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:getxattr", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, path_converter, &attribute, &follow_symlinks)) {
         goto exit;
     }
@@ -5179,14 +5237,15 @@
 os_setxattr(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "attribute", "value", "flags", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"path", "attribute", "value", "flags", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"O&O&y*|i$p:setxattr", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 1);
     path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0);
     Py_buffer value = {NULL, NULL};
     int flags = 0;
     int follow_symlinks = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&y*|i$p:setxattr", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, path_converter, &attribute, &value, &flags, &follow_symlinks)) {
         goto exit;
     }
@@ -5231,12 +5290,13 @@
 os_removexattr(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "attribute", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"path", "attribute", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"O&O&|$p:removexattr", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 1);
     path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0);
     int follow_symlinks = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:removexattr", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, path_converter, &attribute, &follow_symlinks)) {
         goto exit;
     }
@@ -5277,11 +5337,12 @@
 os_listxattr(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", "follow_symlinks", NULL};
+    static const char * const _keywords[] = {"path", "follow_symlinks", NULL};
+    static _PyArg_Parser _parser = {"|O&$p:listxattr", _keywords, 0};
     path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 1);
     int follow_symlinks = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&$p:listxattr", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         path_converter, &path, &follow_symlinks)) {
         goto exit;
     }
@@ -5496,10 +5557,11 @@
 os_fspath(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"path", NULL};
+    static const char * const _keywords[] = {"path", NULL};
+    static _PyArg_Parser _parser = {"O:fspath", _keywords, 0};
     PyObject *path;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:fspath", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &path)) {
         goto exit;
     }
@@ -5980,4 +6042,4 @@
 #ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF
     #define OS_SET_HANDLE_INHERITABLE_METHODDEF
 #endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */
-/*[clinic end generated code: output=e91e62d8e8f1b6ac input=a9049054013a1b77]*/
+/*[clinic end generated code: output=97180b6734421a7d input=a9049054013a1b77]*/
diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h
--- a/Modules/clinic/pyexpat.c.h
+++ b/Modules/clinic/pyexpat.c.h
@@ -243,12 +243,13 @@
 pyexpat_ParserCreate(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"encoding", "namespace_separator", "intern", NULL};
+    static const char * const _keywords[] = {"encoding", "namespace_separator", "intern", NULL};
+    static _PyArg_Parser _parser = {"|zzO:ParserCreate", _keywords, 0};
     const char *encoding = NULL;
     const char *namespace_separator = NULL;
     PyObject *intern = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zzO:ParserCreate", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &encoding, &namespace_separator, &intern)) {
         goto exit;
     }
@@ -288,4 +289,4 @@
 #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF
     #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF
 #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */
-/*[clinic end generated code: output=9de21f46734b1311 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=93cfe662f2bc48e5 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha1module.c.h b/Modules/clinic/sha1module.c.h
--- a/Modules/clinic/sha1module.c.h
+++ b/Modules/clinic/sha1module.c.h
@@ -81,10 +81,11 @@
 _sha1_sha1(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {"|O:sha1", _keywords, 0};
     PyObject *string = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:sha1", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string)) {
         goto exit;
     }
@@ -93,4 +94,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=475c4cc749ab31b1 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=549a5d08c248337d input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha256module.c.h b/Modules/clinic/sha256module.c.h
--- a/Modules/clinic/sha256module.c.h
+++ b/Modules/clinic/sha256module.c.h
@@ -81,10 +81,11 @@
 _sha256_sha256(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {"|O:sha256", _keywords, 0};
     PyObject *string = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:sha256", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string)) {
         goto exit;
     }
@@ -110,10 +111,11 @@
 _sha256_sha224(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {"|O:sha224", _keywords, 0};
     PyObject *string = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:sha224", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string)) {
         goto exit;
     }
@@ -122,4 +124,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=a41a21c08fcddd70 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=a1296ba6d0780051 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha512module.c.h b/Modules/clinic/sha512module.c.h
--- a/Modules/clinic/sha512module.c.h
+++ b/Modules/clinic/sha512module.c.h
@@ -99,10 +99,11 @@
 _sha512_sha512(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {"|O:sha512", _keywords, 0};
     PyObject *string = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:sha512", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string)) {
         goto exit;
     }
@@ -132,10 +133,11 @@
 _sha512_sha384(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"string", NULL};
+    static const char * const _keywords[] = {"string", NULL};
+    static _PyArg_Parser _parser = {"|O:sha384", _keywords, 0};
     PyObject *string = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:sha384", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &string)) {
         goto exit;
     }
@@ -170,4 +172,4 @@
 #ifndef _SHA512_SHA384_METHODDEF
     #define _SHA512_SHA384_METHODDEF
 #endif /* !defined(_SHA512_SHA384_METHODDEF) */
-/*[clinic end generated code: output=e314c0f773abd5d7 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=cf0da76cb603d1bf input=a9049054013a1b77]*/
diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h
--- a/Modules/clinic/zlibmodule.c.h
+++ b/Modules/clinic/zlibmodule.c.h
@@ -23,11 +23,12 @@
 zlib_compress(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"", "level", NULL};
+    static const char * const _keywords[] = {"", "level", NULL};
+    static _PyArg_Parser _parser = {"y*|i:compress", _keywords, 0};
     Py_buffer data = {NULL, NULL};
     int level = Z_DEFAULT_COMPRESSION;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|i:compress", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &data, &level)) {
         goto exit;
     }
@@ -126,7 +127,8 @@
 zlib_compressobj(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"level", "method", "wbits", "memLevel", "strategy", "zdict", NULL};
+    static const char * const _keywords[] = {"level", "method", "wbits", "memLevel", "strategy", "zdict", NULL};
+    static _PyArg_Parser _parser = {"|iiiiiy*:compressobj", _keywords, 0};
     int level = Z_DEFAULT_COMPRESSION;
     int method = DEFLATED;
     int wbits = MAX_WBITS;
@@ -134,7 +136,7 @@
     int strategy = Z_DEFAULT_STRATEGY;
     Py_buffer zdict = {NULL, NULL};
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iiiiiy*:compressobj", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &level, &method, &wbits, &memLevel, &strategy, &zdict)) {
         goto exit;
     }
@@ -171,11 +173,12 @@
 zlib_decompressobj(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"wbits", "zdict", NULL};
+    static const char * const _keywords[] = {"wbits", "zdict", NULL};
+    static _PyArg_Parser _parser = {"|iO:decompressobj", _keywords, 0};
     int wbits = MAX_WBITS;
     PyObject *zdict = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:decompressobj", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &wbits, &zdict)) {
         goto exit;
     }
@@ -460,4 +463,4 @@
 #ifndef ZLIB_COMPRESS_COPY_METHODDEF
     #define ZLIB_COMPRESS_COPY_METHODDEF
 #endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */
-/*[clinic end generated code: output=9046866b1ac5de7e input=a9049054013a1b77]*/
+/*[clinic end generated code: output=1fed251c15a9bffa input=a9049054013a1b77]*/
diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h
--- a/Objects/clinic/bytearrayobject.c.h
+++ b/Objects/clinic/bytearrayobject.c.h
@@ -200,11 +200,12 @@
 bytearray_split(PyByteArrayObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"sep", "maxsplit", NULL};
+    static const char * const _keywords[] = {"sep", "maxsplit", NULL};
+    static _PyArg_Parser _parser = {"|On:split", _keywords, 0};
     PyObject *sep = Py_None;
     Py_ssize_t maxsplit = -1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:split", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &sep, &maxsplit)) {
         goto exit;
     }
@@ -273,11 +274,12 @@
 bytearray_rsplit(PyByteArrayObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"sep", "maxsplit", NULL};
+    static const char * const _keywords[] = {"sep", "maxsplit", NULL};
+    static _PyArg_Parser _parser = {"|On:rsplit", _keywords, 0};
     PyObject *sep = Py_None;
     Py_ssize_t maxsplit = -1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:rsplit", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &sep, &maxsplit)) {
         goto exit;
     }
@@ -564,11 +566,12 @@
 bytearray_decode(PyByteArrayObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"encoding", "errors", NULL};
+    static const char * const _keywords[] = {"encoding", "errors", NULL};
+    static _PyArg_Parser _parser = {"|ss:decode", _keywords, 0};
     const char *encoding = NULL;
     const char *errors = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &encoding, &errors)) {
         goto exit;
     }
@@ -610,10 +613,11 @@
 bytearray_splitlines(PyByteArrayObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"keepends", NULL};
+    static const char * const _keywords[] = {"keepends", NULL};
+    static _PyArg_Parser _parser = {"|i:splitlines", _keywords, 0};
     int keepends = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:splitlines", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &keepends)) {
         goto exit;
     }
@@ -716,4 +720,4 @@
 {
     return bytearray_sizeof_impl(self);
 }
-/*[clinic end generated code: output=a32f183ebef159cc input=a9049054013a1b77]*/
+/*[clinic end generated code: output=0af30f8c0b1ecd76 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h
--- a/Objects/clinic/bytesobject.c.h
+++ b/Objects/clinic/bytesobject.c.h
@@ -26,11 +26,12 @@
 bytes_split(PyBytesObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"sep", "maxsplit", NULL};
+    static const char * const _keywords[] = {"sep", "maxsplit", NULL};
+    static _PyArg_Parser _parser = {"|On:split", _keywords, 0};
     PyObject *sep = Py_None;
     Py_ssize_t maxsplit = -1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:split", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &sep, &maxsplit)) {
         goto exit;
     }
@@ -144,11 +145,12 @@
 bytes_rsplit(PyBytesObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"sep", "maxsplit", NULL};
+    static const char * const _keywords[] = {"sep", "maxsplit", NULL};
+    static _PyArg_Parser _parser = {"|On:rsplit", _keywords, 0};
     PyObject *sep = Py_None;
     Py_ssize_t maxsplit = -1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:rsplit", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &sep, &maxsplit)) {
         goto exit;
     }
@@ -429,11 +431,12 @@
 bytes_decode(PyBytesObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"encoding", "errors", NULL};
+    static const char * const _keywords[] = {"encoding", "errors", NULL};
+    static _PyArg_Parser _parser = {"|ss:decode", _keywords, 0};
     const char *encoding = NULL;
     const char *errors = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &encoding, &errors)) {
         goto exit;
     }
@@ -462,10 +465,11 @@
 bytes_splitlines(PyBytesObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"keepends", NULL};
+    static const char * const _keywords[] = {"keepends", NULL};
+    static _PyArg_Parser _parser = {"|i:splitlines", _keywords, 0};
     int keepends = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:splitlines", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &keepends)) {
         goto exit;
     }
@@ -504,4 +508,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=6fe884a74e7d49cf input=a9049054013a1b77]*/
+/*[clinic end generated code: output=637c2c14610d3c8d input=a9049054013a1b77]*/
diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h
--- a/PC/clinic/winreg.c.h
+++ b/PC/clinic/winreg.c.h
@@ -87,12 +87,13 @@
 winreg_HKEYType___exit__(PyHKEYObject *self, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"exc_type", "exc_value", "traceback", NULL};
+    static const char * const _keywords[] = {"exc_type", "exc_value", "traceback", NULL};
+    static _PyArg_Parser _parser = {"OOO:__exit__", _keywords, 0};
     PyObject *exc_type;
     PyObject *exc_value;
     PyObject *traceback;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOO:__exit__", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &exc_type, &exc_value, &traceback)) {
         goto exit;
     }
@@ -244,14 +245,15 @@
 winreg_CreateKeyEx(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"key", "sub_key", "reserved", "access", NULL};
+    static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL};
+    static _PyArg_Parser _parser = {"O&Z|ii:CreateKeyEx", _keywords, 0};
     HKEY key;
     Py_UNICODE *sub_key;
     int reserved = 0;
     REGSAM access = KEY_WRITE;
     HKEY _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&Z|ii:CreateKeyEx", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) {
         goto exit;
     }
@@ -342,13 +344,14 @@
 winreg_DeleteKeyEx(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"key", "sub_key", "access", "reserved", NULL};
+    static const char * const _keywords[] = {"key", "sub_key", "access", "reserved", NULL};
+    static _PyArg_Parser _parser = {"O&u|ii:DeleteKeyEx", _keywords, 0};
     HKEY key;
     Py_UNICODE *sub_key;
     REGSAM access = KEY_WOW64_64KEY;
     int reserved = 0;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&u|ii:DeleteKeyEx", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         clinic_HKEY_converter, &key, &sub_key, &access, &reserved)) {
         goto exit;
     }
@@ -627,14 +630,15 @@
 winreg_OpenKey(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"key", "sub_key", "reserved", "access", NULL};
+    static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL};
+    static _PyArg_Parser _parser = {"O&Z|ii:OpenKey", _keywords, 0};
     HKEY key;
     Py_UNICODE *sub_key;
     int reserved = 0;
     REGSAM access = KEY_READ;
     HKEY _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&Z|ii:OpenKey", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) {
         goto exit;
     }
@@ -678,14 +682,15 @@
 winreg_OpenKeyEx(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"key", "sub_key", "reserved", "access", NULL};
+    static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL};
+    static _PyArg_Parser _parser = {"O&Z|ii:OpenKeyEx", _keywords, 0};
     HKEY key;
     Py_UNICODE *sub_key;
     int reserved = 0;
     REGSAM access = KEY_READ;
     HKEY _return_value;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&Z|ii:OpenKeyEx", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) {
         goto exit;
     }
@@ -1086,4 +1091,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=c35ce71f825424d1 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5b53d19cbe3f37cd input=a9049054013a1b77]*/
diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h
--- a/Python/clinic/bltinmodule.c.h
+++ b/Python/clinic/bltinmodule.c.h
@@ -159,7 +159,8 @@
 builtin_compile(PyObject *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
-    static char *_keywords[] = {"source", "filename", "mode", "flags", "dont_inherit", "optimize", NULL};
+    static const char * const _keywords[] = {"source", "filename", "mode", "flags", "dont_inherit", "optimize", NULL};
+    static _PyArg_Parser _parser = {"OO&s|iii:compile", _keywords, 0};
     PyObject *source;
     PyObject *filename;
     const char *mode;
@@ -167,7 +168,7 @@
     int dont_inherit = 0;
     int optimize = -1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO&s|iii:compile", _keywords,
+    if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &source, PyUnicode_FSDecoder, &filename, &mode, &flags, &dont_inherit, &optimize)) {
         goto exit;
     }
@@ -673,4 +674,4 @@
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=6ab37e6c6d2e7b19 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=790cb3d26531dfda input=a9049054013a1b77]*/
diff --git a/Python/getargs.c b/Python/getargs.c
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -18,6 +18,11 @@
 int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,
                                 const char *, char **, va_list);
 
+int _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *,
+                                            struct _PyArg_Parser *, ...);
+int _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
+                                            struct _PyArg_Parser *, va_list);
+
 #ifdef HAVE_DECLSPEC_DLL
 /* Export functions */
 PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);
@@ -28,6 +33,11 @@
 PyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, const char *, va_list);
 PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *,
                                               const char *, char **, va_list);
+
+PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *, PyObject *,
+                                            struct _PyArg_Parser *, ...);
+PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *, PyObject *,
+                                            struct _PyArg_Parser *, va_list);
 #endif
 
 #define FLAG_COMPAT 1
@@ -67,6 +77,8 @@
 
 static int vgetargskeywords(PyObject *, PyObject *,
                             const char *, char **, va_list *, int);
+static int vgetargskeywordsfast(PyObject *, PyObject *,
+                            struct _PyArg_Parser *, va_list *, int);
 static const char *skipitem(const char **, va_list *, int);
 
 int
@@ -1418,6 +1430,91 @@
 }
 
 int
+_PyArg_ParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,
+                            struct _PyArg_Parser *parser, ...)
+{
+    int retval;
+    va_list va;
+
+    if ((args == NULL || !PyTuple_Check(args)) ||
+        (keywords != NULL && !PyDict_Check(keywords)) ||
+        parser == NULL)
+    {
+        PyErr_BadInternalCall();
+        return 0;
+    }
+
+    va_start(va, parser);
+    retval = vgetargskeywordsfast(args, keywords, parser, &va, 0);
+    va_end(va);
+    return retval;
+}
+
+int
+_PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,
+                            struct _PyArg_Parser *parser, ...)
+{
+    int retval;
+    va_list va;
+
+    if ((args == NULL || !PyTuple_Check(args)) ||
+        (keywords != NULL && !PyDict_Check(keywords)) ||
+        parser == NULL)
+    {
+        PyErr_BadInternalCall();
+        return 0;
+    }
+
+    va_start(va, parser);
+    retval = vgetargskeywordsfast(args, keywords, parser, &va, FLAG_SIZE_T);
+    va_end(va);
+    return retval;
+}
+
+
+int
+_PyArg_VaParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,
+                            struct _PyArg_Parser *parser, va_list va)
+{
+    int retval;
+    va_list lva;
+
+    if ((args == NULL || !PyTuple_Check(args)) ||
+        (keywords != NULL && !PyDict_Check(keywords)) ||
+        parser == NULL)
+    {
+        PyErr_BadInternalCall();
+        return 0;
+    }
+
+    Py_VA_COPY(lva, va);
+
+    retval = vgetargskeywordsfast(args, keywords, parser, &lva, 0);
+    return retval;
+}
+
+int
+_PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,
+                            struct _PyArg_Parser *parser, va_list va)
+{
+    int retval;
+    va_list lva;
+
+    if ((args == NULL || !PyTuple_Check(args)) ||
+        (keywords != NULL && !PyDict_Check(keywords)) ||
+        parser == NULL)
+    {
+        PyErr_BadInternalCall();
+        return 0;
+    }
+
+    Py_VA_COPY(lva, va);
+
+    retval = vgetargskeywordsfast(args, keywords, parser, &lva, FLAG_SIZE_T);
+    return retval;
+}
+
+int
 PyArg_ValidateKeywordArguments(PyObject *kwargs)
 {
     if (!PyDict_Check(kwargs)) {
@@ -1541,6 +1638,9 @@
                 return cleanreturn(0, &freelist);
             }
             if (skip) {
+                /* Now we know the minimal and the maximal numbers of
+                 * positional arguments and can raise an exception with
+                 * informative message (see below). */
                 break;
             }
             if (max < nargs) {
@@ -1595,6 +1695,10 @@
                     assert (min == INT_MAX);
                     assert (max == INT_MAX);
                     skip = 1;
+                    /* At that moment we still don't know the minimal and
+                     * the maximal numbers of positional arguments.  Raising
+                     * an exception is deferred until we encounter | and $
+                     * or the end of the format. */
                 }
                 else {
                     PyErr_Format(PyExc_TypeError, "Required argument "
@@ -1669,6 +1773,300 @@
 }
 
 
+/* List of static parsers. */
+static struct _PyArg_Parser *static_arg_parsers = NULL;
+
+static int
+parser_init(struct _PyArg_Parser *parser)
+{
+    const char * const *keywords;
+    const char *format, *msg;
+    int i, len, min, max, nkw;
+    PyObject *kwtuple;
+
+    assert(parser->format != NULL);
+    assert(parser->keywords != NULL);
+    if (parser->kwtuple != NULL) {
+        return 1;
+    }
+
+    /* grab the function name or custom error msg first (mutually exclusive) */
+    parser->fname = strchr(parser->format, ':');
+    if (parser->fname) {
+        parser->fname++;
+        parser->custom_msg = NULL;
+    }
+    else {
+        parser->custom_msg = strchr(parser->format,';');
+        if (parser->custom_msg)
+            parser->custom_msg++;
+    }
+
+    keywords = parser->keywords;
+    /* scan keywords and count the number of positional-only parameters */
+    for (i = 0; keywords[i] && !*keywords[i]; i++) {
+    }
+    parser->pos = i;
+    /* scan keywords and get greatest possible nbr of args */
+    for (; keywords[i]; i++) {
+        if (!*keywords[i]) {
+            PyErr_SetString(PyExc_SystemError,
+                            "Empty keyword parameter name");
+            return 0;
+        }
+    }
+    len = i;
+
+    min = max = INT_MAX;
+    format = parser->format;
+    for (i = 0; i < len; i++) {
+        if (*format == '|') {
+            if (min != INT_MAX) {
+                PyErr_SetString(PyExc_SystemError,
+                                "Invalid format string (| specified twice)");
+                return 0;
+            }
+            if (max != INT_MAX) {
+                PyErr_SetString(PyExc_SystemError,
+                                "Invalid format string ($ before |)");
+                return 0;
+            }
+            min = i;
+            format++;
+        }
+        if (*format == '$') {
+            if (max != INT_MAX) {
+                PyErr_SetString(PyExc_SystemError,
+                                "Invalid format string ($ specified twice)");
+                return 0;
+            }
+            if (i < parser->pos) {
+                PyErr_SetString(PyExc_SystemError,
+                                "Empty parameter name after $");
+                return 0;
+            }
+            max = i;
+            format++;
+        }
+        if (IS_END_OF_FORMAT(*format)) {
+            PyErr_Format(PyExc_SystemError,
+                         "More keyword list entries (%d) than "
+                         "format specifiers (%d)", len, i);
+            return 0;
+        }
+
+        msg = skipitem(&format, NULL, 0);
+        if (msg) {
+            PyErr_Format(PyExc_SystemError, "%s: '%s'", msg,
+                         format);
+            return 0;
+        }
+    }
+    parser->min = Py_MIN(min, len);
+    parser->max = Py_MIN(max, len);
+
+    if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {
+        PyErr_Format(PyExc_SystemError,
+            "more argument specifiers than keyword list entries "
+            "(remaining format:'%s')", format);
+        return 0;
+    }
+
+    nkw = len - parser->pos;
+    kwtuple = PyTuple_New(nkw);
+    if (kwtuple == NULL) {
+        return 0;
+    }
+    keywords = parser->keywords + parser->pos;
+    for (i = 0; i < nkw; i++) {
+        PyObject *str = PyUnicode_FromString(keywords[i]);
+        if (str == NULL) {
+            Py_DECREF(kwtuple);
+            return 0;
+        }
+        PyUnicode_InternInPlace(&str);
+        PyTuple_SET_ITEM(kwtuple, i, str);
+    }
+    parser->kwtuple = kwtuple;
+
+    assert(parser->next == NULL);
+    parser->next = static_arg_parsers;
+    static_arg_parsers = parser;
+    return 1;
+}
+
+static void
+parser_clear(struct _PyArg_Parser *parser)
+{
+    Py_CLEAR(parser->kwtuple);
+}
+
+static int
+vgetargskeywordsfast(PyObject *args, PyObject *keywords,
+                     struct _PyArg_Parser *parser,
+                     va_list *p_va, int flags)
+{
+    PyObject *kwtuple;
+    char msgbuf[512];
+    int levels[32];
+    const char *format;
+    const char *msg;
+    PyObject *keyword;
+    int i, pos, len;
+    Py_ssize_t nargs, nkeywords;
+    PyObject *current_arg;
+    freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
+    freelist_t freelist;
+
+    freelist.entries = static_entries;
+    freelist.first_available = 0;
+    freelist.entries_malloced = 0;
+
+    assert(args != NULL && PyTuple_Check(args));
+    assert(keywords == NULL || PyDict_Check(keywords));
+    assert(parser != NULL);
+    assert(p_va != NULL);
+
+    if (!parser_init(parser)) {
+        return 0;
+    }
+
+    kwtuple = parser->kwtuple;
+    pos = parser->pos;
+    len = pos + PyTuple_GET_SIZE(kwtuple);
+
+    if (len > STATIC_FREELIST_ENTRIES) {
+        freelist.entries = PyMem_NEW(freelistentry_t, len);
+        if (freelist.entries == NULL) {
+            PyErr_NoMemory();
+            return 0;
+        }
+        freelist.entries_malloced = 1;
+    }
+
+    nargs = PyTuple_GET_SIZE(args);
+    nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords);
+    if (nargs + nkeywords > len) {
+        PyErr_Format(PyExc_TypeError,
+                     "%s%s takes at most %d argument%s (%zd given)",
+                     (parser->fname == NULL) ? "function" : parser->fname,
+                     (parser->fname == NULL) ? "" : "()",
+                     len,
+                     (len == 1) ? "" : "s",
+                     nargs + nkeywords);
+        return cleanreturn(0, &freelist);
+    }
+    if (parser->max < nargs) {
+        PyErr_Format(PyExc_TypeError,
+                     "Function takes %s %d positional arguments (%d given)",
+                     (parser->min != INT_MAX) ? "at most" : "exactly",
+                     parser->max, nargs);
+        return cleanreturn(0, &freelist);
+    }
+
+    format = parser->format;
+    /* convert tuple args and keyword args in same loop, using kwtuple to drive process */
+    for (i = 0; i < len; i++) {
+        keyword = (i >= pos) ? PyTuple_GET_ITEM(kwtuple, i - pos) : NULL;
+        if (*format == '|') {
+            format++;
+        }
+        if (*format == '$') {
+            format++;
+        }
+        assert(!IS_END_OF_FORMAT(*format));
+
+        current_arg = NULL;
+        if (nkeywords && i >= pos) {
+            current_arg = PyDict_GetItem(keywords, keyword);
+            if (!current_arg && PyErr_Occurred()) {
+                return cleanreturn(0, &freelist);
+            }
+        }
+        if (current_arg) {
+            --nkeywords;
+            if (i < nargs) {
+                /* arg present in tuple and in dict */
+                PyErr_Format(PyExc_TypeError,
+                             "Argument given by name ('%U') "
+                             "and position (%d)",
+                             keyword, i+1);
+                return cleanreturn(0, &freelist);
+            }
+        }
+        else if (i < nargs)
+            current_arg = PyTuple_GET_ITEM(args, i);
+
+        if (current_arg) {
+            msg = convertitem(current_arg, &format, p_va, flags,
+                levels, msgbuf, sizeof(msgbuf), &freelist);
+            if (msg) {
+                seterror(i+1, msg, levels, parser->fname, parser->custom_msg);
+                return cleanreturn(0, &freelist);
+            }
+            continue;
+        }
+
+        if (i < parser->min) {
+            /* Less arguments than required */
+            if (i < pos) {
+                PyErr_Format(PyExc_TypeError,
+                             "Function takes %s %d positional arguments"
+                             " (%d given)",
+                             (Py_MIN(pos, parser->min) < parser->max) ? "at least" : "exactly",
+                             Py_MIN(pos, parser->min), nargs);
+            }
+            else {
+                PyErr_Format(PyExc_TypeError, "Required argument "
+                             "'%U' (pos %d) not found",
+                             keyword, i+1);
+            }
+            return cleanreturn(0, &freelist);
+        }
+        /* current code reports success when all required args
+         * fulfilled and no keyword args left, with no further
+         * validation. XXX Maybe skip this in debug build ?
+         */
+        if (!nkeywords) {
+            return cleanreturn(1, &freelist);
+        }
+
+        /* We are into optional args, skip thru to any remaining
+         * keyword args */
+        msg = skipitem(&format, p_va, flags);
+        assert(msg == NULL);
+    }
+
+    assert(IS_END_OF_FORMAT(*format) || (*format == '|') || (*format == '$'));
+
+    /* make sure there are no extraneous keyword arguments */
+    if (nkeywords > 0) {
+        PyObject *key, *value;
+        Py_ssize_t pos = 0;
+        while (PyDict_Next(keywords, &pos, &key, &value)) {
+            int match;
+            if (!PyUnicode_Check(key)) {
+                PyErr_SetString(PyExc_TypeError,
+                                "keywords must be strings");
+                return cleanreturn(0, &freelist);
+            }
+            match = PySequence_Contains(kwtuple, key);
+            if (match <= 0) {
+                if (!match) {
+                    PyErr_Format(PyExc_TypeError,
+                                 "'%U' is an invalid keyword "
+                                 "argument for this function",
+                                 key);
+                }
+                return cleanreturn(0, &freelist);
+            }
+        }
+    }
+
+    return cleanreturn(1, &freelist);
+}
+
+
 static const char *
 skipitem(const char **p_format, va_list *p_va, int flags)
 {
@@ -1705,7 +2103,9 @@
     case 'Y': /* string object */
     case 'U': /* unicode string object */
         {
-            (void) va_arg(*p_va, void *);
+            if (p_va != NULL) {
+                (void) va_arg(*p_va, void *);
+            }
             break;
         }
 
@@ -1713,7 +2113,9 @@
 
     case 'e': /* string with encoding */
         {
-            (void) va_arg(*p_va, const char *);
+            if (p_va != NULL) {
+                (void) va_arg(*p_va, const char *);
+            }
             if (!(*format == 's' || *format == 't'))
                 /* after 'e', only 's' and 't' is allowed */
                 goto err;
@@ -1728,12 +2130,16 @@
     case 'Z': /* unicode string or None */
     case 'w': /* buffer, read-write */
         {
-            (void) va_arg(*p_va, char **);
+            if (p_va != NULL) {
+                (void) va_arg(*p_va, char **);
+            }
             if (*format == '#') {
-                if (flags & FLAG_SIZE_T)
-                    (void) va_arg(*p_va, Py_ssize_t *);
-                else
-                    (void) va_arg(*p_va, int *);
+                if (p_va != NULL) {
+                    if (flags & FLAG_SIZE_T)
+                        (void) va_arg(*p_va, Py_ssize_t *);
+                    else
+                        (void) va_arg(*p_va, int *);
+                }
                 format++;
             } else if ((c == 's' || c == 'z' || c == 'y') && *format == '*') {
                 format++;
@@ -1745,17 +2151,23 @@
         {
             if (*format == '!') {
                 format++;
-                (void) va_arg(*p_va, PyTypeObject*);
-                (void) va_arg(*p_va, PyObject **);
+                if (p_va != NULL) {
+                    (void) va_arg(*p_va, PyTypeObject*);
+                    (void) va_arg(*p_va, PyObject **);
+                }
             }
             else if (*format == '&') {
                 typedef int (*converter)(PyObject *, void *);
-                (void) va_arg(*p_va, converter);
-                (void) va_arg(*p_va, void *);
+                if (p_va != NULL) {
+                    (void) va_arg(*p_va, converter);
+                    (void) va_arg(*p_va, void *);
+                }
                 format++;
             }
             else {
-                (void) va_arg(*p_va, PyObject **);
+                if (p_va != NULL) {
+                    (void) va_arg(*p_va, PyObject **);
+                }
             }
             break;
         }
@@ -1891,6 +2303,19 @@
     return 0;
 }
 
+void
+_PyArg_Fini(void)
+{
+    struct _PyArg_Parser *tmp, *s = static_arg_parsers;
+    while (s) {
+        tmp = s->next;
+        s->next = NULL;
+        parser_clear(s);
+        s = tmp;
+    }
+    static_arg_parsers = NULL;
+}
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -674,6 +674,7 @@
     PySlice_Fini();
     _PyGC_Fini();
     _PyRandom_Fini();
+    _PyArg_Fini();
 
     /* Cleanup Unicode implementation */
     _PyUnicode_Fini();
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -743,7 +743,10 @@
             return output()
 
         def insert_keywords(s):
-            return linear_format(s, declarations="static char *_keywords[] = {{{keywords}, NULL}};\n{declarations}")
+            return linear_format(s, declarations=
+                'static const char * const _keywords[] = {{{keywords}, NULL}};\n'
+                'static _PyArg_Parser _parser = {{"{format_units}:{name}", _keywords, 0}};\n'
+                '{declarations}')
 
         if not parameters:
             # no parameters, METH_NOARGS
@@ -849,17 +852,12 @@
             parser_prototype = parser_prototype_keyword
 
             body = normalize_snippet("""
-                if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords,
+                if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
                     {parse_arguments})) {{
                     goto exit;
                 }}
                 """, indent=4)
-            parser_definition = parser_body(parser_prototype, normalize_snippet("""
-                if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords,
-                    {parse_arguments})) {{
-                    goto exit;
-                }}
-                """, indent=4))
+            parser_definition = parser_body(parser_prototype, body)
             parser_definition = insert_keywords(parser_definition)
 
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list