[Python-Dev] Using argument clinic to replace timemodule.c:parse_time_t_args()

Nikolaus Rath Nikolaus at rath.org
Sun Jan 19 04:42:35 CET 2014


Hi Ryan,


Ryan Smith-Roberts <rmsr at lab.net> writes:
> Hi Nikolaus. I also started a conversion of timemodule, but dropped it when
> I saw in the issue that you had taken over that conversion. I also tried to
> turn parse_time_t_args into a converter. However, it won't work. The
> problem is that parse_time_t_args must be called whether or not the user
> supplies an argument to the function, but an Argument Clinic converter only
> gets called if the user actually supplies something, and not on the default
> value.

I don't quite follow. My approach was to drop parse_time_t_args()
completely and use _PyTime_ObjectToTime_t() as the conversion function
(which only needs to be called if the user supplied something).

In other words, I would have expected

>> ,----
>> | /*[python input]
>> | class time_t_converter(CConverter):
>> |     type = 'time_t'
>> |     converter = 'time_t_converter'
>> |     default = None
>> |     py_default = 'None'
>> |     c_default = 'time(NULL)'
>> |     converter = '_PyTime_ObjectToTime_t'
>> | [python start generated code]*/
>> |
>> | /*[clinic input]
>> | time.localtime
>> |
>> |     seconds: time_t
>> |     /
>> |
>> | bla.
>> | [clinic start generated code]*/
>> `----

to produce something like this:

static PyObject *
time_localtime(PyObject *self, PyObject *args)
{
     PyObject *obj = NULL;
     time_t seconds;
     struct tm buf;

     if (!PyArg_ParseTuple(args, "|O:localtime", &obj))
         return NULL;
     if (obj == NULL || obj == Py_None)
         seconds = time(NULL);
     else {
         if (_PyTime_ObjectToTime_t(obj, &seconds) == -1)
             return NULL;
     }
     return time_localtime_impl(self, seconds);
}


Apart from getting an error from clinic.py, it seems to me that this
should in principle be possible.

Best,
Nikolaus


>
> So, the best idea is to
>
> * Remove the PyArgs_ParseTuple code from parse_time_t_args
> * Declare seconds as a plain object in Argument Clinic
> * Call the modified parse_time_t_args on seconds first thing in the _impl
> functions
>
>
> On Sat, Jan 18, 2014 at 4:56 PM, Nikolaus Rath <Nikolaus at rath.org> wrote:
>
>> Hello,
>>
>> I'm trying to convert functions using parse_time_t_args() (from
>> timemodule.c) for argument parsing to argument clinic.
>>
>> The function is defined as:
>>
>> ,----
>> | static int
>> | parse_time_t_args(PyObject *args, char *format, time_t *pwhen)
>> | {
>> |     PyObject *ot = NULL;
>> |     time_t whent;
>> |
>> |     if (!PyArg_ParseTuple(args, format, &ot))
>> |         return 0;
>> |     if (ot == NULL || ot == Py_None) {
>> |         whent = time(NULL);
>> |     }
>> |     else {
>> |         if (_PyTime_ObjectToTime_t(ot, &whent) == -1)
>> |             return 0;
>> |     }
>> |     *pwhen = whent;
>> |     return 1;
>> | }
>> `----
>>
>> and used like this:
>>
>> ,----
>> | static PyObject *
>> | time_localtime(PyObject *self, PyObject *args)
>> | {
>> |     time_t when;
>> |     struct tm buf;
>> |
>> |     if (!parse_time_t_args(args, "|O:localtime", &when))
>> |         return NULL;
>> |     if (pylocaltime(&when, &buf) == -1)
>> |         return NULL;
>> |     return tmtotuple(&buf);
>> | }
>> `----
>>
>> In other words, if any Python object is passed to it, it calls
>> _PyTime_ObjectToTime_t on it to convert it to time_t, and otherwise uses
>> time(NULL) as the default value.
>>
>> May first attempt to implement something similar in argument clinic was:
>>
>> ,----
>> | /*[python input]
>> | class time_t_converter(CConverter):
>> |     type = 'time_t'
>> |     converter = 'time_t_converter'
>> |     default = None
>> |     py_default = 'None'
>> |     c_default = 'time(NULL)'
>> |     converter = '_PyTime_ObjectToTime_t'
>> | [python start generated code]*/
>> |
>> | /*[clinic input]
>> | time.localtime
>> |
>> |     seconds: time_t
>> |     /
>> |
>> | bla.
>> | [clinic start generated code]*/
>> `----
>>
>> However, running clinic.py on this file gives:
>>
>> ,----
>> | $ Tools/clinic/clinic.py Modules/timemodule.c
>> | Error in file "Modules/timemodule.c" on line 529:
>> | Exception raised during parsing:
>> | Traceback (most recent call last):
>> |   File "Tools/clinic/clinic.py", line 1445, in parse
>> |     parser.parse(block)
>> |   File "Tools/clinic/clinic.py", line 2738, in parse
>> |     self.state(None)
>> |   File "Tools/clinic/clinic.py", line 3468, in state_terminal
>> |     self.function.docstring = self.format_docstring()
>> |   File "Tools/clinic/clinic.py", line 3344, in format_docstring
>> |     s += "".join(a)
>> | TypeError: sequence item 2: expected str instance, NoneType found
>> `----
>>
>> What am I doing wrong?
>>
>>
>> Best,
>> Nikolaus
>>
>> --
>> Encrypted emails preferred.
>> PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6  02CF A9AD B7F8 AE4E 425C
>>
>>              »Time flies like an arrow, fruit flies like a Banana.«
>> _______________________________________________
>> Python-Dev mailing list
>> Python-Dev at python.org
>> https://mail.python.org/mailman/listinfo/python-dev
>> Unsubscribe:
>> https://mail.python.org/mailman/options/python-dev/rmsr%40lab.net
>>


-- 
Encrypted emails preferred.
PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6  02CF A9AD B7F8 AE4E 425C

             »Time flies like an arrow, fruit flies like a Banana.«


More information about the Python-Dev mailing list