[Python-checkins] bpo-36346: Prepare for removing the legacy Unicode C API (AC only). (GH-21223)

Serhiy Storchaka webhook-mailer at python.org
Tue Jun 30 02:03:23 EDT 2020


https://github.com/python/cpython/commit/349f76c6aace5a4a2b57f6b442a532faf0027d6b
commit: 349f76c6aace5a4a2b57f6b442a532faf0027d6b
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-06-30T09:03:15+03:00
summary:

bpo-36346: Prepare for removing the legacy Unicode C API (AC only). (GH-21223)

files:
M Include/cpython/unicodeobject.h
M Lib/test/clinic.test
M Modules/clinic/_winapi.c.h
M Modules/clinic/posixmodule.c.h
M Objects/unicodeobject.c
M PC/clinic/winreg.c.h
M Tools/clinic/clinic.py

diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h
index 88a97a4cb5f71..0f19b2a14bcd0 100644
--- a/Include/cpython/unicodeobject.h
+++ b/Include/cpython/unicodeobject.h
@@ -11,6 +11,8 @@
 
 /* --- Internal Unicode Operations ---------------------------------------- */
 
+#define USE_UNICODE_WCHAR_CACHE 1
+
 /* Since splitting on whitespace is an important use case, and
    whitespace in most situations is solely ASCII whitespace, we
    optimize for the common case by using a quick look-up table
@@ -1169,4 +1171,7 @@ PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*);
    and where the hash values are equal (i.e. a very probable match) */
 PyAPI_FUNC(int) _PyUnicode_EQ(PyObject *, PyObject *);
 
+PyAPI_FUNC(int) _PyUnicode_WideCharString_Converter(PyObject *, void *);
+PyAPI_FUNC(int) _PyUnicode_WideCharString_Opt_Converter(PyObject *, void *);
+
 PyAPI_FUNC(Py_ssize_t) _PyUnicode_ScanIdentifier(PyObject *);
diff --git a/Lib/test/clinic.test b/Lib/test/clinic.test
index f2be61355cc97..07e13829d5db9 100644
--- a/Lib/test/clinic.test
+++ b/Lib/test/clinic.test
@@ -1813,13 +1813,26 @@ test_Py_UNICODE_converter(PyObject *module, PyObject *const *args, Py_ssize_t na
     const Py_UNICODE *e;
     Py_ssize_clean_t e_length;
 
-    if (!_PyArg_ParseStack(args, nargs, "uuZu#Z#:test_Py_UNICODE_converter",
-        &a, &b, &c, &d, &d_length, &e, &e_length)) {
+    if (!_PyArg_ParseStack(args, nargs, "O&O&O&u#Z#:test_Py_UNICODE_converter",
+        _PyUnicode_WideCharString_Converter, &a, _PyUnicode_WideCharString_Converter, &b, _PyUnicode_WideCharString_Opt_Converter, &c, &d, &d_length, &e, &e_length)) {
         goto exit;
     }
     return_value = test_Py_UNICODE_converter_impl(module, a, b, c, d, d_length, e, e_length);
 
 exit:
+    /* Cleanup for a */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)a);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    /* Cleanup for b */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)b);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    /* Cleanup for c */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)c);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -1830,7 +1843,7 @@ test_Py_UNICODE_converter_impl(PyObject *module, const Py_UNICODE *a,
                                Py_ssize_clean_t d_length,
                                const Py_UNICODE *e,
                                Py_ssize_clean_t e_length)
