[Python-Dev] Using argument clinic to replace timemodule.c:parse_time_t_args() (original) (raw)
Larry Hastings larry at hastings.org
Tue Jan 21 08:19:11 CET 2014
- Previous message: [Python-Dev] Using argument clinic to replace timemodule.c:parse_time_t_args()
- Next message: [Python-Dev] Using argument clinic to replace timemodule.c:parse_time_t_args()
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 01/20/2014 06:44 PM, Nikolaus Rath wrote:
All in all, I'm still not sure how I'm supposed to proceed. I see the following options (and I'm fine with all of them):
1. Use the option group with a custom converter. This means a time(NULL) call even if the caller passed a parameter. 2. Declare the impl parameter as PyObject* instead of timet, and explicitly call a C conversion function. 3. Patch clinic.py to only evaluate the C default if the caller does not pass a parameter. This seemest cleanest, but I don't know if the design of clinic.py actually allows that.
clinic.py is not flexible enough to allow initialization code after the call to the converter.
A comment on your approach so far: I'm very much against giving "default" a default value in the constructor. I realize that hack saves you having to say "= NULL" in a lot of places. But explicit is better than implicit, and we're going to read these signatures a lot more often than we write them, and I want Clinic signatures to be easy to read at first glance.
Anyway, you're right, the converter function is not called if a value is not passed in to convert it. I think this is more complicated than you suspect, because PyArg_ParseWhatnot doesn't tell you whether or not it processed a parameter. You have to detect it yourself, generally through a clever choice of a default value in C. But there are no illegal values of time_t.
All is not lost! What follows is rough pseudo-C code, hopefully you can take it from here.
typedef struct {
int set;
time_t when;
} clinic_time_t;
#define DEFAULT_CLINIC_TIME_T {0, 0}
static int
parse_clinic_time_t_arg(PyObject *arg, clinic_time_t *ct)
{
if (arg == NULL)
return 1;
if (arg == Py_None)
return 0;
if (_PyTime_ObjectToTime_t(arg, &ct->when) == -1) {
set = 1;
return 0;
}
return 1;
}
static int post_parse_clinic_time_t(clinic_time_t *ct) {
if (ct->set)
return 0;
ct->when = time(NULL);
return 0;
}
/*[python input]
class clinic_time_t_converter(CConverter):
type = 'clinic_time_t'
converter = 'parse_clinic_time_t'
c_default = 'DEFAULT_CLINIC_TIME_T'
[python start generated code]*/
/*[python end generated code: checksum=...]*/
Now you can use clinic_time_t. Parameters declared clinic_time_t can be required, or they can be optional; if they're optional give them a default value of None. You'll have to call post_parse_clinic_time_t() by hand in your impl function; I'll see if I can extend Clinic so converters can emit code after a successful call to the parse function but before the call to the impl. Also, the converter probably isn't quite right, you'll have to play with "impl_by_reference" and "parse_by_reference" and add and remove asterisks and ampersands to make sure the code is 100% correct. Examine the implementation of path_t in Modules/posixmodule.c, as that does about the same thing.
And of course clinic_time_t is a poor name, perhaps you can come up with a better one.
That should work,
//arry/ -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-dev/attachments/20140120/314529f1/attachment.html>
- Previous message: [Python-Dev] Using argument clinic to replace timemodule.c:parse_time_t_args()
- Next message: [Python-Dev] Using argument clinic to replace timemodule.c:parse_time_t_args()
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]