Index: Doc/library/os.rst =================================================================== --- Doc/library/os.rst (revision 73251) +++ Doc/library/os.rst (working copy) @@ -378,7 +378,10 @@ is slightly deceptive; on Unix platforms, sockets and pipes are also referenced by file descriptors. +For these functions, the file descriptor can either be an integer, or an object +with a fileno() method which returns the actual file descriptor. + .. function:: close(fd) Close file descriptor *fd*. Availability: Unix, Windows. @@ -493,7 +496,6 @@ Return ``True`` if the file descriptor *fd* is open and connected to a tty(-like) device, else ``False``. Availability: Unix. - .. function:: lseek(fd, pos, how) Set the current position of file descriptor *fd* to position *pos*, modified @@ -502,7 +504,6 @@ current position; :const:`os.SEEK_END` or ``2`` to set it relative to the end of the file. Availability: Unix, Windows. - .. function:: open(file, flags[, mode]) Open the file *file* and set various flags according to *flags* and possibly @@ -558,7 +559,6 @@ Return the process group associated with the terminal given by *fd* (an open file descriptor as returned by :func:`os.open`). Availability: Unix. - .. function:: tcsetpgrp(fd, pg) Set the process group associated with the terminal given by *fd* (an open file Index: Lib/test/test_posix.py =================================================================== --- Lib/test/test_posix.py (revision 73251) +++ Lib/test/test_posix.py (working copy) @@ -49,6 +49,7 @@ fp = open(support.TESTFN) try: self.assert_(posix.fstatvfs(fp.fileno())) + self.assert_(posix.fstatvfs(fp)) finally: fp.close() @@ -62,7 +63,15 @@ posix.ftruncate(fp.fileno(), 0) finally: fp.close() + fp = open(support.TESTFN, 'w+') + try: + fp.write('test') + fp.flush() + posix.ftruncate(fp, 0) + finally: + fp.close() + def test_dup(self): if hasattr(posix, 'dup'): fp = open(support.TESTFN) @@ -72,7 +81,15 @@ os.close(fd) finally: fp.close() + fp = open(support.TESTFN) + try: + fd = posix.dup(fp) + self.assert_(isinstance(fd, int)) + os.close(fd) + finally: + fp.close() + def test_confstr(self): if hasattr(posix, 'confstr'): self.assertRaises(ValueError, posix.confstr, "CS_garbage") @@ -124,6 +141,7 @@ fp = open(support.TESTFN) try: self.assert_(posix.fstat(fp.fileno())) + self.assert_(posix.fstat(fp)) finally: fp.close() Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 73251) +++ Modules/posixmodule.c (working copy) @@ -1913,9 +1913,13 @@ static PyObject * posix_fchmod(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd, mode, res; - if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode)) + if (!PyArg_ParseTuple(args, "Oi:fchmod", &fdobj, &mode)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ Py_BEGIN_ALLOW_THREADS res = fchmod(fd, mode); Py_END_ALLOW_THREADS @@ -2088,10 +2092,14 @@ static PyObject * posix_fchown(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd, uid, gid; int res; - if (!PyArg_ParseTuple(args, "iii:chown", &fd, &uid, &gid)) + if (!PyArg_ParseTuple(args, "Oii:chown", &fdobj, &uid, &gid)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ Py_BEGIN_ALLOW_THREADS res = fchown(fd, (uid_t) uid, (gid_t) gid); Py_END_ALLOW_THREADS @@ -4880,10 +4888,14 @@ static PyObject * posix_tcgetpgrp(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; pid_t pgid; - if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd)) + if (!PyArg_ParseTuple(args, "O:tcgetpgrp", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ pgid = tcgetpgrp(fd); if (pgid < 0) return posix_error(); @@ -4900,10 +4912,14 @@ static PyObject * posix_tcsetpgrp(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; pid_t pgid; - if (!PyArg_ParseTuple(args, "i" PARSE_PID ":tcsetpgrp", &fd, &pgid)) + if (!PyArg_ParseTuple(args, "O" PARSE_PID ":tcsetpgrp", &fdobj, &pgid)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ if (tcsetpgrp(fd, pgid) < 0) return posix_error(); Py_INCREF(Py_None); @@ -4967,9 +4983,12 @@ static PyObject * posix_close(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd, res; - if (!PyArg_ParseTuple(args, "i:close", &fd)) + if (!PyArg_ParseTuple(args, "O:close", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + /* Rely on PyVerify to detect error cases */ if (!_PyVerify_fd(fd)) return posix_error(); Py_BEGIN_ALLOW_THREADS @@ -5008,9 +5027,12 @@ static PyObject * posix_dup(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; - if (!PyArg_ParseTuple(args, "i:dup", &fd)) + if (!PyArg_ParseTuple(args, "O:dup", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + /* Rely on PyVerify to detect error cases */ if (!_PyVerify_fd(fd)) return posix_error(); Py_BEGIN_ALLOW_THREADS @@ -5029,9 +5051,12 @@ static PyObject * posix_dup2(PyObject *self, PyObject *args) { + PyObject *fdobj1, *fdobj2; int fd, fd2, res; - if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2)) + if (!PyArg_ParseTuple(args, "OO:dup2", &fdobj1, &fdobj2)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj1); + fd2 = PyObject_AsFileDescriptor(fdobj2); if (!_PyVerify_fd_dup2(fd, fd2)) return posix_error(); Py_BEGIN_ALLOW_THREADS @@ -5057,9 +5082,13 @@ #else off_t pos, res; #endif + PyObject *fdobj; PyObject *posobj; - if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how)) + if (!PyArg_ParseTuple(args, "OOi:lseek", &fdobj, &posobj, &how)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ #ifdef SEEK_SET /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ switch (how) { @@ -5105,11 +5134,15 @@ static PyObject * posix_read(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd, size; Py_ssize_t n; PyObject *buffer; - if (!PyArg_ParseTuple(args, "ii:read", &fd, &size)) + if (!PyArg_ParseTuple(args, "Oi:read", &fdobj, &size)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ if (size < 0) { errno = EINVAL; return posix_error(); @@ -5139,12 +5172,15 @@ static PyObject * posix_write(PyObject *self, PyObject *args) { + PyObject *fdobj; Py_buffer pbuf; int fd; Py_ssize_t size; - if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf)) + if (!PyArg_ParseTuple(args, "Oy*:write", &fdobj, &pbuf)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + /* Rely on PyVerify to detect error cases */ if (!_PyVerify_fd(fd)) return posix_error(); Py_BEGIN_ALLOW_THREADS @@ -5164,11 +5200,15 @@ static PyObject * posix_fstat(PyObject *self, PyObject *args) { - int fd; + PyObject *fdobj; STRUCT_STAT st; int res; - if (!PyArg_ParseTuple(args, "i:fstat", &fd)) + int fd; + if (!PyArg_ParseTuple(args, "O:fstat", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ #ifdef __VMS /* on OpenVMS we must ensure that all bytes are written to the file */ fsync(fd); @@ -5197,9 +5237,12 @@ static PyObject * posix_isatty(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; - if (!PyArg_ParseTuple(args, "i:isatty", &fd)) + if (!PyArg_ParseTuple(args, "O:isatty", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + /* Rely on PyVerify to detect error cases */ if (!_PyVerify_fd(fd)) return PyBool_FromLong(0); return PyBool_FromLong(isatty(fd)); @@ -5356,13 +5399,17 @@ static PyObject * posix_ftruncate(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd; off_t length; int res; PyObject *lenobj; - if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj)) + if (!PyArg_ParseTuple(args, "OO:ftruncate", &fdobj, &lenobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ #if !defined(HAVE_LARGEFILE_SUPPORT) length = PyLong_AsLong(lenobj); @@ -5752,11 +5799,15 @@ static PyObject * posix_fstatvfs(PyObject *self, PyObject *args) { + PyObject *fdobj; int fd, res; struct statvfs st; - if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd)) + if (!PyArg_ParseTuple(args, "O:fstatvfs", &fdobj)) return NULL; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ Py_BEGIN_ALLOW_THREADS res = fstatvfs(fd, &st); Py_END_ALLOW_THREADS @@ -5924,10 +5975,15 @@ posix_fpathconf(PyObject *self, PyObject *args) { PyObject *result = NULL; + PyObject *fdobj; int name, fd; - if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd, + if (PyArg_ParseTuple(args, "OO&:fpathconf", &fdobj, conv_path_confname, &name)) { + + fd = PyObject_AsFileDescriptor(fdobj); + if (fd == -1) + return NULL; /* Rely on AsFileDescriptor's error handling */ long limit; errno = 0;