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

Ryan Smith-Roberts rmsr at lab.net
Sun Jan 19 06:52:01 CET 2014


Ah yes, my apologies, I was thrown off by the first converter declaration
in your class and didn't spot the second, so didn't realize what you were
up to.

I still advise you not to use this solution. time() is a system call on
many operating systems, and so it can be a heavier operation than you'd
think. Best to avoid it unless it's needed (on FreeBSD it seems to add
about 15% overhead to localtime(), for instance).

As for why you're getting that exception, it definitely looks like a bug in
Argument Clinic. I spotted another bug that would have bitten you while I
was looking for this one, so I've opened bugs on both issues, and put you
on the nosy list for them.


On Sat, Jan 18, 2014 at 7:42 PM, Nikolaus Rath <Nikolaus at rath.org> wrote:

> 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.«
> _______________________________________________
> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20140118/e020bcbc/attachment-0001.html>


More information about the Python-Dev mailing list