Author: Armin Rigo <ar...@tunes.org> Branch: py3.5 Changeset: r86397:9629ba2a4200 Date: 2016-08-22 10:27 +0200 http://bitbucket.org/pypy/pypy/changeset/9629ba2a4200/
Log: hg merge py3k 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 @@ -838,8 +838,7 @@ raise wrap_oserror(space, e) -@unwrap_spec(w_path=WrappedDefault(u".")) -def listdir(space, w_path): +def listdir(space, w_path=None): """listdir(path='.') -> list_of_filenames Return a list containing the names of the files in the directory. @@ -852,6 +851,8 @@ On some platforms, path may also be specified as an open file descriptor; the file descriptor must refer to a directory. If this functionality is unavailable, using it raises NotImplementedError.""" + if space.is_none(w_path): + w_path = space.newunicode(u".") if space.isinstance_w(w_path, space.w_bytes): dirname = space.str0_w(w_path) try: @@ -869,9 +870,9 @@ "listdir: illegal type for path argument") fd = unwrap_fd(space, w_path, "string, bytes or integer") try: - result = rposix.fdlistdir(fd) + result = rposix.fdlistdir(os.dup(fd)) except OSError as e: - raise wrap_oserror2(space, e, w_path) + raise wrap_oserror(space, e) else: dirname = FileEncoder(space, w_path) try: diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -313,7 +313,7 @@ def test_listdir_default(self): posix = self.posix - assert posix.listdir() == posix.listdir('.') + assert posix.listdir() == posix.listdir('.') == posix.listdir(None) def test_listdir_bytes(self): import sys @@ -325,6 +325,17 @@ expected = b'caf%E9' if sys.platform == 'darwin' else b'caf\xe9' assert expected in result + def test_fdlistdir(self): + posix = self.posix + dirfd = posix.open('.', posix.O_RDONLY) + lst1 = posix.listdir(dirfd) # does not close dirfd + lst2 = posix.listdir('.') + assert lst1 == lst2 + # + lst3 = posix.listdir(dirfd) # rewinddir() was used + assert lst3 == lst1 + posix.close(dirfd) + def test_undecodable_filename(self): import sys posix = self.posix diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -620,15 +620,18 @@ [rffi.CCHARP], DIRP, save_err=rffi.RFFI_SAVE_ERRNO) c_fdopendir = external('fdopendir', [rffi.INT], DIRP, save_err=rffi.RFFI_SAVE_ERRNO) + c_rewinddir = external('rewinddir', + [DIRP], lltype.Void, releasegil=False) # 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, save_err=rffi.RFFI_FULL_ERRNO_ZERO) c_closedir = external('closedir', [DIRP], rffi.INT, releasegil=False) + c_dirfd = external('dirfd', [DIRP], rffi.INT, releasegil=False) else: dirent_config = {} -def _listdir(dirp): +def _listdir(dirp, rewind=False): result = [] while True: direntp = c_readdir(dirp) @@ -639,6 +642,8 @@ name = rffi.charp2str(namep) if name != '.' and name != '..': result.append(name) + if rewind: + c_rewinddir(dirp) c_closedir(dirp) if error: raise OSError(error, "readdir failed") @@ -649,12 +654,16 @@ Like listdir(), except that the directory is specified as an open file descriptor. - Note: fdlistdir() closes the file descriptor. + Note: fdlistdir() closes the file descriptor. To emulate the + Python 3.x 'os.opendir(dirfd)', you must first duplicate the + file descriptor. """ dirp = c_fdopendir(dirfd) if not dirp: - raise OSError(get_saved_errno(), "opendir failed") - return _listdir(dirp) + error = get_saved_errno() + c_close(dirfd) + raise OSError(error, "opendir failed") + return _listdir(dirp, rewind=True) @replace_os_function('listdir') @specialize.argtype(0) @@ -1791,12 +1800,7 @@ # Support for f... and ...at families of POSIX functions class CConfig: - _compilation_info_ = ExternalCompilationInfo( - includes=['sys/stat.h', - 'sys/time.h', - 'unistd.h', - 'fcntl.h'], - ) + _compilation_info_ = eci for _name in """faccessat fchdir fchmod fchmodat fchown fchownat fexecve fdopendir fpathconf fstat fstatat fstatvfs ftruncate futimens futimes futimesat linkat chflags lchflags lchmod lchown diff --git a/rpython/rlib/rposix_scandir.py b/rpython/rlib/rposix_scandir.py --- a/rpython/rlib/rposix_scandir.py +++ b/rpython/rlib/rposix_scandir.py @@ -1,6 +1,6 @@ from rpython.rlib import rposix from rpython.rlib.objectmodel import specialize -from rpython.rtyper.lltypesystem import rffi +from rpython.rtyper.lltypesystem import lltype, rffi @specialize.argtype(0) @@ -17,21 +17,22 @@ def closedir(dirp): rposix.c_closedir(dirp) +NULL_DIRP = lltype.nullptr(rposix.DIRENT) + def nextentry(dirp): """Read the next entry and returns an opaque object. Use the methods has_xxx() and get_xxx() to read from that opaque object. The opaque object is valid until the next time nextentry() or closedir() is called. This may raise - StopIteration, or OSError. Note that this doesn't filter - out the "." and ".." entries. + OSError, or return a NULL pointer when exhausted. Note + that this doesn't filter out the "." and ".." entries. """ direntp = rposix.c_readdir(dirp) if direntp: - return direntp - error = rposix.get_saved_errno() - if error: - raise OSError(error, "readdir failed") - raise StopIteration + error = rposix.get_saved_errno() + if error: + raise OSError(error, "readdir failed") + return direntp def has_name_bytes(direntp): return True @@ -40,20 +41,12 @@ namep = rffi.cast(rffi.CCHARP, direntp.c_d_name) return rffi.charp2str(namep) -DT_UNKNOWN = rposix.dirent_config.get('DT_UNKNOWN', None) -DT_REG = rposix.dirent_config.get('DT_REG', None) -DT_DIR = rposix.dirent_config.get('DT_DIR', None) -DT_LNK = rposix.dirent_config.get('DT_LNK', None) +DT_UNKNOWN = rposix.dirent_config.get('DT_UNKNOWN', 0) +DT_REG = rposix.dirent_config.get('DT_REG', 255) +DT_DIR = rposix.dirent_config.get('DT_DIR', 255) +DT_LNK = rposix.dirent_config.get('DT_LNK', 255) -def has_type(direntp): - return (DT_UNKNOWN is not None and - rffi.getintfield(direntp, 'c_d_type') != DT_UNKNOWN) - -def type_is_regular(direntp): - return rffi.getintfield(direntp, 'c_d_type') == DT_REG - -def type_is_dir(direntp): - return rffi.getintfield(direntp, 'c_d_type') == DT_DIR - -def type_is_link(direntp): - return rffi.getintfield(direntp, 'c_d_type') == DT_LNK +def get_known_type(direntp): + if rposix.HAVE_D_TYPE: + return rffi.getintfield(direntp, 'c_d_type') + return DT_UNKNOWN diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py --- a/rpython/rlib/test/test_rposix.py +++ b/rpython/rlib/test/test_rposix.py @@ -552,6 +552,14 @@ # Note: fdlistdir() always closes dirfd assert result == ['file'] +@rposix_requires('fdlistdir') +def test_fdlistdir_rewinddir(tmpdir): + tmpdir.join('file').write('text') + dirfd = os.open(str(tmpdir), os.O_RDONLY) + result1 = rposix.fdlistdir(os.dup(dirfd)) + result2 = rposix.fdlistdir(dirfd) + assert result1 == result2 == ['file'] + @rposix_requires('symlinkat') def test_symlinkat(tmpdir): tmpdir.join('file').write('text') diff --git a/rpython/rlib/test/test_rposix_scandir.py b/rpython/rlib/test/test_rposix_scandir.py --- a/rpython/rlib/test/test_rposix_scandir.py +++ b/rpython/rlib/test/test_rposix_scandir.py @@ -10,9 +10,8 @@ scan = rposix_scandir.opendir('/') found = [] while True: - try: - p = rposix_scandir.nextentry(scan) - except StopIteration: + p = rposix_scandir.nextentry(scan) + if not p: break assert rposix_scandir.has_name_bytes(p) found.append(rposix_scandir.get_name_bytes(p)) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit