mirror of
https://github.com/python/cpython.git
synced 2025-10-17 20:28:43 +00:00
PEP 410
This commit is contained in:
parent
6f91ce74a0
commit
ccd5715a14
9 changed files with 814 additions and 174 deletions
|
@ -1702,6 +1702,12 @@ stat_float_times(PyObject* self, PyObject *args)
|
|||
int newval = -1;
|
||||
if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
|
||||
return NULL;
|
||||
if (PyErr_WarnEx(PyExc_DeprecationWarning,
|
||||
"os.stat_float_times() has been deprecated, "
|
||||
"use timestamp argument of os.stat() instead",
|
||||
1))
|
||||
return NULL;
|
||||
|
||||
if (newval == -1)
|
||||
/* Return old value */
|
||||
return PyBool_FromLong(_stat_float_times);
|
||||
|
@ -1711,9 +1717,12 @@ stat_float_times(PyObject* self, PyObject *args)
|
|||
}
|
||||
|
||||
static void
|
||||
fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
|
||||
fill_time(PyObject *v, int index, time_t sec, unsigned long nsec,
|
||||
int has_nsec, PyObject *timestamp)
|
||||
{
|
||||
PyObject *fval,*ival;
|
||||
_PyTime_t ts;
|
||||
|
||||
#if SIZEOF_TIME_T > SIZEOF_LONG
|
||||
ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
|
||||
#else
|
||||
|
@ -1721,9 +1730,21 @@ fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
|
|||
#endif
|
||||
if (!ival)
|
||||
return;
|
||||
if (_stat_float_times) {
|
||||
fval = PyFloat_FromDouble(sec + 1e-9*nsec);
|
||||
} else {
|
||||
if (timestamp == NULL && _stat_float_times)
|
||||
timestamp = (PyObject*)&PyFloat_Type;
|
||||
if (timestamp != NULL) {
|
||||
ts.seconds = sec;
|
||||
if (has_nsec) {
|
||||
ts.numerator = nsec;
|
||||
ts.denominator = 1000000000;
|
||||
}
|
||||
else {
|
||||
ts.numerator = 0;
|
||||
ts.denominator = 1;
|
||||
}
|
||||
fval = _PyTime_Convert(&ts, timestamp);
|
||||
}
|
||||
else {
|
||||
fval = ival;
|
||||
Py_INCREF(fval);
|
||||
}
|
||||
|
@ -1734,9 +1755,14 @@ fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
|
|||
/* pack a system stat C structure into the Python stat tuple
|
||||
(used by posix_stat() and posix_fstat()) */
|
||||
static PyObject*
|
||||
_pystat_fromstructstat(STRUCT_STAT *st)
|
||||
_pystat_fromstructstat(STRUCT_STAT *st, PyObject *timestamp)
|
||||
{
|
||||
unsigned long ansec, mnsec, cnsec;
|
||||
int has_nsec;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
|
||||
_PyTime_t ts;
|
||||
#endif
|
||||
|
||||
PyObject *v = PyStructSequence_New(&StatResultType);
|
||||
if (v == NULL)
|
||||
return NULL;
|
||||
|
@ -1768,20 +1794,24 @@ _pystat_fromstructstat(STRUCT_STAT *st)
|
|||
ansec = st->st_atim.tv_nsec;
|
||||
mnsec = st->st_mtim.tv_nsec;
|
||||
cnsec = st->st_ctim.tv_nsec;
|
||||
has_nsec = 1;
|
||||
#elif defined(HAVE_STAT_TV_NSEC2)
|
||||
ansec = st->st_atimespec.tv_nsec;
|
||||
mnsec = st->st_mtimespec.tv_nsec;
|
||||
cnsec = st->st_ctimespec.tv_nsec;
|
||||
has_nsec = 1;
|
||||
#elif defined(HAVE_STAT_NSEC)
|
||||
ansec = st->st_atime_nsec;
|
||||
mnsec = st->st_mtime_nsec;
|
||||
cnsec = st->st_ctime_nsec;
|
||||
has_nsec = 1;
|
||||
#else
|
||||
ansec = mnsec = cnsec = 0;
|
||||
has_nsec = 0;
|
||||
#endif
|
||||
fill_time(v, 7, st->st_atime, ansec);
|
||||
fill_time(v, 8, st->st_mtime, mnsec);
|
||||
fill_time(v, 9, st->st_ctime, cnsec);
|
||||
fill_time(v, 7, st->st_atime, ansec, has_nsec, timestamp);
|
||||
fill_time(v, 8, st->st_mtime, mnsec, has_nsec, timestamp);
|
||||
fill_time(v, 9, st->st_ctime, cnsec, has_nsec, timestamp);
|
||||
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
|
||||
|
@ -1801,21 +1831,26 @@ _pystat_fromstructstat(STRUCT_STAT *st)
|
|||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
|
||||
{
|
||||
PyObject *val;
|
||||
unsigned long bsec,bnsec;
|
||||
bsec = (long)st->st_birthtime;
|
||||
PyObject *val;
|
||||
ts.seconds = (long)st->st_birthtime;
|
||||
#ifdef HAVE_STAT_TV_NSEC2
|
||||
bnsec = st->st_birthtimespec.tv_nsec;
|
||||
ts.numerator = st->st_birthtimespec.tv_nsec;
|
||||
ts.denominator = 1000000000;
|
||||
#else
|
||||
bnsec = 0;
|
||||
ts.numerator = 0;
|
||||
ts.denominator = 1;
|
||||
#endif
|
||||
if (_stat_float_times) {
|
||||
val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
|
||||
} else {
|
||||
val = PyLong_FromLong((long)bsec);
|
||||
}
|
||||
PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
|
||||
val);
|
||||
if (timestamp == NULL) {
|
||||
if (_stat_float_times)
|
||||
val = _PyTime_Convert(&ts, (PyObject*)&PyFloat_Type);
|
||||
else
|
||||
val = _PyTime_Convert(&ts, (PyObject*)&PyLong_Type);
|
||||
}
|
||||
else {
|
||||
val = _PyTime_Convert(&ts, timestamp);
|
||||
}
|
||||
PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
|
||||
val);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
|
||||
|
@ -1832,7 +1867,7 @@ _pystat_fromstructstat(STRUCT_STAT *st)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
posix_do_stat(PyObject *self, PyObject *args,
|
||||
posix_do_stat(PyObject *self, PyObject *args, PyObject *kw,
|
||||
char *format,
|
||||
#ifdef __VMS
|
||||
int (*statfunc)(const char *, STRUCT_STAT *, ...),
|
||||
|
@ -1842,15 +1877,18 @@ posix_do_stat(PyObject *self, PyObject *args,
|
|||
char *wformat,
|
||||
int (*wstatfunc)(const wchar_t *, STRUCT_STAT *))
|
||||
{
|
||||
static char *kwlist[] = {"path", "timestamp", NULL};
|
||||
STRUCT_STAT st;
|
||||
PyObject *opath;
|
||||
char *path;
|
||||
int res;
|
||||
PyObject *result;
|
||||
PyObject *timestamp = NULL;
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
PyObject *po;
|
||||
if (PyArg_ParseTuple(args, wformat, &po)) {
|
||||
if (PyArg_ParseTupleAndKeywords(args, kw, wformat, kwlist,
|
||||
&po, ×tamp)) {
|
||||
wchar_t *wpath = PyUnicode_AsUnicode(po);
|
||||
if (wpath == NULL)
|
||||
return NULL;
|
||||
|
@ -1861,15 +1899,17 @@ posix_do_stat(PyObject *self, PyObject *args,
|
|||
|
||||
if (res != 0)
|
||||
return win32_error_object("stat", po);
|
||||
return _pystat_fromstructstat(&st);
|
||||
return _pystat_fromstructstat(&st, timestamp);
|
||||
}
|
||||
/* Drop the argument parsing error as narrow strings
|
||||
are also valid. */
|
||||
PyErr_Clear();
|
||||
timestamp = NULL;
|
||||
#endif
|
||||
|
||||
if (!PyArg_ParseTuple(args, format,
|
||||
PyUnicode_FSConverter, &opath))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, format, kwlist,
|
||||
PyUnicode_FSConverter, &opath,
|
||||
×tamp))
|
||||
return NULL;
|
||||
#ifdef MS_WINDOWS
|
||||
if (win32_warn_bytes_api()) {
|
||||
|
@ -1890,7 +1930,7 @@ posix_do_stat(PyObject *self, PyObject *args,
|
|||
#endif
|
||||
}
|
||||
else
|
||||
result = _pystat_fromstructstat(&st);
|
||||
result = _pystat_fromstructstat(&st, timestamp);
|
||||
|
||||
Py_DECREF(opath);
|
||||
return result;
|
||||
|
@ -3381,16 +3421,16 @@ posix_rmdir(PyObject *self, PyObject *args)
|
|||
|
||||
|
||||
PyDoc_STRVAR(posix_stat__doc__,
|
||||
"stat(path) -> stat result\n\n\
|
||||
"stat(path, timestamp=None) -> stat result\n\n\
|
||||
Perform a stat system call on the given path.");
|
||||
|
||||
static PyObject *
|
||||
posix_stat(PyObject *self, PyObject *args)
|
||||
posix_stat(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
#ifdef MS_WINDOWS
|
||||
return posix_do_stat(self, args, "O&:stat", STAT, "U:stat", win32_stat_w);
|
||||
return posix_do_stat(self, args, kw, "O&|O:stat", STAT, "U|O:stat", win32_stat_w);
|
||||
#else
|
||||
return posix_do_stat(self, args, "O&:stat", STAT, NULL, NULL);
|
||||
return posix_do_stat(self, args, kw, "O&|O:stat", STAT, NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -6118,11 +6158,12 @@ posix_setgroups(PyObject *self, PyObject *groups)
|
|||
|
||||
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
|
||||
static PyObject *
|
||||
wait_helper(pid_t pid, int status, struct rusage *ru)
|
||||
wait_helper(pid_t pid, int status, struct rusage *ru, PyObject *timestamp)
|
||||
{
|
||||
PyObject *result;
|
||||
static PyObject *struct_rusage;
|
||||
_Py_IDENTIFIER(struct_rusage);
|
||||
_PyTime_t ts;
|
||||
|
||||
if (pid == -1)
|
||||
return posix_error();
|
||||
|
@ -6146,10 +6187,17 @@ wait_helper(pid_t pid, int status, struct rusage *ru)
|
|||
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
|
||||
#endif
|
||||
|
||||
ts.seconds = ru->ru_utime.tv_sec;
|
||||
ts.numerator = ru->ru_utime.tv_usec;
|
||||
ts.denominator = 1000000;
|
||||
PyStructSequence_SET_ITEM(result, 0,
|
||||
PyFloat_FromDouble(doubletime(ru->ru_utime)));
|
||||
_PyTime_Convert(&ts, timestamp));
|
||||
|
||||
ts.seconds = ru->ru_stime.tv_sec;
|
||||
ts.numerator = ru->ru_stime.tv_usec;
|
||||
ts.denominator = 1000000;
|
||||
PyStructSequence_SET_ITEM(result, 1,
|
||||
PyFloat_FromDouble(doubletime(ru->ru_stime)));
|
||||
_PyTime_Convert(&ts, timestamp));
|
||||
#define SET_INT(result, index, value)\
|
||||
PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
|
||||
SET_INT(result, 2, ru->ru_maxrss);
|
||||
|
@ -6179,51 +6227,55 @@ wait_helper(pid_t pid, int status, struct rusage *ru)
|
|||
|
||||
#ifdef HAVE_WAIT3
|
||||
PyDoc_STRVAR(posix_wait3__doc__,
|
||||
"wait3(options) -> (pid, status, rusage)\n\n\
|
||||
"wait3(options[, timestamp=float]) -> (pid, status, rusage)\n\n\
|
||||
Wait for completion of a child process.");
|
||||
|
||||
static PyObject *
|
||||
posix_wait3(PyObject *self, PyObject *args)
|
||||
posix_wait3(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"options", "timestamp", NULL};
|
||||
pid_t pid;
|
||||
int options;
|
||||
struct rusage ru;
|
||||
WAIT_TYPE status;
|
||||
WAIT_STATUS_INT(status) = 0;
|
||||
PyObject *timestamp = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:wait3", &options))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|O:wait3", kwlist, &options, ×tamp))
|
||||
return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
pid = wait3(&status, options, &ru);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
|
||||
return wait_helper(pid, WAIT_STATUS_INT(status), &ru, timestamp);
|
||||
}
|
||||
#endif /* HAVE_WAIT3 */
|
||||
|
||||
#ifdef HAVE_WAIT4
|
||||
PyDoc_STRVAR(posix_wait4__doc__,
|
||||
"wait4(pid, options) -> (pid, status, rusage)\n\n\
|
||||
"wait4(pid, options[, timestamp=float]) -> (pid, status, rusage)\n\n\
|
||||
Wait for completion of a given child process.");
|
||||
|
||||
static PyObject *
|
||||
posix_wait4(PyObject *self, PyObject *args)
|
||||
posix_wait4(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"pid", "options", "timestamp", NULL};
|
||||
pid_t pid;
|
||||
int options;
|
||||
struct rusage ru;
|
||||
WAIT_TYPE status;
|
||||
WAIT_STATUS_INT(status) = 0;
|
||||
PyObject *timestamp = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:wait4", &pid, &options))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, _Py_PARSE_PID "i|O:wait4", kwlist, &pid, &options, ×tamp))
|
||||
return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
pid = wait4(pid, &status, options, &ru);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
|
||||
return wait_helper(pid, WAIT_STATUS_INT(status), &ru, timestamp);
|
||||
}
|
||||
#endif /* HAVE_WAIT4 */
|
||||
|
||||
|
@ -6350,20 +6402,20 @@ posix_wait(PyObject *self, PyObject *noargs)
|
|||
|
||||
|
||||
PyDoc_STRVAR(posix_lstat__doc__,
|
||||
"lstat(path) -> stat result\n\n\
|
||||
"lstat(path, timestamp=None) -> stat result\n\n\
|
||||
Like stat(path), but do not follow symbolic links.");
|
||||
|
||||
static PyObject *
|
||||
posix_lstat(PyObject *self, PyObject *args)
|
||||
posix_lstat(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
#ifdef HAVE_LSTAT
|
||||
return posix_do_stat(self, args, "O&:lstat", lstat, NULL, NULL);
|
||||
return posix_do_stat(self, args, kw, "O&|O:lstat", lstat, NULL, NULL);
|
||||
#else /* !HAVE_LSTAT */
|
||||
#ifdef MS_WINDOWS
|
||||
return posix_do_stat(self, args, "O&:lstat", win32_lstat, "U:lstat",
|
||||
return posix_do_stat(self, args, kw, "O&|O:lstat", win32_lstat, "U|O:lstat",
|
||||
win32_lstat_w);
|
||||
#else
|
||||
return posix_do_stat(self, args, "O&:lstat", STAT, NULL, NULL);
|
||||
return posix_do_stat(self, args, "kw, O&|O:lstat", STAT, NULL, NULL);
|
||||
#endif
|
||||
#endif /* !HAVE_LSTAT */
|
||||
}
|
||||
|
@ -7322,16 +7374,19 @@ done:
|
|||
#endif
|
||||
|
||||
PyDoc_STRVAR(posix_fstat__doc__,
|
||||
"fstat(fd) -> stat result\n\n\
|
||||
"fstat(fd, timestamp=None) -> stat result\n\n\
|
||||
Like stat(), but for an open file descriptor.");
|
||||
|
||||
static PyObject *
|
||||
posix_fstat(PyObject *self, PyObject *args)
|
||||
posix_fstat(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"fd", "timestamp", NULL};
|
||||
int fd;
|
||||
STRUCT_STAT st;
|
||||
int res;
|
||||
if (!PyArg_ParseTuple(args, "i:fstat", &fd))
|
||||
PyObject *timestamp = NULL;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|O:fstat", kwlist,
|
||||
&fd, ×tamp))
|
||||
return NULL;
|
||||
#ifdef __VMS
|
||||
/* on OpenVMS we must ensure that all bytes are written to the file */
|
||||
|
@ -7350,7 +7405,7 @@ posix_fstat(PyObject *self, PyObject *args)
|
|||
#endif
|
||||
}
|
||||
|
||||
return _pystat_fromstructstat(&st);
|
||||
return _pystat_fromstructstat(&st, timestamp);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(posix_isatty__doc__,
|
||||
|
@ -9634,22 +9689,25 @@ posix_fchownat(PyObject *self, PyObject *args)
|
|||
|
||||
#ifdef HAVE_FSTATAT
|
||||
PyDoc_STRVAR(posix_fstatat__doc__,
|
||||
"fstatat(dirfd, path, flags=0) -> stat result\n\n\
|
||||
"fstatat(dirfd, path, flags=0, timestamp=None) -> stat result\n\n\
|
||||
Like stat() but if path is relative, it is taken as relative to dirfd.\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.");
|
||||
|
||||
static PyObject *
|
||||
posix_fstatat(PyObject *self, PyObject *args)
|
||||
posix_fstatat(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"dirfd", "path", "flags", "timestamp", NULL};
|
||||
PyObject *opath;
|
||||
char *path;
|
||||
STRUCT_STAT st;
|
||||
int dirfd, res, flags = 0;
|
||||
PyObject *timestamp = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iO&|i:fstatat",
|
||||
&dirfd, PyUnicode_FSConverter, &opath, &flags))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO&|iO:fstatat", kwlist,
|
||||
&dirfd, PyUnicode_FSConverter, &opath,
|
||||
&flags, ×tamp))
|
||||
return NULL;
|
||||
path = PyBytes_AsString(opath);
|
||||
|
||||
|
@ -9660,7 +9718,7 @@ posix_fstatat(PyObject *self, PyObject *args)
|
|||
if (res != 0)
|
||||
return posix_error();
|
||||
|
||||
return _pystat_fromstructstat(&st);
|
||||
return _pystat_fromstructstat(&st, timestamp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -10524,7 +10582,7 @@ static PyMethodDef posix_methods[] = {
|
|||
#ifdef HAVE_FDOPENDIR
|
||||
{"flistdir", posix_flistdir, METH_VARARGS, posix_flistdir__doc__},
|
||||
#endif
|
||||
{"lstat", posix_lstat, METH_VARARGS, posix_lstat__doc__},
|
||||
{"lstat", (PyCFunction)posix_lstat, METH_VARARGS | METH_KEYWORDS, posix_lstat__doc__},
|
||||
{"mkdir", posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
|
||||
#ifdef HAVE_NICE
|
||||
{"nice", posix_nice, METH_VARARGS, posix_nice__doc__},
|
||||
|
@ -10544,7 +10602,8 @@ static PyMethodDef posix_methods[] = {
|
|||
{"rename", posix_rename, METH_VARARGS, posix_rename__doc__},
|
||||
{"replace", posix_replace, METH_VARARGS, posix_replace__doc__},
|
||||
{"rmdir", posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
|
||||
{"stat", posix_stat, METH_VARARGS, posix_stat__doc__},
|
||||
{"stat", (PyCFunction)posix_stat,
|
||||
METH_VARARGS | METH_KEYWORDS, posix_stat__doc__},
|
||||
{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
|
||||
#if defined(HAVE_SYMLINK) && !defined(MS_WINDOWS)
|
||||
{"symlink", posix_symlink, METH_VARARGS, posix_symlink__doc__},
|
||||
|
@ -10705,10 +10764,12 @@ static PyMethodDef posix_methods[] = {
|
|||
{"wait", posix_wait, METH_NOARGS, posix_wait__doc__},
|
||||
#endif /* HAVE_WAIT */
|
||||
#ifdef HAVE_WAIT3
|
||||
{"wait3", posix_wait3, METH_VARARGS, posix_wait3__doc__},
|
||||
{"wait3", (PyCFunction)posix_wait3,
|
||||
METH_VARARGS | METH_KEYWORDS, posix_wait3__doc__},
|
||||
#endif /* HAVE_WAIT3 */
|
||||
#ifdef HAVE_WAIT4
|
||||
{"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__},
|
||||
{"wait4", (PyCFunction)posix_wait4,
|
||||
METH_VARARGS | METH_KEYWORDS, posix_wait4__doc__},
|
||||
#endif /* HAVE_WAIT4 */
|
||||
#if defined(HAVE_WAITID) && !defined(__APPLE__)
|
||||
{"waitid", posix_waitid, METH_VARARGS, posix_waitid__doc__},
|
||||
|
@ -10759,7 +10820,8 @@ static PyMethodDef posix_methods[] = {
|
|||
{"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS,
|
||||
posix_sendfile__doc__},
|
||||
#endif
|
||||
{"fstat", posix_fstat, METH_VARARGS, posix_fstat__doc__},
|
||||
{"fstat", (PyCFunction)posix_fstat, METH_VARARGS | METH_KEYWORDS,
|
||||
posix_fstat__doc__},
|
||||
{"isatty", posix_isatty, METH_VARARGS, posix_isatty__doc__},
|
||||
#ifdef HAVE_PIPE
|
||||
{"pipe", posix_pipe, METH_NOARGS, posix_pipe__doc__},
|
||||
|
@ -10894,7 +10956,8 @@ static PyMethodDef posix_methods[] = {
|
|||
{"fchownat", posix_fchownat, METH_VARARGS, posix_fchownat__doc__},
|
||||
#endif /* HAVE_FCHOWNAT */
|
||||
#ifdef HAVE_FSTATAT
|
||||
{"fstatat", posix_fstatat, METH_VARARGS, posix_fstatat__doc__},
|
||||
{"fstatat", (PyCFunction)posix_fstatat, METH_VARARGS | METH_KEYWORDS,
|
||||
posix_fstatat__doc__},
|
||||
#endif
|
||||
#ifdef HAVE_FUTIMESAT
|
||||
{"futimesat", posix_futimesat, METH_VARARGS, posix_futimesat__doc__},
|
||||
|
|
|
@ -40,24 +40,30 @@
|
|||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
|
||||
# define HAVE_PYCLOCK
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
static int floatsleep(double);
|
||||
static double floattime(void);
|
||||
|
||||
static PyObject *
|
||||
time_time(PyObject *self, PyObject *unused)
|
||||
time_time(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
double secs;
|
||||
secs = floattime();
|
||||
if (secs == 0.0) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
static char *kwlist[] = {"timestamp", NULL};
|
||||
PyObject *timestamp = NULL;
|
||||
_PyTime_t ts;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:time", kwlist,
|
||||
×tamp))
|
||||
return NULL;
|
||||
}
|
||||
return PyFloat_FromDouble(secs);
|
||||
|
||||
_PyTime_get(&ts);
|
||||
return _PyTime_Convert(&ts, timestamp);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(time_doc,
|
||||
"time() -> floating point number\n\
|
||||
"time(timestamp=float) -> floating point number\n\
|
||||
\n\
|
||||
Return the current time in seconds since the Epoch.\n\
|
||||
Fractions of a second may be present if the system clock provides them.");
|
||||
|
@ -72,65 +78,91 @@ Fractions of a second may be present if the system clock provides them.");
|
|||
#endif
|
||||
#endif
|
||||
|
||||
static PyObject *
|
||||
pyclock(void)
|
||||
static int
|
||||
pyclock(_PyTime_t *ts)
|
||||
{
|
||||
clock_t value;
|
||||
value = clock();
|
||||
if (value == (clock_t)-1) {
|
||||
clock_t processor_time;
|
||||
processor_time = clock();
|
||||
if (processor_time == (clock_t)-1) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"the processor time used is not available "
|
||||
"or its value cannot be represented");
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
return PyFloat_FromDouble((double)value / CLOCKS_PER_SEC);
|
||||
ts->seconds = 0;
|
||||
assert(sizeof(clock_t) <= sizeof(_PyTime_fraction_t));
|
||||
ts->numerator = Py_SAFE_DOWNCAST(processor_time,
|
||||
clock_t, _PyTime_fraction_t);
|
||||
ts->denominator = CLOCKS_PER_SEC;
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_CLOCK */
|
||||
|
||||
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
||||
/* Win32 has better clock replacement; we have our own version, due to Mark
|
||||
Hammond and Tim Peters */
|
||||
static PyObject *
|
||||
win32_clock(int fallback)
|
||||
static int
|
||||
win32_clock(_PyTime_t *ts, int fallback)
|
||||
{
|
||||
static LONGLONG cpu_frequency = 0;
|
||||
static LONGLONG ctrStart;
|
||||
static LONGLONG start;
|
||||
LARGE_INTEGER now;
|
||||
double diff;
|
||||
LONGLONG dt;
|
||||
|
||||
if (cpu_frequency == 0) {
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceCounter(&now);
|
||||
ctrStart = now.QuadPart;
|
||||
start = now.QuadPart;
|
||||
if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) {
|
||||
/* Unlikely to happen - this works on all intel
|
||||
machines at least! Revert to clock() */
|
||||
if (fallback)
|
||||
return pyclock();
|
||||
else
|
||||
return PyErr_SetFromWindowsErr(0);
|
||||
if (fallback) {
|
||||
return pyclock(ts);
|
||||
}
|
||||
else {
|
||||
PyErr_SetFromWindowsErr(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
cpu_frequency = freq.QuadPart;
|
||||
}
|
||||
QueryPerformanceCounter(&now);
|
||||
diff = (double)(now.QuadPart - ctrStart);
|
||||
return PyFloat_FromDouble(diff / (double)cpu_frequency);
|
||||
dt = now.QuadPart - start;
|
||||
|
||||
ts->seconds = 0;
|
||||
assert(sizeof(LONGLONG) <= sizeof(_PyTime_fraction_t));
|
||||
ts->numerator = Py_SAFE_DOWNCAST(dt,
|
||||
LONGLONG, _PyTime_fraction_t);
|
||||
ts->denominator = Py_SAFE_DOWNCAST(cpu_frequency,
|
||||
LONGLONG, _PyTime_fraction_t);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
|
||||
static PyObject *
|
||||
time_clock(PyObject *self, PyObject *unused)
|
||||
time_clock(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"timestamp", NULL};
|
||||
_PyTime_t ts;
|
||||
PyObject *timestamp = NULL;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:clock", kwlist,
|
||||
×tamp))
|
||||
return NULL;
|
||||
|
||||
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
||||
return win32_clock(1);
|
||||
if (win32_clock(&ts, 1) == -1)
|
||||
return NULL;
|
||||
#else
|
||||
return pyclock();
|
||||
if (pyclock(&ts) == -1)
|
||||
return NULL;
|
||||
#endif
|
||||
return _PyTime_Convert(&ts, timestamp);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(clock_doc,
|
||||
"clock() -> floating point number\n\
|
||||
"clock(timestamp=float) -> floating point number\n\
|
||||
\n\
|
||||
Return the CPU time or real time since the start of the process or since\n\
|
||||
the first call to clock(). This has as much precision as the system\n\
|
||||
|
@ -139,13 +171,17 @@ records.");
|
|||
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
static PyObject *
|
||||
time_clock_gettime(PyObject *self, PyObject *args)
|
||||
time_clock_gettime(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"clk_id", "timestamp", NULL};
|
||||
PyObject *timestamp = NULL;
|
||||
int ret;
|
||||
clockid_t clk_id;
|
||||
struct timespec tp;
|
||||
_PyTime_t ts;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|O:clock_gettime", kwlist,
|
||||
&clk_id, ×tamp))
|
||||
return NULL;
|
||||
|
||||
ret = clock_gettime((clockid_t)clk_id, &tp);
|
||||
|
@ -153,25 +189,31 @@ time_clock_gettime(PyObject *self, PyObject *args)
|
|||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||
ts.seconds = tp.tv_sec;
|
||||
ts.numerator = tp.tv_nsec;
|
||||
ts.denominator = 1000000000;
|
||||
return _PyTime_Convert(&ts, timestamp);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(clock_gettime_doc,
|
||||
"clock_gettime(clk_id) -> floating point number\n\
|
||||
"clock_gettime(clk_id, timestamp=float) -> floating point number\n\
|
||||
\n\
|
||||
Return the time of the specified clock clk_id.");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CLOCK_GETRES
|
||||
static PyObject *
|
||||
time_clock_getres(PyObject *self, PyObject *args)
|
||||
time_clock_getres(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"clk_id", "timestamp", NULL};
|
||||
PyObject *timestamp = NULL;
|
||||
int ret;
|
||||
clockid_t clk_id;
|
||||
struct timespec tp;
|
||||
_PyTime_t ts;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|O:clock_getres", kwlist,
|
||||
&clk_id, ×tamp))
|
||||
return NULL;
|
||||
|
||||
ret = clock_getres((clockid_t)clk_id, &tp);
|
||||
|
@ -179,12 +221,14 @@ time_clock_getres(PyObject *self, PyObject *args)
|
|||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||
ts.seconds = tp.tv_sec;
|
||||
ts.numerator = tp.tv_nsec;
|
||||
ts.denominator = 1000000000;
|
||||
return _PyTime_Convert(&ts, timestamp);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(clock_getres_doc,
|
||||
"clock_getres(clk_id) -> floating point number\n\
|
||||
"clock_getres(clk_id, timestamp=float) -> floating point number\n\
|
||||
\n\
|
||||
Return the resolution (precision) of the specified clock clk_id.");
|
||||
#endif
|
||||
|
@ -707,10 +751,19 @@ not present, current time as returned by localtime() is used.");
|
|||
|
||||
#ifdef HAVE_MKTIME
|
||||
static PyObject *
|
||||
time_mktime(PyObject *self, PyObject *tup)
|
||||
time_mktime(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"t", "timestamp", NULL};
|
||||
PyObject *timestamp = NULL;
|
||||
PyObject *tup;
|
||||
struct tm buf;
|
||||
time_t tt;
|
||||
_PyTime_t ts;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:mktime", kwlist,
|
||||
&tup, ×tamp))
|
||||
return NULL;
|
||||
|
||||
if (!gettmarg(tup, &buf))
|
||||
return NULL;
|
||||
buf.tm_wday = -1; /* sentinel; original value ignored */
|
||||
|
@ -722,7 +775,10 @@ time_mktime(PyObject *self, PyObject *tup)
|
|||
"mktime argument out of range");
|
||||
return NULL;
|
||||
}
|
||||
return PyFloat_FromDouble((double)tt);
|
||||
ts.seconds = tt;
|
||||
ts.numerator = 0;
|
||||
ts.denominator = 1;
|
||||
return _PyTime_Convert(&ts, timestamp);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(mktime_doc,
|
||||
|
@ -768,12 +824,14 @@ the local timezone used by methods such as localtime, but this behaviour\n\
|
|||
should not be relied on.");
|
||||
#endif /* HAVE_WORKING_TZSET */
|
||||
|
||||
static PyObject *
|
||||
time_wallclock(PyObject *self, PyObject *unused)
|
||||
static int
|
||||
pywallclock(_PyTime_t *ts)
|
||||
{
|
||||
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
||||
return win32_clock(1);
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
return win32_clock(ts, 1);
|
||||
#else
|
||||
|
||||
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
static int clk_index = 0;
|
||||
clockid_t clk_ids[] = {
|
||||
#ifdef CLOCK_MONOTONIC_RAW
|
||||
|
@ -793,20 +851,41 @@ time_wallclock(PyObject *self, PyObject *unused)
|
|||
clockid_t clk_id = clk_ids[clk_index];
|
||||
ret = clock_gettime(clk_id, &tp);
|
||||
if (ret == 0)
|
||||
return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||
{
|
||||
ts->seconds = tp.tv_sec;
|
||||
ts->numerator = tp.tv_nsec;
|
||||
ts->denominator = 1000000000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
clk_index++;
|
||||
if (Py_ARRAY_LENGTH(clk_ids) <= clk_index)
|
||||
clk_index = -1;
|
||||
}
|
||||
return time_time(self, NULL);
|
||||
#else
|
||||
return time_time(self, NULL);
|
||||
#endif /* defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) */
|
||||
|
||||
_PyTime_get(ts);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
time_wallclock(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"timestamp", NULL};
|
||||
PyObject *timestamp = NULL;
|
||||
_PyTime_t ts;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:wallclock", kwlist,
|
||||
×tamp))
|
||||
return NULL;
|
||||
if (pywallclock(&ts))
|
||||
return NULL;
|
||||
return _PyTime_Convert(&ts, timestamp);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(wallclock_doc,
|
||||
"wallclock() -> float\n\
|
||||
"wallclock(timestamp=float)\n\
|
||||
\n\
|
||||
Return the current time in fractions of a second to the system's best\n\
|
||||
ability. Use this when the most accurate representation of wall-clock is\n\
|
||||
|
@ -821,11 +900,11 @@ calls is valid.");
|
|||
|
||||
#ifdef HAVE_PYTIME_MONOTONIC
|
||||
static PyObject *
|
||||
time_monotonic(PyObject *self, PyObject *unused)
|
||||
time_monotonic(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
||||
return win32_clock(0);
|
||||
#else
|
||||
static char *kwlist[] = {"timestamp", NULL};
|
||||
PyObject *timestamp = NULL;
|
||||
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
|
||||
static int clk_index = 0;
|
||||
clockid_t clk_ids[] = {
|
||||
#ifdef CLOCK_MONOTONIC_RAW
|
||||
|
@ -835,12 +914,28 @@ time_monotonic(PyObject *self, PyObject *unused)
|
|||
};
|
||||
int ret;
|
||||
struct timespec tp;
|
||||
#endif
|
||||
_PyTime_t ts;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:monotonic", kwlist,
|
||||
×tamp))
|
||||
return NULL;
|
||||
|
||||
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
|
||||
if (win32_clock(&ts, 0) == -1)
|
||||
return NULL;
|
||||
return _PyTime_Convert(&ts, timestamp);
|
||||
#else
|
||||
while (0 <= clk_index) {
|
||||
clockid_t clk_id = clk_ids[clk_index];
|
||||
ret = clock_gettime(clk_id, &tp);
|
||||
if (ret == 0)
|
||||
return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||
{
|
||||
ts.seconds = tp.tv_sec;
|
||||
ts.numerator = tp.tv_nsec;
|
||||
ts.denominator = 1000000000;
|
||||
return _PyTime_Convert(&ts, timestamp);
|
||||
}
|
||||
|
||||
clk_index++;
|
||||
if (Py_ARRAY_LENGTH(clk_ids) <= clk_index)
|
||||
|
@ -968,15 +1063,19 @@ PyInit_timezone(PyObject *m) {
|
|||
|
||||
|
||||
static PyMethodDef time_methods[] = {
|
||||
{"time", time_time, METH_NOARGS, time_doc},
|
||||
#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
|
||||
{"clock", time_clock, METH_NOARGS, clock_doc},
|
||||
{"time", (PyCFunction)time_time,
|
||||
METH_VARARGS | METH_KEYWORDS, time_doc},
|
||||
#ifdef HAVE_PYCLOCK
|
||||
{"clock", (PyCFunction)time_clock,
|
||||
METH_VARARGS | METH_KEYWORDS, clock_doc},
|
||||
#endif
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
{"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc},
|
||||
{"clock_gettime", (PyCFunction)time_clock_gettime,
|
||||
METH_VARARGS | METH_KEYWORDS, clock_gettime_doc},
|
||||
#endif
|
||||
#ifdef HAVE_CLOCK_GETRES
|
||||
{"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc},
|
||||
{"clock_getres", (PyCFunction)time_clock_getres,
|
||||
METH_VARARGS | METH_KEYWORDS, clock_getres_doc},
|
||||
#endif
|
||||
{"sleep", time_sleep, METH_VARARGS, sleep_doc},
|
||||
{"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
|
||||
|
@ -984,10 +1083,12 @@ static PyMethodDef time_methods[] = {
|
|||
{"asctime", time_asctime, METH_VARARGS, asctime_doc},
|
||||
{"ctime", time_ctime, METH_VARARGS, ctime_doc},
|
||||
#ifdef HAVE_MKTIME
|
||||
{"mktime", time_mktime, METH_O, mktime_doc},
|
||||
{"mktime", (PyCFunction)time_mktime,
|
||||
METH_VARARGS | METH_KEYWORDS, mktime_doc},
|
||||
#endif
|
||||
#ifdef HAVE_PYTIME_MONOTONIC
|
||||
{"monotonic", time_monotonic, METH_NOARGS, monotonic_doc},
|
||||
{"monotonic", (PyCFunction)time_monotonic,
|
||||
METH_VARARGS | METH_KEYWORDS, monotonic_doc},
|
||||
#endif
|
||||
#ifdef HAVE_STRFTIME
|
||||
{"strftime", time_strftime, METH_VARARGS, strftime_doc},
|
||||
|
@ -996,7 +1097,8 @@ static PyMethodDef time_methods[] = {
|
|||
#ifdef HAVE_WORKING_TZSET
|
||||
{"tzset", time_tzset, METH_NOARGS, tzset_doc},
|
||||
#endif
|
||||
{"wallclock", time_wallclock, METH_NOARGS, wallclock_doc},
|
||||
{"wallclock", (PyCFunction)time_wallclock,
|
||||
METH_VARARGS | METH_KEYWORDS, wallclock_doc},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
@ -1081,15 +1183,6 @@ PyInit_time(void)
|
|||
return m;
|
||||
}
|
||||
|
||||
static double
|
||||
floattime(void)
|
||||
{
|
||||
_PyTime_timeval t;
|
||||
_PyTime_gettimeofday(&t);
|
||||
return (double)t.tv_sec + t.tv_usec*0.000001;
|
||||
}
|
||||
|
||||
|
||||
/* Implement floatsleep() for various platforms.
|
||||
When interrupted (or when another error occurs), return -1 and
|
||||
set an exception; else return 0. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue