From 4a1b001e311589dc3acffc6e110a7e4fafeb2bce Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Mon, 1 Jan 2018 23:03:58 +0200 Subject: [PATCH 1/6] wip - test start to pass --HG-- branch : py3-winreg --- pypy/interpreter/gateway.py | 9 + pypy/module/_winreg/interp_winreg.py | 235 +++++++++++++----------- pypy/module/_winreg/test/test_winreg.py | 36 ++-- rpython/rlib/rwinreg.py | 2 +- 4 files changed, 152 insertions(+), 130 deletions(-) diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py index e325e25199..b006b3fa2c 100644 --- a/pypy/interpreter/gateway.py +++ b/pypy/interpreter/gateway.py @@ -171,6 +171,9 @@ class UnwrapSpec_Check(UnwrapSpecRecipe): def visit_text0(self, el, app_sig): self.checked_space_method(el, app_sig) + def visit_unicode(self, el, app_sig): + self.checked_space_method(el, app_sig) + def visit_fsencode(self, el, app_sig): self.checked_space_method(el, app_sig) @@ -320,6 +323,9 @@ class UnwrapSpec_EmitRun(UnwrapSpecEmit): def visit_text0(self, typ): self.run_args.append("space.text0_w(%s)" % (self.scopenext(),)) + def visit_unicode(self, typ): + self.run_args.append("space.unicode_w(%s)" % (self.scopenext(),)) + def visit_fsencode(self, typ): self.run_args.append("space.fsencode_w(%s)" % (self.scopenext(),)) @@ -485,6 +491,9 @@ class UnwrapSpec_FastFunc_Unwrap(UnwrapSpecEmit): def visit_text(self, typ): self.unwrap.append("space.text_w(%s)" % (self.nextarg(),)) + def visit_unicode(self, typ): + self.unwrap.append("space.unicode_w(%s)" % (self.nextarg(),)) + def visit_text0(self, typ): self.unwrap.append("space.text0_w(%s)" % (self.nextarg(),)) diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py index d1b07a6dbf..414b9f97d1 100644 --- a/pypy/module/_winreg/interp_winreg.py +++ b/pypy/module/_winreg/interp_winreg.py @@ -8,10 +8,10 @@ from rpython.rlib import rwinreg, rwin32 from rpython.rlib.rarithmetic import r_uint, intmask def raiseWindowsError(space, errcode, context): - message = rwin32.FormatErrorW(errcode) + message = rwin32.FormatError(errcode) raise OperationError(space.w_WindowsError, space.newtuple([space.newint(errcode), - space.newunicode(message)])) + space.newtext(message)])) class W_HKEY(W_Root): def __init__(self, space, hkey): @@ -32,7 +32,7 @@ class W_HKEY(W_Root): return space.newint(self.as_int()) def descr_repr(self, space): - return space.newtext("" % (self.as_int(),)) + return space.newunicode(u"" % (self.as_int(),)) def descr_int(self, space): return space.newint(self.as_int()) @@ -110,8 +110,8 @@ def hkey_w(w_hkey, space): elif isinstance(w_hkey, W_HKEY): return w_hkey.hkey elif space.isinstance_w(w_hkey, space.w_int): - if space.is_true(space.lt(w_hkey, space.newint(0))): - return rffi.cast(rwinreg.HKEY, space.int_w(w_hkey)) + return rffi.cast(rwinreg.HKEY, space.int_w(w_hkey)) + elif space.isinstance_w(w_hkey, space.w_long): return rffi.cast(rwinreg.HKEY, space.uint_w(w_hkey)) else: raise oefmt(space.w_TypeError, "The object is not a PyHKEY object") @@ -149,7 +149,7 @@ If you don't know whether a FlushKey() call is required, it probably isn't.""" if ret != 0: raiseWindowsError(space, ret, 'RegFlushKey') -@unwrap_spec(subkey="text", filename="text") +@unwrap_spec(subkey="unicode", filename="unicode") def LoadKey(space, w_hkey, subkey, filename): """LoadKey(key, sub_key, file_name) - Creates a subkey under the specified key and stores registration information from a specified file into that subkey. @@ -174,7 +174,7 @@ The docs imply key must be in the HKEY_USER or HKEY_LOCAL_MACHINE tree""" if ret != 0: raiseWindowsError(space, ret, 'RegLoadKey') -@unwrap_spec(filename="text") +@unwrap_spec(filename="unicode") def SaveKey(space, w_hkey, filename): """SaveKey(key, file_name) - Saves the specified key, and all its subkeys to the specified file. @@ -193,7 +193,7 @@ This function passes NULL for security_attributes to the API.""" if ret != 0: raiseWindowsError(space, ret, 'RegSaveKey') -@unwrap_spec(typ=int, value="text") +@unwrap_spec(typ=int, value="unicode") def SetValue(space, w_hkey, w_subkey, typ, value): """SetValue(key, sub_key, type, value) - Associates a value with a specified key. @@ -215,14 +215,14 @@ KEY_SET_VALUE access.""" if typ != rwinreg.REG_SZ: raise oefmt(space.w_ValueError, "Type must be winreg.REG_SZ") hkey = hkey_w(w_hkey, space) - if space.is_w(w_subkey, space.w_None): - subkey = None - else: - subkey = space.text_w(w_subkey) - with rffi.scoped_str2charp(value) as dataptr: - ret = rwinreg.RegSetValue(hkey, subkey, rwinreg.REG_SZ, dataptr, len(value)) - if ret != 0: - raiseWindowsError(space, ret, 'RegSetValue') + with rffi.scoped_unicode2wcharp(space.unicode_w(w_subkey)) as subkey: + c_subkey = rffi.cast(rffi.CCHARP, subkey) + with rffi.scoped_unicode2wcharp(value) as dataptr: + c_dataptr = rffi.cast(rffi.CCHARP, dataptr) + ret = rwinreg.RegSetValue(hkey, c_subkey, rwinreg.REG_SZ, + c_dataptr, len(value)) + if ret != 0: + raiseWindowsError(space, ret, 'RegSetValue') def QueryValue(space, w_hkey, w_subkey): """string = QueryValue(key, sub_key) - retrieves the unnamed value for a key. @@ -239,28 +239,32 @@ But the underlying API call doesn't return the type, Lame Lame Lame, DONT USE TH if space.is_w(w_subkey, space.w_None): subkey = None else: - subkey = space.text_w(w_subkey) - with lltype.scoped_alloc(rwin32.PLONG.TO, 1) as bufsize_p: - ret = rwinreg.RegQueryValue(hkey, subkey, None, bufsize_p) - bufSize = intmask(bufsize_p[0]) - if ret == rwinreg.ERROR_MORE_DATA: - bufSize = 256 - elif ret != 0: - raiseWindowsError(space, ret, 'RegQueryValue') - - while True: - with lltype.scoped_alloc(rffi.CCHARP.TO, bufSize) as buf: - ret = rwinreg.RegQueryValue(hkey, subkey, buf, bufsize_p) - if ret == rwinreg.ERROR_MORE_DATA: - # Resize and retry - bufSize *= 2 - bufsize_p[0] = bufSize - continue + subkey = space.unicode_w(w_subkey) + with rffi.scoped_unicode2wcharp(subkey) as wide_subkey: + c_subkey = rffi.cast(rffi.CCHARP, wide_subkey) + with lltype.scoped_alloc(rwin32.PLONG.TO, 1) as bufsize_p: + ret = rwinreg.RegQueryValue(hkey, c_subkey, None, bufsize_p) + bufSize = intmask(bufsize_p[0]) + if ret == rwinreg.ERROR_MORE_DATA: + bufSize = 256 + elif ret != 0: + raiseWindowsError(space, ret, 'RegQueryValue') - if ret != 0: - raiseWindowsError(space, ret, 'RegQueryValue') - length = intmask(bufsize_p[0] - 1) - return space.newtext(rffi.charp2strn(buf, length)) + while True: + with lltype.scoped_alloc(rffi.CCHARP.TO, bufSize) as buf: + ret = rwinreg.RegQueryValue(hkey, c_subkey, buf, bufsize_p) + if ret == rwinreg.ERROR_MORE_DATA: + print 'bufSize was %d, too small' % bufSize + # Resize and retry + bufSize *= 2 + bufsize_p[0] = bufSize + continue + + if ret != 0: + raiseWindowsError(space, ret, 'RegQueryValue') + length = intmask(bufsize_p[0] - 1) / 2 + wide_buf = rffi.cast(rffi.CWCHARP, buf) + return space.newunicode(rffi.wcharp2unicoden(wide_buf, length)) def convert_to_regdata(space, w_value, typ): buf = None @@ -282,10 +286,8 @@ def convert_to_regdata(space, w_value, typ): buf = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw') buf[0] = '\0' else: - if space.isinstance_w(w_value, space.w_unicode): - w_value = space.call_method(w_value, 'encode', - space.newtext('mbcs')) - buf = rffi.str2charp(space.text_w(w_value)) + buf = rffi.unicode2wcharp(space.unicode_w(w_value)) + buf = rffi.cast(rffi.CCHARP, buf) buflen = space.len_w(w_value) + 1 elif typ == rwinreg.REG_MULTI_SZ: @@ -302,10 +304,7 @@ def convert_to_regdata(space, w_value, typ): while True: try: w_item = space.next(w_iter) - if space.isinstance_w(w_item, space.w_unicode): - w_item = space.call_method(w_item, 'encode', - space.newtext('mbcs')) - item = space.bytes_w(w_item) + item = space.unicode_w(w_item) strings.append(item) buflen += len(item) + 1 except OperationError as e: @@ -318,8 +317,10 @@ def convert_to_regdata(space, w_value, typ): # Now copy data buflen = 0 for string in strings: - for i in range(len(string)): - buf[buflen + i] = string[i] + with rffi.scoped_unicode2wcharp(string) as wchr: + c_str = rffi.cast(rffi.CCHARP, wchr) + for i in range(len(string)): + buf[buflen + i] = wchr[i] buflen += len(string) + 1 buf[buflen - 1] = '\0' buflen += 1 @@ -360,12 +361,12 @@ def convert_from_regdata(space, buf, buflen, typ): s = "" else: # may or may not have a trailing NULL in the buffer. - buf = rffi.cast(rffi.CCHARP, buf) + buf = rffi.cast(rffi.CWCHARP, buf) if buf[buflen - 1] == '\x00': buflen -= 1 - s = rffi.charp2strn(buf, buflen) + s = rffi.wcharp2unicoden(buf, buflen) w_s = space.newbytes(s) - return space.call_method(w_s, 'decode', space.newtext('mbcs')) + return w_s elif typ == rwinreg.REG_MULTI_SZ: if not buflen: @@ -380,14 +381,14 @@ def convert_from_regdata(space, buf, buflen, typ): if len(s) == 0: break s = ''.join(s) - l.append(space.newtext(s)) + l.append(space.newunicode(s)) i += 1 return space.newlist(l) else: # REG_BINARY and all other types return space.newbytes(rffi.charpsize2str(buf, buflen)) -@unwrap_spec(value_name="text", typ=int) +@unwrap_spec(value_name="unicode", typ=int) def SetValueEx(space, w_hkey, value_name, w_reserved, typ, w_value): """SetValueEx(key, value_name, reserved, type, value) - Stores data in the value field of an open registry key. @@ -422,7 +423,9 @@ the configuration registry. This helps the registry perform efficiently.""" hkey = hkey_w(w_hkey, space) buf, buflen = convert_to_regdata(space, w_value, typ) try: - ret = rwinreg.RegSetValueEx(hkey, value_name, 0, typ, buf, buflen) + with rffi.scoped_unicode2wcharp(value_name) as wide_vn: + c_vn = rffi.cast(rffi.CCHARP, wide_vn) + ret = rwinreg.RegSetValueEx(hkey, c_vn, 0, typ, buf, buflen) finally: lltype.free(buf, flavor='raw') if ret != 0: @@ -437,38 +440,40 @@ value_name is a string indicating the value to query""" if space.is_w(w_subkey, space.w_None): subkey = None else: - subkey = space.text_w(w_subkey) + subkey = space.unicode_w(w_subkey) null_dword = lltype.nullptr(rwin32.LPDWORD.TO) - with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retDataSize: - ret = rwinreg.RegQueryValueEx(hkey, subkey, null_dword, null_dword, - None, retDataSize) - bufSize = intmask(retDataSize[0]) - if ret == rwinreg.ERROR_MORE_DATA: - bufSize = 256 - elif ret != 0: - raiseWindowsError(space, ret, 'RegQueryValueEx') - - while True: - with lltype.scoped_alloc(rffi.CCHARP.TO, bufSize) as databuf: - with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retType: - - ret = rwinreg.RegQueryValueEx(hkey, subkey, null_dword, - retType, databuf, retDataSize) - if ret == rwinreg.ERROR_MORE_DATA: - # Resize and retry - bufSize *= 2 - retDataSize[0] = rffi.cast(rwin32.DWORD, bufSize) - continue - if ret != 0: - raiseWindowsError(space, ret, 'RegQueryValueEx') - length = intmask(retDataSize[0]) - return space.newtuple([ - convert_from_regdata(space, databuf, - length, retType[0]), - space.newint(intmask(retType[0])), + with rffi.scoped_unicode2wcharp(subkey) as wide_subkey: + c_subkey = rffi.cast(rffi.CCHARP, wide_subkey) + with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retDataSize: + ret = rwinreg.RegQueryValueEx(hkey, c_subkey, null_dword, null_dword, + None, retDataSize) + bufSize = intmask(retDataSize[0]) + if ret == rwinreg.ERROR_MORE_DATA: + bufSize = 256 + elif ret != 0: + raiseWindowsError(space, ret, 'RegQueryValueEx') + + while True: + with lltype.scoped_alloc(rffi.CCHARP.TO, bufSize) as databuf: + with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retType: + + ret = rwinreg.RegQueryValueEx(hkey, c_subkey, null_dword, + retType, databuf, retDataSize) + if ret == rwinreg.ERROR_MORE_DATA: + # Resize and retry + bufSize *= 2 + retDataSize[0] = rffi.cast(rwin32.DWORD, bufSize) + continue + if ret != 0: + raiseWindowsError(space, ret, 'RegQueryValueEx') + length = intmask(retDataSize[0]) + return space.newtuple([ + convert_from_regdata(space, databuf, + length, retType[0]), + space.newint(intmask(retType[0])), ]) -@unwrap_spec(subkey="text") +@unwrap_spec(subkey="unicode") def CreateKey(space, w_hkey, subkey): """key = CreateKey(key, sub_key) - Creates or opens the specified key. @@ -482,14 +487,16 @@ If the key already exists, this function opens the existing key The return value is the handle of the opened key. If the function fails, an exception is raised.""" hkey = hkey_w(w_hkey, space) - with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey: - ret = rwinreg.RegCreateKey(hkey, subkey, rethkey) - if ret != 0: - raiseWindowsError(space, ret, 'CreateKey') - return W_HKEY(space, rethkey[0]) + with rffi.scoped_unicode2wcharp(subkey) as wide_subkey: + c_subkey = rffi.cast(rffi.CCHARP, wide_subkey) + with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey: + ret = rwinreg.RegCreateKey(hkey, c_subkey, rethkey) + if ret != 0: + raiseWindowsError(space, ret, 'CreateKey') + return W_HKEY(space, rethkey[0]) -@unwrap_spec(sub_key="text", reserved=int, access=rffi.r_uint) -def CreateKeyEx(space, w_key, sub_key, reserved=0, access=rwinreg.KEY_WRITE): +@unwrap_spec(subkey="unicode", reserved=int, access=rffi.r_uint) +def CreateKeyEx(space, w_key, subkey, reserved=0, access=rwinreg.KEY_WRITE): """key = CreateKey(key, sub_key) - Creates or opens the specified key. key is an already open key, or one of the predefined HKEY_* constants @@ -502,17 +509,19 @@ If the key already exists, this function opens the existing key The return value is the handle of the opened key. If the function fails, an exception is raised.""" hkey = hkey_w(w_key, space) - with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey: - ret = rwinreg.RegCreateKeyEx(hkey, sub_key, reserved, None, 0, - access, None, rethkey, - lltype.nullptr(rwin32.LPDWORD.TO)) - if ret != 0: - raiseWindowsError(space, ret, 'CreateKeyEx') - return W_HKEY(space, rethkey[0]) + with rffi.scoped_unicode2wcharp(subkey) as wide_subkey: + c_subkey = rffi.cast(rffi.CCHARP, wide_subkey) + with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey: + ret = rwinreg.RegCreateKeyEx(hkey, c_subkey, reserved, None, 0, + access, None, rethkey, + lltype.nullptr(rwin32.LPDWORD.TO)) + if ret != 0: + raiseWindowsError(space, ret, 'CreateKeyEx') + return W_HKEY(space, rethkey[0]) -@unwrap_spec(subkey="text") +@unwrap_spec(subkey="unicode") def DeleteKey(space, w_hkey, subkey): - """DeleteKey(key, sub_key) - Deletes the specified key. + """DeleteKey(key, subkey) - Deletes the specified key. key is an already open key, or any one of the predefined HKEY_* constants. sub_key is a string that must be a subkey of the key identified by the key parameter. @@ -523,11 +532,13 @@ This method can not delete keys with subkeys. If the method succeeds, the entire key, including all of its values, is removed. If the method fails, an EnvironmentError exception is raised.""" hkey = hkey_w(w_hkey, space) - ret = rwinreg.RegDeleteKey(hkey, subkey) - if ret != 0: - raiseWindowsError(space, ret, 'RegDeleteKey') + with rffi.scoped_unicode2wcharp(subkey) as wide_subkey: + c_subkey = rffi.cast(rffi.CCHARP, wide_subkey) + ret = rwinreg.RegDeleteKey(hkey, c_subkey) + if ret != 0: + raiseWindowsError(space, ret, 'RegDeleteKey') -@unwrap_spec(subkey="text") +@unwrap_spec(subkey="unicode") def DeleteValue(space, w_hkey, subkey): """DeleteValue(key, value) - Removes a named value from a registry key. @@ -538,7 +549,7 @@ value is a string that identifies the value to remove.""" if ret != 0: raiseWindowsError(space, ret, 'RegDeleteValue') -@unwrap_spec(sub_key="text", reserved=int, access=rffi.r_uint) +@unwrap_spec(sub_key="unicode", reserved=int, access=rffi.r_uint) def OpenKey(space, w_key, sub_key, reserved=0, access=rwinreg.KEY_READ): """key = OpenKey(key, sub_key, res = 0, sam = KEY_READ) - Opens the specified key. @@ -551,11 +562,13 @@ sam is an integer that specifies an access mask that describes the desired The result is a new handle to the specified key If the function fails, an EnvironmentError exception is raised.""" hkey = hkey_w(w_key, space) - with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey: - ret = rwinreg.RegOpenKeyEx(hkey, sub_key, reserved, access, rethkey) - if ret != 0: - raiseWindowsError(space, ret, 'RegOpenKeyEx') - return W_HKEY(space, rethkey[0]) + with rffi.scoped_unicode2wcharp(sub_key) as wide_subkey: + c_subkey = rffi.cast(rffi.CCHARP, wide_subkey) + with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey: + ret = rwinreg.RegOpenKeyEx(hkey, c_subkey, reserved, access, rethkey) + if ret != 0: + raiseWindowsError(space, ret, 'RegOpenKeyEx') + return W_HKEY(space, rethkey[0]) @unwrap_spec(index=int) def EnumValue(space, w_hkey, index): @@ -614,7 +627,7 @@ data_type is an integer that identifies the type of the value data.""" length = intmask(retDataSize[0]) return space.newtuple([ - space.newtext(rffi.charp2str(valuebuf)), + space.newunicode(rffi.wcharp2unicode(valuebuf)), convert_from_regdata(space, databuf, length, retType[0]), space.newint(intmask(retType[0])), @@ -647,7 +660,7 @@ raised, indicating no more values are available.""" lltype.nullptr(rwin32.PFILETIME.TO)) if ret != 0: raiseWindowsError(space, ret, 'RegEnumKeyEx') - return space.newtext(rffi.charp2str(buf)) + return space.newunicode(rffi.wcharp2unicode(rffi.cast(CWCHARP, buf))) def QueryInfoKey(space, w_hkey): """tuple = QueryInfoKey(key) - Returns information about a key. @@ -726,7 +739,7 @@ def QueryReflectionKey(space, w_key): raise oefmt(space.w_NotImplementedError, "not implemented on this platform") -@unwrap_spec(sub_key="text", reserved=int, access=rffi.r_uint) +@unwrap_spec(sub_key="unicode", reserved=int, access=rffi.r_uint) def DeleteKeyEx(space, w_key, sub_key, reserved=0, access=rwinreg.KEY_WOW64_64KEY): """DeleteKeyEx(key, sub_key, sam, res) - Deletes the specified key. diff --git a/pypy/module/_winreg/test/test_winreg.py b/pypy/module/_winreg/test/test_winreg.py index 883dfd0f29..68ccc41d48 100644 --- a/pypy/module/_winreg/test/test_winreg.py +++ b/pypy/module/_winreg/test/test_winreg.py @@ -19,7 +19,7 @@ else: canSaveKey = len(ret) > 0 class AppTestHKey: - #spaceconfig = dict(usemodules=('_winreg',)) + spaceconfig = dict(usemodules=('_winreg',)) def test_repr(self): import winreg @@ -27,12 +27,12 @@ class AppTestHKey: assert str(k) == "" class AppTestFfi: - #spaceconfig = dict(usemodules=('_winreg',)) + spaceconfig = dict(usemodules=('_winreg',)) def setup_class(cls): - import _winreg + import _winreg as winreg space = cls.space - cls.root_key = _winreg.HKEY_CURRENT_USER + cls.root_key = winreg.HKEY_CURRENT_USER cls.test_key_name = "SOFTWARE\\Pypy Registry Test Key - Delete Me" cls.w_root_key = space.wrap(cls.root_key) cls.w_test_key_name = space.wrap(cls.test_key_name) @@ -40,22 +40,22 @@ class AppTestFfi: cls.w_tmpfilename = space.wrap(str(udir.join('winreg-temp'))) test_data = [ - ("Int Value", 0xFEDCBA98, _winreg.REG_DWORD), - ("Str Value", "A string Value", _winreg.REG_SZ), - ("Unicode Value", u"A unicode Value", _winreg.REG_SZ), - ("Str Expand", "The path is %path%", _winreg.REG_EXPAND_SZ), - ("Multi Str", ["Several", "string", u"values"], _winreg.REG_MULTI_SZ), + ("Int Value", 0xFEDCBA98, winreg.REG_DWORD), + ("Str Value", b"A string Value", winreg.REG_SZ), + ("Unicode Value", u"A unicode Value", winreg.REG_SZ), + ("Str Expand", u"The path is %path%", winreg.REG_EXPAND_SZ), + ("Multi Str", [b"Several", u"string", u"values"], winreg.REG_MULTI_SZ), ] cls.w_test_data = w_test_data = space.wrap(test_data) w_btest = space.newtuple([space.wrap("Raw data"), space.newbytes("binary\x00data"), - space.wrap(_winreg.REG_BINARY)]) + space.wrap(winreg.REG_BINARY)]) w_test_data.append(w_btest) def teardown_class(cls): - import winreg + import _winreg try: - winreg.DeleteKey(cls.root_key, cls.test_key_name) + _winreg.DeleteKey(cls.root_key, cls.test_key_name) except WindowsError: pass @@ -67,14 +67,14 @@ class AppTestFfi: def test_simple_write(self): from winreg import SetValue, QueryValue, REG_SZ - value = "Some Default value" + value = u"Some Default value" SetValue(self.root_key, self.test_key_name, REG_SZ, value) assert QueryValue(self.root_key, self.test_key_name) == value def test_CreateKey(self): from winreg import CreateKey, QueryInfoKey key = CreateKey(self.root_key, self.test_key_name) - sub_key = CreateKey(key, "sub_key") + sub_key = CreateKey(key, u"sub_key") nkeys, nvalues, since_mod = QueryInfoKey(key) assert nkeys == 1 @@ -86,7 +86,7 @@ class AppTestFfi: from winreg import CreateKeyEx, QueryInfoKey from winreg import KEY_ALL_ACCESS, KEY_READ key = CreateKeyEx(self.root_key, self.test_key_name, 0, KEY_ALL_ACCESS) - sub_key = CreateKeyEx(key, "sub_key", 0, KEY_READ) + sub_key = CreateKeyEx(key, u"sub_key", 0, KEY_READ) nkeys, nvalues, since_mod = QueryInfoKey(key) assert nkeys == 1 @@ -97,7 +97,7 @@ class AppTestFfi: def test_close(self): from winreg import OpenKey, CloseKey, FlushKey, QueryInfoKey key = OpenKey(self.root_key, self.test_key_name) - sub_key = OpenKey(key, "sub_key") + sub_key = OpenKey(key, u"sub_key") int_sub_key = int(sub_key) FlushKey(sub_key) @@ -119,7 +119,7 @@ class AppTestFfi: def test_with(self): from winreg import OpenKey with OpenKey(self.root_key, self.test_key_name) as key: - with OpenKey(key, "sub_key") as sub_key: + with OpenKey(key, u"sub_key") as sub_key: assert key.handle != 0 assert sub_key.handle != 0 assert key.handle == 0 @@ -142,7 +142,7 @@ class AppTestFfi: def test_SetValueEx(self): from winreg import CreateKey, SetValueEx, REG_BINARY, REG_DWORD key = CreateKey(self.root_key, self.test_key_name) - sub_key = CreateKey(key, "sub_key") + sub_key = CreateKey(key, u"sub_key") SetValueEx(sub_key, 'Int Value', 0, REG_DWORD, None) SetValueEx(sub_key, 'Int Value', 0, REG_DWORD, 45) for name, value, type in self.test_data: diff --git a/rpython/rlib/rwinreg.py b/rpython/rlib/rwinreg.py index 1dd5913d1b..bb216a51b6 100644 --- a/rpython/rlib/rwinreg.py +++ b/rpython/rlib/rwinreg.py @@ -47,7 +47,7 @@ def external(name, args, result, **kwds): HKEY = rwin32.HANDLE PHKEY = rffi.CArrayPtr(HKEY) REGSAM = rwin32.DWORD -suffix = 'A' +suffix = 'W' RegSetValue = external( 'RegSetValue' + suffix, -- GitLab From 95ec53bc17300eed2e106048d5f64a325d7a9843 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Tue, 2 Jan 2018 09:55:20 +0200 Subject: [PATCH 2/6] fix translation --HG-- branch : py3-winreg --- pypy/module/_winreg/interp_winreg.py | 48 +++++++++++++++++----------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py index 414b9f97d1..9bf06f5811 100644 --- a/pypy/module/_winreg/interp_winreg.py +++ b/pypy/module/_winreg/interp_winreg.py @@ -110,8 +110,8 @@ def hkey_w(w_hkey, space): elif isinstance(w_hkey, W_HKEY): return w_hkey.hkey elif space.isinstance_w(w_hkey, space.w_int): - return rffi.cast(rwinreg.HKEY, space.int_w(w_hkey)) - elif space.isinstance_w(w_hkey, space.w_long): + if space.is_true(space.lt(w_hkey, space.newint(0))): + return rffi.cast(rwinreg.HKEY, space.int_w(w_hkey)) return rffi.cast(rwinreg.HKEY, space.uint_w(w_hkey)) else: raise oefmt(space.w_TypeError, "The object is not a PyHKEY object") @@ -170,9 +170,13 @@ in fileName is relative to the remote computer. The docs imply key must be in the HKEY_USER or HKEY_LOCAL_MACHINE tree""" # XXX should filename use space.fsencode_w? hkey = hkey_w(w_hkey, space) - ret = rwinreg.RegLoadKey(hkey, subkey, filename) - if ret != 0: - raiseWindowsError(space, ret, 'RegLoadKey') + with rffi.scoped_unicode2wcharp(subkey) as wide_subkey: + c_subkey = rffi.cast(rffi.CCHARP, wide_subkey) + with rffi.scoped_unicode2wcharp(filename) as wide_filename: + c_filename = rffi.cast(rffi.CCHARP, wide_filename) + ret = rwinreg.RegLoadKey(hkey, c_subkey, c_filename) + if ret != 0: + raiseWindowsError(space, ret, 'RegLoadKey') @unwrap_spec(filename="unicode") def SaveKey(space, w_hkey, filename): @@ -189,9 +193,11 @@ file_name is relative to the remote computer. The caller of this method must possess the SeBackupPrivilege security privilege. This function passes NULL for security_attributes to the API.""" hkey = hkey_w(w_hkey, space) - ret = rwinreg.RegSaveKey(hkey, filename, None) - if ret != 0: - raiseWindowsError(space, ret, 'RegSaveKey') + with rffi.scoped_unicode2wcharp(filename) as wide_filename: + c_filename = rffi.cast(rffi.CCHARP, wide_filename) + ret = rwinreg.RegSaveKey(hkey, c_filename, None) + if ret != 0: + raiseWindowsError(space, ret, 'RegSaveKey') @unwrap_spec(typ=int, value="unicode") def SetValue(space, w_hkey, w_subkey, typ, value): @@ -267,6 +273,9 @@ But the underlying API call doesn't return the type, Lame Lame Lame, DONT USE TH return space.newunicode(rffi.wcharp2unicoden(wide_buf, length)) def convert_to_regdata(space, w_value, typ): + ''' + returns CCHARP, int + ''' buf = None if typ == rwinreg.REG_DWORD: @@ -320,7 +329,7 @@ def convert_to_regdata(space, w_value, typ): with rffi.scoped_unicode2wcharp(string) as wchr: c_str = rffi.cast(rffi.CCHARP, wchr) for i in range(len(string)): - buf[buflen + i] = wchr[i] + buf[buflen + i] = c_str[i] buflen += len(string) + 1 buf[buflen - 1] = '\0' buflen += 1 @@ -358,14 +367,14 @@ def convert_from_regdata(space, buf, buflen, typ): elif typ == rwinreg.REG_SZ or typ == rwinreg.REG_EXPAND_SZ: if not buflen: - s = "" + s = u"" else: # may or may not have a trailing NULL in the buffer. buf = rffi.cast(rffi.CWCHARP, buf) if buf[buflen - 1] == '\x00': buflen -= 1 s = rffi.wcharp2unicoden(buf, buflen) - w_s = space.newbytes(s) + w_s = space.newunicode(s) return w_s elif typ == rwinreg.REG_MULTI_SZ: @@ -380,7 +389,7 @@ def convert_from_regdata(space, buf, buflen, typ): i += 1 if len(s) == 0: break - s = ''.join(s) + s = u''.join(s) l.append(space.newunicode(s)) i += 1 return space.newlist(l) @@ -545,9 +554,11 @@ def DeleteValue(space, w_hkey, subkey): key is an already open key, or any one of the predefined HKEY_* constants. value is a string that identifies the value to remove.""" hkey = hkey_w(w_hkey, space) - ret = rwinreg.RegDeleteValue(hkey, subkey) - if ret != 0: - raiseWindowsError(space, ret, 'RegDeleteValue') + with rffi.scoped_unicode2wcharp(subkey) as wide_subkey: + c_subkey = rffi.cast(rffi.CCHARP, wide_subkey) + ret = rwinreg.RegDeleteValue(hkey, c_subkey) + if ret != 0: + raiseWindowsError(space, ret, 'RegDeleteValue') @unwrap_spec(sub_key="unicode", reserved=int, access=rffi.r_uint) def OpenKey(space, w_key, sub_key, reserved=0, access=rwinreg.KEY_READ): @@ -603,15 +614,16 @@ data_type is an integer that identifies the type of the value data.""" bufDataSize = intmask(retDataSize[0]) bufValueSize = intmask(retValueSize[0]) - with lltype.scoped_alloc(rffi.CCHARP.TO, + with lltype.scoped_alloc(rffi.CWCHARP.TO, intmask(retValueSize[0])) as valuebuf: while True: with lltype.scoped_alloc(rffi.CCHARP.TO, bufDataSize) as databuf: with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retType: + c_valuebuf = rffi.cast(rffi.CCHARP, valuebuf) ret = rwinreg.RegEnumValue( - hkey, index, valuebuf, retValueSize, + hkey, index, c_valuebuf, retValueSize, null_dword, retType, databuf, retDataSize) if ret == rwinreg.ERROR_MORE_DATA: # Resize and retry @@ -660,7 +672,7 @@ raised, indicating no more values are available.""" lltype.nullptr(rwin32.PFILETIME.TO)) if ret != 0: raiseWindowsError(space, ret, 'RegEnumKeyEx') - return space.newunicode(rffi.wcharp2unicode(rffi.cast(CWCHARP, buf))) + return space.newunicode(rffi.wcharp2unicode(rffi.cast(rffi.CWCHARP, buf))) def QueryInfoKey(space, w_hkey): """tuple = QueryInfoKey(key) - Returns information about a key. -- GitLab From 8ec1a726db57b76c53f3e1ec93ef4160e895cc44 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Tue, 2 Jan 2018 12:25:49 +0200 Subject: [PATCH 3/6] fixes, multibytes is two bytes, memoryview can be stored now --HG-- branch : py3-winreg --- pypy/module/_winreg/interp_winreg.py | 27 +++++++++++++++---------- pypy/module/_winreg/test/test_winreg.py | 24 +++++++++++++--------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py index 9bf06f5811..b0365c33ba 100644 --- a/pypy/module/_winreg/interp_winreg.py +++ b/pypy/module/_winreg/interp_winreg.py @@ -297,7 +297,7 @@ def convert_to_regdata(space, w_value, typ): else: buf = rffi.unicode2wcharp(space.unicode_w(w_value)) buf = rffi.cast(rffi.CCHARP, buf) - buflen = space.len_w(w_value) + 1 + buflen = (space.len_w(w_value) * 2) + 1 elif typ == rwinreg.REG_MULTI_SZ: if space.is_w(w_value, space.w_None): @@ -315,12 +315,12 @@ def convert_to_regdata(space, w_value, typ): w_item = space.next(w_iter) item = space.unicode_w(w_item) strings.append(item) - buflen += len(item) + 1 + buflen += 2 * (len(item) + 1) except OperationError as e: if not e.match(space, space.w_StopIteration): raise # re-raise other app-level exceptions break - buflen += 1 + buflen += 2 buf = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw') # Now copy data @@ -328,12 +328,14 @@ def convert_to_regdata(space, w_value, typ): for string in strings: with rffi.scoped_unicode2wcharp(string) as wchr: c_str = rffi.cast(rffi.CCHARP, wchr) - for i in range(len(string)): + for i in range(len(string) * 2): buf[buflen + i] = c_str[i] - buflen += len(string) + 1 + buflen += (len(string) + 1) * 2 buf[buflen - 1] = '\0' - buflen += 1 + buf[buflen - 2] = '\0' + buflen += 2 buf[buflen - 1] = '\0' + buf[buflen - 2] = '\0' else: # REG_BINARY and ALL unknown data types. if space.is_w(w_value, space.w_None): @@ -371,6 +373,7 @@ def convert_from_regdata(space, buf, buflen, typ): else: # may or may not have a trailing NULL in the buffer. buf = rffi.cast(rffi.CWCHARP, buf) + buflen /= 2 if buf[buflen - 1] == '\x00': buflen -= 1 s = rffi.wcharp2unicoden(buf, buflen) @@ -380,11 +383,13 @@ def convert_from_regdata(space, buf, buflen, typ): elif typ == rwinreg.REG_MULTI_SZ: if not buflen: return space.newlist([]) + buf = rffi.cast(rffi.CWCHARP, buf) + buflen /= 2 i = 0 l = [] while i < buflen and buf[i]: s = [] - while i < buflen and buf[i] != '\0': + while i < buflen and buf[i] != u'\0': s.append(buf[i]) i += 1 if len(s) == 0: @@ -504,8 +509,8 @@ If the function fails, an exception is raised.""" raiseWindowsError(space, ret, 'CreateKey') return W_HKEY(space, rethkey[0]) -@unwrap_spec(subkey="unicode", reserved=int, access=rffi.r_uint) -def CreateKeyEx(space, w_key, subkey, reserved=0, access=rwinreg.KEY_WRITE): +@unwrap_spec(sub_key="unicode", reserved=int, access=rffi.r_uint) +def CreateKeyEx(space, w_key, sub_key, reserved=0, access=rwinreg.KEY_WRITE): """key = CreateKey(key, sub_key) - Creates or opens the specified key. key is an already open key, or one of the predefined HKEY_* constants @@ -518,8 +523,8 @@ If the key already exists, this function opens the existing key The return value is the handle of the opened key. If the function fails, an exception is raised.""" hkey = hkey_w(w_key, space) - with rffi.scoped_unicode2wcharp(subkey) as wide_subkey: - c_subkey = rffi.cast(rffi.CCHARP, wide_subkey) + with rffi.scoped_unicode2wcharp(sub_key) as wide_sub_key: + c_subkey = rffi.cast(rffi.CCHARP, wide_sub_key) with lltype.scoped_alloc(rwinreg.PHKEY.TO, 1) as rethkey: ret = rwinreg.RegCreateKeyEx(hkey, c_subkey, reserved, None, 0, access, None, rethkey, diff --git a/pypy/module/_winreg/test/test_winreg.py b/pypy/module/_winreg/test/test_winreg.py index 68ccc41d48..22b3fa586f 100644 --- a/pypy/module/_winreg/test/test_winreg.py +++ b/pypy/module/_winreg/test/test_winreg.py @@ -42,8 +42,8 @@ class AppTestFfi: test_data = [ ("Int Value", 0xFEDCBA98, winreg.REG_DWORD), ("Str Value", b"A string Value", winreg.REG_SZ), - ("Unicode Value", u"A unicode Value", winreg.REG_SZ), - ("Str Expand", u"The path is %path%", winreg.REG_EXPAND_SZ), + ("Unicode Value", "A unicode Value", winreg.REG_SZ), + ("Str Expand", "The path is %path%", winreg.REG_EXPAND_SZ), ("Multi Str", [b"Several", u"string", u"values"], winreg.REG_MULTI_SZ), ] cls.w_test_data = w_test_data = space.wrap(test_data) @@ -140,6 +140,7 @@ class AppTestFfi: assert 0, "Did not raise" def test_SetValueEx(self): + # this test leaves open keys. If it fails, others will too from winreg import CreateKey, SetValueEx, REG_BINARY, REG_DWORD key = CreateKey(self.root_key, self.test_key_name) sub_key = CreateKey(key, u"sub_key") @@ -147,10 +148,9 @@ class AppTestFfi: SetValueEx(sub_key, 'Int Value', 0, REG_DWORD, 45) for name, value, type in self.test_data: SetValueEx(sub_key, name, 0, type, value) - exc = raises(TypeError, SetValueEx, sub_key, 'test_name', None, - REG_BINARY, memoryview('abc')) - assert str(exc.value) == ("Objects of type 'memoryview' can not " - "be used as binary registry values") + # cannot wrap a memoryview in setup_class for test_data + SetValueEx(sub_key, u'test_name', None, + REG_BINARY, memoryview(b'abc')) def test_readValues(self): from winreg import OpenKey, EnumValue, QueryValueEx, EnumKey @@ -163,27 +163,31 @@ class AppTestFfi: data = EnumValue(sub_key, index) except EnvironmentError as e: break - assert data in self.test_data + if data[0] != 'test_name': + # cannot wrap a memoryview in setup_class for test_data + assert data in self.test_data index = index + 1 - assert index == len(self.test_data) + assert index == len(self.test_data) + 1 for name, value, type in self.test_data: result = QueryValueEx(sub_key, name) assert result == (value, type) if type == REG_SZ or type == REG_EXPAND_SZ: - assert isinstance(result[0], unicode) # not string + assert not isinstance(result[0], bytes) assert EnumKey(key, 0) == "sub_key" raises(EnvironmentError, EnumKey, key, 1) def test_delete(self): # must be run after test_SetValueEx - from _winreg import OpenKey, KEY_ALL_ACCESS, DeleteValue, DeleteKey + from winreg import OpenKey, KEY_ALL_ACCESS, DeleteValue, DeleteKey key = OpenKey(self.root_key, self.test_key_name, 0, KEY_ALL_ACCESS) sub_key = OpenKey(key, "sub_key", 0, KEY_ALL_ACCESS) for name, value, type in self.test_data: DeleteValue(sub_key, name) + # cannot wrap a memoryview in setup_class for test_data + DeleteValue(sub_key, 'test_name') DeleteKey(key, "sub_key") -- GitLab From f7fd8f8cf4f573fea8bc2f1f47378523bb7615e6 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Tue, 2 Jan 2018 20:31:18 +0200 Subject: [PATCH 4/6] CPython does not accept None and we don't either --HG-- branch : py3-winreg --- pypy/module/_winreg/test/test_winreg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pypy/module/_winreg/test/test_winreg.py b/pypy/module/_winreg/test/test_winreg.py index 22b3fa586f..661c78281d 100644 --- a/pypy/module/_winreg/test/test_winreg.py +++ b/pypy/module/_winreg/test/test_winreg.py @@ -246,7 +246,7 @@ class AppTestFfi: skip("access denied to registry key " "(are you running in a non-interactive session?)") raise - QueryValueEx(HKEY_PERFORMANCE_DATA, None) + QueryValueEx(HKEY_PERFORMANCE_DATA, 'Global') def test_reflection_unsupported(self): import sys -- GitLab From b9c979ee319f92575e12537d8d4796de8c95d148 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Tue, 2 Jan 2018 20:47:51 +0200 Subject: [PATCH 5/6] fix WindowsError instantiation --HG-- branch : py3-winreg --- pypy/module/_winreg/interp_winreg.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py index b0365c33ba..e8cff2395e 100644 --- a/pypy/module/_winreg/interp_winreg.py +++ b/pypy/module/_winreg/interp_winreg.py @@ -9,9 +9,10 @@ from rpython.rlib.rarithmetic import r_uint, intmask def raiseWindowsError(space, errcode, context): message = rwin32.FormatError(errcode) + w_errcode = space.newint(errcode) raise OperationError(space.w_WindowsError, - space.newtuple([space.newint(errcode), - space.newtext(message)])) + space.newtuple([w_errcode, space.newtext(message), + space.w_None, w_errcode])) class W_HKEY(W_Root): def __init__(self, space, hkey): -- GitLab From 94aca6a0162bc102afea14428708c85981309333 Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Sun, 7 Jan 2018 00:14:44 +0200 Subject: [PATCH 6/6] fix FormatError -> FormatErrorW --HG-- branch : py3-winreg --- pypy/module/_winreg/interp_winreg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py index e8cff2395e..9f7c8beca2 100644 --- a/pypy/module/_winreg/interp_winreg.py +++ b/pypy/module/_winreg/interp_winreg.py @@ -8,10 +8,10 @@ from rpython.rlib import rwinreg, rwin32 from rpython.rlib.rarithmetic import r_uint, intmask def raiseWindowsError(space, errcode, context): - message = rwin32.FormatError(errcode) + message = rwin32.FormatErrorW(errcode) w_errcode = space.newint(errcode) raise OperationError(space.w_WindowsError, - space.newtuple([w_errcode, space.newtext(message), + space.newtuple([w_errcode, space.newunicode(message), space.w_None, w_errcode])) class W_HKEY(W_Root): -- GitLab