Author: Amaury Forgeot d'Arc <[email protected]>
Branch: more-rposix
Changeset: r74390:8d7118f6770e
Date: 2014-11-07 22:36 +0100
http://bitbucket.org/pypy/pypy/changeset/8d7118f6770e/
Log: os.listdir()
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -144,7 +144,7 @@
else:
includes = ['unistd.h', 'sys/types.h',
'utime.h', 'sys/time.h', 'sys/times.h',
- 'grp.h']
+ 'grp.h', 'dirent.h']
libraries = ['util']
eci = ExternalCompilationInfo(
includes=includes,
@@ -284,14 +284,6 @@
return os.rename(_as_bytes(path1), _as_bytes(path2))
@specialize.argtype(0)
-def listdir(dirname):
- return os.listdir(_as_bytes(dirname))
-
[email protected](0)
-def access(path, mode):
- return os.access(_as_bytes(path), mode)
-
[email protected](0)
def chmod(path, mode):
return os.chmod(_as_bytes(path), mode)
@@ -526,6 +518,92 @@
lltype.free(buf, flavor='raw')
return result
+if not _WIN32:
+ class CConfig:
+ _compilation_info_ = eci
+ DIRENT = rffi_platform.Struct('struct dirent',
+ [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1))])
+
+ DIRP = rffi.COpaquePtr('DIR')
+ config = rffi_platform.configure(CConfig)
+ DIRENT = config['DIRENT']
+ DIRENTP = lltype.Ptr(DIRENT)
+ c_opendir = external('opendir', [rffi.CCHARP], DIRP)
+ # XXX macro=True is hack to make sure we get the correct kind of
+ # dirent struct (which depends on defines)
+ c_readdir = external('readdir', [DIRP], DIRENTP, macro=True)
+ c_closedir = external('closedir', [DIRP], rffi.INT)
+
+@replace_os_function('listdir')
[email protected](0)
+def listdir(path):
+ if not _WIN32:
+ path = _as_bytes0(path)
+ dirp = c_opendir(path)
+ if not dirp:
+ raise OSError(get_errno(), "opendir failed")
+ result = []
+ while True:
+ set_errno(0)
+ direntp = c_readdir(dirp)
+ if not direntp:
+ error = get_errno()
+ break
+ namep = rffi.cast(rffi.CCHARP, direntp.c_d_name)
+ name = rffi.charp2str(namep)
+ if name != '.' and name != '..':
+ result.append(name)
+ c_closedir(dirp)
+ if error:
+ raise OSError(error, "readdir failed")
+ return result
+ else: # _WIN32 case
+ from rpython.rlib.rwin32file import make_win32_traits
+ traits = _preferred_traits(path)
+ win32traits = make_win32_traits(traits)
+ path = traits.as_str0(path)
+
+ if traits.str is unicode:
+ if path and path[-1] not in (u'/', u'\\', u':'):
+ path += u'/'
+ mask = path + u'*.*'
+ else:
+ if path and path[-1] not in ('/', '\\', ':'):
+ path += '/'
+ mask = path + '*.*'
+
+ filedata = lltype.malloc(win32traits.WIN32_FIND_DATA, flavor='raw')
+ try:
+ result = []
+ hFindFile = win32traits.FindFirstFile(mask, filedata)
+ if hFindFile == rwin32.INVALID_HANDLE_VALUE:
+ error = rwin32.GetLastError()
+ if error == win32traits.ERROR_FILE_NOT_FOUND:
+ return result
+ else:
+ raise WindowsError(error, "FindFirstFile failed")
+ while True:
+ name = traits.charp2str(rffi.cast(traits.CCHARP,
+ filedata.c_cFileName))
+ if traits.str is unicode:
+ if not (name == u"." or name == u".."):
+ result.append(name)
+ else:
+ if not (name == "." or name == ".."):
+ result.append(name)
+ if not win32traits.FindNextFile(hFindFile, filedata):
+ break
+ # FindNextFile sets error to ERROR_NO_MORE_FILES if
+ # it got to the end of the directory
+ error = rwin32.GetLastError()
+ win32traits.FindClose(hFindFile)
+ if error == win32traits.ERROR_NO_MORE_FILES:
+ return result
+ else:
+ raise WindowsError(error, "FindNextFile failed")
+ finally:
+ lltype.free(filedata, flavor='raw')
+
#___________________________________________________________________
c_execv = external('execv', [rffi.CCHARP, rffi.CCHARPP], rffi.INT)
diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py
--- a/rpython/rtyper/module/ll_os.py
+++ b/rpython/rtyper/module/ll_os.py
@@ -173,61 +173,6 @@
separate_module_sources = ["\n".join(defs)]
))
- @registering_str_unicode(os.listdir)
- def register_os_listdir(self, traits):
- # we need a different approach on Windows and on Posix
- if sys.platform.startswith('win'):
- from rpython.rtyper.module.ll_win32file import make_listdir_impl
- os_listdir_llimpl = make_listdir_impl(traits)
- else:
- assert traits.str is str
- compilation_info = ExternalCompilationInfo(
- includes = ['sys/types.h', 'dirent.h']
- )
- class CConfig:
- _compilation_info_ = compilation_info
- DIRENT = platform.Struct('struct dirent',
- [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1))])
-
- DIRP = rffi.COpaquePtr('DIR')
- config = platform.configure(CConfig)
- DIRENT = config['DIRENT']
- DIRENTP = lltype.Ptr(DIRENT)
- os_opendir = self.llexternal('opendir', [rffi.CCHARP], DIRP,
- compilation_info=compilation_info)
- # XXX macro=True is hack to make sure we get the correct kind of
- # dirent struct (which depends on defines)
- os_readdir = self.llexternal('readdir', [DIRP], DIRENTP,
- compilation_info=compilation_info,
- macro=True)
- os_closedir = self.llexternal('closedir', [DIRP], rffi.INT,
- compilation_info=compilation_info)
-
- def os_listdir_llimpl(path):
- dirp = os_opendir(path)
- if not dirp:
- raise OSError(rposix.get_errno(), "os_opendir failed")
- result = []
- while True:
- rposix.set_errno(0)
- direntp = os_readdir(dirp)
- if not direntp:
- error = rposix.get_errno()
- break
- namep = rffi.cast(rffi.CCHARP, direntp.c_d_name)
- name = rffi.charp2str(namep)
- if name != '.' and name != '..':
- result.append(name)
- os_closedir(dirp)
- if error:
- raise OSError(error, "os_readdir failed")
- return result
-
- return extdef([traits.str0], # a single argument which is a str
- [traits.str0], # returns a list of strings
- traits.ll_os_name('listdir'),
- llimpl=os_listdir_llimpl)
-
@registering(os.pipe)
def register_os_pipe(self):
# we need a different approach on Windows and on Posix
diff --git a/rpython/rtyper/module/ll_win32file.py
b/rpython/rtyper/module/ll_win32file.py
--- a/rpython/rtyper/module/ll_win32file.py
+++ b/rpython/rtyper/module/ll_win32file.py
@@ -12,65 +12,6 @@
#_______________________________________________________________
-# listdir
-
-def make_listdir_impl(traits):
- from rpython.rlib import rwin32
- from rpython.rlib.rwin32file import make_win32_traits
-
- win32traits = make_win32_traits(traits)
-
- if traits.str is unicode:
- def make_listdir_mask(path):
- if path and path[-1] not in (u'/', u'\\', u':'):
- path += u'/'
- return path + u'*.*'
-
- def skip_listdir(name):
- return name == u"." or name == u".."
- else:
- def make_listdir_mask(path):
- if path and path[-1] not in ('/', '\\', ':'):
- path += '/'
- return path + '*.*'
-
- def skip_listdir(name):
- return name == "." or name == ".."
-
- @func_renamer('listdir_llimpl_%s' % traits.str.__name__)
- def listdir_llimpl(path):
- mask = make_listdir_mask(path)
- filedata = lltype.malloc(win32traits.WIN32_FIND_DATA, flavor='raw')
- try:
- result = []
- hFindFile = win32traits.FindFirstFile(mask, filedata)
- if hFindFile == rwin32.INVALID_HANDLE_VALUE:
- error = rwin32.GetLastError()
- if error == win32traits.ERROR_FILE_NOT_FOUND:
- return result
- else:
- raise WindowsError(error, "FindFirstFile failed")
- while True:
- name = traits.charp2str(rffi.cast(traits.CCHARP,
- filedata.c_cFileName))
- if not skip_listdir(name):
- result.append(name)
- if not win32traits.FindNextFile(hFindFile, filedata):
- break
- # FindNextFile sets error to ERROR_NO_MORE_FILES if
- # it got to the end of the directory
- error = rwin32.GetLastError()
- win32traits.FindClose(hFindFile)
- if error == win32traits.ERROR_NO_MORE_FILES:
- return result
- else:
- raise WindowsError(error, "FindNextFile failed")
- finally:
- lltype.free(filedata, flavor='raw')
-
- return listdir_llimpl
-
-#_______________________________________________________________
# chdir
def make_chdir_impl(traits):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit