Author: Matti Picus <[email protected]>
Branch: py3.6
Changeset: r98042:d3664d4fd243
Date: 2019-11-12 22:34 -0500
http://bitbucket.org/pypy/pypy/changeset/d3664d4fd243/
Log: merge code_page-utf8: adds encoding, decoding codepages on win32
diff --git a/pypy/doc/whatsnew-pypy3-head.rst b/pypy/doc/whatsnew-pypy3-head.rst
--- a/pypy/doc/whatsnew-pypy3-head.rst
+++ b/pypy/doc/whatsnew-pypy3-head.rst
@@ -9,3 +9,11 @@
.. branch: py3.6-asyncgen
Fix asyncgen_hooks and refactor coroutine execution
+
+.. branch: py3.6-exc-info
+
+Follow CPython's use of exc_info more closely (issue 3096)
+
+.. branch: code_page-utf8
+
+Add encoding, decoding of codepages on windows
diff --git a/pypy/interpreter/unicodehelper.py
b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -61,11 +61,10 @@
state = space.fromcache(interp_codecs.CodecState)
errorhandler=state.decode_error_handler
if _WIN32:
+ import pypy.interpreter.unicodehelper_win32 as win32
bytes = space.bytes_w(w_string)
slen = len(bytes)
- uni, lgt = runicode.str_decode_mbcs(bytes, slen, 'strict', final=True,
- errorhandler=errorhandler, force_ignore=False)
- utf8 = uni.encode('utf-8')
+ utf8, _, lgt = str_decode_mbcs(bytes, 'strict', True, errorhandler)
elif 0 and _MACOSX:
bytes = space.bytes_w(w_string)
utf8, lgt, pos = str_decode_utf8(bytes, 'surrogateescape', True,
@@ -362,17 +361,31 @@
return result.build()
if _WIN32:
+ import pypy.interpreter.unicodehelper_win32 as win32
def utf8_encode_mbcs(s, errors, errorhandler, allow_surrogates=False):
- res = rutf8.utf8_encode_mbcs(s, errors, errorhandler,
- force_replace=False)
+ res = win32.utf8_encode_mbcs(s, errors, errorhandler)
return res
- def str_decode_mbcs(s, errors, final, errorhandler, force_ignore=True):
- slen = len(s)
- res, size = runicode.str_decode_mbcs(s, slen, errors, final=final,
- errorhandler=errorhandler,
force_ignore=force_ignore)
- res_utf8 = runicode.unicode_encode_utf_8(res, size, 'strict')
- return res_utf8, len(res), size
+ def str_decode_mbcs(s, errors, final, errorhandler):
+ res, size = win32.str_decode_mbcs(s, errors, errorhandler, final=final)
+ return res, len(res), size
+
+ def utf8_encode_oem(s, errors, errorhandler, allow_surrogates=False):
+ res = win32.utf8_encode_oem(s, errors, errorhandler)
+ return res
+
+ def str_decode_oem(s, errors, final, errorhandler):
+ res, size = win32.str_decode_oem(s, errors, errorhandler, final)
+ return res, len(res), size
+
+ def utf8_encode_code_page(cp, s, errors, errorhandler,
allow_surrogates=False):
+ res = win32.utf8_encode_code_page(cp, s, errors, errorhandler)
+ return res
+
+ def str_decode_code_page(cp, s, errors, final, errorhandler):
+ res, size = win32.str_decode_code_page(cp, s, errors, errorhandler,
final)
+ return res, len(res), size
+
def str_decode_utf8(s, errors, final, errorhandler, allow_surrogates=False):
try:
diff --git a/pypy/interpreter/unicodehelper_win32.py
b/pypy/interpreter/unicodehelper_win32.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/unicodehelper_win32.py
@@ -0,0 +1,210 @@
+from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib.runicode import (BOOLP, WideCharToMultiByte,
+ MultiByteToWideChar)
+from rpython.rlib.rutf8 import (Utf8StringIterator, next_codepoint_pos,
+ StringBuilder)
+from rpython.rlib import rwin32
+
+def Py_UNICODE_HIGH_SURROGATE(ch):
+ return rffi.cast(lltype.UniChar, 0xD800 - (0x10000 >> 10) + ((ch) >> 10))
+
+def Py_UNICODE_LOW_SURROGATE(ch):
+ return rffi.cast(lltype.UniChar, 0xDC00 + ((ch) & 0x3FF))
+
+if rffi.sizeof(rffi.INT) < rffi.sizeof(rffi.SIZE_T):
+ NEED_RETRY = True
+else:
+ NEED_RETRY = False
+WC_ERR_INVALID_CHARS = 0x0080
+
+code_page_map = {
+ rwin32.CP_ACP: "mbcs",
+ rwin32.CP_UTF7:"CP_UTF7",
+ rwin32.CP_UTF8:"CP_UTF8",
+ }
+
+def _code_page_name(code_page):
+ return code_page_map.get(code_page, "cp%d" % code_page)
+
+def _decode_code_page_flags(code_page):
+ if code_page == rwin32.CP_UTF7:
+ # The CP_UTF7 decoder only supports flags==0
+ return 0
+ return rwin32.MB_ERR_INVALID_CHARS
+
+def _encode_code_page_flags(code_page, errors):
+ if code_page == rwin32.CP_UTF8:
+ return WC_ERR_INVALID_CHARS
+ elif code_page == rwin32.CP_UTF7:
+ return 0
+ if errors == 'replace':
+ return 0
+ return rwin32.WC_NO_BEST_FIT_CHARS
+
+def _decode_cp_error(s, errorhandler, encoding, errors, start, end):
+ # late import to avoid circular import
+ from pypy.interpreter.unicodehelper import _str_decode_utf8_slowpath
+ if rwin32.GetLastError_saved() == rwin32.ERROR_NO_UNICODE_TRANSLATION:
+ msg = ("No mapping for the Unicode character exists in the target "
+ "multi-byte code page.")
+ r, ignore1, ignore2 = _str_decode_utf8_slowpath(s[start:end], errors,
False, errorhandler, False)
+ return r, end
+ else:
+ raise rwin32.lastSavedWindowsError()
+
+def _unibuf_to_utf8(uni, insize):
+ """Encode the widechar unicode buffer u to utf8
+ Should never error, since the buffer comes from a call to
+ MultiByteToWideChar
+ """
+ flags = 0
+ cp = rwin32.CP_UTF8
+ used_default_p = lltype.nullptr(BOOLP.TO)
+ assert uni is not None
+ with rffi.scoped_nonmoving_unicodebuffer(uni) as dataptr:
+ # first get the size of the result
+ outsize = WideCharToMultiByte(cp, flags, dataptr, insize,
+ None, 0, None, used_default_p)
+ if outsize == 0:
+ raise rwin32.lastSavedWindowsError()
+ with rffi.scoped_alloc_buffer(outsize) as buf:
+ # do the conversion
+ if WideCharToMultiByte(cp, flags, dataptr, insize, buf.raw,
+ outsize, None, used_default_p) == 0:
+ raise rwin32.lastSavedWindowsError()
+ result = buf.str(outsize)
+ assert result is not None
+ return result
+
+def _decode_helper(cp, s, flags, encoding, errors, errorhandler,
+ start, end, res):
+ if end > len(s):
+ end = len(s)
+ piece = s[start:end]
+ with rffi.scoped_nonmovingbuffer(piece) as dataptr:
+ # first get the size of the result
+ outsize = MultiByteToWideChar(cp, flags, dataptr, len(piece),
+ lltype.nullptr(rffi.CWCHARP.TO), 0)
+ if outsize == 0:
+ r, pos = _decode_cp_error(s, errorhandler,
+ encoding, errors, start, end)
+ res.append(r)
+ return pos
+
+ with rffi.scoped_alloc_unicodebuffer(outsize) as buf:
+ # do the conversion
+ if MultiByteToWideChar(cp, flags, dataptr, len(piece),
+ buf.raw, outsize) == 0:
+ r, pos = _decode_cp_error(s, errorhandler,
+ encoding, errors, start, end)
+ res.append(r)
+ return pos
+ else:
+ res.append(_unibuf_to_utf8(buf.str(outsize), outsize))
+ return end
+
+def str_decode_code_page(cp, s, errors, errorhandler, final=False):
+ """Decodes a byte string s from a code page cp with an error handler.
+ Returns utf8 result, original s length
+ """
+ insize = len(s)
+ if insize == 0:
+ return '', 0
+ flags = _decode_code_page_flags(cp)
+ encoding = _code_page_name(cp)
+ assert errorhandler is not None
+ res = StringBuilder(insize)
+ if errors == 'strict':
+ _decode_helper(cp, s, flags, encoding, errors, errorhandler,
+ 0, len(s), res)
+ else:
+ prev_pos = 0
+ pos = 0
+ while pos < len(s):
+ pos = next_codepoint_pos(s, prev_pos)
+ pos = _decode_helper(cp, s, flags, encoding,
+ errors, errorhandler, prev_pos, pos, res)
+ prev_pos = pos
+ return res.build(), insize
+
+def str_decode_mbcs(s, errors, errorhandler, final=False):
+ return str_decode_code_page(rwin32.CP_ACP, s, errors, errorhandler, final)
+
+def str_decode_oem(s, errors, errorhandler, final=False):
+ return str_decode_code_page(rwin32.CP_OEMCP, s, errors, errorhandler,
final)
+
+def utf8_encode_code_page(cp, s, errors, errorhandler):
+ """Encode a utf8 string s using code page cp and the given
+ errors/errorhandler.
+ Returns a encoded byte string
+ """
+
+ name = _code_page_name(cp)
+ lgt = len(s)
+
+ if lgt == 0:
+ return ''
+ flags = _encode_code_page_flags(cp, errors)
+ if cp in (rwin32.CP_UTF8, rwin32.CP_UTF7):
+ used_default_p = lltype.nullptr(BOOLP.TO)
+ else:
+ used_default_p = lltype.malloc(BOOLP.TO, 1, flavor='raw')
+ # Encode one codpoint at a time to allow the errorhandlers to do
+ # their thing
+ chars = lltype.malloc(rffi.CWCHARP.TO, 2, flavor = 'raw')
+ res = StringBuilder(lgt)
+ try:
+ pos = 0
+ for uni in Utf8StringIterator(s):
+ if used_default_p:
+ used_default_p[0] = rffi.cast(rwin32.BOOL, False)
+ if uni < 0x10000:
+ chars[0] = rffi.cast(lltype.UniChar, uni)
+ charsize = 1
+ else:
+ chars[0] = Py_UNICODE_HIGH_SURROGATE(uni)
+ chars[1] = Py_UNICODE_LOW_SURROGATE(uni)
+ charsize = 2
+ # first get the size of the result
+ outsize = WideCharToMultiByte(cp, flags, chars, charsize, None, 0,
+ None, used_default_p)
+
+ if outsize == 0:
+ if rwin32.GetLastError_saved() ==
rwin32.ERROR_NO_UNICODE_TRANSLATION:
+ r, pos, retype = errorhandler(errors, name,
+ "invalid character", s, pos, pos+1)
+ res.append(r)
+ continue
+ raise rwin32.lastSavedWindowsError()
+ # If we used a default char, then we failed!
+ if (used_default_p and rffi.cast(lltype.Bool, used_default_p[0])):
+ r, pos, retype = errorhandler(errors, name, "invalid
character", s, pos, pos+1)
+ res.append(r)
+ continue
+ with rffi.scoped_alloc_buffer(outsize) as buf:
+ # do the conversion
+ if WideCharToMultiByte(cp, flags,
+ chars, charsize, buf.raw, outsize,
+ None, used_default_p) == 0:
+ raise rwin32.lastSavedWindowsError()
+ if (used_default_p and
+ rffi.cast(lltype.Bool, used_default_p[0])):
+ r, pos, rettype = errorhandler(errors, name, "invalid
character",
+ s, pos, pos + 1)
+ res.append(r)
+ else:
+ result = buf.str(outsize)
+ assert result is not None
+ res.append(result)
+ pos += 1
+ return res.build()
+ finally:
+ lltype.free(chars, flavor='raw')
+ if used_default_p:
+ lltype.free(used_default_p, flavor='raw')
+
+def utf8_encode_mbcs(s, errors, errorhandler):
+ return utf8_encode_code_page(rwin32.CP_ACP, s, errors, errorhandler)
+
+def utf8_encode_oem(s, errors, errorhandler):
+ return utf8_encode_code_page(rwin32.CP_OEMCP, s, errors, errorhandler)
diff --git a/pypy/module/_codecs/interp_codecs.py
b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -3,7 +3,7 @@
from rpython.rlib.objectmodel import we_are_translated, not_rpython
from rpython.rlib.rstring import StringBuilder, UnicodeBuilder
from rpython.rlib.rutf8 import MAXUNICODE
-from rpython.rlib.runicode import raw_unicode_escape_helper
+from rpython.rlib import runicode
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
@@ -291,7 +291,7 @@
obj = w_obj._utf8
while pos < end:
code = rutf8.codepoint_at_pos(obj, pos)
- raw_unicode_escape_helper(builder, code)
+ unicodehelper.raw_unicode_escape_helper(builder, code)
pos = rutf8.next_codepoint_pos(obj, pos)
return space.newtuple([space.newtext(builder.build()), w_end])
elif space.isinstance_w(w_exc, space.w_UnicodeDecodeError):
@@ -303,7 +303,7 @@
pos = start
while pos < end:
oc = ord(obj[pos])
- raw_unicode_escape_helper(builder, oc)
+ unicodehelper.raw_unicode_escape_helper(builder, oc)
pos += 1
return space.newtuple([space.newtext(builder.build()), w_end])
else:
@@ -705,10 +705,43 @@
]:
make_decoder_wrapper(decoder)
-from rpython.rlib import runicode
-if hasattr(runicode, 'str_decode_mbcs'):
+if getattr(unicodehelper, '_WIN32', False):
make_encoder_wrapper('mbcs_encode')
make_decoder_wrapper('mbcs_decode')
+ make_encoder_wrapper('oem_encode')
+ make_decoder_wrapper('oem_decode')
+
+ # need to add the code_page argument
+
+ @unwrap_spec(code_page=int, errors='text_or_none')
+ def code_page_encode(space, code_page, w_arg, errors="strict"):
+ # w_arg is a W_Unicode or W_Bytes?
+ w_arg = space.convert_arg_to_w_unicode(w_arg, errors)
+ if errors is None:
+ errors = 'strict'
+ allow_surrogates = False
+ if errors in ('surrogatepass',):
+ allow_surrogates = True
+ state = space.fromcache(CodecState)
+ ulen = w_arg._length
+ result = unicodehelper.utf8_encode_code_page(code_page, w_arg._utf8,
+ errors, state.encode_error_handler,
+ allow_surrogates=allow_surrogates)
+ return space.newtuple([space.newbytes(result), space.newint(ulen)])
+
+ @unwrap_spec(code_page=int, string='bufferstr', errors='text_or_none',
+ w_final=WrappedDefault(False))
+ def code_page_decode(space, code_page, string, errors="strict",
w_final=None):
+ if errors is None:
+ errors = 'strict'
+ final = space.is_true(w_final)
+ state = space.fromcache(CodecState)
+ result, length, pos = unicodehelper.str_decode_code_page(code_page,
+ string, errors, final,
+ state.decode_error_handler)
+ # must return bytes, pos
+ return space.newtuple([space.newutf8(result, length),
space.newint(pos)])
+
# utf-8 functions are not regular, because we have to pass
# "allow_surrogates=False"
diff --git a/pypy/module/_codecs/moduledef.py b/pypy/module/_codecs/moduledef.py
--- a/pypy/module/_codecs/moduledef.py
+++ b/pypy/module/_codecs/moduledef.py
@@ -1,5 +1,6 @@
from pypy.interpreter.mixedmodule import MixedModule
from rpython.rlib.objectmodel import not_rpython
+from rpython.rlib import rwin32
from pypy.module._codecs import interp_codecs
class Module(MixedModule):
@@ -87,11 +88,14 @@
@not_rpython
def __init__(self, space, *args):
- # mbcs codec is Windows specific, and based on rffi.
- from rpython.rlib import runicode
- if (hasattr(runicode, 'str_decode_mbcs')):
+ # mbcs codec is Windows specific, and based on rffi system calls.
+ if rwin32.WIN32:
self.interpleveldefs['mbcs_encode'] = 'interp_codecs.mbcs_encode'
+ self.interpleveldefs['oem_encode'] = 'interp_codecs.oem_encode'
+ self.interpleveldefs['code_page_encode'] =
'interp_codecs.code_page_encode'
self.interpleveldefs['mbcs_decode'] = 'interp_codecs.mbcs_decode'
+ self.interpleveldefs['oem_decode'] = 'interp_codecs.oem_decode'
+ self.interpleveldefs['code_page_decode'] =
'interp_codecs.code_page_decode'
MixedModule.__init__(self, space, *args)
diff --git a/pypy/module/_codecs/test/test_codecs.py
b/pypy/module/_codecs/test/test_codecs.py
--- a/pypy/module/_codecs/test/test_codecs.py
+++ b/pypy/module/_codecs/test/test_codecs.py
@@ -1,4 +1,5 @@
import sys
+import pytest
class AppTestCodecs:
spaceconfig = {
@@ -432,6 +433,151 @@
assert((b'aaaa' + seq + b'bbbb').decode('utf-8', 'ignore') ==
'aaaa' + res + 'bbbb')
[email protected](sys.platform != 'win32', reason='win32-only')
+class AppTestCodePage:
+ spaceconfig = {
+ }
+
+ def test_code_pages(self):
+ import _codecs as codecs
+ def check_decode(cp, test):
+ raw, errors, expected = test
+ if expected is not None:
+ try:
+ decoded = codecs.code_page_decode(cp, raw, errors, True)
+ except UnicodeDecodeError as err:
+ assert False, ('Unable to decode %a from "cp%s" with '
+ 'errors=%r: %s' % (raw, cp, errors, err))
+ assert decoded[0] == expected, ('%a.decode("cp%s", %r)=%a !=
%a'
+ % (raw, cp, errors, decoded[0], expected))
+ assert decoded[1] >= 0
+ assert decoded[1] <= len(raw)
+ else:
+ raises(UnicodeDecodeError,
+ codecs.code_page_decode, cp, raw, errors, True)
+
+ def check_encode(cp, test):
+ text, errors, expected = test
+ if expected is not None:
+ try:
+ encoded = codecs.code_page_encode(cp, text, errors)
+ except UnicodeEncodeError as err:
+ assert False, ('Unable to encode %a to "cp%s" with '
+ 'errors=%r: %s' % (text, cp, errors, err))
+ assert encoded[0] == expected, ('%a.encode("cp%s", %r)=%a !=
%a'
+ % (text, cp, errors, encoded[0], expected))
+ assert encoded[1] == len(text)
+ else:
+ raises(UnicodeEncodeError,
+ codecs.code_page_encode, cp, text, errors)
+
+ for test in (
+ (u'abc', 'strict', b'abc'),
+ (u'\uff44\u9a3e', 'strict', b'\x82\x84\xe9\x80'),
+ # test error handlers
+ (u'\xff', 'strict', None),
+ (u'[\xff]', 'ignore', b'[]'),
+ (u'[\xff]', 'replace', b'[y]'),
+ (u'[\u20ac]', 'replace', b'[?]'),
+ (u'[\xff]', 'backslashreplace', b'[\\xff]'),
+ (u'[\xff]', 'namereplace',
+ b'[\\N{LATIN SMALL LETTER Y WITH DIAERESIS}]'),
+ (u'[\xff]', 'xmlcharrefreplace', b'[ÿ]'),
+ (u'\udcff', 'strict', None),
+ (u'[\udcff]', 'surrogateescape', b'[\xff]'),
+ (u'[\udcff]', 'surrogatepass', None),
+ ):
+ check_encode(932, test)
+
+ for test in (
+ (b'abc', 'strict', u'abc'),
+ (b'\x82\x84\xe9\x80', 'strict', u'\uff44\u9a3e'),
+ # invalid bytes
+ (b'[\xff]', 'strict', None),
+ (b'[\xff]', 'ignore', u'[]'),
+ (b'[\xff]', 'replace', u'[\ufffd]'),
+ (b'[\xff]', 'backslashreplace', u'[\\xff]'),
+ (b'[\xff]', 'surrogateescape', u'[\udcff]'),
+ (b'[\xff]', 'surrogatepass', None),
+ (b'\x81\x00abc', 'strict', None),
+ (b'\x81\x00abc', 'ignore', u'\x00abc'),
+ (b'\x81\x00abc', 'replace', u'\ufffd\x00abc'),
+ (b'\x81\x00abc', 'backslashreplace', u'\\x81\x00abc'),
+ ):
+ check_decode(932, test)
+
+ for test in (
+ (u'abc', 'strict', b'abc'),
+ (u'\xe9\u20ac', 'strict', b'\xe9\x80'),
+ (u'\xff', 'strict', b'\xff'),
+ # test error handlers
+ (u'\u0141', 'strict', None),
+ (u'\u0141', 'ignore', b''),
+ (u'\u0141', 'replace', b'L'),
+ (u'\udc98', 'surrogateescape', b'\x98'),
+ (u'\udc98', 'surrogatepass', None),
+ ):
+ check_encode(1252, test)
+
+ for test in (
+ (b'abc', 'strict', u'abc'),
+ (b'\xe9\x80', 'strict', u'\xe9\u20ac'),
+ (b'\xff', 'strict', u'\xff'),
+ ):
+ check_decode(1252, test)
+
+ def test_encode_65001(self):
+ tests = [
+ ('abc', 'strict', b'abc'),
+ ('\xe9\u20ac', 'strict', b'\xc3\xa9\xe2\x82\xac'),
+ ('\U0010ffff', 'strict', b'\xf4\x8f\xbf\xbf'),
+ ('\udc80', 'strict', None),
+ ('\udc80', 'ignore', b''),
+ ('\udc80', 'replace', b'?'),
+ ('\udc80', 'backslashreplace', b'\\udc80'),
+ ('\udc80', 'namereplace', b'\\udc80'),
+ ('\udc80', 'surrogatepass', b'\xed\xb2\x80'),
+ ]
+ for text, errors, expected in tests:
+ if expected is not None:
+ try:
+ encoded = text.encode('cp65001', errors)
+ except UnicodeEncodeError as err:
+ assert False, ('Unable to encode %a to cp65001 with '
+ 'errors=%r: %s' % (text, errors, err))
+ assert encoded ==expected, ('%a.encode("cp65001", %r)=%a != %a'
+ % (text, errors, encoded, expected))
+ else:
+ raises(UnicodeEncodeError, text.encode, "cp65001", errors)
+
+ def test_decode_65001(self):
+ tests = [
+ (b'abc', 'strict', 'abc'),
+ (b'\xc3\xa9\xe2\x82\xac', 'strict', '\xe9\u20ac'),
+ (b'\xf4\x8f\xbf\xbf', 'strict', '\U0010ffff'),
+ (b'\xef\xbf\xbd', 'strict', '\ufffd'),
+ (b'[\xc3\xa9]', 'strict', '[\xe9]'),
+ # invalid bytes
+ (b'[\xff]', 'strict', None),
+ (b'[\xff]', 'ignore', '[]'),
+ (b'[\xff]', 'replace', '[\ufffd]'),
+ (b'[\xff]', 'surrogateescape', '[\udcff]'),
+ (b'[\xed\xb2\x80]', 'strict', None),
+ (b'[\xed\xb2\x80]', 'ignore', '[]'),
+ (b'[\xed\xb2\x80]', 'replace', '[\ufffd\ufffd\ufffd]'),
+ ]
+ for raw, errors, expected in tests:
+ if expected is not None:
+ try:
+ decoded = raw.decode('cp65001', errors)
+ except UnicodeDecodeError as err:
+ assert False, ('Unable to decode %a from cp65001 with '
+ 'errors=%r: %s' % (raw, errors, err))
+ assert decoded == expected, ('%a.decode("cp65001", %r)=%a !=
%a'
+ % (raw, errors, decoded, expected))
+ else:
+ raises(UnicodeDecodeError, raw.decode, 'cp65001', errors)
+
class AppTestPartialEvaluation:
spaceconfig = dict(usemodules=['array',])
diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py
--- a/rpython/rlib/rwin32.py
+++ b/rpython/rlib/rwin32.py
@@ -114,6 +114,7 @@
WC_NO_BEST_FIT_CHARS STD_INPUT_HANDLE STD_OUTPUT_HANDLE
STD_ERROR_HANDLE HANDLE_FLAG_INHERIT FILE_TYPE_CHAR
LOAD_WITH_ALTERED_SEARCH_PATH
+ CP_ACP CP_UTF8 CP_UTF7 CP_OEMCP MB_ERR_INVALID_CHARS
"""
from rpython.translator.platform import host_factory
static_platform = host_factory()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit