mirror of
https://github.com/python/cpython
synced 2024-10-14 13:28:02 +00:00
Implement #8521. Added named argument handling to winreg's CreateKeyEx,
DeleteKeyEx, and OpenKeyEx. Note that CKE and DKE are new functions for 3.2 so I didn't give them a versionchanged because of the existing versionadded. OpenKeyEx already existed so it gets a versionchanged tag.
This commit is contained in:
parent
6d7df63837
commit
1771b54bed
|
@ -60,7 +60,7 @@ This module offers the following functions:
|
||||||
:exc:`WindowsError` exception is raised.
|
:exc:`WindowsError` exception is raised.
|
||||||
|
|
||||||
|
|
||||||
.. function:: CreateKeyEx(key, sub_key[, res[, sam]])
|
.. function:: CreateKeyEx(key, sub_key, reserved=0, access=KEY_ALL_ACCESS)
|
||||||
|
|
||||||
Creates or opens the specified key, returning a
|
Creates or opens the specified key, returning a
|
||||||
:ref:`handle object <handle-object>`.
|
:ref:`handle object <handle-object>`.
|
||||||
|
@ -103,7 +103,7 @@ This module offers the following functions:
|
||||||
If the method fails, a :exc:`WindowsError` exception is raised.
|
If the method fails, a :exc:`WindowsError` exception is raised.
|
||||||
|
|
||||||
|
|
||||||
.. function:: DeleteKeyEx(key, sub_key[, sam[, res]])
|
.. function:: DeleteKeyEx(key, sub_key, access=KEY_ALL_ACCESS, reserved=0)
|
||||||
|
|
||||||
Deletes the specified key.
|
Deletes the specified key.
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ This module offers the following functions:
|
||||||
specified in *file_name* is relative to the remote computer.
|
specified in *file_name* is relative to the remote computer.
|
||||||
|
|
||||||
|
|
||||||
.. function:: OpenKey(key, sub_key[, res[, sam]])
|
.. function:: OpenKey(key, sub_key, reserved=0, access=KEY_ALL_ACCESS)
|
||||||
|
|
||||||
Opens the specified key, returning a :ref:`handle object <handle-object>`.
|
Opens the specified key, returning a :ref:`handle object <handle-object>`.
|
||||||
|
|
||||||
|
@ -262,6 +262,8 @@ This module offers the following functions:
|
||||||
|
|
||||||
If the function fails, :exc:`WindowsError` is raised.
|
If the function fails, :exc:`WindowsError` is raised.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.2 Allow the use of named arguments.
|
||||||
|
|
||||||
|
|
||||||
.. function:: OpenKeyEx()
|
.. function:: OpenKeyEx()
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,16 @@ def _test_all(self, root_key, subkeystr="sub_key"):
|
||||||
self._read_test_data(root_key, subkeystr)
|
self._read_test_data(root_key, subkeystr)
|
||||||
self._delete_test_data(root_key, subkeystr)
|
self._delete_test_data(root_key, subkeystr)
|
||||||
|
|
||||||
|
def _test_named_args(self, key, sub_key):
|
||||||
|
with CreateKeyEx(key=key, sub_key=sub_key, reserved=0,
|
||||||
|
access=KEY_ALL_ACCESS) as ckey:
|
||||||
|
self.assertTrue(ckey.handle != 0)
|
||||||
|
|
||||||
|
with OpenKeyEx(key=key, sub_key=sub_key, reserved=0,
|
||||||
|
access=KEY_ALL_ACCESS) as okey:
|
||||||
|
self.assertTrue(okey.handle != 0)
|
||||||
|
|
||||||
|
|
||||||
class LocalWinregTests(BaseWinregTests):
|
class LocalWinregTests(BaseWinregTests):
|
||||||
|
|
||||||
def test_registry_works(self):
|
def test_registry_works(self):
|
||||||
|
@ -203,6 +213,12 @@ def test_registry_works_extended_functions(self):
|
||||||
|
|
||||||
self._delete_test_data(HKEY_CURRENT_USER)
|
self._delete_test_data(HKEY_CURRENT_USER)
|
||||||
|
|
||||||
|
def test_named_arguments(self):
|
||||||
|
self._test_named_args(HKEY_CURRENT_USER, test_key_name)
|
||||||
|
# Use the regular DeleteKey to clean up
|
||||||
|
# DeleteKeyEx takes named args and is tested separately
|
||||||
|
DeleteKey(HKEY_CURRENT_USER, test_key_name)
|
||||||
|
|
||||||
def test_connect_registry_to_local_machine_works(self):
|
def test_connect_registry_to_local_machine_works(self):
|
||||||
# perform minimal ConnectRegistry test which just invokes it
|
# perform minimal ConnectRegistry test which just invokes it
|
||||||
h = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
|
h = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
|
||||||
|
@ -314,6 +330,12 @@ def test_remote_registry_works(self):
|
||||||
@unittest.skipUnless(WIN64_MACHINE, "x64 specific registry tests")
|
@unittest.skipUnless(WIN64_MACHINE, "x64 specific registry tests")
|
||||||
class Win64WinregTests(BaseWinregTests):
|
class Win64WinregTests(BaseWinregTests):
|
||||||
|
|
||||||
|
def test_named_arguments(self):
|
||||||
|
self._test_named_args(HKEY_CURRENT_USER, test_key_name)
|
||||||
|
# Clean up and also exercise the named arguments
|
||||||
|
DeleteKeyEx(key=HKEY_CURRENT_USER, sub_key=test_key_name,
|
||||||
|
access=KEY_ALL_ACCESS, reserved=0)
|
||||||
|
|
||||||
def test_reflection_functions(self):
|
def test_reflection_functions(self):
|
||||||
# Test that we can call the query, enable, and disable functions
|
# Test that we can call the query, enable, and disable functions
|
||||||
# on a key which isn't on the reflection list with no consequences.
|
# on a key which isn't on the reflection list with no consequences.
|
||||||
|
|
|
@ -10,6 +10,9 @@ What's New in Python 3.2 Alpha 3?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #8521: Allow CreateKeyEx, OpenKeyEx, and DeleteKeyEx functions
|
||||||
|
of winreg to use named arguments.
|
||||||
|
|
||||||
- Issue #9930: Remove bogus subtype check that was causing (e.g.)
|
- Issue #9930: Remove bogus subtype check that was causing (e.g.)
|
||||||
float.__rdiv__(2.0, 3) to return NotImplemented instead of the
|
float.__rdiv__(2.0, 3) to return NotImplemented instead of the
|
||||||
expected 1.5.
|
expected 1.5.
|
||||||
|
|
76
PC/winreg.c
76
PC/winreg.c
|
@ -989,23 +989,26 @@ PyCreateKey(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
PyCreateKeyEx(PyObject *self, PyObject *args)
|
PyCreateKeyEx(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
PyObject *obKey;
|
PyObject *key;
|
||||||
wchar_t *subKey;
|
wchar_t *sub_key;
|
||||||
HKEY retKey;
|
HKEY retKey;
|
||||||
int res = 0;
|
int reserved = 0;
|
||||||
REGSAM sam = KEY_WRITE;
|
REGSAM access = KEY_WRITE;
|
||||||
long rc;
|
long rc;
|
||||||
if (!PyArg_ParseTuple(args, "OZ|ii:CreateKeyEx", &obKey, &subKey,
|
|
||||||
&res, &sam))
|
char *kwlist[] = {"key", "sub_key", "reserved", "access", NULL};
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OZ|ii:CreateKeyEx", kwlist,
|
||||||
|
&key, &sub_key, &reserved, &access))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
|
if (!PyHKEY_AsHKEY(key, &hKey, FALSE))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
rc = RegCreateKeyExW(hKey, subKey, res, NULL, (DWORD)NULL,
|
rc = RegCreateKeyExW(hKey, sub_key, reserved, NULL, (DWORD)NULL,
|
||||||
sam, NULL, &retKey, NULL);
|
access, NULL, &retKey, NULL);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
return PyErr_SetFromWindowsErrWithFunction(rc, "CreateKeyEx");
|
return PyErr_SetFromWindowsErrWithFunction(rc, "CreateKeyEx");
|
||||||
return PyHKEY_FromHKEY(retKey);
|
return PyHKEY_FromHKEY(retKey);
|
||||||
|
@ -1030,22 +1033,23 @@ PyDeleteKey(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
PyDeleteKeyEx(PyObject *self, PyObject *args)
|
PyDeleteKeyEx(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
PyObject *obKey;
|
PyObject *key;
|
||||||
HMODULE hMod;
|
HMODULE hMod;
|
||||||
typedef LONG (WINAPI *RDKEFunc)(HKEY, const wchar_t*, REGSAM, int);
|
typedef LONG (WINAPI *RDKEFunc)(HKEY, const wchar_t*, REGSAM, int);
|
||||||
RDKEFunc pfn = NULL;
|
RDKEFunc pfn = NULL;
|
||||||
wchar_t *subKey;
|
wchar_t *sub_key;
|
||||||
long rc;
|
long rc;
|
||||||
int res = 0;
|
int reserved = 0;
|
||||||
REGSAM sam = KEY_WOW64_64KEY;
|
REGSAM access = KEY_WOW64_64KEY;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "Ou|ii:DeleteKeyEx",
|
char *kwlist[] = {"key", "sub_key", "access", "reserved", NULL};
|
||||||
&obKey, &subKey, &sam, &res))
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ou|ii:DeleteKeyEx", kwlist,
|
||||||
|
&key, &sub_key, &access, &reserved))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
|
if (!PyHKEY_AsHKEY(key, &hKey, FALSE))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Only available on 64bit platforms, so we must load it
|
/* Only available on 64bit platforms, so we must load it
|
||||||
|
@ -1060,7 +1064,7 @@ PyDeleteKeyEx(PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
rc = (*pfn)(hKey, subKey, sam, res);
|
rc = (*pfn)(hKey, sub_key, access, reserved);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
|
@ -1282,24 +1286,26 @@ PyLoadKey(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
PyOpenKey(PyObject *self, PyObject *args)
|
PyOpenKey(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
PyObject *obKey;
|
PyObject *key;
|
||||||
|
wchar_t *sub_key;
|
||||||
wchar_t *subKey;
|
int reserved = 0;
|
||||||
int res = 0;
|
|
||||||
HKEY retKey;
|
HKEY retKey;
|
||||||
long rc;
|
long rc;
|
||||||
REGSAM sam = KEY_READ;
|
REGSAM access = KEY_READ;
|
||||||
if (!PyArg_ParseTuple(args, "OZ|ii:OpenKey", &obKey, &subKey,
|
|
||||||
&res, &sam))
|
char *kwlist[] = {"key", "sub_key", "reserved", "access", NULL};
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OZ|ii:OpenKey", kwlist,
|
||||||
|
&key, &sub_key, &reserved, &access))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
|
if (!PyHKEY_AsHKEY(key, &hKey, FALSE))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
rc = RegOpenKeyExW(hKey, subKey, res, sam, &retKey);
|
rc = RegOpenKeyExW(hKey, sub_key, reserved, access, &retKey);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
return PyErr_SetFromWindowsErrWithFunction(rc, "RegOpenKeyEx");
|
return PyErr_SetFromWindowsErrWithFunction(rc, "RegOpenKeyEx");
|
||||||
|
@ -1667,9 +1673,11 @@ static struct PyMethodDef winreg_methods[] = {
|
||||||
{"CloseKey", PyCloseKey, METH_VARARGS, CloseKey_doc},
|
{"CloseKey", PyCloseKey, METH_VARARGS, CloseKey_doc},
|
||||||
{"ConnectRegistry", PyConnectRegistry, METH_VARARGS, ConnectRegistry_doc},
|
{"ConnectRegistry", PyConnectRegistry, METH_VARARGS, ConnectRegistry_doc},
|
||||||
{"CreateKey", PyCreateKey, METH_VARARGS, CreateKey_doc},
|
{"CreateKey", PyCreateKey, METH_VARARGS, CreateKey_doc},
|
||||||
{"CreateKeyEx", PyCreateKeyEx, METH_VARARGS, CreateKeyEx_doc},
|
{"CreateKeyEx", (PyCFunction)PyCreateKeyEx,
|
||||||
|
METH_VARARGS | METH_KEYWORDS, CreateKeyEx_doc},
|
||||||
{"DeleteKey", PyDeleteKey, METH_VARARGS, DeleteKey_doc},
|
{"DeleteKey", PyDeleteKey, METH_VARARGS, DeleteKey_doc},
|
||||||
{"DeleteKeyEx", PyDeleteKeyEx, METH_VARARGS, DeleteKeyEx_doc},
|
{"DeleteKeyEx", (PyCFunction)PyDeleteKeyEx,
|
||||||
|
METH_VARARGS | METH_KEYWORDS, DeleteKeyEx_doc},
|
||||||
{"DeleteValue", PyDeleteValue, METH_VARARGS, DeleteValue_doc},
|
{"DeleteValue", PyDeleteValue, METH_VARARGS, DeleteValue_doc},
|
||||||
{"DisableReflectionKey", PyDisableReflectionKey, METH_VARARGS, DisableReflectionKey_doc},
|
{"DisableReflectionKey", PyDisableReflectionKey, METH_VARARGS, DisableReflectionKey_doc},
|
||||||
{"EnableReflectionKey", PyEnableReflectionKey, METH_VARARGS, EnableReflectionKey_doc},
|
{"EnableReflectionKey", PyEnableReflectionKey, METH_VARARGS, EnableReflectionKey_doc},
|
||||||
|
@ -1679,8 +1687,10 @@ static struct PyMethodDef winreg_methods[] = {
|
||||||
ExpandEnvironmentStrings_doc },
|
ExpandEnvironmentStrings_doc },
|
||||||
{"FlushKey", PyFlushKey, METH_VARARGS, FlushKey_doc},
|
{"FlushKey", PyFlushKey, METH_VARARGS, FlushKey_doc},
|
||||||
{"LoadKey", PyLoadKey, METH_VARARGS, LoadKey_doc},
|
{"LoadKey", PyLoadKey, METH_VARARGS, LoadKey_doc},
|
||||||
{"OpenKey", PyOpenKey, METH_VARARGS, OpenKey_doc},
|
{"OpenKey", (PyCFunction)PyOpenKey, METH_VARARGS | METH_KEYWORDS,
|
||||||
{"OpenKeyEx", PyOpenKey, METH_VARARGS, OpenKeyEx_doc},
|
OpenKey_doc},
|
||||||
|
{"OpenKeyEx", (PyCFunction)PyOpenKey, METH_VARARGS | METH_KEYWORDS,
|
||||||
|
OpenKeyEx_doc},
|
||||||
{"QueryValue", PyQueryValue, METH_VARARGS, QueryValue_doc},
|
{"QueryValue", PyQueryValue, METH_VARARGS, QueryValue_doc},
|
||||||
{"QueryValueEx", PyQueryValueEx, METH_VARARGS, QueryValueEx_doc},
|
{"QueryValueEx", PyQueryValueEx, METH_VARARGS, QueryValueEx_doc},
|
||||||
{"QueryInfoKey", PyQueryInfoKey, METH_VARARGS, QueryInfoKey_doc},
|
{"QueryInfoKey", PyQueryInfoKey, METH_VARARGS, QueryInfoKey_doc},
|
||||||
|
|
Loading…
Reference in a new issue