Added utils.h file

utils.c functions definition moved out of psycopg.h

Some utility functions defined into psycopgmodule.c moved into utils.c.
This commit is contained in:
Daniele Varrazzo 2018-12-29 16:13:12 +01:00
parent daff2ea1be
commit 7a1fb9a2e4
5 changed files with 176 additions and 141 deletions

View File

@ -36,6 +36,7 @@
#include "psycopg/config.h"
#include "psycopg/python.h"
#include "psycopg/utils.h"
#ifdef __cplusplus
extern "C" {
@ -115,35 +116,6 @@ typedef struct {
char *pyenc;
} encodingPair;
/* the Decimal type, used by the DECIMAL typecaster */
HIDDEN PyObject *psyco_GetDecimalType(void);
/* forward declarations */
typedef struct cursorObject cursorObject;
typedef struct connectionObject connectionObject;
typedef struct replicationMessageObject replicationMessageObject;
/* some utility functions */
RAISES HIDDEN PyObject *psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg);
HIDDEN char *psycopg_escape_string(connectionObject *conn,
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen);
HIDDEN char *psycopg_escape_identifier(connectionObject *conn,
const char *str, Py_ssize_t len);
HIDDEN int psycopg_strdup(char **to, const char *from, Py_ssize_t len);
HIDDEN int psycopg_is_text_file(PyObject *f);
HIDDEN PyObject *psycopg_text_from_chars_safe(
const char *str, Py_ssize_t len, PyObject *decoder);
STEALS(1) HIDDEN PyObject * psycopg_ensure_bytes(PyObject *obj);
STEALS(1) HIDDEN PyObject * psycopg_ensure_text(PyObject *obj);
HIDDEN PyObject *psycopg_dict_from_conninfo_options(PQconninfoOption *options,
int include_password);
HIDDEN PyObject *psycopg_make_dsn(PyObject *dsn, PyObject *kwargs);
/* Exceptions docstrings */
#define Error_doc \
"Base class for error exceptions."

View File

@ -39,7 +39,6 @@
#include "psycopg/typecast.h"
#include "psycopg/microprotocols.h"
#include "psycopg/microprotocols_proto.h"
#include "psycopg/error.h"
#include "psycopg/conninfo.h"
#include "psycopg/diagnostics.h"
@ -722,116 +721,6 @@ psyco_errors_set(PyObject *type)
}
}
/* psyco_set_error
Create a new error of the given type with extra attributes. */
/* TODO: may have been changed to BORROWED */
RAISES PyObject *
psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg)
{
PyObject *pymsg;
PyObject *err = NULL;
connectionObject *conn = NULL;
if (curs) {
conn = ((cursorObject *)curs)->conn;
}
if ((pymsg = conn_text_from_chars(conn, msg))) {
err = PyObject_CallFunctionObjArgs(exc, pymsg, NULL);
Py_DECREF(pymsg);
}
else {
/* what's better than an error in an error handler in the morning?
* Anyway, some error was set, refcount is ok... get outta here. */
return NULL;
}
if (err && PyObject_TypeCheck(err, &errorType)) {
errorObject *perr = (errorObject *)err;
if (curs) {
Py_CLEAR(perr->cursor);
Py_INCREF(curs);
perr->cursor = curs;
}
}
if (err) {
PyErr_SetObject(exc, err);
Py_DECREF(err);
}
return err;
}
/* Return nonzero if the current one is the main interpreter */
static int
psyco_is_main_interp(void)
{
static PyInterpreterState *main_interp = NULL; /* Cached reference */
PyInterpreterState *interp;
if (main_interp) {
return (main_interp == PyThreadState_Get()->interp);
}
/* No cached value: cache the proper value and try again. */
interp = PyInterpreterState_Head();
while (interp->next)
interp = interp->next;
main_interp = interp;
assert (main_interp);
return psyco_is_main_interp();
}
/* psyco_GetDecimalType
Return a new reference to the adapter for decimal type.
If decimals should be used but the module import fails, fall back on
the float type.
If decimals are not to be used, return NULL.
*/
PyObject *
psyco_GetDecimalType(void)
{
static PyObject *cachedType = NULL;
PyObject *decimalType = NULL;
PyObject *decimal;
/* Use the cached object if running from the main interpreter. */
int can_cache = psyco_is_main_interp();
if (can_cache && cachedType) {
Py_INCREF(cachedType);
return cachedType;
}
/* Get a new reference to the Decimal type. */
decimal = PyImport_ImportModule("decimal");
if (decimal) {
decimalType = PyObject_GetAttrString(decimal, "Decimal");
Py_DECREF(decimal);
}
else {
PyErr_Clear();
decimalType = NULL;
}
/* Store the object from future uses. */
if (can_cache && !cachedType && decimalType) {
Py_INCREF(decimalType);
cachedType = decimalType;
}
return decimalType;
}
/** method table and module initialization **/

View File