-/*[clinic end generated code: output=dd0a09a1b772e57b input=064a3b68ad7f04b0]*/
+/*[clinic end generated code: output=ef45e982fedf0b3d input=064a3b68ad7f04b0]*/
 
 
 /*[clinic input]
diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h
index e21f2bc2b6fd6..6022dfe0db4b2 100644
--- a/Modules/clinic/_winapi.c.h
+++ b/Modules/clinic/_winapi.c.h
@@ -367,13 +367,22 @@ _winapi_CreateProcess(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     const Py_UNICODE *current_directory;
     PyObject *startup_info;
 
-    if (!_PyArg_ParseStack(args, nargs, "ZOOOikOZO:CreateProcess",
-        &application_name, &command_line, &proc_attrs, &thread_attrs, &inherit_handles, &creation_flags, &env_mapping, &current_directory, &startup_info)) {
+    if (!_PyArg_ParseStack(args, nargs, "O&OOOikOO&O:CreateProcess",
+        _PyUnicode_WideCharString_Opt_Converter, &application_name, &command_line, &proc_attrs, &thread_attrs, &inherit_handles, &creation_flags, &env_mapping, _PyUnicode_WideCharString_Opt_Converter, &current_directory, &startup_info)) {
         goto exit;
     }
     return_value = _winapi_CreateProcess_impl(module, application_name, command_line, proc_attrs, thread_attrs, inherit_handles, creation_flags, env_mapping, current_directory, startup_info);
 
 exit:
+    /* Cleanup for application_name */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)application_name);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    /* Cleanup for current_directory */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)current_directory);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -1097,4 +1106,4 @@ _winapi_GetFileType(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=f3897898ea1da99d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=db87076a32fa7abe input=a9049054013a1b77]*/
diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h
index b691cfbc6edef..6533edfdb47d2 100644
--- a/Modules/clinic/posixmodule.c.h
+++ b/Modules/clinic/posixmodule.c.h
@@ -1674,12 +1674,28 @@ os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k
 {
     PyObject *return_value = NULL;
     static const char * const _keywords[] = {"command", NULL};
-    static _PyArg_Parser _parser = {"u:system", _keywords, 0};
+    static _PyArg_Parser _parser = {NULL, _keywords, "system", 0};
+    PyObject *argsbuf[1];
     const Py_UNICODE *command;
     long _return_value;
 
-    if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
-        &command)) {
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!PyUnicode_Check(args[0])) {
+        _PyArg_BadArgument("system", "argument 'command'", "str", args[0]);
+        goto exit;
+    }
+    #if USE_UNICODE_WCHAR_CACHE
+    _Py_COMP_DIAG_PUSH
+    _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+    command = _PyUnicode_AsUnicode(args[0]);
+    _Py_COMP_DIAG_POP
+    #else /* USE_UNICODE_WCHAR_CACHE */
+    command = PyUnicode_AsWideCharString(args[0], NULL);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    if (command == NULL) {
         goto exit;
     }
     _return_value = os_system_impl(module, command);
@@ -1689,6 +1705,11 @@ os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k
     return_value = PyLong_FromLong(_return_value);
 
 exit:
+    /* Cleanup for command */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)command);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -6998,19 +7019,47 @@ os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
 {
     PyObject *return_value = NULL;
     static const char * const _keywords[] = {"filepath", "operation", NULL};
-    static _PyArg_Parser _parser = {"O&|u:startfile", _keywords, 0};
+    static _PyArg_Parser _parser = {NULL, _keywords, "startfile", 0};
+    PyObject *argsbuf[2];
+    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
     path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0);
     const Py_UNICODE *operation = NULL;
 
-    if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
-        path_converter, &filepath, &operation)) {
+    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
+    if (!args) {
+        goto exit;
+    }
+    if (!path_converter(args[0], &filepath)) {
+        goto exit;
+    }
+    if (!noptargs) {
+        goto skip_optional_pos;
+    }
+    if (!PyUnicode_Check(args[1])) {
+        _PyArg_BadArgument("startfile", "argument 'operation'", "str", args[1]);
         goto exit;
     }
+    #if USE_UNICODE_WCHAR_CACHE
+    _Py_COMP_DIAG_PUSH
+    _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+    operation = _PyUnicode_AsUnicode(args[1]);
+    _Py_COMP_DIAG_POP
+    #else /* USE_UNICODE_WCHAR_CACHE */
+    operation = PyUnicode_AsWideCharString(args[1], NULL);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    if (operation == NULL) {
+        goto exit;
+    }
+skip_optional_pos:
     return_value = os_startfile_impl(module, &filepath, operation);
 
 exit:
     /* Cleanup for filepath */
     path_cleanup(&filepath);
+    /* Cleanup for operation */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)operation);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
 
     return return_value;
 }
@@ -8876,4 +8925,4 @@ os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t na
 #ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF
     #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF
 #endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */
