[pypy-commit] pypy py3k: rework the internal fsencode/decode to use the new 'locale' codec and have
pjenvey
noreply at buildbot.pypy.org
Fri Mar 1 02:56:32 CET 2013
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r61881:c4bbf219771f
Date: 2013-02-28 17:52 -0800
http://bitbucket.org/pypy/pypy/changeset/c4bbf219771f/
Log: rework the internal fsencode/decode to use the new 'locale' codec
and have import use it
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1397,6 +1397,11 @@
"""
return w_obj.identifier_w(self)
+ def fsencode_w(self, w_obj):
+ if self.isinstance_w(w_obj, self.w_unicode):
+ w_obj = self.fsencode(w_obj)
+ return self.bytes0_w(w_obj)
+
def bool_w(self, w_obj):
# Unwraps a bool, also accepting an int for compatibility.
# This is here mostly just for gateway.int_unwrapping_space_method().
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -135,6 +135,9 @@
def visit_str0(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)
+
def visit_nonnegint(self, el, app_sig):
self.checked_space_method(el, app_sig)
@@ -256,6 +259,9 @@
def visit_str0(self, typ):
self.run_args.append("space.str0_w(%s)" % (self.scopenext(),))
+ def visit_fsencode(self, typ):
+ self.run_args.append("space.fsencode_w(%s)" % (self.scopenext(),))
+
def visit_nonnegint(self, typ):
self.run_args.append("space.gateway_nonnegint_w(%s)" % (
self.scopenext(),))
@@ -396,6 +402,9 @@
def visit_str0(self, typ):
self.unwrap.append("space.str0_w(%s)" % (self.nextarg(),))
+ def visit_fsencode(self, typ):
+ self.unwrap.append("space.fsencode_w(%s)" % (self.nextarg(),))
+
def visit_nonnegint(self, typ):
self.unwrap.append("space.gateway_nonnegint_w(%s)" % (self.nextarg(),))
diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py
--- a/pypy/interpreter/test/test_gateway.py
+++ b/pypy/interpreter/test/test_gateway.py
@@ -385,6 +385,17 @@
w_app_g3_idx,
space.mul(space.wrap(sys.maxint), space.wrap(-7)))
+ def test_interp2app_unwrap_spec_fsencode(self):
+ space = self.space
+ w = space.wrap
+ def f(filename):
+ return space.wrapbytes(filename)
+ app_f = gateway.interp2app_temp(f, unwrap_spec=['fsencode'])
+ w_app_f = space.wrap(app_f)
+ assert space.eq_w(
+ space.call_function(w_app_f, w(u'\udc80')),
+ space.wrapbytes('\x80'))
+
def test_interp2app_unwrap_spec_typechecks(self):
space = self.space
w = space.wrap
diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -1,7 +1,15 @@
+import sys
from pypy.interpreter.error import OperationError
from rpython.rlib.objectmodel import specialize
from rpython.rlib import runicode
from pypy.module._codecs import interp_codecs
+_WIN32 = sys.platform == 'win32'
+_MACOSX = sys.platform == 'darwin'
+if _WIN32:
+ from rpython.rlib.runicode import str_decode_mbcs, unicode_encode_mbcs
+else:
+ # Workaround translator's confusion
+ str_decode_mbcs = unicode_encode_mbcs = lambda *args, **kwargs: None
@specialize.memo()
def decode_error_handler(space):
@@ -29,6 +37,60 @@
# ____________________________________________________________
+def PyUnicode_DecodeFSDefault(space, w_string):
+ state = space.fromcache(interp_codecs.CodecState)
+ if _WIN32:
+ bytes = space.bytes_w(w_string)
+ uni = str_decode_mbcs(bytes, len(bytes), 'strict',
+ errorhandler=decode_error_handler(space))[0]
+ elif _MACOSX:
+ bytes = space.bytes_w(w_string)
+ uni = runicode.str_decode_utf_8(
+ bytes, len(bytes), 'surrogateescape',
+ errorhandler=state.decode_error_handler)[0]
+ elif state.codec_need_encodings:
+ # bootstrap check: if the filesystem codec is implemented in
+ # Python we cannot use it before the codecs are ready. use the
+ # locale codec instead
+ from pypy.module._codecs.locale import (
+ unicode_decode_locale_surrogateescape)
+ bytes = space.bytes_w(w_string)
+ uni = unicode_decode_locale_surrogateescape(
+ bytes, errorhandler=encode_decode_handler(space))
+ else:
+ from pypy.module.sys.interp_encoding import getfilesystemencoding
+ return space.call_method(w_string, 'decode',
+ getfilesystemencoding(space),
+ space.wrap('surrogateescape'))
+ return space.wrap(uni)
+
+def PyUnicode_EncodeFSDefault(space, w_uni):
+ state = space.fromcache(interp_codecs.CodecState)
+ if _WIN32:
+ uni = space.unicode_w(w_uni)
+ bytes = unicode_encode_mbcs(uni, len(uni), 'strict',
+ errorhandler=encode_error_handler(space))
+ elif _MACOSX:
+ uni = space.unicode_w(w_uni)
+ bytes = runicode.unicode_encode_utf_8(
+ uni, len(uni), 'surrogateescape',
+ errorhandler=state.encode_error_handler)
+ elif state.codec_need_encodings:
+ # bootstrap check: if the filesystem codec is implemented in
+ # Python we cannot use it before the codecs are ready. use the
+ # locale codec instead
+ from pypy.module._codecs.locale import (
+ unicode_encode_locale_surrogateescape)
+ uni = space.unicode_w(w_uni)
+ bytes = unicode_encode_locale_surrogateescape(
+ uni, errorhandler=encode_error_handler(space))
+ else:
+ from pypy.module.sys.interp_encoding import getfilesystemencoding
+ return space.call_method(w_uni, 'encode',
+ getfilesystemencoding(space),
+ space.wrap('surrogateescape'))
+ return space.wrapbytes(bytes)
+
def PyUnicode_AsEncodedString(space, w_data, w_encoding):
return interp_codecs.encode(space, w_data, w_encoding)
diff --git a/pypy/module/_posixsubprocess/interp_subprocess.py b/pypy/module/_posixsubprocess/interp_subprocess.py
--- a/pypy/module/_posixsubprocess/interp_subprocess.py
+++ b/pypy/module/_posixsubprocess/interp_subprocess.py
@@ -1,5 +1,5 @@
from rpython.rtyper.lltypesystem import rffi, lltype, llmemory
-from pypy.module.posix.interp_posix import fsencode_w, run_fork_hooks
+from pypy.module.posix.interp_posix import run_fork_hooks
from pypy.interpreter.gateway import unwrap_spec
from pypy.interpreter.error import (
OperationError, exception_from_errno, wrap_oserror)
@@ -115,7 +115,7 @@
l_exec_array = rffi.liststr2charpp(exec_array)
if not space.is_none(w_process_args):
- argv = [fsencode_w(space, w_item)
+ argv = [space.fsencode_w(w_item)
for w_item in space.listview(w_process_args)]
l_argv = rffi.liststr2charpp(argv)
@@ -136,7 +136,7 @@
preexec.w_preexec_fn = None
if not space.is_none(w_cwd):
- cwd = fsencode_w(space, w_cwd)
+ cwd = space.fsencode_w(w_cwd)
l_cwd = rffi.str2charp(cwd)
run_fork_hooks('before', space)
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -12,7 +12,6 @@
make_typedescr, get_typedescr)
from pypy.module.cpyext.bytesobject import PyBytes_Check, PyBytes_FromObject
from pypy.module._codecs.interp_codecs import CodecState
-from pypy.module.posix.interp_posix import fsencode, fsdecode
from pypy.objspace.std import unicodeobject, unicodetype, stringtype
from rpython.rlib import runicode, rstring
from rpython.tool.sourcetools import func_renamer
@@ -423,7 +422,7 @@
w_output = w_obj
else:
w_obj = PyUnicode_FromObject(space, w_obj)
- w_output = fsencode(space, w_obj)
+ w_output = space.fsencode(w_obj)
if not space.isinstance_w(w_output, space.w_bytes):
raise OperationError(space.w_TypeError,
space.wrap("encoder failed to return bytes"))
@@ -447,7 +446,7 @@
w_output = w_obj
else:
w_obj = PyBytes_FromObject(space, w_obj)
- w_output = fsdecode(space, w_obj)
+ w_output = space.fsdecode(w_obj)
if not space.isinstance_w(w_output, space.w_unicode):
raise OperationError(space.w_TypeError,
space.wrap("decoder failed to return unicode"))
@@ -466,7 +465,7 @@
Use 'strict' error handler on Windows."""
w_bytes = space.wrapbytes(rffi.charpsize2str(s, size))
- return fsdecode(space, w_bytes)
+ return space.fsdecode(w_bytes)
@cpython_api([rffi.CCHARP], PyObject)
@@ -481,7 +480,7 @@
Use 'strict' error handler on Windows."""
w_bytes = space.wrapbytes(rffi.charp2str(s))
- return fsdecode(space, w_bytes)
+ return space.fsdecode(w_bytes)
@cpython_api([PyObject], PyObject)
@@ -494,7 +493,7 @@
If Py_FileSystemDefaultEncoding is not set, fall back to the
locale encoding.
"""
- return fsencode(space, w_unicode)
+ return space.fsencode(w_unicode)
@cpython_api([CONST_STRING], PyObject)
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -421,7 +421,7 @@
def __init__(self, space):
pass
- @unwrap_spec(path='str0')
+ @unwrap_spec(path='fsencode')
def descr_init(self, space, path):
if not path:
raise OperationError(space.w_ImportError, space.wrap(
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -57,7 +57,7 @@
return streamio.fdopen_as_stream(fd, filemode)
def find_module(space, w_name, w_path=None):
- name = space.str0_w(w_name)
+ name = space.fsencode_w(w_name)
if space.is_none(w_path):
w_path = None
@@ -68,7 +68,7 @@
space.w_ImportError,
"No module named %s", name)
- w_filename = space.wrap(find_info.filename)
+ w_filename = space.fsdecode(space.wrapbytes(find_info.filename))
stream = find_info.stream
if stream is not None:
@@ -107,7 +107,7 @@
def load_module(space, w_name, w_file, w_filename, w_info):
w_suffix, w_filemode, w_modtype = space.unpackiterable(w_info)
- filename = space.str0_w(w_filename)
+ filename = space.fsencode_w(w_filename)
filemode = space.str_w(w_filemode)
if space.is_w(w_file, space.w_None):
stream = None
@@ -124,7 +124,7 @@
space, w_name, find_info, reuse=True)
def load_source(space, w_modulename, w_filename, w_file=None):
- filename = space.str0_w(w_filename)
+ filename = space.fsencode_w(w_filename)
stream = get_file(space, w_file, filename, 'U')
@@ -138,7 +138,7 @@
stream.close()
return w_mod
- at unwrap_spec(filename='str0', write_paths=bool)
+ at unwrap_spec(filename='fsencode', write_paths=bool)
def _run_compiled_module(space, w_modulename, filename, w_file, w_module,
write_paths=True):
# the function 'imp._run_compiled_module' is a pypy-only extension
@@ -153,14 +153,14 @@
if space.is_none(w_file):
stream.close()
- at unwrap_spec(filename='str0')
+ at unwrap_spec(filename='fsencode')
def load_compiled(space, w_modulename, filename, w_file=None):
w_mod = space.wrap(Module(space, w_modulename))
importing._prepare_module(space, w_mod, filename, None)
_run_compiled_module(space, w_modulename, filename, w_file, w_mod)
return w_mod
- at unwrap_spec(filename=str)
+ at unwrap_spec(filename='fsencode')
def load_dynamic(space, w_modulename, filename, w_file=None):
if not space.config.objspace.usemodules.cpyext:
raise OperationError(space.w_ImportError, space.wrap(
@@ -215,7 +215,7 @@
if space.config.objspace.usemodules.thread:
importing.getimportlock(space).reinit_lock()
- at unwrap_spec(pathname='str0')
+ at unwrap_spec(pathname='fsencode')
def cache_from_source(space, pathname, w_debug_override=None):
"""cache_from_source(path, [debug_override]) -> path
Given the path to a .py file, return the path to its .pyc/.pyo file.
@@ -226,9 +226,10 @@
If debug_override is not None, then it must be a boolean and is taken as
the value of __debug__ instead."""
- return space.wrap(importing.make_compiled_pathname(pathname))
+ return space.fsdecode(space.wrapbytes(
+ importing.make_compiled_pathname(pathname)))
- at unwrap_spec(pathname='str0')
+ at unwrap_spec(pathname='fsencode')
def source_from_cache(space, pathname):
"""source_from_cache(path) -> path
Given the path to a .pyc./.pyo file, return the path to its .py file.
@@ -240,4 +241,4 @@
if sourcename is None:
raise operationerrfmt(space.w_ValueError,
"Not a PEP 3147 pyc path: %s", pathname)
- return space.wrap(sourcename)
+ return space.fsdecode(space.wrapbytes(sourcename))
diff --git a/pypy/module/imp/test/__init__.py b/pypy/module/imp/test/__init__.py
new file mode 100644
diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -1,8 +1,10 @@
+# coding: utf-8
import py
from pypy.interpreter.module import Module
from pypy.interpreter import gateway
from pypy.interpreter.error import OperationError
from pypy.interpreter.pycode import PyCode
+from pypy.module.imp.test.support import BaseImportTest
from rpython.tool.udir import udir
from rpython.rlib import streamio
from pypy.tool.option import make_config
@@ -31,7 +33,8 @@
f.close()
return p
-def setup_directory_structure(space):
+def setup_directory_structure(cls):
+ space = cls.space
root = setuppkg("",
a = "imamodule = 1\ninpackage = 0",
ambig = "imamodule = 1",
@@ -90,11 +93,40 @@
'a=5\nb=6\rc="""hello\r\nworld"""\r', mode='wb')
p.join('mod.py').write(
'a=15\nb=16\rc="""foo\r\nbar"""\r', mode='wb')
- setuppkg("encoded",
+ p = setuppkg("encoded",
# actually a line 2, setuppkg() sets up a line1
line2 = "# encoding: iso-8859-1\n",
bad = "# encoding: uft-8\n")
+ fsenc = sys.getfilesystemencoding()
+ # covers utf-8 and Windows ANSI code pages one non-space symbol from
+ # every page (http://en.wikipedia.org/wiki/Code_page)
+ known_locales = {
+ 'utf-8' : b'\xc3\xa4',
+ 'cp1250' : b'\x8C',
+ 'cp1251' : b'\xc0',
+ 'cp1252' : b'\xc0',
+ 'cp1253' : b'\xc1',
+ 'cp1254' : b'\xc0',
+ 'cp1255' : b'\xe0',
+ 'cp1256' : b'\xe0',
+ 'cp1257' : b'\xc0',
+ 'cp1258' : b'\xc0',
+ }
+
+ if sys.platform == 'darwin':
+ # Mac OS X uses the Normal Form D decomposition
+ # http://developer.apple.com/mac/library/qa/qa2001/qa1173.html
+ special_char = b'a\xcc\x88'
+ else:
+ special_char = known_locales.get(fsenc)
+
+ if special_char:
+ p.join(special_char + '.py').write('pass')
+ cls.w_special_char = space.wrap(special_char.decode(fsenc))
+ else:
+ cls.w_special_char = space.w_None
+
# create compiled/x.py and a corresponding pyc file
p = setuppkg("compiled", x = "x = 84")
if conftest.option.runappdirect:
@@ -132,8 +164,9 @@
return str(root)
-def _setup(space):
- dn = setup_directory_structure(space)
+def _setup(cls):
+ space = cls.space
+ dn = setup_directory_structure(cls)
return space.appexec([space.wrap(dn)], """
(dn):
import sys
@@ -153,14 +186,15 @@
""")
-class AppTestImport:
+class AppTestImport(BaseImportTest):
spaceconfig = {
"usemodules": ['rctime'],
}
def setup_class(cls):
+ BaseImportTest.setup_class.im_func(cls)
cls.w_runappdirect = cls.space.wrap(conftest.option.runappdirect)
- cls.w_saved_modules = _setup(cls.space)
+ cls.w_saved_modules = _setup(cls)
#XXX Compile class
def teardown_class(cls):
@@ -681,6 +715,30 @@
import encoded
raises(SyntaxError, imp.find_module, 'bad', encoded.__path__)
+ def test_find_module_fsdecode(self):
+ import sys
+ name = self.special_char
+ if not name:
+ skip("can't run this test with %s as filesystem encoding"
+ % sys.getfilesystemencoding())
+ import imp
+ import encoded
+ f, filename, _ = imp.find_module(name, encoded.__path__)
+ assert f is not None
+ assert filename[:-3].endswith(name)
+
+ def test_unencodable(self):
+ if not self.testfn_unencodable:
+ skip("need an unencodable filename")
+ import imp
+ import os
+ name = self.testfn_unencodable
+ os.mkdir(name)
+ try:
+ raises(ImportError, imp.NullImporter, name)
+ finally:
+ os.rmdir(name)
+
class TestAbi:
def test_abi_tag(self):
@@ -1316,7 +1374,7 @@
def setup_class(cls):
usepycfiles = cls.spaceconfig['objspace.usepycfiles']
cls.w_usepycfiles = cls.space.wrap(usepycfiles)
- cls.saved_modules = _setup(cls.space)
+ cls.saved_modules = _setup(cls)
def teardown_class(cls):
_teardown(cls.space, cls.saved_modules)
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -10,7 +10,6 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rtyper.tool import rffi_platform
from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from pypy.module.sys.interp_encoding import getfilesystemencoding
import os, sys
@@ -36,30 +35,13 @@
raise OperationError(space.w_OverflowError,
space.wrap("integer out of range"))
-def fsencode_w(space, w_obj):
- if space.isinstance_w(w_obj, space.w_unicode):
- w_obj = fsencode(space, w_obj)
- return space.bytes0_w(w_obj)
-
-def fsencode(space, w_obj):
- w_bytes = space.call_method(w_obj, 'encode',
- getfilesystemencoding(space),
- space.wrap('surrogateescape'))
- return w_bytes
-
-def fsdecode(space, w_obj):
- w_unicode = space.call_method(w_obj, 'decode',
- getfilesystemencoding(space),
- space.wrap('surrogateescape'))
- return w_unicode
-
class FileEncoder(object):
def __init__(self, space, w_obj):
self.space = space
self.w_obj = w_obj
def as_bytes(self):
- return fsencode_w(self.space, self.w_obj)
+ return self.space.fsencode_w(self.w_obj)
def as_unicode(self):
return self.space.unicode0_w(self.w_obj)
@@ -74,7 +56,7 @@
def as_unicode(self):
space = self.space
- w_unicode = fsdecode(space, self.w_obj)
+ w_unicode = space.fsdecode(self.w_obj)
return space.unicode0_w(w_unicode)
@specialize.memo()
@@ -443,7 +425,7 @@
else:
def getcwd(space):
"""Return the current working directory as a string."""
- return fsdecode(space, getcwdb(space))
+ return space.fsdecode(getcwdb(space))
def chdir(space, w_path):
"""Change the current working directory to the specified path."""
@@ -557,7 +539,7 @@
result_w = [None] * len_result
for i in range(len_result):
w_bytes = space.wrapbytes(result[i])
- result_w[i] = fsdecode(space, w_bytes)
+ result_w[i] = space.fsdecode(w_bytes)
else:
dirname = space.str0_w(w_dirname)
result = rposix.listdir(dirname)
@@ -783,13 +765,13 @@
args: iterable of arguments
env: dictionary of strings mapping to strings
"""
- command = fsencode_w(space, w_command)
+ command = space.fsencode_w(w_command)
try:
args_w = space.unpackiterable(w_args)
if len(args_w) < 1:
w_msg = space.wrap("execv() must have at least one argument")
raise OperationError(space.w_ValueError, w_msg)
- args = [fsencode_w(space, w_arg) for w_arg in args_w]
+ args = [space.fsencode_w(w_arg) for w_arg in args_w]
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
diff --git a/pypy/module/zipimport/interp_zipimport.py b/pypy/module/zipimport/interp_zipimport.py
--- a/pypy/module/zipimport/interp_zipimport.py
+++ b/pypy/module/zipimport/interp_zipimport.py
@@ -351,7 +351,7 @@
space = self.space
return space.wrap(self.filename)
- at unwrap_spec(name='str0')
+ at unwrap_spec(name='fsencode')
def descr_new_zipimporter(space, w_type, name):
ok = False
parts_ends = [i for i in range(0, len(name))
diff --git a/pypy/module/zipimport/test/test_zipimport.py b/pypy/module/zipimport/test/test_zipimport.py
--- a/pypy/module/zipimport/test/test_zipimport.py
+++ b/pypy/module/zipimport/test/test_zipimport.py
@@ -2,13 +2,14 @@
import time
import struct
from pypy.module.imp.importing import get_pyc_magic, _w_long
+from pypy.module.imp.test.support import BaseImportTest
from StringIO import StringIO
from rpython.tool.udir import udir
from zipfile import ZIP_STORED, ZIP_DEFLATED
-class AppTestZipimport:
+class AppTestZipimport(BaseImportTest):
""" A bit structurized tests stolen and adapted from
cpy's regression tests
"""
@@ -40,6 +41,7 @@
@classmethod
def make_class(cls):
+ BaseImportTest.setup_class.im_func(cls)
source = """\
def get_name():
return __name__
@@ -358,6 +360,24 @@
co_filename = code.co_filename
assert co_filename == expected
+ def test_unencodable(self):
+ if not self.testfn_unencodable:
+ skip("need an unencodable filename")
+ import os
+ import time
+ import zipimport
+ from zipfile import ZipFile, ZipInfo
+ filename = self.testfn_unencodable + ".zip"
+ z = ZipFile(filename, "w")
+ zinfo = ZipInfo("uu.py", time.localtime(self.now))
+ zinfo.compress_type = self.compression
+ z.writestr(zinfo, '')
+ z.close()
+ try:
+ zipimport.zipimporter(filename)
+ finally:
+ os.remove(filename)
+
class AppTestZipimportDeflated(AppTestZipimport):
compression = ZIP_DEFLATED
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -497,6 +497,14 @@
"'%s' does not support the buffer interface", typename)
return space.get_and_call_function(w_impl, w_obj)
+ def fsencode(space, w_obj):
+ from pypy.interpreter.unicodehelper import PyUnicode_EncodeFSDefault
+ return PyUnicode_EncodeFSDefault(space, w_obj)
+
+ def fsdecode(space, w_obj):
+ from pypy.interpreter.unicodehelper import PyUnicode_DecodeFSDefault
+ return PyUnicode_DecodeFSDefault(space, w_obj)
+
# helpers
More information about the pypy-commit
mailing list