From: Billy G. A. <bal...@us...> - 2001-09-14 04:01:40
|
Update of /cvsroot/pypgsql/pypgsql In directory usw-pr-cvs1:/tmp/cvs-serv14906 Modified Files: pgversion.c Log Message: 12SEP2001 bga Improved detection of erronious input strings. --- Various minor bug fixes and code cleanup. --- Made constructed version string more closely mimic the actual format of the PostgreSQL version string. 09SEP2001 bga Fixed the broken comparison function. This proved to be a not so easy task since any errors set in the extensions module's coerce() function are ignored (unless called by Python's built- in coerce() function). Python will clear the error and try to convert the PgVersion object to the other type if the coersion to PgVersion fails. I do not want that to happen. If the ob- ject can't be coerced to a PgVersion, then the comparison does not make sense, so an exception should occur. To get this be- haviour required a bit sneaky-ness. See the comments in the code for details. A concequence of this change is that coerce will always succeed. I can not see any way around this. --- Having a __dict__ attribute and calling PyMember_Get() in the PyVersion_getattr function causes dir() to do strange things (like list members twice). I've removed the __dict__ attribute and adding methods to emulate a mapping object to PgVersion. A PgVersion object will now act like a dictionary, so use version[key] instead of version.__dict__[key]. Index: pgversion.c =================================================================== RCS file: /cvsroot/pypgsql/pypgsql/pgversion.c,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** pgversion.c 2001/09/10 04:41:32 1.7 --- pgversion.c 2001/09/14 04:01:37 1.8 *************** *** 32,35 **** --- 32,39 ---- | Date Ini Description | | --------- --- ------------------------------------------------------- | + | 12SEP2001 bga Improved detection of erronious input strings. | + | --- Various minor bug fixes and code cleanup. | + | --- Made constructed version string more closely mimic the | + | actual format of the PostgreSQL version string. | | 09SEP2001 bga Fixed the broken comparison function. This proved to | | be a not so easy task since any errors set in the ex- | *************** *** 76,79 **** --- 80,84 ---- #include <ctype.h> #include <limits.h> + #include <errno.h> #include <Python.h> #include <structmember.h> *************** *** 90,95 **** PyObject *minor; PyObject *patch; - PyObject *value; PyObject *post70; } PgVersion; --- 95,100 ---- PyObject *minor; PyObject *patch; PyObject *post70; + PyObject *value; } PgVersion; *************** *** 110,126 **** char *last; ! *result = strtol(token, &last, 0); ! if ((token == (char *)NULL) || ! (*token == '\0') || ! isspace(*token) || ! (*last != 0)) ! { ! PyErr_SetString(PyExc_ValueError, ! "Invalid format for PgVersion construction."); ! return (1); ! } ! return (0); } --- 115,134 ---- char *last; ! /*******************************************************************\ ! | For our purposes, an error occurs when parsing a token if: | ! | 1. the 1st character of token is not a digit. | ! | 2. strtol() set errno to something other than 0. | ! | 3. strtol() could not translate the entire token (i.e. *last is | ! | not the ASCII NUL character). | ! \*******************************************************************/ ! if (!isdigit(*token)) ! return 1; ! errno = 0; ! ! *result = strtol(token, &last, 0); ! ! return ((errno != 0) || (*last != (char)0)); } *************** *** 159,164 **** if ((self->version == (PyObject *)NULL) || (s == (char *)NULL)) { ! PyErr_SetString(PyExc_MemoryError, ! "Can't allocate memory in PgVersion_New()."); goto new_error; } --- 167,171 ---- if ((self->version == (PyObject *)NULL) || (s == (char *)NULL)) { ! PyErr_NoMemory(); goto new_error; } *************** *** 176,186 **** major = minor = patch = value = 0; token = strtok_r(s, " \t", &save_ptr); if (strcmp(token, "PostgreSQL") != 0) - { - PyErr_SetString(PyExc_ValueError, - "Ivalid format for PgVersion construction."); goto new_error; - } vstr = strtok_r((char *)NULL, " \t", &save_ptr); --- 183,196 ---- major = minor = patch = value = 0; + /* Pre-set the error condition. + * We'll clear it if everything's OK + */ + PyErr_SetString(PyExc_ValueError, + "Ivalid format for PgVersion construction."); + + token = strtok_r(s, " \t", &save_ptr); if (strcmp(token, "PostgreSQL") != 0) goto new_error; vstr = strtok_r((char *)NULL, " \t", &save_ptr); *************** *** 188,196 **** token = strtok_r((char *)NULL, " \t", &save_ptr); if (strcmp(token, "on") != 0) - { - PyErr_SetString(PyExc_ValueError, - "Ivalid format for PgVersion construction."); goto new_error; ! } /***************************************************************\ --- 198,211 ---- token = strtok_r((char *)NULL, " \t", &save_ptr); if (strcmp(token, "on") != 0) goto new_error; ! ! /***************************************************************\ ! | This test is in case someone tries to compares against a | ! | string such as '7.2 on'. | ! \***************************************************************/ ! ! token = strtok_r((char *)NULL, " \t", &save_ptr); ! if (strcmp(token, "on") == 0) ! goto new_error; /***************************************************************\ *************** *** 217,220 **** --- 232,241 ---- value = (((major * 100) + minor) * 100) + patch; + /* OK, the version information has been parsed, + * Clear the pre-set error + */ + (void)PyErr_Clear(); + + /* And build the attributes */ self->major = Py_BuildValue("i", major); self->minor = Py_BuildValue("i", minor); *************** *** 227,231 **** PyMem_Free(s); - return (PyObject *)self; --- 248,251 ---- *************** *** 249,264 **** { PgVersion *s; char *vstr; if (PyString_Check(*r)) { ! vstr = PyMem_Malloc(32 + strlen(PyString_AsString(*r))); ! if (vstr == (char *)NULL) ! { ! PyErr_SetString(PyExc_MemoryError, ! "Can't allocate memory in PgVersion_coerce()."); ! return (1); ! } ! sprintf(vstr, "PostgreSQL %s on Dummy", PyString_AsString(*r)); } else --- 269,285 ---- { PgVersion *s; + PyObject *exception, *message, *traceback; char *vstr; + if ((vstr = PyMem_Malloc(128)) == (char *)NULL) + { + PyErr_NoMemory(); + return (1); + } + if (PyString_Check(*r)) { ! sprintf(vstr, "PostgreSQL %.80s on UNKNOWN, compiled by UNKNOWN", ! PyString_AsString(*r)); } else *************** *** 266,275 **** long value = 0; - if ((vstr = PyMem_Malloc(128)) == (char *)NULL) - { - PyErr_NoMemory(); - return (1); - } - if (PgInt2_Check(*r)) { --- 287,290 ---- *************** *** 295,299 **** { PyErr_SetString(PyExc_OverflowError, ! "converting Float to Integer"); } else --- 310,314 ---- { PyErr_SetString(PyExc_OverflowError, ! "float too large to convert"); } else *************** *** 304,310 **** goto coerce_error; ! sprintf(vstr, "PostgreSQL %ld.%ld.%ld on Dummy", (value / 10000), ! ((value / 100) % 100), (value % 100)); } s = (PgVersion *)PgVersion_New(vstr); --- 319,326 ---- goto coerce_error; ! sprintf(vstr, "PostgreSQL %ld.%ld.%ld on UNKNOWN, compiled by UNKNOWN", ! (value / 10000), ((value / 100) % 100), (value % 100)); } + s = (PgVersion *)PgVersion_New(vstr); *************** *** 336,347 **** PyMem_Free(vstr); s = (PgVersion *)PyObject_New(PgVersion, &PgVersion_Type); if (s == (PgVersion *)NULL) return (1); ! PyErr_Fetch(&s->major, &s->version, &s->minor); ! s->value = Py_BuildValue("i", -1); ! s->patch = Py_None; Py_INCREF(Py_None); ! s->post70 = Py_None; Py_INCREF(Py_None); if (PyErr_Occurred()) --- 352,367 ---- PyMem_Free(vstr); + PyErr_Fetch(&exception, &message, &traceback); + s = (PgVersion *)PyObject_New(PgVersion, &PgVersion_Type); if (s == (PgVersion *)NULL) return (1); ! s->version = message; ! s->major = exception; ! s->minor = traceback; ! s->patch = Py_None; Py_INCREF(Py_None); ! s->post70 = Py_None; Py_INCREF(Py_None); ! s->value = Py_BuildValue("i", -1); if (PyErr_Occurred()) *************** *** 462,468 **** PyErr_Restore(t->major, t->version, t->minor); ! Py_XINCREF(t->major); ! Py_XINCREF(t->version); ! Py_XINCREF(t->minor); } return (left < right) ? -1 : (left > right) ? 1 : 0; --- 482,488 ---- PyErr_Restore(t->major, t->version, t->minor); ! t->major = Py_None; Py_XINCREF(t->major); ! t->version = Py_None; Py_XINCREF(t->version); ! t->minor = Py_None; Py_XINCREF(t->minor); } return (left < right) ? -1 : (left > right) ? 1 : 0; |