[Python-checkins] cpython: Issue #14127: Add ns= parameter to utime, futimes, and lutimes.

Benjamin Peterson benjamin at python.org
Fri May 4 07:07:04 CEST 2012


2012/5/3 larry.hastings <python-checkins at python.org>:
> diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
> --- a/Modules/posixmodule.c
> +++ b/Modules/posixmodule.c
> @@ -3572,28 +3572,194 @@
>  #endif /* HAVE_UNAME */
>
>
> +static int
> +split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
> +{
> +    int result = 0;
> +    PyObject *divmod;
> +    divmod = PyNumber_Divmod(py_long, billion);
> +    if (!divmod)
> +        goto exit;
> +    *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
> +    if ((*s == -1) && PyErr_Occurred())
> +        goto exit;
> +    *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
> +    if ((*s == -1) && PyErr_Occurred())
> +        goto exit;
> +
> +    result = 1;
> +exit:
> +    Py_XDECREF(divmod);
> +    return result;
> +}
> +
> +
> +typedef int (*parameter_converter_t)(PyObject *, void *);
> +
> +typedef struct {
> +    /* input only */
> +    char path_format;
> +    parameter_converter_t converter;
> +    char *function_name;
> +    char *first_argument_name;
> +    PyObject *args;
> +    PyObject *kwargs;
> +
> +    /* input/output */
> +    PyObject **path;
> +
> +    /* output only */
> +    int now;
> +    time_t atime_s;
> +    long   atime_ns;
> +    time_t mtime_s;
> +    long   mtime_ns;
> +} utime_arguments;
> +
> +#define DECLARE_UA(ua, fname) \
> +    utime_arguments ua; \
> +    memset(&ua, 0, sizeof(ua)); \
> +    ua.function_name = fname; \
> +    ua.args = args; \
> +    ua.kwargs = kwargs; \
> +    ua.first_argument_name = "path"; \
> +
> +/* UA_TO_FILETIME doesn't declare atime and mtime for you */
> +#define UA_TO_FILETIME(ua, atime, mtime) \
> +    time_t_to_FILE_TIME(ua.atime_s, ua.atime_ns, &atime); \
> +    time_t_to_FILE_TIME(ua.mtime_s, ua.mtime_ns, &mtime)
> +
> +/* the rest of these macros declare the output variable for you */
> +#define UA_TO_TIMESPEC(ua, ts) \
> +    struct timespec ts[2]; \
> +    ts[0].tv_sec = ua.atime_s; \
> +    ts[0].tv_nsec = ua.atime_ns; \
> +    ts[1].tv_sec = ua.mtime_s; \
> +    ts[1].tv_nsec = ua.mtime_ns
> +
> +#define UA_TO_TIMEVAL(ua, tv) \
> +    struct timeval tv[2]; \
> +    tv[0].tv_sec = ua.atime_s; \
> +    tv[0].tv_usec = ua.atime_ns / 1000; \
> +    tv[1].tv_sec = ua.mtime_s; \
> +    tv[1].tv_usec = ua.mtime_ns / 1000
> +
> +#define UA_TO_UTIMBUF(ua, u) \
> +    struct utimbuf u; \
> +    utimbuf.actime = ua.atime_s; \
> +    utimbuf.modtime = ua.mtime_s
> +
> +#define UA_TO_TIME_T(ua, timet) \
> +    time_t timet[2]; \
> +    timet[0] = ua.atime_s; \
> +    timet[1] = ua.mtime_s
> +
> +
> +/*
> + * utime_read_time_arguments() processes arguments for the utime
> + * family of functions.
> + * returns zero on failure.
> + */
> +static int
> +utime_read_time_arguments(utime_arguments *ua)
> +{
> +    PyObject *times = NULL;
> +    PyObject *ns = NULL;
> +    char format[24];
> +    char *kwlist[4];
> +    char **kw = kwlist;
> +    int return_value;
> +
> +    *kw++ = ua->first_argument_name;
> +    *kw++ = "times";
> +    *kw++ = "ns";
> +    *kw = NULL;
> +
> +    sprintf(format, "%c%s|O$O:%s",
> +            ua->path_format,
> +            ua->converter ? "&" : "",
> +            ua->function_name);
> +
> +    if (ua->converter)
> +        return_value = PyArg_ParseTupleAndKeywords(ua->args, ua->kwargs,
> +            format, kwlist, ua->converter, ua->path, &times, &ns);
> +    else
> +        return_value = PyArg_ParseTupleAndKeywords(ua->args, ua->kwargs,
> +            format, kwlist, ua->path, &times, &ns);
> +
> +    if (!return_value)
> +        return 0;
> +
> +    if (times && ns) {
> +        PyErr_Format(PyExc_RuntimeError,

Why not a ValueError or TypeError?

> +                     "%s: you may specify either 'times'"
> +                     " or 'ns' but not both",
> +                     ua->function_name);
> +        return 0;
> +    }
> +
> +    if (times && (times != Py_None)) {

Conditions in parenthesis like this is not style.

> +        if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
> +            PyErr_Format(PyExc_TypeError,
> +                         "%s: 'time' must be either"
> +                         " a valid tuple of two ints or None",
> +                         ua->function_name);
> +            return 0;
> +        }
> +        ua->now = 0;
> +        return (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
> +                    &(ua->atime_s), &(ua->atime_ns)) != -1)
> +            && (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),

Put && on previous line like Python.

> +                    &(ua->mtime_s), &(ua->mtime_ns)) != -1);
> +    }
> +
> +    if (ns) {
> +        if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
> +            PyErr_Format(PyExc_TypeError,
> +                         "%s: 'ns' must be a valid tuple of two ints",
> +                         ua->function_name);
> +            return 0;
> +        }
> +        ua->now = 0;
> +        return (split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
> +                    &(ua->atime_s), &(ua->atime_ns)))
> +            && (split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
> +                    &(ua->mtime_s), &(ua->mtime_ns)));
> +    }
> +
> +    /* either times=None, or neither times nor ns was specified. use "now". */
> +    ua->now = 1;
> +    return 1;
> +}



-- 
Regards,
Benjamin


More information about the Python-checkins mailing list