-/*[clinic end generated code: output=d7c1212a94613496 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=ba3d4b35fda2c208 input=a9049054013a1b77]*/
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 8eafdacf55974..db3f55e02b98b 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -3273,6 +3273,80 @@ PyUnicode_AsWideCharString(PyObject *unicode,
 
 #endif /* HAVE_WCHAR_H */
 
+int
+_PyUnicode_WideCharString_Converter(PyObject *obj, void *ptr)
+{
+    wchar_t **p = (wchar_t **)ptr;
+    if (obj == NULL) {
+#if !USE_UNICODE_WCHAR_CACHE
+        PyMem_Free(*p);
+#endif /* USE_UNICODE_WCHAR_CACHE */
+        *p = NULL;
+        return 1;
+    }
+    if (PyUnicode_Check(obj)) {
+#if USE_UNICODE_WCHAR_CACHE
+_Py_COMP_DIAG_PUSH
+_Py_COMP_DIAG_IGNORE_DEPR_DECLS
+        *p = (wchar_t *)_PyUnicode_AsUnicode(obj);
+        if (*p == NULL) {
+            return 0;
+        }
+        return 1;
+_Py_COMP_DIAG_POP
+#else /* USE_UNICODE_WCHAR_CACHE */
+        *p = PyUnicode_AsWideCharString(obj, NULL);
+        if (*p == NULL) {
+            return 0;
+        }
+        return Py_CLEANUP_SUPPORTED;
+#endif /* USE_UNICODE_WCHAR_CACHE */
+    }
+    PyErr_Format(PyExc_TypeError,
+                 "argument must be str, not %.50s",
+                 obj->ob_type->tp_name);
+    return 0;
+}
+
+int
+_PyUnicode_WideCharString_Opt_Converter(PyObject *obj, void *ptr)
+{
+    wchar_t **p = (wchar_t **)ptr;
+    if (obj == NULL) {
+#if !USE_UNICODE_WCHAR_CACHE
+        PyMem_Free(*p);
+#endif /* USE_UNICODE_WCHAR_CACHE */
+        *p = NULL;
+        return 1;
+    }
+    if (obj == Py_None) {
+        *p = NULL;
+        return 1;
+    }
+    if (PyUnicode_Check(obj)) {
+#if USE_UNICODE_WCHAR_CACHE
+_Py_COMP_DIAG_PUSH
+_Py_COMP_DIAG_IGNORE_DEPR_DECLS
+        *p = (wchar_t *)_PyUnicode_AsUnicode(obj);
+        if (*p == NULL) {
+            return 0;
+        }
+        return 1;
+_Py_COMP_DIAG_POP
+#else /* USE_UNICODE_WCHAR_CACHE */
+        *p = PyUnicode_AsWideCharString(obj, NULL);
+        if (*p == NULL) {
+            return 0;
+        }
+        return Py_CLEANUP_SUPPORTED;
+#endif /* USE_UNICODE_WCHAR_CACHE */
+    }
+    PyErr_Format(PyExc_TypeError,
+                 "argument must be str or None, not %.50s",
+                 obj->ob_type->tp_name);
+    return 0;
+}
+
 PyObject *
 PyUnicode_FromOrdinal(int ordinal)
 {
diff --git a/PC/clinic/winreg.c.h b/PC/clinic/winreg.c.h
index 5f37fcda0a9ab..5c97eaeee9e27 100644
--- a/PC/clinic/winreg.c.h
+++ b/PC/clinic/winreg.c.h
@@ -152,8 +152,30 @@ winreg_ConnectRegistry(PyObject *module, PyObject *const *args, Py_ssize_t nargs
     HKEY key;
     HKEY _return_value;
 
-    if (!_PyArg_ParseStack(args, nargs, "ZO&:ConnectRegistry",
-        &computer_name, clinic_HKEY_converter, &key)) {
+    if (!_PyArg_CheckPositional("ConnectRegistry", nargs, 2, 2)) {
+        goto exit;
+    }
+    if (args[0] == Py_None) {
+        computer_name = NULL;
+    }
+    else if (PyUnicode_Check(args[0])) {
+        #if USE_UNICODE_WCHAR_CACHE
+        _Py_COMP_DIAG_PUSH
+        _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+        computer_name = _PyUnicode_AsUnicode(args[0]);
+        _Py_COMP_DIAG_POP
+        #else /* USE_UNICODE_WCHAR_CACHE */
+        computer_name = PyUnicode_AsWideCharString(args[0], NULL);
+        #endif /* USE_UNICODE_WCHAR_CACHE */
+        if (computer_name == NULL) {
+            goto exit;
+        }
+    }
+    else {
+        _PyArg_BadArgument("ConnectRegistry", "argument 1", "str or None", args[0]);
+        goto exit;
+    }
+    if (!clinic_HKEY_converter(args[1], &key)) {
         goto exit;
     }
     _return_value = winreg_ConnectRegistry_impl(module, computer_name, key);
@@ -163,6 +185,11 @@ winreg_ConnectRegistry(PyObject *module, PyObject *const *args, Py_ssize_t nargs
     return_value = PyHKEY_FromHKEY(_return_value);
 
 exit:
+    /* Cleanup for computer_name */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)computer_name);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -199,8 +226,30 @@ winreg_CreateKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     const Py_UNICODE *sub_key;
     HKEY _return_value;
 
-    if (!_PyArg_ParseStack(args, nargs, "O&Z:CreateKey",
-        clinic_HKEY_converter, &key, &sub_key)) {
+    if (!_PyArg_CheckPositional("CreateKey", nargs, 2, 2)) {
+        goto exit;
+    }
+    if (!clinic_HKEY_converter(args[0], &key)) {
+        goto exit;
+    }
+    if (args[1] == Py_None) {
+        sub_key = NULL;
+    }
+    else if (PyUnicode_Check(args[1])) {
+        #if USE_UNICODE_WCHAR_CACHE
+        _Py_COMP_DIAG_PUSH
+        _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+        sub_key = _PyUnicode_AsUnicode(args[1]);
+        _Py_COMP_DIAG_POP
+        #else /* USE_UNICODE_WCHAR_CACHE */
+        sub_key = PyUnicode_AsWideCharString(args[1], NULL);
+        #endif /* USE_UNICODE_WCHAR_CACHE */
+        if (sub_key == NULL) {
+            goto exit;
+        }
+    }
+    else {
+        _PyArg_BadArgument("CreateKey", "argument 2", "str or None", args[1]);
         goto exit;
     }
     _return_value = winreg_CreateKey_impl(module, key, sub_key);
@@ -210,6 +259,11 @@ winreg_CreateKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     return_value = PyHKEY_FromHKEY(_return_value);
 
 exit:
+    /* Cleanup for sub_key */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)sub_key);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -251,7 +305,7 @@ winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py
 {
     PyObject *return_value = NULL;
     static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL};
-    static _PyArg_Parser _parser = {"O&Z|ii:CreateKeyEx", _keywords, 0};
+    static _PyArg_Parser _parser = {"O&O&|ii:CreateKeyEx", _keywords, 0};
     HKEY key;
     const Py_UNICODE *sub_key;
     int reserved = 0;
@@ -259,7 +313,7 @@ winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py
     HKEY _return_value;
 
     if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
-        clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) {
+        clinic_HKEY_converter, &key, _PyUnicode_WideCharString_Opt_Converter, &sub_key, &reserved, &access)) {
         goto exit;
     }
     _return_value = winreg_CreateKeyEx_impl(module, key, sub_key, reserved, access);
