[pypy-svn] r76181 - in pypy/branch/unicode_filename-2/pypy: module/posix rlib rlib/test rpython/module rpython/module/test
afa at codespeak.net
afa at codespeak.net
Tue Jul 13 15:28:45 CEST 2010
Author: afa
Date: Tue Jul 13 15:28:42 2010
New Revision: 76181
Modified:
pypy/branch/unicode_filename-2/pypy/module/posix/interp_posix.py
pypy/branch/unicode_filename-2/pypy/rlib/rposix.py
pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py
pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py
pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os_stat.py
pypy/branch/unicode_filename-2/pypy/rpython/module/test/test_ll_os_stat.py
Log:
Add unicode support to os.stat() and os.lstat()
Modified: pypy/branch/unicode_filename-2/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/module/posix/interp_posix.py (original)
+++ pypy/branch/unicode_filename-2/pypy/module/posix/interp_posix.py Tue Jul 13 15:28:42 2010
@@ -183,7 +183,7 @@
return build_stat_result(space, st)
fstat.unwrap_spec = [ObjSpace, "c_int"]
-def stat(space, path):
+def stat(space, w_path):
"""Perform a stat system call on the given path. Return an object
with (at least) the following attributes:
st_mode
@@ -199,22 +199,22 @@
"""
try:
- st = os.stat(path)
+ st = dispatch_filename(rposix.stat)(space, w_path)
except OSError, e:
- raise wrap_oserror(space, e, path)
+ raise wrap_oserror2(space, e, w_path)
else:
return build_stat_result(space, st)
-stat.unwrap_spec = [ObjSpace, 'path']
+stat.unwrap_spec = [ObjSpace, W_Root]
-def lstat(space, path):
+def lstat(space, w_path):
"Like stat(path), but do no follow symbolic links."
try:
- st = os.lstat(path)
+ st = dispatch_filename(rposix.lstat)(space, w_path)
except OSError, e:
- raise wrap_oserror(space, e, path)
+ raise wrap_oserror2(space, e, w_path)
else:
return build_stat_result(space, st)
-lstat.unwrap_spec = [ObjSpace, 'path']
+lstat.unwrap_spec = [ObjSpace, W_Root]
class StatState(object):
def __init__(self, space):
Modified: pypy/branch/unicode_filename-2/pypy/rlib/rposix.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rlib/rposix.py (original)
+++ pypy/branch/unicode_filename-2/pypy/rlib/rposix.py Tue Jul 13 15:28:42 2010
@@ -53,3 +53,17 @@
return os.open(path, flags, mode)
else:
return os.open(path.encode(), flags, mode)
+
+ at specialize.argtype(0)
+def stat(path):
+ if isinstance(path, str):
+ return os.stat(path)
+ else:
+ return os.stat(path.encode())
+
+ at specialize.argtype(0)
+def lstat(path):
+ if isinstance(path, str):
+ return os.lstat(path)
+ else:
+ return os.lstat(path.encode())
Modified: pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py (original)
+++ pypy/branch/unicode_filename-2/pypy/rlib/test/test_rposix.py Tue Jul 13 15:28:42 2010
@@ -7,13 +7,12 @@
return ''.join(s.chars)
class TestPosixUnicode:
- def test_access(self):
- ufilename = (unicode(udir.join('test_open')) +
+ def setup_class(cls):
+ cls.ufilename = (unicode(udir.join('test_open')) +
u'\u65e5\u672c.txt') # "Japan"
- f = file(ufilename, 'w')
+ f = file(cls.ufilename, 'w')
f.write("test")
f.close()
- filename = str(udir.join('test_open'))
class UnicodeWithEncoding:
def __init__(self, unistr):
@@ -27,11 +26,12 @@
def gettext(self):
return self.unistr
- path = UnicodeWithEncoding(ufilename)
+ cls.path = UnicodeWithEncoding(cls.ufilename)
+ def test_access(self):
def f():
try:
- fd = rposix.open(path, os.O_RDONLY, 0777)
+ fd = rposix.open(self.path, os.O_RDONLY, 0777)
try:
text = os.read(fd, 50)
return text
@@ -41,3 +41,9 @@
return ''
assert ll_to_string(interpret(f, [])) == "test"
+
+ def test_stat(self):
+ def f():
+ return rposix.stat(self.path).st_mtime
+
+ assert interpret(f, []) == os.stat(self.ufilename).st_mtime
Modified: pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py (original)
+++ pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os.py Tue Jul 13 15:28:42 2010
@@ -1485,17 +1485,27 @@
@registering(os.fstat)
def register_os_fstat(self):
from pypy.rpython.module import ll_os_stat
- ll_os_stat.register_stat_variant('fstat')
+ return ll_os_stat.register_stat_variant('fstat')
@registering(os.stat)
def register_os_stat(self):
from pypy.rpython.module import ll_os_stat
- ll_os_stat.register_stat_variant('stat')
+ return ll_os_stat.register_stat_variant('stat')
@registering(os.lstat)
def register_os_lstat(self):
from pypy.rpython.module import ll_os_stat
- ll_os_stat.register_stat_variant('lstat')
+ return ll_os_stat.register_stat_variant('lstat')
+
+ @registering_unicode_version(os.stat, 1, [0], sys.platform=='win32')
+ def register_os_stat_unicode(self):
+ from pypy.rpython.module import ll_os_stat
+ return ll_os_stat.register_stat_variant_unicode('stat')
+
+ @registering_unicode_version(os.lstat, 1, [0], sys.platform=='win32')
+ def register_os_lstat_unicode(self):
+ from pypy.rpython.module import ll_os_stat
+ return ll_os_stat.register_stat_variant_unicode('lstat')
# ------------------------------- os.W* ---------------------------------
Modified: pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os_stat.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os_stat.py (original)
+++ pypy/branch/unicode_filename-2/pypy/rpython/module/ll_os_stat.py Tue Jul 13 15:28:42 2010
@@ -7,11 +7,12 @@
from pypy.tool.pairtype import pairtype
from pypy.tool.sourcetools import func_with_new_name
from pypy.rpython import extregistry
-from pypy.rpython.extfunc import register_external
+from pypy.rpython.extfunc import register_external, extdef
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.tool import rffi_platform as platform
from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE
from pypy.rlib import rposix
+from pypy.rlib.objectmodel import specialize
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.rpython.annlowlevel import hlstr
@@ -271,8 +272,8 @@
[ARG1, STAT_STRUCT], rffi.INT,
compilation_info=compilation_info)
- register_external(
- getattr(os, name), [s_arg], s_StatResult,
+ return extdef(
+ [s_arg], s_StatResult,
"ll_os.ll_os_%s" % (name,),
llimpl=func_with_new_name(posix_stat_llimpl,
'os_%s_llimpl' % (name,)),
@@ -281,13 +282,24 @@
)
else:
# See Win32 implementation below
- register_external(
- getattr(os, name), [s_arg], s_StatResult,
+ return extdef(
+ [s_arg], s_StatResult,
"ll_os.ll_os_%s" % (name,),
llimpl=func_with_new_name(globals()['win32_%s_llimpl' % (name,)],
'os_%s_llimpl' % (name,)),
)
+def register_stat_variant_unicode(name):
+ assert name in ('stat', 'lstat')
+
+ # See Win32 implementation below
+ return extdef(
+ [unicode], s_StatResult,
+ "ll_os.ll_os_%s" % (name,),
+ llimpl=func_with_new_name(globals()['win32_wstat_llimpl'],
+ 'os_wstat_llimpl')
+ )
+
# ____________________________________________________________
if sys.platform == 'win32':
# The CRT of Windows has a number of flaws wrt. its stat() implementation:
@@ -344,7 +356,7 @@
('ftLastAccessTime', rwin32.FILETIME),
('ftLastWriteTime', rwin32.FILETIME)])
- WIN32_FIND_DATA = platform.Struct(
+ WIN32_FIND_DATAA = platform.Struct(
'WIN32_FIND_DATAA',
# Only interesting fields
[('dwFileAttributes', rwin32.DWORD),
@@ -353,17 +365,33 @@
('ftCreationTime', rwin32.FILETIME),
('ftLastAccessTime', rwin32.FILETIME),
('ftLastWriteTime', rwin32.FILETIME)])
+ WIN32_FIND_DATAW = platform.Struct(
+ 'WIN32_FIND_DATAW',
+ # Only interesting fields
+ [('dwFileAttributes', rwin32.DWORD),
+ ('nFileSizeHigh', rwin32.DWORD),
+ ('nFileSizeLow', rwin32.DWORD),
+ ('ftCreationTime', rwin32.FILETIME),
+ ('ftLastAccessTime', rwin32.FILETIME),
+ ('ftLastWriteTime', rwin32.FILETIME)])
globals().update(platform.configure(CConfig))
GET_FILEEX_INFO_LEVELS = rffi.ULONG # an enumeration
- GetFileAttributesEx = rffi.llexternal(
+ GetFileAttributesExA = rffi.llexternal(
'GetFileAttributesExA',
[rffi.CCHARP, GET_FILEEX_INFO_LEVELS,
lltype.Ptr(WIN32_FILE_ATTRIBUTE_DATA)],
rwin32.BOOL,
calling_conv='win')
+ GetFileAttributesExW = rffi.llexternal(
+ 'GetFileAttributesExW',
+ [rffi.CWCHARP, GET_FILEEX_INFO_LEVELS,
+ lltype.Ptr(WIN32_FILE_ATTRIBUTE_DATA)],
+ rwin32.BOOL,
+ calling_conv='win')
+
GetFileInformationByHandle = rffi.llexternal(
'GetFileInformationByHandle',
[rwin32.HANDLE, lltype.Ptr(BY_HANDLE_FILE_INFORMATION)],
@@ -376,9 +404,15 @@
rwin32.DWORD,
calling_conv='win')
- FindFirstFile = rffi.llexternal(
+ FindFirstFileA = rffi.llexternal(
'FindFirstFileA',
- [rffi.CCHARP, lltype.Ptr(WIN32_FIND_DATA)],
+ [rffi.CCHARP, lltype.Ptr(WIN32_FIND_DATAA)],
+ rwin32.HANDLE,
+ calling_conv='win')
+
+ FindFirstFileW = rffi.llexternal(
+ 'FindFirstFileW',
+ [rffi.CWCHARP, lltype.Ptr(WIN32_FIND_DATAW)],
rwin32.HANDLE,
calling_conv='win')
@@ -455,25 +489,37 @@
return make_stat_result(result)
+ @specialize.ll()
+ def findfirstfile(l_path):
+ if lltype.typeOf(l_path) == rffi.CWCHARP:
+ filedata = lltype.malloc(WIN32_FIND_DATAW, flavor='raw')
+ return FindFirstFileW(l_path, filedata), filedata
+ else:
+ filedata = lltype.malloc(WIN32_FIND_DATAA, flavor='raw')
+ return FindFirstFileA(l_path, filedata), filedata
+
+ @specialize.ll()
def attributes_from_dir(l_path, data):
- filedata = lltype.malloc(WIN32_FIND_DATA, flavor='raw')
- hFindFile = FindFirstFile(l_path, filedata)
- if hFindFile == rwin32.INVALID_HANDLE_VALUE:
- return 0
- FindClose(hFindFile)
- data.c_dwFileAttributes = filedata.c_dwFileAttributes
- rffi.structcopy(data.c_ftCreationTime, filedata.c_ftCreationTime)
- rffi.structcopy(data.c_ftLastAccessTime, filedata.c_ftLastAccessTime)
- rffi.structcopy(data.c_ftLastWriteTime, filedata.c_ftLastWriteTime)
- data.c_nFileSizeHigh = filedata.c_nFileSizeHigh
- data.c_nFileSizeLow = filedata.c_nFileSizeLow
- return 1
+ hFindFile, filedata = findfirstfile(l_path)
+ try:
+ if hFindFile == rwin32.INVALID_HANDLE_VALUE:
+ return 0
+ FindClose(hFindFile)
+ data.c_dwFileAttributes = filedata.c_dwFileAttributes
+ rffi.structcopy(data.c_ftCreationTime, filedata.c_ftCreationTime)
+ rffi.structcopy(data.c_ftLastAccessTime, filedata.c_ftLastAccessTime)
+ rffi.structcopy(data.c_ftLastWriteTime, filedata.c_ftLastWriteTime)
+ data.c_nFileSizeHigh = filedata.c_nFileSizeHigh
+ data.c_nFileSizeLow = filedata.c_nFileSizeLow
+ return 1
+ finally:
+ lltype.free(filedata, flavor='raw')
def win32_stat_llimpl(path):
data = lltype.malloc(WIN32_FILE_ATTRIBUTE_DATA, flavor='raw')
try:
l_path = rffi.str2charp(path)
- res = GetFileAttributesEx(l_path, GetFileExInfoStandard, data)
+ res = GetFileAttributesExA(l_path, GetFileExInfoStandard, data)
errcode = rwin32.GetLastError()
if res == 0:
if errcode == ERROR_SHARING_VIOLATION:
@@ -487,6 +533,23 @@
lltype.free(data, flavor='raw')
win32_lstat_llimpl = win32_stat_llimpl
+ def win32_wstat_llimpl(path):
+ data = lltype.malloc(WIN32_FILE_ATTRIBUTE_DATA, flavor='raw')
+ try:
+ l_path = rffi.unicode2wcharp(path)
+ res = GetFileAttributesExW(l_path, GetFileExInfoStandard, data)
+ errcode = rwin32.GetLastError()
+ if res == 0:
+ if errcode == ERROR_SHARING_VIOLATION:
+ res = attributes_from_dir(l_path, data)
+ errcode = rwin32.GetLastError()
+ rffi.free_wcharp(l_path)
+ if res == 0:
+ raise WindowsError(errcode, "os_stat failed")
+ return attribute_data_to_stat(data)
+ finally:
+ lltype.free(data, flavor='raw')
+
def win32_fstat_llimpl(fd):
handle = rwin32._get_osfhandle(fd)
Modified: pypy/branch/unicode_filename-2/pypy/rpython/module/test/test_ll_os_stat.py
==============================================================================
--- pypy/branch/unicode_filename-2/pypy/rpython/module/test/test_ll_os_stat.py (original)
+++ pypy/branch/unicode_filename-2/pypy/rpython/module/test/test_ll_os_stat.py Tue Jul 13 15:28:42 2010
@@ -9,8 +9,11 @@
def test_stat(self):
stat = ll_os_stat.win32_stat_llimpl
+ wstat = ll_os_stat.win32_wstat_llimpl
def check(f):
- assert stat(f).st_mtime == os.stat(f).st_mtime
+ expected = os.stat(f).st_mtime
+ assert stat(f).st_mtime == expected
+ assert wstat(unicode(f)).st_mtime == expected
check('c:/')
check('c:/temp')
More information about the Pypy-commit
mailing list