[pypy-commit] pypy default: Support for the Python3 version of os.stat()
arigo
pypy.commits at gmail.com
Sun Jun 11 17:22:41 EDT 2017
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r91577:6f7b1081c651
Date: 2017-06-11 23:11 +0200
http://bitbucket.org/pypy/pypy/changeset/6f7b1081c651/
Log: Support for the Python3 version of os.stat()
diff --git a/rpython/rlib/rposix_stat.py b/rpython/rlib/rposix_stat.py
--- a/rpython/rlib/rposix_stat.py
+++ b/rpython/rlib/rposix_stat.py
@@ -600,6 +600,28 @@
path = traits.as_str0(path)
return win32_xstat(traits, path, traverse=False)
+ at specialize.argtype(0)
+def stat3(path):
+ # On Windows, the algorithm behind os.stat() changed a lot between
+ # Python 2 and Python 3. This is the Python 3 version.
+ if not _WIN32:
+ return stat(path)
+ else:
+ traits = _preferred_traits(path)
+ path = traits.as_str0(path)
+ return win32_xstat3(traits, path, traverse=True)
+
+ at specialize.argtype(0)
+def lstat3(path):
+ # On Windows, the algorithm behind os.lstat() changed a lot between
+ # Python 2 and Python 3. This is the Python 3 version.
+ if not _WIN32:
+ return lstat(path)
+ else:
+ traits = _preferred_traits(path)
+ path = traits.as_str0(path)
+ return win32_xstat3(traits, path, traverse=False)
+
if rposix.HAVE_FSTATAT:
from rpython.rlib.rposix import AT_FDCWD, AT_SYMLINK_NOFOLLOW
c_fstatat = rffi.llexternal('fstatat64' if _LINUX else 'fstatat',
@@ -658,6 +680,45 @@
return win32_attribute_data_to_stat(win32traits, data)
@specialize.arg(0)
+ def win32_xstat3(traits, path, traverse=False):
+ # This is the Python3 version of os.stat() or lstat().
+ # XXX 'traverse' is ignored, and everything related to
+ # the "reparse points" is missing
+ win32traits = make_win32_traits(traits)
+
+ hFile = win32traits.CreateFile(path,
+ win32traits.FILE_READ_ATTRIBUTES,
+ 0,
+ lltype.nullptr(rwin32.LPSECURITY_ATTRIBUTES.TO),
+ win32traits.OPEN_EXISTING,
+ win32traits.FILE_ATTRIBUTE_NORMAL |
+ win32traits.FILE_FLAG_BACKUP_SEMANTICS |
+ 0, # win32traits.FILE_FLAG_OPEN_REPARSE_POINT,
+ rwin32.NULL_HANDLE)
+
+ if hFile == rwin32.INVALID_HANDLE_VALUE:
+ errcode = rwin32.GetLastError_saved()
+ if (errcode != win32traits.ERROR_ACCESS_DENIED and
+ errcode != win32traits.ERROR_SHARING_VIOLATION):
+ raise WindowsError(errcode, "os_stat failed")
+
+ with lltype.scoped_alloc(
+ win32traits.WIN32_FILE_ATTRIBUTE_DATA) as data:
+ if win32_attributes_from_dir(win32traits, path, data) == 0:
+ raise WindowsError(rwin32.GetLastError_saved(),
+ "win32_attributes_from_dir failed")
+ return win32_attribute_data_to_stat(win32traits, data)
+
+ with lltype.scoped_alloc(
+ win32traits.BY_HANDLE_FILE_INFORMATION) as data:
+ res = rwin32.GetFileInformationByHandle(hFile, data)
+ errcode = rwin32.GetLastError_saved()
+ win32.CloseHandle(hFile)
+ if res == 0:
+ raise WindowsError(errcode, "GetFileInformationByHandle failed")
+ return win32_by_handle_info_to_stat(win32traits, data)
+
+ @specialize.arg(0)
def win32_attributes_to_mode(win32traits, attributes):
m = 0
attributes = intmask(attributes)
@@ -697,10 +758,11 @@
# specific to fstat()
st_ino = make_longlong(info.c_nFileIndexHigh, info.c_nFileIndexLow)
+ st_dev = info.c_dwVolumeSerialNumber
st_nlink = info.c_nNumberOfLinks
result = (st_mode,
- st_ino, 0, st_nlink, 0, 0,
+ st_ino, st_dev, st_nlink, 0, 0,
st_size,
atime, mtime, ctime,
extra_atime, extra_mtime, extra_ctime)
@@ -724,4 +786,3 @@
return 1
finally:
lltype.free(filedata, flavor='raw')
-
diff --git a/rpython/rlib/rwin32file.py b/rpython/rlib/rwin32file.py
--- a/rpython/rlib/rwin32file.py
+++ b/rpython/rlib/rwin32file.py
@@ -46,6 +46,8 @@
'INVALID_FILE_ATTRIBUTES')
ERROR_SHARING_VIOLATION = platform.ConstantInteger(
'ERROR_SHARING_VIOLATION')
+ ERROR_ACCESS_DENIED = platform.ConstantInteger(
+ 'ERROR_ACCESS_DENIED')
MOVEFILE_REPLACE_EXISTING = platform.ConstantInteger(
'MOVEFILE_REPLACE_EXISTING')
_S_IFDIR = platform.ConstantInteger('_S_IFDIR')
@@ -56,10 +58,14 @@
FILE_TYPE_CHAR = platform.ConstantInteger('FILE_TYPE_CHAR')
FILE_TYPE_PIPE = platform.ConstantInteger('FILE_TYPE_PIPE')
+ FILE_READ_ATTRIBUTES = platform.ConstantInteger(
+ 'FILE_READ_ATTRIBUTES')
FILE_WRITE_ATTRIBUTES = platform.ConstantInteger(
'FILE_WRITE_ATTRIBUTES')
OPEN_EXISTING = platform.ConstantInteger(
'OPEN_EXISTING')
+ FILE_ATTRIBUTE_NORMAL = platform.ConstantInteger(
+ 'FILE_ATTRIBUTE_NORMAL')
FILE_FLAG_BACKUP_SEMANTICS = platform.ConstantInteger(
'FILE_FLAG_BACKUP_SEMANTICS')
VOLUME_NAME_DOS = platform.ConstantInteger('VOLUME_NAME_DOS')
@@ -103,10 +109,12 @@
INVALID_FILE_ATTRIBUTES
_S_IFDIR _S_IFREG _S_IFCHR _S_IFIFO
FILE_TYPE_UNKNOWN FILE_TYPE_CHAR FILE_TYPE_PIPE
+ FILE_READ_ATTRIBUTES
FILE_WRITE_ATTRIBUTES OPEN_EXISTING FILE_FLAG_BACKUP_SEMANTICS
VOLUME_NAME_DOS VOLUME_NAME_NT
ERROR_FILE_NOT_FOUND ERROR_NO_MORE_FILES
ERROR_SHARING_VIOLATION MOVEFILE_REPLACE_EXISTING
+ ERROR_ACCESS_DENIED
'''.split():
locals()[name] = config[name]
LPWIN32_FIND_DATA = lltype.Ptr(WIN32_FIND_DATA)
diff --git a/rpython/rlib/test/test_rposix_stat.py b/rpython/rlib/test/test_rposix_stat.py
--- a/rpython/rlib/test/test_rposix_stat.py
+++ b/rpython/rlib/test/test_rposix_stat.py
@@ -68,6 +68,16 @@
py.test.skip("the underlying os.fstatvfs() failed: %s" % e)
rposix_stat.fstatvfs(0)
+ @py.test.mark.skipif(sys.platform != 'win32', reason='win32 test')
+ def test_stat3_ino_dev(self):
+ st = rposix.stat2('C:\\')
+ assert st.st_dev == st.st_ino == 0
+ st = rposix.stat3('C:\\')
+ assert st.st_dev != 0 and st.st_ino != 0
+ st2 = rposix.lstat3('C:\\')
+ assert (st2.st_dev, st2.st_ino) == (st.st_dev, st.st_ino)
+
+
@py.test.mark.skipif("not hasattr(rposix_stat, 'fstatat')")
def test_fstatat(tmpdir):
tmpdir.join('file').write('text')
More information about the pypy-commit
mailing list