@@ -269,6 +323,11 @@ winreg_CreateKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py
     return_value = PyHKEY_FromHKEY(_return_value);
 
 exit:
+    /* Cleanup for sub_key */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)sub_key);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -303,13 +362,35 @@ winreg_DeleteKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     HKEY key;
     const Py_UNICODE *sub_key;
 
-    if (!_PyArg_ParseStack(args, nargs, "O&u:DeleteKey",
-        clinic_HKEY_converter, &key, &sub_key)) {
+    if (!_PyArg_CheckPositional("DeleteKey", nargs, 2, 2)) {
+        goto exit;
+    }
+    if (!clinic_HKEY_converter(args[0], &key)) {
+        goto exit;
+    }
+    if (!PyUnicode_Check(args[1])) {
+        _PyArg_BadArgument("DeleteKey", "argument 2", "str", args[1]);
+        goto exit;
+    }
+    #if USE_UNICODE_WCHAR_CACHE
+    _Py_COMP_DIAG_PUSH
+    _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+    sub_key = _PyUnicode_AsUnicode(args[1]);
+    _Py_COMP_DIAG_POP
+    #else /* USE_UNICODE_WCHAR_CACHE */
+    sub_key = PyUnicode_AsWideCharString(args[1], NULL);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    if (sub_key == NULL) {
         goto exit;
     }
     return_value = winreg_DeleteKey_impl(module, key, sub_key);
 
 exit:
+    /* Cleanup for sub_key */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)sub_key);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -351,19 +432,24 @@ winreg_DeleteKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py
 {
     PyObject *return_value = NULL;
     static const char * const _keywords[] = {"key", "sub_key", "access", "reserved", NULL};
-    static _PyArg_Parser _parser = {"O&u|ii:DeleteKeyEx", _keywords, 0};
+    static _PyArg_Parser _parser = {"O&O&|ii:DeleteKeyEx", _keywords, 0};
     HKEY key;
     const Py_UNICODE *sub_key;
     REGSAM access = KEY_WOW64_64KEY;
     int reserved = 0;
 
     if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
-        clinic_HKEY_converter, &key, &sub_key, &access, &reserved)) {
+        clinic_HKEY_converter, &key, _PyUnicode_WideCharString_Converter, &sub_key, &access, &reserved)) {
         goto exit;
     }
     return_value = winreg_DeleteKeyEx_impl(module, key, sub_key, access, reserved);
 
 exit:
+    /* Cleanup for sub_key */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)sub_key);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -391,13 +477,40 @@ winreg_DeleteValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     HKEY key;
     const Py_UNICODE *value;
 
-    if (!_PyArg_ParseStack(args, nargs, "O&Z:DeleteValue",
-        clinic_HKEY_converter, &key, &value)) {
+    if (!_PyArg_CheckPositional("DeleteValue", nargs, 2, 2)) {
+        goto exit;
+    }
+    if (!clinic_HKEY_converter(args[0], &key)) {
+        goto exit;
+    }
+    if (args[1] == Py_None) {
+        value = NULL;
+    }
+    else if (PyUnicode_Check(args[1])) {
+        #if USE_UNICODE_WCHAR_CACHE
+        _Py_COMP_DIAG_PUSH
+        _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+        value = _PyUnicode_AsUnicode(args[1]);
+        _Py_COMP_DIAG_POP
+        #else /* USE_UNICODE_WCHAR_CACHE */
+        value = PyUnicode_AsWideCharString(args[1], NULL);
+        #endif /* USE_UNICODE_WCHAR_CACHE */
+        if (value == NULL) {
+            goto exit;
+        }
+    }
+    else {
+        _PyArg_BadArgument("DeleteValue", "argument 2", "str or None", args[1]);
         goto exit;
     }
     return_value = winreg_DeleteValue_impl(module, key, value);
 
 exit:
+    /* Cleanup for value */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)value);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -517,12 +630,29 @@ winreg_ExpandEnvironmentStrings(PyObject *module, PyObject *arg)
     PyObject *return_value = NULL;
     const Py_UNICODE *string;
 
-    if (!PyArg_Parse(arg, "u:ExpandEnvironmentStrings", &string)) {
+    if (!PyUnicode_Check(arg)) {
+        _PyArg_BadArgument("ExpandEnvironmentStrings", "argument", "str", arg);
+        goto exit;
+    }
+    #if USE_UNICODE_WCHAR_CACHE
+    _Py_COMP_DIAG_PUSH
+    _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+    string = _PyUnicode_AsUnicode(arg);
+    _Py_COMP_DIAG_POP
+    #else /* USE_UNICODE_WCHAR_CACHE */
+    string = PyUnicode_AsWideCharString(arg, NULL);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    if (string == NULL) {
         goto exit;
     }
     return_value = winreg_ExpandEnvironmentStrings_impl(module, string);
 
 exit:
+    /* Cleanup for string */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)string);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -609,13 +739,54 @@ winreg_LoadKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     const Py_UNICODE *sub_key;
     const Py_UNICODE *file_name;
 
