mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-25 02:13:44 +03:00
Try to annotate a function as raising on returning null
It would be the same semantics of the PyObject* returning functions but this returns a char* for success. Currently the annotated function is validated alright but can't validate the caller just yet, hence the need of a FAKE_RAISE().
This commit is contained in:
parent
07b8cfe4a5
commit
aabb868ca6
|
@ -195,6 +195,13 @@ static double round(double num)
|
||||||
#define RAISES_NEG
|
#define RAISES_NEG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WITH_CPYCHECKER_NULL_RESULT_SETS_EXCEPTION_ATTRIBUTE)
|
||||||
|
#define RAISES_NULL \
|
||||||
|
__attribute__((cpychecker_null_result_sets_exception))
|
||||||
|
#else
|
||||||
|
#define RAISES_NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(WITH_CPYCHECKER_SETS_EXCEPTION_ATTRIBUTE)
|
#if defined(WITH_CPYCHECKER_SETS_EXCEPTION_ATTRIBUTE)
|
||||||
#define RAISES \
|
#define RAISES \
|
||||||
__attribute__((cpychecker_sets_exception))
|
__attribute__((cpychecker_sets_exception))
|
||||||
|
|
|
@ -88,6 +88,7 @@ psyco_curs_close(cursorObject *self, PyObject *dummy)
|
||||||
if (!self->query && self->conn->server_version >= 80200) {
|
if (!self->query && self->conn->server_version >= 80200) {
|
||||||
if (!(lname = psycopg_escape_string(
|
if (!(lname = psycopg_escape_string(
|
||||||
self->conn, self->name, -1, NULL, NULL))) {
|
self->conn, self->name, -1, NULL, NULL))) {
|
||||||
|
FAKE_RAISE();
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
PyOS_snprintf(buffer, sizeof(buffer),
|
PyOS_snprintf(buffer, sizeof(buffer),
|
||||||
|
@ -1423,11 +1424,13 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||||
|
|
||||||
if (!(quoted_delimiter = psycopg_escape_string(
|
if (!(quoted_delimiter = psycopg_escape_string(
|
||||||
self->conn, sep, -1, NULL, NULL))) {
|
self->conn, sep, -1, NULL, NULL))) {
|
||||||
|
FAKE_RAISE();
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(quoted_null = psycopg_escape_string(
|
if (!(quoted_null = psycopg_escape_string(
|
||||||
self->conn, null, -1, NULL, NULL))) {
|
self->conn, null, -1, NULL, NULL))) {
|
||||||
|
FAKE_RAISE();
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1515,11 +1518,13 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||||
|
|
||||||
if (!(quoted_delimiter = psycopg_escape_string(
|
if (!(quoted_delimiter = psycopg_escape_string(
|
||||||
self->conn, sep, -1, NULL, NULL))) {
|
self->conn, sep, -1, NULL, NULL))) {
|
||||||
|
FAKE_RAISE();
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(quoted_null = psycopg_escape_string(
|
if (!(quoted_null = psycopg_escape_string(
|
||||||
self->conn, null, -1, NULL, NULL))) {
|
self->conn, null, -1, NULL, NULL))) {
|
||||||
|
FAKE_RAISE();
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
* If tolen is set, it will contain the length of the escaped string,
|
* If tolen is set, it will contain the length of the escaped string,
|
||||||
* including quotes.
|
* including quotes.
|
||||||
*/
|
*/
|
||||||
char *
|
RAISES_NULL char *
|
||||||
psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len,
|
psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len,
|
||||||
char *to, Py_ssize_t *tolen)
|
char *to, Py_ssize_t *tolen)
|
||||||
{
|
{
|
||||||
|
@ -467,6 +467,8 @@ psyco_GetDecimalType(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WITH_CPYCHECKER_RETURNS_BORROWED_REF_ATTRIBUTE
|
||||||
|
|
||||||
/* Transfer ownership of an object to another object's state.
|
/* Transfer ownership of an object to another object's state.
|
||||||
*
|
*
|
||||||
* Work around what seems a bug to the cpychecker which doesn't recognise
|
* Work around what seems a bug to the cpychecker which doesn't recognise
|
||||||
|
@ -474,10 +476,22 @@ psyco_GetDecimalType(void)
|
||||||
*
|
*
|
||||||
* See davidmalcolm/gcc-python-plugin#109
|
* See davidmalcolm/gcc-python-plugin#109
|
||||||
*/
|
*/
|
||||||
#ifdef WITH_CPYCHECKER_RETURNS_BORROWED_REF_ATTRIBUTE
|
|
||||||
STEALS(1) IGNORE_REFCOUNT BORROWED PyObject *
|
STEALS(1) IGNORE_REFCOUNT BORROWED PyObject *
|
||||||
TO_STATE(PyObject* obj)
|
TO_STATE(PyObject* obj)
|
||||||
{
|
{
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fake a function raising an exception.
|
||||||
|
*
|
||||||
|
* Useful to play together with functions with peculiar semantics such as
|
||||||
|
* psycopg_escape_string() which doesn't return a PyObject*, but raises an
|
||||||
|
* exception on NULL. I'm trying to implement a function attribute to raise
|
||||||
|
* on NULL, similar to raise on negative, but haven't finished it yet.
|
||||||
|
*/
|
||||||
|
RAISES IGNORE_REFCOUNT void
|
||||||
|
FAKE_RAISE()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,7 +31,7 @@ typedef struct cursorObject cursorObject;
|
||||||
typedef struct connectionObject connectionObject;
|
typedef struct connectionObject connectionObject;
|
||||||
typedef struct replicationMessageObject replicationMessageObject;
|
typedef struct replicationMessageObject replicationMessageObject;
|
||||||
|
|
||||||
HIDDEN char *psycopg_escape_string(
|
HIDDEN RAISES_NULL char *psycopg_escape_string(
|
||||||
connectionObject *conn,
|
connectionObject *conn,
|
||||||
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen);
|
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen);
|
||||||
|
|
||||||
|
@ -58,10 +58,14 @@ HIDDEN RAISES BORROWED PyObject *psyco_set_error(
|
||||||
|
|
||||||
HIDDEN PyObject *psyco_GetDecimalType(void);
|
HIDDEN PyObject *psyco_GetDecimalType(void);
|
||||||
|
|
||||||
|
/* Using this macro arbitrarily to check if we are under cpychecker.
|
||||||
|
* Otherwise don't compile this function. */
|
||||||
#ifdef WITH_CPYCHECKER_RETURNS_BORROWED_REF_ATTRIBUTE
|
#ifdef WITH_CPYCHECKER_RETURNS_BORROWED_REF_ATTRIBUTE
|
||||||
HIDDEN STEALS(1) IGNORE_REFCOUNT BORROWED PyObject *TO_STATE(PyObject* obj);
|
HIDDEN STEALS(1) IGNORE_REFCOUNT BORROWED PyObject *TO_STATE(PyObject* obj);
|
||||||
|
HIDDEN RAISES HIDDEN void FAKE_RAISE(void);
|
||||||
#else
|
#else
|
||||||
#define TO_STATE(x) x
|
#define TO_STATE(x) x
|
||||||
|
#define FAKE_RAISE() do {} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* !defined(UTILS_H) */
|
#endif /* !defined(UTILS_H) */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user