@ -27,7 +27,9 @@
#include "psycopg/psycopg.h"
#include "psycopg/connection.h"
#include "psycopg/cursor.h"
#include "psycopg/pgtypes.h"
#include "psycopg/error.h"
#include <string.h>
#include <stdlib.h>
@ -356,3 +358,114 @@ exit:
#endif
}
/* psyco_set_error
*
* Create a new error of the given type with extra attributes.
*/
/* TODO: may have been changed to BORROWED */
RAISES PyObject *
psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg)
{
PyObject *pymsg;
PyObject *err = NULL;
connectionObject *conn = NULL;
if (curs) {
conn = ((cursorObject *)curs)->conn;
}
if ((pymsg = conn_text_from_chars(conn, msg))) {
err = PyObject_CallFunctionObjArgs(exc, pymsg, NULL);
Py_DECREF(pymsg);
}
else {
/* what's better than an error in an error handler in the morning?
* Anyway, some error was set, refcount is ok... get outta here. */
return NULL;
}
if (err && PyObject_TypeCheck(err, &errorType)) {
errorObject *perr = (errorObject *)err;
if (curs) {
Py_CLEAR(perr->cursor);
Py_INCREF(curs);
perr->cursor = curs;
}
}
if (err) {
PyErr_SetObject(exc, err);
Py_DECREF(err);
}
return err;
}
/* Return nonzero if the current one is the main interpreter */
static int
psyco_is_main_interp(void)
{
static PyInterpreterState *main_interp = NULL; /* Cached reference */
PyInterpreterState *interp;
if (main_interp) {
return (main_interp == PyThreadState_Get()->interp);
}
/* No cached value: cache the proper value and try again. */
interp = PyInterpreterState_Head();
while (interp->next)
interp = interp->next;
main_interp = interp;
assert (main_interp);
return psyco_is_main_interp();
}
/* psyco_GetDecimalType
Return a new reference to the adapter for decimal type.
If decimals should be used but the module import fails, fall back on
the float type.
If decimals are not to be used, return NULL.
*/
PyObject *
psyco_GetDecimalType(void)
{
static PyObject *cachedType = NULL;
PyObject *decimalType = NULL;
PyObject *decimal;
/* Use the cached object if running from the main interpreter. */
int can_cache = psyco_is_main_interp();
if (can_cache && cachedType) {
Py_INCREF(cachedType);
return cachedType;
}
/* Get a new reference to the Decimal type. */
decimal = PyImport_ImportModule("decimal");
if (decimal) {
decimalType = PyObject_GetAttrString(decimal, "Decimal");
Py_DECREF(decimal);
}
else {
PyErr_Clear();
decimalType = NULL;
}
/* Store the object from future uses. */
if (can_cache && !cachedType && decimalType) {
Py_INCREF(decimalType);
cachedType = decimalType;
}
return decimalType;
}

61
psycopg/utils.h Normal file
View File

@ -0,0 +1,61 @@
/* utils.h - function definitions for utility file
*
* Copyright (C) 2018 Daniele Varrazzo <daniele.varrazzo@gmail.com>
*
* This file is part of psycopg.
*
* psycopg2 is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, as a special exception, the copyright holders give
* permission to link this program with the OpenSSL library (or with
* modified versions of OpenSSL that use the same license as OpenSSL),
* and distribute linked combinations including the two.
*
* You must obey the GNU Lesser General Public License in all respects for
* all of the code used other than OpenSSL.
*
* psycopg2 is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*/
#ifndef UTILS_H
#define UTILS_H 1
/* forward declarations */
typedef struct cursorObject cursorObject;
typedef struct connectionObject connectionObject;
typedef struct replicationMessageObject replicationMessageObject;
HIDDEN char *psycopg_escape_string(
connectionObject *conn,
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen);
HIDDEN char *psycopg_escape_identifier(
connectionObject *conn, const char *str, Py_ssize_t len);
HIDDEN int psycopg_strdup(char **to, const char *from, Py_ssize_t len);
STEALS(1) HIDDEN PyObject * psycopg_ensure_bytes(PyObject *obj);
STEALS(1) HIDDEN PyObject * psycopg_ensure_text(PyObject *obj);
HIDDEN int psycopg_is_text_file(PyObject *f);
HIDDEN PyObject *psycopg_dict_from_conninfo_options(
PQconninfoOption *options, int include_password);
HIDDEN PyObject *psycopg_make_dsn(PyObject *dsn, PyObject *kwargs);
HIDDEN PyObject *psycopg_text_from_chars_safe(
const char *str, Py_ssize_t len, PyObject *decoder);
RAISES HIDDEN PyObject *psyco_set_error(
PyObject *exc, cursorObject *curs, const char *msg);
HIDDEN PyObject *psyco_GetDecimalType(void);
#endif /* !defined(UTILS_H) */

View File

@ -509,7 +509,7 @@ depends = [
'replication_cursor.h',
'replication_message.h',
'notify.h', 'pqpath.h', 'xid.h', 'column.h', 'conninfo.h',
'libpq_support.h', 'win32_support.h',
'libpq_support.h', 'win32_support.h', 'utils.h',
'adapter_asis.h', 'adapter_binary.h', 'adapter_datetime.h',
'adapter_list.h', 'adapter_pboolean.h', 'adapter_pdecimal.h',