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 <nikol...@rath.org> wrote: > Hi Ryan, > > > Ryan Smith-Roberts <r...@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 <nikol...@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@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@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/rmsr%40lab.net >
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com