mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-02-12 07:10:33 +03:00
Fixed crash and win32 patches.
This commit is contained in:
parent
d6f2aa27b7
commit
2a6b523506
|
@ -1,3 +1,11 @@
|
||||||
|
2007-04-11 Federico Di Gregorio <fog@initd.org>
|
||||||
|
|
||||||
|
* psycopg/cursor_type.c: added check to raise an error when
|
||||||
|
some crazy programmer tries to use different argument formats
|
||||||
|
in the same query string. Fixes #162.
|
||||||
|
|
||||||
|
* Applied patch from David Rushby to fix win32 builds.
|
||||||
|
|
||||||
2007-04-10 Federico Di Gregorio <fog@initd.org>
|
2007-04-10 Federico Di Gregorio <fog@initd.org>
|
||||||
|
|
||||||
* Applied patch from David Rushby to fix mem and ref leaks in
|
* Applied patch from David Rushby to fix mem and ref leaks in
|
||||||
|
|
|
@ -52,6 +52,17 @@ static void Dprintf(const char *fmt, ...) {}
|
||||||
#if defined(_WIN32) || defined(__BEOS__)
|
#if defined(_WIN32) || defined(__BEOS__)
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
/* A Python extension should be linked to only one C runtime: the same one as
|
||||||
|
* the Python interpreter itself. Straightforwardly using the strdup function
|
||||||
|
* causes MinGW to implicitly link to the msvcrt.dll, which is not appropriate
|
||||||
|
* for any Python version later than 2.3.
|
||||||
|
* Microsoft C runtimes for Windows 98 and later make a _strdup function
|
||||||
|
* available, which replaces the "normal" strdup. If we replace all psycopg
|
||||||
|
* calls to strdup with calls to _strdup, MinGW no longer implicitly links to
|
||||||
|
* the obsolete C runtime. */
|
||||||
|
#define strdup _strdup
|
||||||
|
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#define pthread_mutex_t HANDLE
|
#define pthread_mutex_t HANDLE
|
||||||
#define pthread_condvar_t HANDLE
|
#define pthread_condvar_t HANDLE
|
||||||
|
@ -102,7 +113,7 @@ static struct tm *localtime_r(time_t *t, struct tm *tm)
|
||||||
#define inline
|
#define inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(_WIN32) || defined(__sun__)
|
#if defined(__FreeBSD__) || (defined(_WIN32) && !defined(__GNUC__)) || defined(__sun__)
|
||||||
/* what's this, we have no round function either? */
|
/* what's this, we have no round function either? */
|
||||||
static double round(double num)
|
static double round(double num)
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,7 +79,7 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
|
||||||
PyObject *key, *value, *n, *item;
|
PyObject *key, *value, *n, *item;
|
||||||
char *d, *c;
|
char *d, *c;
|
||||||
Py_ssize_t index = 0;
|
Py_ssize_t index = 0;
|
||||||
int force = 0;
|
int force = 0, kind = 0;
|
||||||
|
|
||||||
/* from now on we'll use n and replace its value in *new only at the end,
|
/* from now on we'll use n and replace its value in *new only at the end,
|
||||||
just before returning. we also init *new to NULL to exit with an error
|
just before returning. we also init *new to NULL to exit with an error
|
||||||
|
@ -88,6 +88,15 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
|
||||||
c = PyString_AsString(fmt);
|
c = PyString_AsString(fmt);
|
||||||
|
|
||||||
while(*c) {
|
while(*c) {
|
||||||
|
/* check if some crazy guy mixed formats */
|
||||||
|
if (kind == 2) {
|
||||||
|
Py_XDECREF(n);
|
||||||
|
psyco_set_error(ProgrammingError, (PyObject*)conn,
|
||||||
|
"argument formats can't be mixed", NULL, NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
kind = 1;
|
||||||
|
|
||||||
/* handle plain percent symbol in format string */
|
/* handle plain percent symbol in format string */
|
||||||
if (c[0] == '%' && c[1] == '%') {
|
if (c[0] == '%' && c[1] == '%') {
|
||||||
c+=2; force = 1;
|
c+=2; force = 1;
|
||||||
|
@ -182,6 +191,15 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
|
||||||
because we don't need to check the old/new dictionary for
|
because we don't need to check the old/new dictionary for
|
||||||
keys */
|
keys */
|
||||||
|
|
||||||
|
/* check if some crazy guy mixed formats */
|
||||||
|
if (kind == 1) {
|
||||||
|
Py_XDECREF(n);
|
||||||
|
psyco_set_error(ProgrammingError, (PyObject*)conn,
|
||||||
|
"argument formats can't be mixed", NULL, NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
kind = 2;
|
||||||
|
|
||||||
value = PySequence_GetItem(var, index);
|
value = PySequence_GetItem(var, index);
|
||||||
/* value has refcnt inc'ed by 1 here */
|
/* value has refcnt inc'ed by 1 here */
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[build_ext]
|
[build_ext]
|
||||||
define=PSYCOPG_EXTENSIONS,PSYCOPG_DISPLAY_SIZE,PSYCOPG_NEW_BOOLEAN,HAVE_PQFREEMEM,HAVE_PQPROTOCOL3
|
define=PSYCOPG_EXTENSIONS,PSYCOPG_DISPLAY_SIZE,PSYCOPG_NEW_BOOLEAN,HAVE_PQFREEMEM,HAVE_PQPROTOCOL3,PSYCOPG_DEBUG
|
||||||
# PSYCOPG_EXTENSIONS enables extensions to PEP-249 (you really want this)
|
# PSYCOPG_EXTENSIONS enables extensions to PEP-249 (you really want this)
|
||||||
# PSYCOPG_DISPLAY_SIZE enable display size calculation (a little slower)
|
# PSYCOPG_DISPLAY_SIZE enable display size calculation (a little slower)
|
||||||
# HAVE_PQFREEMEM should be defined on PostgreSQL >= 7.4
|
# HAVE_PQFREEMEM should be defined on PostgreSQL >= 7.4
|
||||||
|
|
154
setup.py
154
setup.py
|
@ -44,8 +44,10 @@ Operating System :: Unix
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
import popen2
|
import popen2
|
||||||
|
import ConfigParser
|
||||||
from distutils.core import setup, Extension
|
from distutils.core import setup, Extension
|
||||||
from distutils.errors import DistutilsFileError
|
from distutils.errors import DistutilsFileError
|
||||||
from distutils.command.build_ext import build_ext
|
from distutils.command.build_ext import build_ext
|
||||||
|
@ -55,6 +57,8 @@ from distutils.ccompiler import get_default_compiler
|
||||||
PSYCOPG_VERSION = '2.0.6b1'
|
PSYCOPG_VERSION = '2.0.6b1'
|
||||||
version_flags = []
|
version_flags = []
|
||||||
|
|
||||||
|
PLATFORM_IS_WINDOWS = sys.platform.lower().startswith('win')
|
||||||
|
|
||||||
# to work around older distutil limitations
|
# to work around older distutil limitations
|
||||||
if sys.version < '2.2.3':
|
if sys.version < '2.2.3':
|
||||||
from distutils.dist import DistributionMetadata
|
from distutils.dist import DistributionMetadata
|
||||||
|
@ -97,35 +101,76 @@ class psycopg_build_ext(build_ext):
|
||||||
build_ext.initialize_options(self)
|
build_ext.initialize_options(self)
|
||||||
self.use_pg_dll = 1
|
self.use_pg_dll = 1
|
||||||
self.pgdir = None
|
self.pgdir = None
|
||||||
self.pg_config = self.DEFAULT_PG_CONFIG
|
|
||||||
self.mx_include_dir = None
|
self.mx_include_dir = None
|
||||||
|
|
||||||
|
self.pg_config = self.autodetect_pg_config_path()
|
||||||
|
|
||||||
def get_compiler(self):
|
def get_compiler(self):
|
||||||
"""Return the c compiler to compile extensions.
|
"""Return the name of the C compiler used to compile extensions.
|
||||||
|
|
||||||
If a compiler was not explicitely set (on the command line, for
|
If a compiler was not explicitely set (on the command line, for
|
||||||
example), fall back on the default compiler.
|
example), fall back on the default compiler.
|
||||||
"""
|
"""
|
||||||
return self.compiler or get_default_compiler()
|
if self.compiler:
|
||||||
|
# distutils doesn't keep the type of self.compiler uniform; we
|
||||||
|
# compensate:
|
||||||
|
if isinstance(self.compiler, str):
|
||||||
|
name = self.compiler
|
||||||
|
else:
|
||||||
|
name = self.compiler.compiler_type
|
||||||
|
else:
|
||||||
|
name = get_default_compiler()
|
||||||
|
return name
|
||||||
|
|
||||||
def get_pg_config(self, kind):
|
def get_pg_config(self, kind):
|
||||||
return get_pg_config(kind, self.pg_config)
|
return get_pg_config(kind, self.pg_config)
|
||||||
|
|
||||||
def build_extensions(self):
|
|
||||||
# Linking against this library causes psycopg2 to crash
|
|
||||||
# on Python >= 2.4. Maybe related to strdup calls, cfr.
|
|
||||||
# http://mail.python.org/pipermail/distutils-sig/2005-April/004433.html
|
|
||||||
if self.get_compiler().compiler_type == "mingw32" \
|
|
||||||
and 'msvcr71' in self.compiler.dll_libraries:
|
|
||||||
self.compiler.dll_libraries.remove('msvcr71')
|
|
||||||
|
|
||||||
build_ext.build_extensions(self)
|
|
||||||
|
|
||||||
def finalize_win32(self):
|
def finalize_win32(self):
|
||||||
"""Finalize build system configuration on win32 platform."""
|
"""Finalize build system configuration on win32 platform."""
|
||||||
|
import struct
|
||||||
|
sysVer = sys.version_info[:2]
|
||||||
|
|
||||||
|
# Add compiler-specific arguments:
|
||||||
|
extra_compiler_args = []
|
||||||
|
|
||||||
|
compiler_name = self.get_compiler().lower()
|
||||||
|
compiler_is_msvc = compiler_name.startswith('msvc')
|
||||||
|
compiler_is_mingw = compiler_name.startswith('mingw')
|
||||||
|
if compiler_is_msvc:
|
||||||
|
# If we're using MSVC 7.1 or later on a 32-bit platform, add the
|
||||||
|
# /Wp64 option to generate warnings about Win64 portability
|
||||||
|
# problems.
|
||||||
|
if sysVer >= (2,4) and struct.calcsize('P') == 4:
|
||||||
|
extra_compiler_args.append('/Wp64')
|
||||||
|
elif compiler_is_mingw:
|
||||||
|
# Default MinGW compilation of Python extensions on Windows uses
|
||||||
|
# only -O:
|
||||||
|
extra_compiler_args.append('-O3')
|
||||||
|
|
||||||
|
# GCC-compiled Python on non-Windows platforms is built with strict
|
||||||
|
# aliasing disabled, but that must be done explicitly on Windows to
|
||||||
|
# avoid large numbers of warnings for perfectly idiomatic Python C
|
||||||
|
# API code.
|
||||||
|
extra_compiler_args.append('-fno-strict-aliasing')
|
||||||
|
|
||||||
|
# Force correct C runtime library linkage:
|
||||||
|
if sysVer <= (2,3):
|
||||||
|
# Yes: 'msvcr60', rather than 'msvcrt', is the correct value
|
||||||
|
# on the line below:
|
||||||
|
self.libraries.append('msvcr60')
|
||||||
|
elif sysVer in ((2,4), (2,5)):
|
||||||
|
self.libraries.append('msvcr71')
|
||||||
|
# Beyond Python 2.5, we take our chances on the default C runtime
|
||||||
|
# library, because we don't know what compiler those future
|
||||||
|
# versions of Python will use.
|
||||||
|
|
||||||
|
for exten in ext: # ext is a global list of Extension objects
|
||||||
|
exten.extra_compile_args.extend(extra_compiler_args)
|
||||||
|
# End of add-compiler-specific arguments section.
|
||||||
|
|
||||||
self.libraries.append("ws2_32")
|
self.libraries.append("ws2_32")
|
||||||
self.libraries.append("advapi32")
|
self.libraries.append("advapi32")
|
||||||
if self.get_compiler() == "msvc":
|
if compiler_is_msvc:
|
||||||
# MSVC requires an explicit "libpq"
|
# MSVC requires an explicit "libpq"
|
||||||
self.libraries.remove("pq")
|
self.libraries.remove("pq")
|
||||||
self.libraries.append("libpq")
|
self.libraries.append("libpq")
|
||||||
|
@ -172,6 +217,82 @@ class psycopg_build_ext(build_ext):
|
||||||
if hasattr(self, "finalize_" + sys.platform):
|
if hasattr(self, "finalize_" + sys.platform):
|
||||||
getattr(self, "finalize_" + sys.platform)()
|
getattr(self, "finalize_" + sys.platform)()
|
||||||
|
|
||||||
|
def autodetect_pg_config_path(self):
|
||||||
|
res = None
|
||||||
|
|
||||||
|
if PLATFORM_IS_WINDOWS:
|
||||||
|
res = self.autodetect_pg_config_path_windows()
|
||||||
|
|
||||||
|
return res or self.DEFAULT_PG_CONFIG
|
||||||
|
|
||||||
|
def autodetect_pg_config_path_windows(self):
|
||||||
|
# Find the first PostgreSQL installation listed in the registry and
|
||||||
|
# return the full path to its pg_config utility.
|
||||||
|
#
|
||||||
|
# This autodetection is performed *only* if the following conditions
|
||||||
|
# hold:
|
||||||
|
#
|
||||||
|
# 1) The pg_config utility is not already available on the PATH:
|
||||||
|
if os.popen('pg_config').close() is None: # .close()->None == success
|
||||||
|
return None
|
||||||
|
# 2) The user has not specified any of the following settings in
|
||||||
|
# setup.cfg:
|
||||||
|
# - pg_config
|
||||||
|
# - include_dirs
|
||||||
|
# - library_dirs
|
||||||
|
for settingName in ('pg_config', 'include_dirs', 'library_dirs'):
|
||||||
|
try:
|
||||||
|
val = parser.get('build_ext', settingName)
|
||||||
|
except ConfigParser.NoOptionError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if val.strip() != '':
|
||||||
|
return None
|
||||||
|
# end of guard conditions
|
||||||
|
|
||||||
|
import _winreg
|
||||||
|
|
||||||
|
pg_inst_base_dir = None
|
||||||
|
pg_config_path = None
|
||||||
|
|
||||||
|
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
|
||||||
|
pg_inst_list_key = _winreg.OpenKey(reg,
|
||||||
|
'SOFTWARE\\PostgreSQL\\Installations'
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
# Determine the name of the first subkey, if any:
|
||||||
|
try:
|
||||||
|
first_sub_key_name = _winreg.EnumKey(pg_inst_list_key, 0)
|
||||||
|
except EnvironmentError:
|
||||||
|
first_sub_key_name = None
|
||||||
|
|
||||||
|
if first_sub_key_name is not None:
|
||||||
|
pg_first_inst_key = _winreg.OpenKey(reg,
|
||||||
|
'SOFTWARE\\PostgreSQL\\Installations\\'
|
||||||
|
+ first_sub_key_name
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
pg_inst_base_dir = _winreg.QueryValueEx(
|
||||||
|
pg_first_inst_key, 'Base Directory'
|
||||||
|
)[0]
|
||||||
|
finally:
|
||||||
|
_winreg.CloseKey(pg_first_inst_key)
|
||||||
|
finally:
|
||||||
|
_winreg.CloseKey(pg_inst_list_key)
|
||||||
|
|
||||||
|
if pg_inst_base_dir and os.path.exists(pg_inst_base_dir):
|
||||||
|
pg_config_path = os.path.join(pg_inst_base_dir, 'bin',
|
||||||
|
'pg_config.exe'
|
||||||
|
)
|
||||||
|
# Support unicode paths, if this version of Python provides the
|
||||||
|
# necessary infrastructure:
|
||||||
|
if hasattr(sys, 'getfilesystemencoding'):
|
||||||
|
pg_config_path = pg_config_path.encode(
|
||||||
|
sys.getfilesystemencoding()
|
||||||
|
)
|
||||||
|
|
||||||
|
return pg_config_path
|
||||||
|
|
||||||
# let's start with macro definitions (the ones not already in setup.cfg)
|
# let's start with macro definitions (the ones not already in setup.cfg)
|
||||||
define_macros = []
|
define_macros = []
|
||||||
include_dirs = []
|
include_dirs = []
|
||||||
|
@ -196,8 +317,7 @@ sources = [
|
||||||
'adapter_qstring.c', 'adapter_pboolean.c', 'adapter_binary.c',
|
'adapter_qstring.c', 'adapter_pboolean.c', 'adapter_binary.c',
|
||||||
'adapter_asis.c', 'adapter_list.c']
|
'adapter_asis.c', 'adapter_list.c']
|
||||||
|
|
||||||
from ConfigParser import ConfigParser
|
parser = ConfigParser.ConfigParser()
|
||||||
parser = ConfigParser()
|
|
||||||
parser.read('setup.cfg')
|
parser.read('setup.cfg')
|
||||||
|
|
||||||
# Choose if to use Decimal type
|
# Choose if to use Decimal type
|
||||||
|
@ -259,7 +379,7 @@ if version_flags:
|
||||||
else:
|
else:
|
||||||
PSYCOPG_VERSION_EX = PSYCOPG_VERSION
|
PSYCOPG_VERSION_EX = PSYCOPG_VERSION
|
||||||
|
|
||||||
if sys.platform != 'win32':
|
if not PLATFORM_IS_WINDOWS:
|
||||||
define_macros.append(('PSYCOPG_VERSION', '"'+PSYCOPG_VERSION_EX+'"'))
|
define_macros.append(('PSYCOPG_VERSION', '"'+PSYCOPG_VERSION_EX+'"'))
|
||||||
else:
|
else:
|
||||||
define_macros.append(('PSYCOPG_VERSION', '\\"'+PSYCOPG_VERSION_EX+'\\"'))
|
define_macros.append(('PSYCOPG_VERSION', '\\"'+PSYCOPG_VERSION_EX+'\\"'))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user