-    if (!_PyArg_ParseStack(args, nargs, "O&uu:LoadKey",
-        clinic_HKEY_converter, &key, &sub_key, &file_name)) {
+    if (!_PyArg_CheckPositional("LoadKey", nargs, 3, 3)) {
+        goto exit;
+    }
+    if (!clinic_HKEY_converter(args[0], &key)) {
+        goto exit;
+    }
+    if (!PyUnicode_Check(args[1])) {
+        _PyArg_BadArgument("LoadKey", "argument 2", "str", args[1]);
+        goto exit;
+    }
+    #if USE_UNICODE_WCHAR_CACHE
+    _Py_COMP_DIAG_PUSH
+    _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+    sub_key = _PyUnicode_AsUnicode(args[1]);
+    _Py_COMP_DIAG_POP
+    #else /* USE_UNICODE_WCHAR_CACHE */
+    sub_key = PyUnicode_AsWideCharString(args[1], NULL);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    if (sub_key == NULL) {
+        goto exit;
+    }
+    if (!PyUnicode_Check(args[2])) {
+        _PyArg_BadArgument("LoadKey", "argument 3", "str", args[2]);
+        goto exit;
+    }
+    #if USE_UNICODE_WCHAR_CACHE
+    _Py_COMP_DIAG_PUSH
+    _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+    file_name = _PyUnicode_AsUnicode(args[2]);
+    _Py_COMP_DIAG_POP
+    #else /* USE_UNICODE_WCHAR_CACHE */
+    file_name = PyUnicode_AsWideCharString(args[2], NULL);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    if (file_name == NULL) {
         goto exit;
     }
     return_value = winreg_LoadKey_impl(module, key, sub_key, file_name);
 
 exit:
+    /* Cleanup for sub_key */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)sub_key);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    /* Cleanup for file_name */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)file_name);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -650,7 +821,7 @@ winreg_OpenKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
 {
     PyObject *return_value = NULL;
     static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL};
-    static _PyArg_Parser _parser = {"O&Z|ii:OpenKey", _keywords, 0};
+    static _PyArg_Parser _parser = {"O&O&|ii:OpenKey", _keywords, 0};
     HKEY key;
     const Py_UNICODE *sub_key;
     int reserved = 0;
@@ -658,7 +829,7 @@ winreg_OpenKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
     HKEY _return_value;
 
     if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
-        clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) {
+        clinic_HKEY_converter, &key, _PyUnicode_WideCharString_Opt_Converter, &sub_key, &reserved, &access)) {
         goto exit;
     }
     _return_value = winreg_OpenKey_impl(module, key, sub_key, reserved, access);
@@ -668,6 +839,11 @@ winreg_OpenKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
     return_value = PyHKEY_FromHKEY(_return_value);
 
 exit:
+    /* Cleanup for sub_key */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)sub_key);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -702,7 +878,7 @@ winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb
 {
     PyObject *return_value = NULL;
     static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL};
-    static _PyArg_Parser _parser = {"O&Z|ii:OpenKeyEx", _keywords, 0};
+    static _PyArg_Parser _parser = {"O&O&|ii:OpenKeyEx", _keywords, 0};
     HKEY key;
     const Py_UNICODE *sub_key;
     int reserved = 0;
@@ -710,7 +886,7 @@ winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb
     HKEY _return_value;
 
     if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
-        clinic_HKEY_converter, &key, &sub_key, &reserved, &access)) {
+        clinic_HKEY_converter, &key, _PyUnicode_WideCharString_Opt_Converter, &sub_key, &reserved, &access)) {
         goto exit;
     }
     _return_value = winreg_OpenKeyEx_impl(module, key, sub_key, reserved, access);
@@ -720,6 +896,11 @@ winreg_OpenKeyEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb
     return_value = PyHKEY_FromHKEY(_return_value);
 
 exit:
+    /* Cleanup for sub_key */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)sub_key);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -792,13 +973,40 @@ winreg_QueryValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     HKEY key;
     const Py_UNICODE *sub_key;
 
-    if (!_PyArg_ParseStack(args, nargs, "O&Z:QueryValue",
-        clinic_HKEY_converter, &key, &sub_key)) {
+    if (!_PyArg_CheckPositional("QueryValue", nargs, 2, 2)) {
+        goto exit;
+    }
+    if (!clinic_HKEY_converter(args[0], &key)) {
+        goto exit;
+    }
+    if (args[1] == Py_None) {
+        sub_key = NULL;
+    }
+    else if (PyUnicode_Check(args[1])) {
+        #if USE_UNICODE_WCHAR_CACHE
+        _Py_COMP_DIAG_PUSH
+        _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+        sub_key = _PyUnicode_AsUnicode(args[1]);
+        _Py_COMP_DIAG_POP
+        #else /* USE_UNICODE_WCHAR_CACHE */
+        sub_key = PyUnicode_AsWideCharString(args[1], NULL);
+        #endif /* USE_UNICODE_WCHAR_CACHE */
+        if (sub_key == NULL) {
+            goto exit;
+        }
+    }
+    else {
+        _PyArg_BadArgument("QueryValue", "argument 2", "str or None", args[1]);
         goto exit;
     }
     return_value = winreg_QueryValue_impl(module, key, sub_key);
 
 exit:
+    /* Cleanup for sub_key */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)sub_key);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -831,13 +1039,40 @@ winreg_QueryValueEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     HKEY key;
     const Py_UNICODE *name;
 
