diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2134,18 +2134,19 @@ Availability: Unix, Windows. -.. function:: utime(path, times) +.. function:: utime(path[, times]) Set the access and modified times of the file specified by *path*. If *times* - is ``None``, then the file's access and modified times are set to the current - time. (The effect is similar to running the Unix program :program:`touch` on - the path.) Otherwise, *times* must be a 2-tuple of numbers, of the form - ``(atime, mtime)`` which is used to set the access and modified times, - respectively. Whether a directory can be given for *path* depends on whether - the operating system implements directories as files (for example, Windows - does not). Note that the exact times you set here may not be returned by a - subsequent :func:`~os.stat` call, depending on the resolution with which your - operating system records access and modification times; see :func:`~os.stat`. + is ``None`` or not specified, then the file's access and modified times are + set to the current time. (The effect is similar to running the Unix program + :program:`touch` on the path.) Otherwise, *times* must be a 2-tuple of + numbers, of the form ``(atime, mtime)`` which is used to set the access and + modified times, respectively. Whether a directory can be given for *path* + depends on whether the operating system implements directories as files + (for example, Windows does not). Note that the exact times you set here may + not be returned by a subsequent :func:`~os.stat` call, depending on the + resolution with which your operating system records access and modification + times; see :func:`~os.stat`. Availability: Unix, Windows. diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -270,6 +270,21 @@ st2 = os.stat(support.TESTFN) self.assertEqual(st2.st_mtime, int(st.st_mtime-delta)) + def test_utime_noargs(self): + # (insert issue#) removed the requirement to pass None as the + # second argument. Check that the previous methods of passing + # a time tuple or None work in addition to no argument. + st = os.stat(support.TESTFN) + # Doesn't set anything new, but sets the time tuple way + os.utime(support.TESTFN, (st.st_atime, st.st_mtime)) + # Set to the current time in the old explicit way. + os.utime(support.TESTFN, None) + st1 = os.stat(support.TESTFN) + # Set to the current time in the new way + os.utime(support.TESTFN) + st2 = os.stat(support.TESTFN) + self.assertEqual(st1.st_mtime, st2.st_mtime) + # Restrict test to Win32, since there is no guarantee other # systems support centiseconds if sys.platform == 'win32': diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3543,7 +3543,7 @@ posix_utime(PyObject *self, PyObject *args) { #ifdef MS_WINDOWS - PyObject *arg; + PyObject *arg = NULL; PyObject *obwpath; wchar_t *wpath = NULL; PyObject *oapath; @@ -3554,7 +3554,7 @@ FILETIME atime, mtime; PyObject *result = NULL; - if (PyArg_ParseTuple(args, "UO|:utime", &obwpath, &arg)) { + if (PyArg_ParseTuple(args, "U|O:utime", &obwpath, &arg)) { wpath = PyUnicode_AsUnicode(obwpath); if (wpath == NULL) return NULL; @@ -3571,7 +3571,7 @@ are also valid. */ PyErr_Clear(); - if (!PyArg_ParseTuple(args, "O&O:utime", + if (!PyArg_ParseTuple(args, "O&|O:utime", PyUnicode_FSConverter, &oapath, &arg)) return NULL; @@ -3589,7 +3589,7 @@ Py_DECREF(oapath); } - if (arg == Py_None) { + if (!arg || (arg == Py_None)) { SYSTEMTIME now; GetSystemTime(&now); if (!SystemTimeToFileTime(&now, &mtime) || @@ -3633,13 +3633,13 @@ time_t atime, mtime; long ausec, musec; int res; - PyObject* arg; - - if (!PyArg_ParseTuple(args, "O&O:utime", + PyObject* arg = NULL; + + if (!PyArg_ParseTuple(args, "O&|O:utime", PyUnicode_FSConverter, &opath, &arg)) return NULL; path = PyBytes_AsString(opath); - if (arg == Py_None) { + if (!arg || (arg == Py_None)) { /* optional time values not given */ Py_BEGIN_ALLOW_THREADS res = utime(path, NULL);