diff --git a/Doc/library/os.rst b/Doc/library/os.rst index acd525b453e..92b24ac9dc3 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1285,17 +1285,17 @@ as internal buffering of data. .. versionadded:: 3.3 -.. function:: utimensat(dirfd, path, (atime_sec, atime_nsec), (mtime_sec, mtime_nsec), flags) - utimensat(dirfd, path, None, None, flags) +.. function:: utimensat(dirfd, path[, atime=(atime_sec, atime_nsec), mtime=(mtime_sec, mtime_nsec), flags=0]) Updates the timestamps of a file with nanosecond precision. - The second form sets *atime* and *mtime* to the current time. + The *atime* and *mtime* tuples default to ``None``, which sets those + values to the current time. If *atime_nsec* or *mtime_nsec* is specified as :data:`UTIME_NOW`, the corresponding timestamp is updated to the current time. If *atime_nsec* or *mtime_nsec* is specified as :data:`UTIME_OMIT`, the corresponding timestamp is not updated. If *path* is relative, it is taken as relative to *dirfd*. - *flags* is optional and may be 0 or :data:`AT_SYMLINK_NOFOLLOW`. + *flags* is optional and may be 0 (the default) or :data:`AT_SYMLINK_NOFOLLOW`. If *path* is relative and *dirfd* is the special value :data:`AT_FDCWD`, then *path* is interpreted relative to the current working directory. diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index cb334775c73..cdd1108b350 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -815,11 +815,16 @@ class PosixTester(unittest.TestCase): try: now = time.time() posix.utimensat(f, support.TESTFN, None, None) + posix.utimensat(f, support.TESTFN) + posix.utimensat(f, support.TESTFN, flags=os.AT_SYMLINK_NOFOLLOW) self.assertRaises(TypeError, posix.utimensat, f, support.TESTFN, (None, None), (None, None)) self.assertRaises(TypeError, posix.utimensat, f, support.TESTFN, (now, 0), None) self.assertRaises(TypeError, posix.utimensat, f, support.TESTFN, None, (now, 0)) posix.utimensat(f, support.TESTFN, (int(now), int((now - int(now)) * 1e9)), (int(now), int((now - int(now)) * 1e9))) + posix.utimensat(dirfd=f, path=support.TESTFN, + atime=(int(now), int((now - int(now)) * 1e9)), + mtime=(int(now), int((now - int(now)) * 1e9))) finally: posix.close(f) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index da42f3a287a..49d11822785 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -10019,12 +10019,13 @@ posix_unlinkat(PyObject *self, PyObject *args) #ifdef HAVE_UTIMENSAT PyDoc_STRVAR(posix_utimensat__doc__, -"utimensat(dirfd, path, (atime_sec, atime_nsec),\n\ - (mtime_sec, mtime_nsec), flags)\n\ +"utimensat(dirfd, path[, atime=(atime_sec, atime_nsec),\n\ + mtime=(mtime_sec, mtime_nsec), flags=0])\n\ utimensat(dirfd, path, None, None, flags)\n\n\ Updates the timestamps of a file with nanosecond precision. If path is\n\ relative, it is taken as relative to dirfd.\n\ -The second form sets atime and mtime to the current time.\n\ +If atime and mtime are both None, which is the default, set atime and\n\ +mtime to the current time.\n\ flags is optional and may be 0 or AT_SYMLINK_NOFOLLOW.\n\ If path is relative and dirfd is the special value AT_FDCWD, then path\n\ is interpreted relative to the current working directory.\n\ @@ -10033,16 +10034,19 @@ current time.\n\ If *_nsec is specified as UTIME_OMIT, the timestamp is not updated."); static PyObject * -posix_utimensat(PyObject *self, PyObject *args) +posix_utimensat(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *opath; char *path; int res, dirfd, flags = 0; - PyObject *atime, *mtime; + PyObject *atime = Py_None; + PyObject *mtime = Py_None; + + static char *kwlist[] = {"dirfd", "path", "atime", "mtime", "flags", NULL}; struct timespec buf[2]; - if (!PyArg_ParseTuple(args, "iO&OO|i:utimensat", + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO&|OOi:utimensat", kwlist, &dirfd, PyUnicode_FSConverter, &opath, &atime, &mtime, &flags)) return NULL; path = PyBytes_AsString(opath); @@ -10939,7 +10943,8 @@ static PyMethodDef posix_methods[] = { {"unlinkat", posix_unlinkat, METH_VARARGS, posix_unlinkat__doc__}, #endif #ifdef HAVE_UTIMENSAT - {"utimensat", posix_utimensat, METH_VARARGS, posix_utimensat__doc__}, + {"utimensat", posix_utimensat, METH_VARARGS | METH_KEYWORDS, + posix_utimensat__doc__}, #endif #ifdef HAVE_MKFIFOAT {"mkfifoat", posix_mkfifoat, METH_VARARGS, posix_mkfifoat__doc__},