-    if (!_PyArg_ParseStack(args, nargs, "O&Z:QueryValueEx",
-        clinic_HKEY_converter, &key, &name)) {
+    if (!_PyArg_CheckPositional("QueryValueEx", nargs, 2, 2)) {
+        goto exit;
+    }
+    if (!clinic_HKEY_converter(args[0], &key)) {
+        goto exit;
+    }
+    if (args[1] == Py_None) {
+        name = NULL;
+    }
+    else if (PyUnicode_Check(args[1])) {
+        #if USE_UNICODE_WCHAR_CACHE
+        _Py_COMP_DIAG_PUSH
+        _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+        name = _PyUnicode_AsUnicode(args[1]);
+        _Py_COMP_DIAG_POP
+        #else /* USE_UNICODE_WCHAR_CACHE */
+        name = PyUnicode_AsWideCharString(args[1], NULL);
+        #endif /* USE_UNICODE_WCHAR_CACHE */
+        if (name == NULL) {
+            goto exit;
+        }
+    }
+    else {
+        _PyArg_BadArgument("QueryValueEx", "argument 2", "str or None", args[1]);
         goto exit;
     }
     return_value = winreg_QueryValueEx_impl(module, key, name);
 
 exit:
+    /* Cleanup for name */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)name);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -875,13 +1110,35 @@ winreg_SaveKey(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     HKEY key;
     const Py_UNICODE *file_name;
 
-    if (!_PyArg_ParseStack(args, nargs, "O&u:SaveKey",
-        clinic_HKEY_converter, &key, &file_name)) {
+    if (!_PyArg_CheckPositional("SaveKey", nargs, 2, 2)) {
+        goto exit;
+    }
+    if (!clinic_HKEY_converter(args[0], &key)) {
+        goto exit;
+    }
+    if (!PyUnicode_Check(args[1])) {
+        _PyArg_BadArgument("SaveKey", "argument 2", "str", args[1]);
+        goto exit;
+    }
+    #if USE_UNICODE_WCHAR_CACHE
+    _Py_COMP_DIAG_PUSH
+    _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+    file_name = _PyUnicode_AsUnicode(args[1]);
+    _Py_COMP_DIAG_POP
+    #else /* USE_UNICODE_WCHAR_CACHE */
+    file_name = PyUnicode_AsWideCharString(args[1], NULL);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+    if (file_name == NULL) {
         goto exit;
     }
     return_value = winreg_SaveKey_impl(module, key, file_name);
 
 exit:
+    /* Cleanup for file_name */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)file_name);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -929,13 +1186,18 @@ winreg_SetValue(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     const Py_UNICODE *value;
     Py_ssize_clean_t value_length;
 
-    if (!_PyArg_ParseStack(args, nargs, "O&Zku#:SetValue",
-        clinic_HKEY_converter, &key, &sub_key, &type, &value, &value_length)) {
+    if (!_PyArg_ParseStack(args, nargs, "O&O&ku#:SetValue",
+        clinic_HKEY_converter, &key, _PyUnicode_WideCharString_Opt_Converter, &sub_key, &type, &value, &value_length)) {
         goto exit;
     }
     return_value = winreg_SetValue_impl(module, key, sub_key, type, value, value_length);
 
 exit:
+    /* Cleanup for sub_key */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)sub_key);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -1000,13 +1262,18 @@ winreg_SetValueEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     DWORD type;
     PyObject *value;
 
-    if (!_PyArg_ParseStack(args, nargs, "O&ZOkO:SetValueEx",
-        clinic_HKEY_converter, &key, &value_name, &reserved, &type, &value)) {
+    if (!_PyArg_ParseStack(args, nargs, "O&O&OkO:SetValueEx",
+        clinic_HKEY_converter, &key, _PyUnicode_WideCharString_Opt_Converter, &value_name, &reserved, &type, &value)) {
         goto exit;
     }
     return_value = winreg_SetValueEx_impl(module, key, value_name, reserved, type, value);
 
 exit:
+    /* Cleanup for value_name */
+    #if !USE_UNICODE_WCHAR_CACHE
+    PyMem_Free((void *)value_name);
+    #endif /* USE_UNICODE_WCHAR_CACHE */
+
     return return_value;
 }
 
@@ -1111,4 +1378,4 @@ winreg_QueryReflectionKey(PyObject *module, PyObject *arg)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=f4f996d40d06f14c input=a9049054013a1b77]*/
+/*[clinic end generated code: output=fa5f21ea6a75d0e9 input=a9049054013a1b77]*/
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index b1bf7826ebf9f..3a9f4c228c22b 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -3374,20 +3374,81 @@ def parse_arg(self, argname, displayname):
                            displayname=displayname)
         return super().parse_arg(argname, displayname)
 
+ at add_legacy_c_converter('u')
 @add_legacy_c_converter('u#', zeroes=True)
 @add_legacy_c_converter('Z', accept={str, NoneType})
 @add_legacy_c_converter('Z#', accept={str, NoneType}, zeroes=True)
 class Py_UNICODE_converter(CConverter):
     type = 'const Py_UNICODE *'
     default_type = (str, Null, NoneType)
-    format_unit = 'u'
 
     def converter_init(self, *, accept={str}, zeroes=False):
         format_unit = 'Z' if accept=={str, NoneType} else 'u'
         if zeroes:
             format_unit += '#'
             self.length = True
-        self.format_unit = format_unit
+            self.format_unit = format_unit
+        else:
+            self.accept = accept
+            if accept == {str}:
+                self.converter = '_PyUnicode_WideCharString_Converter'
+            elif accept == {str, NoneType}:
+                self.converter = '_PyUnicode_WideCharString_Opt_Converter'
+            else:
+                fail("Py_UNICODE_converter: illegal 'accept' argument " + repr(accept))
+
+    def cleanup(self):
+        if not self.length:
+            return """\
+#if !USE_UNICODE_WCHAR_CACHE
+PyMem_Free((void *){name});
+#endif /* USE_UNICODE_WCHAR_CACHE */
+""".format(name=self.name)
+
+    def parse_arg(self, argname, argnum):
+        if not self.length:
+            if self.accept == {str}:
+                return """
+                    if (!PyUnicode_Check({argname})) {{{{
+                        _PyArg_BadArgument("{{name}}", {argnum}, "str", {argname});
+                        goto exit;
+                    }}}}
+                    #if USE_UNICODE_WCHAR_CACHE
+                    _Py_COMP_DIAG_PUSH
+                    _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+                    {paramname} = _PyUnicode_AsUnicode({argname});
+                    _Py_COMP_DIAG_POP
+                    #else /* USE_UNICODE_WCHAR_CACHE */
+                    {paramname} = PyUnicode_AsWideCharString({argname}, NULL);
+                    #endif /* USE_UNICODE_WCHAR_CACHE */
+                    if ({paramname} == NULL) {{{{
+                        goto exit;
+                    }}}}
+                    """.format(argname=argname, paramname=self.name, argnum=argnum)
+            elif self.accept == {str, NoneType}:
+                return """
+                    if ({argname} == Py_None) {{{{
+                        {paramname} = NULL;
+                    }}}}
+                    else if (PyUnicode_Check({argname})) {{{{
+                        #if USE_UNICODE_WCHAR_CACHE
+                        _Py_COMP_DIAG_PUSH
+                        _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+                        {paramname} = _PyUnicode_AsUnicode({argname});
+                        _Py_COMP_DIAG_POP
+                        #else /* USE_UNICODE_WCHAR_CACHE */
+                        {paramname} = PyUnicode_AsWideCharString({argname}, NULL);
+                        #endif /* USE_UNICODE_WCHAR_CACHE */
+                        if ({paramname} == NULL) {{{{
+                            goto exit;
+                        }}}}
+                    }}}}
+                    else {{{{
+                        _PyArg_BadArgument("{{name}}", {argnum}, "str or None", {argname});
+                        goto exit;
+                    }}}}
+                    """.format(argname=argname, paramname=self.name, argnum=argnum)
+        return super().parse_arg(argname, argnum)
 
 @add_legacy_c_converter('s*', accept={str, buffer})
 @add_legacy_c_converter('z*', accept={str, buffer, NoneType})



More information about the Python-checkins mailing list