mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-02-07 12:50:32 +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>
|
||||
|
||||
* 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__)
|
||||
|
||||
#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>
|
||||
#define pthread_mutex_t HANDLE
|
||||
#define pthread_condvar_t HANDLE
|
||||
|
@ -102,7 +113,7 @@ static struct tm *localtime_r(time_t *t, struct tm *tm)
|
|||
#define inline
|
||||
#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? */
|
||||
static double round(double num)
|
||||
{
|
||||
|
|
|
@ -79,7 +79,7 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
|
|||
PyObject *key, *value, *n, *item;
|
||||
char *d, *c;
|
||||
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,
|
||||
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);
|
||||
|
||||
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 */
|
||||
if (c[0] == '%' && c[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
|
||||
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 has refcnt inc'ed by 1 here */
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[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_DISPLAY_SIZE enable display size calculation (a little slower)
|
||||
# HAVE_PQFREEMEM should be defined on PostgreSQL >= 7.4
|
||||
|
|
200
setup.py
200
setup.py
|
@ -13,13 +13,13 @@
|
|||
# for more details.
|
||||
|
||||
"""Python-PostgreSQL Database Adapter
|
||||
|
||||
|
||||
psycopg is a PostgreSQL database adapter for the Python programming
|
||||
language. This is version 2, a complete rewrite of the original code to
|
||||
provide new-style classes for connection and cursor objects and other sweet
|
||||
candies. Like the original, psycopg 2 was written with the aim of being
|
||||
very small and fast, and stable as a rock.
|
||||
|
||||
|
||||
psycopg is different from the other database adapter because it was
|
||||
designed for heavily multi-threaded applications that create and destroy
|
||||
lots of cursors and make a conspicuous number of concurrent INSERTs or
|
||||
|
@ -44,8 +44,10 @@ Operating System :: Unix
|
|||
"""
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
import popen2
|
||||
import ConfigParser
|
||||
from distutils.core import setup, Extension
|
||||
from distutils.errors import DistutilsFileError
|
||||
from distutils.command.build_ext import build_ext
|
||||
|
@ -55,6 +57,8 @@ from distutils.ccompiler import get_default_compiler
|
|||
PSYCOPG_VERSION = '2.0.6b1'
|
||||
version_flags = []
|
||||
|
||||
PLATFORM_IS_WINDOWS = sys.platform.lower().startswith('win')
|
||||
|
||||
# to work around older distutil limitations
|
||||
if sys.version < '2.2.3':
|
||||
from distutils.dist import DistributionMetadata
|
||||
|
@ -67,86 +71,127 @@ def get_pg_config(kind, pg_config="pg_config"):
|
|||
if not r:
|
||||
raise Warning(p[2].readline())
|
||||
return r
|
||||
|
||||
|
||||
class psycopg_build_ext(build_ext):
|
||||
"""Conditionally complement the setup.cfg options file.
|
||||
|
||||
|
||||
This class configures the include_dirs, libray_dirs, libraries
|
||||
options as required by the system. Most of the configuration happens
|
||||
in finalize_options() method.
|
||||
|
||||
|
||||
If you want to set up the build step for a peculiar platform, add a
|
||||
method finalize_PLAT(), where PLAT matches your sys.platform.
|
||||
"""
|
||||
user_options = build_ext.user_options[:]
|
||||
user_options.extend([
|
||||
('use-pydatetime', None,
|
||||
"Use Python datatime objects for date and time representation."),
|
||||
"Use Python datatime objects for date and time representation."),
|
||||
('pg-config=', None,
|
||||
"The name of the pg_config binary and/or full path to find it"),
|
||||
('use-decimal', None,
|
||||
"Use Decimal type even on Python 2.3 if the module is provided."),
|
||||
])
|
||||
|
||||
|
||||
boolean_options = build_ext.boolean_options[:]
|
||||
boolean_options.extend(('use-pydatetime', 'use-decimal'))
|
||||
|
||||
|
||||
DEFAULT_PG_CONFIG = "pg_config"
|
||||
|
||||
|
||||
def initialize_options(self):
|
||||
build_ext.initialize_options(self)
|
||||
self.use_pg_dll = 1
|
||||
self.pgdir = None
|
||||
self.pg_config = self.DEFAULT_PG_CONFIG
|
||||
self.mx_include_dir = None
|
||||
|
||||
|
||||
self.pg_config = self.autodetect_pg_config_path()
|
||||
|
||||
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
|
||||
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):
|
||||
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):
|
||||
"""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("advapi32")
|
||||
if self.get_compiler() == "msvc":
|
||||
if compiler_is_msvc:
|
||||
# MSVC requires an explicit "libpq"
|
||||
self.libraries.remove("pq")
|
||||
self.libraries.append("libpq")
|
||||
self.libraries.append("shfolder")
|
||||
for path in self.library_dirs:
|
||||
if os.path.isfile(os.path.join(path, "ms", "libpq.lib")):
|
||||
self.library_dirs.append(os.path.join(path, "ms"))
|
||||
for path in self.library_dirs:
|
||||
if os.path.isfile(os.path.join(path, "ms", "libpq.lib")):
|
||||
self.library_dirs.append(os.path.join(path, "ms"))
|
||||
break
|
||||
|
||||
|
||||
def finalize_darwin(self):
|
||||
"""Finalize build system configuration on darwin platform."""
|
||||
self.libraries.append('ssl')
|
||||
self.libraries.append('crypto')
|
||||
|
||||
|
||||
def finalize_options(self):
|
||||
"""Complete the build system configuation."""
|
||||
build_ext.finalize_options(self)
|
||||
|
||||
self.include_dirs.append(".")
|
||||
self.include_dirs.append(".")
|
||||
self.libraries.append("pq")
|
||||
|
||||
|
||||
try:
|
||||
self.library_dirs.append(self.get_pg_config("libdir"))
|
||||
self.include_dirs.append(self.get_pg_config("includedir"))
|
||||
|
@ -168,10 +213,86 @@ class psycopg_build_ext(build_ext):
|
|||
else:
|
||||
sys.stderr.write("Error: %s" % str(w))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if hasattr(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)
|
||||
define_macros = []
|
||||
include_dirs = []
|
||||
|
@ -183,7 +304,7 @@ define_macros.append(('PY_MINOR_VERSION', str(sys.version_info[1])))
|
|||
# some macros related to python versions and features
|
||||
if sys.version_info[0] >= 2 and sys.version_info[1] >= 3:
|
||||
define_macros.append(('HAVE_PYBOOL','1'))
|
||||
|
||||
|
||||
# gather information to build the extension module
|
||||
ext = [] ; data_files = []
|
||||
|
||||
|
@ -191,13 +312,12 @@ ext = [] ; data_files = []
|
|||
|
||||
sources = [
|
||||
'psycopgmodule.c', 'pqpath.c', 'typecast.c',
|
||||
'microprotocols.c', 'microprotocols_proto.c',
|
||||
'microprotocols.c', 'microprotocols_proto.c',
|
||||
'connection_type.c', 'connection_int.c', 'cursor_type.c', 'cursor_int.c',
|
||||
'adapter_qstring.c', 'adapter_pboolean.c', 'adapter_binary.c',
|
||||
'adapter_asis.c', 'adapter_list.c']
|
||||
|
||||
from ConfigParser import ConfigParser
|
||||
parser = ConfigParser()
|
||||
parser = ConfigParser.ConfigParser()
|
||||
parser.read('setup.cfg')
|
||||
|
||||
# Choose if to use Decimal type
|
||||
|
@ -230,7 +350,7 @@ if os.path.exists(os.path.join(get_python_inc(plat_specific=1),"datetime.h")):
|
|||
sources.append('adapter_datetime.c')
|
||||
have_pydatetime = True
|
||||
version_flags.append('dt')
|
||||
|
||||
|
||||
# now decide which package will be the default for date/time typecasts
|
||||
if have_pydatetime and use_pydatetime \
|
||||
or have_pydatetime and not have_mxdatetime:
|
||||
|
@ -258,8 +378,8 @@ if version_flags:
|
|||
PSYCOPG_VERSION_EX = PSYCOPG_VERSION + " (%s)" % ' '.join(version_flags)
|
||||
else:
|
||||
PSYCOPG_VERSION_EX = PSYCOPG_VERSION
|
||||
|
||||
if sys.platform != 'win32':
|
||||
|
||||
if not PLATFORM_IS_WINDOWS:
|
||||
define_macros.append(('PSYCOPG_VERSION', '"'+PSYCOPG_VERSION_EX+'"'))
|
||||
else:
|
||||
define_macros.append(('PSYCOPG_VERSION', '\\"'+PSYCOPG_VERSION_EX+'\\"'))
|
||||
|
|
Loading…
Reference in New Issue
Block a user