1 # setup.py - distutils packaging
3 # Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by the
7 # Free Software Foundation; either version 2, or (at your option) any later
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 """Python-PostgreSQL Database Adapter
17 psycopg is a PostgreSQL database adapter for the Python programming
18 language. This is version 2, a complete rewrite of the original code to
19 provide new-style classes for connection and cursor objects and other sweet
20 candies. Like the original, psycopg 2 was written with the aim of being
21 very small and fast, and stable as a rock.
23 psycopg is different from the other database adapter because it was
24 designed for heavily multi-threaded applications that create and destroy
25 lots of cursors and make a conspicuous number of concurrent INSERTs or
26 UPDATEs. psycopg 2 also provide full asycronous operations for the really
31 Development Status :: 4 - Beta
32 Intended Audience :: Developers
33 License :: OSI Approved :: GNU General Public License (GPL)
34 License :: OSI Approved :: Zope Public License
35 Programming Language :: Python
36 Programming Language :: C
37 Programming Language :: SQL
39 Topic :: Database :: Front-Ends
40 Topic :: Software Development
41 Topic :: Software Development :: Libraries :: Python Modules
42 Operating System :: Microsoft :: Windows
43 Operating System :: Unix
49 from distutils.core import setup, Extension
50 from distutils.errors import DistutilsFileError
51 from distutils.command.build_ext import build_ext
52 from distutils.sysconfig import get_python_inc
53 from distutils.ccompiler import get_default_compiler
55 PSYCOPG_VERSION = '2.0.5.1'
58 # to work around older distutil limitations
59 if sys.version < '2.2.3':
60 from distutils.dist import DistributionMetadata
61 DistributionMetadata.classifiers = None
62 DistributionMetadata.download_url = None
64 def get_pg_config(kind, pg_config="pg_config"):
65 p = popen2.popen3(pg_config + " --" + kind)
66 r = p[0].readline().strip()
68 raise Warning(p[2].readline())
71 class psycopg_build_ext(build_ext):
72 """Conditionally complement the setup.cfg options file.
74 This class configures the include_dirs, libray_dirs, libraries
75 options as required by the system. Most of the configuration happens
76 in finalize_options() method.
78 If you want to set up the build step for a peculiar platform, add a
79 method finalize_PLAT(), where PLAT matches your sys.platform.
81 user_options = build_ext.user_options[:]
83 ('use-pydatetime', None,
84 "Use Python datatime objects for date and time representation."),
86 "The name of the pg_config binary and/or full path to find it"),
88 "Use Decimal type even on Python 2.3 if the module is provided."),
91 boolean_options = build_ext.boolean_options[:]
92 boolean_options.extend(('use-pydatetime', 'use-decimal'))
94 DEFAULT_PG_CONFIG = "pg_config"
96 def initialize_options(self):
97 build_ext.initialize_options(self)
100 self.pg_config = self.DEFAULT_PG_CONFIG
101 self.mx_include_dir = None
103 def get_compiler(self):
104 """Return the c compiler to compile extensions.
106 If a compiler was not explicitely set (on the command line, for
107 example), fall back on the default compiler.
109 return self.compiler or get_default_compiler()
111 def get_pg_config(self, kind):
112 return get_pg_config(kind, self.pg_config)
114 def build_extensions(self):
115 # Linking against this library causes psycopg2 to crash
116 # on Python >= 2.4. Maybe related to strdup calls, cfr.
117 # http://mail.python.org/pipermail/distutils-sig/2005-April/004433.html
118 if self.get_compiler().compiler_type == "mingw32" \
119 and 'msvcr71' in self.compiler.dll_libraries:
120 self.compiler.dll_libraries.remove('msvcr71')
122 build_ext.build_extensions(self)
124 def finalize_win32(self):
125 """Finalize build system configuration on win32 platform."""
126 self.libraries.append("ws2_32")
127 self.libraries.append("advapi32")
128 if self.get_compiler() == "msvc":
129 # MSVC requires an explicit "libpq"
130 self.libraries.remove("pq")
131 self.libraries.append("libpq")
132 self.libraries.append("shfolder")
133 for path in self.library_dirs:
134 if os.path.isfile(os.path.join(path, "ms", "libpq.lib")):
135 self.library_dirs.append(os.path.join(path, "ms"))
138 def finalize_darwin(self):
139 """Finalize build system configuration on darwin platform."""
140 self.libraries.append('ssl')
141 self.libraries.append('crypto')
143 def finalize_options(self):
144 """Complete the build system configuation."""
145 build_ext.finalize_options(self)
147 self.include_dirs.append(".")
148 self.libraries.append("pq")
151 self.library_dirs.append(self.get_pg_config("libdir"))
152 self.include_dirs.append(self.get_pg_config("includedir"))
153 self.include_dirs.append(self.get_pg_config("includedir-server"))
155 # Here we take a conservative approach: we suppose that
156 # *at least* PostgreSQL 7.4 is available (this is the only
157 # 7.x series supported by psycopg 2)
158 pgversion = self.get_pg_config("version").split()[1]
159 pgmajor, pgminor, pgpatch = pgversion.split('.')
161 pgmajor, pgminor, pgpatch = 7, 4, 0
162 define_macros.append(("PG_MAJOR_VERSION", pgmajor))
163 define_macros.append(("PG_MINOR_VERSION", pgminor))
164 define_macros.append(("PG_PATCH_VERSION", pgpatch))
166 if self.pg_config == self.DEFAULT_PG_CONFIG:
167 sys.stderr.write("Warning: %s" % str(w))
169 sys.stderr.write("Error: %s" % str(w))
172 if hasattr(self, "finalize_" + sys.platform):
173 getattr(self, "finalize_" + sys.platform)()
175 # let's start with macro definitions (the ones not already in setup.cfg)
180 define_macros.append(('PY_MAJOR_VERSION', str(sys.version_info[0])))
181 define_macros.append(('PY_MINOR_VERSION', str(sys.version_info[1])))
183 # some macros related to python versions and features
184 if sys.version_info[0] >= 2 and sys.version_info[1] >= 3:
185 define_macros.append(('HAVE_PYBOOL','1'))
187 # gather information to build the extension module
188 ext = [] ; data_files = []
193 'psycopgmodule.c', 'pqpath.c', 'typecast.c',
194 'microprotocols.c', 'microprotocols_proto.c',
195 'connection_type.c', 'connection_int.c', 'cursor_type.c', 'cursor_int.c',
196 'adapter_qstring.c', 'adapter_pboolean.c', 'adapter_binary.c',
197 'adapter_asis.c', 'adapter_list.c']
199 from ConfigParser import ConfigParser
200 parser = ConfigParser()
201 parser.read('setup.cfg')
203 # Choose if to use Decimal type
204 use_decimal = int(parser.get('build_ext', 'use_decimal'))
205 if sys.version_info[0] >= 2 and (
206 sys.version_info[1] >= 4 or (sys.version_info[1] == 3 and use_decimal)):
207 define_macros.append(('HAVE_DECIMAL','1'))
208 version_flags.append('dec')
210 # Choose a datetime module
211 have_pydatetime = False
212 have_mxdatetime = False
213 use_pydatetime = int(parser.get('build_ext', 'use_pydatetime'))
215 # check for mx package
216 if parser.has_option('build_ext', 'mx_include_dir'):
217 mxincludedir = parser.get('build_ext', 'mx_include_dir')
219 mxincludedir = os.path.join(get_python_inc(plat_specific=1), "mx")
220 if os.path.exists(mxincludedir):
221 include_dirs.append(mxincludedir)
222 define_macros.append(('HAVE_MXDATETIME','1'))
223 sources.append('adapter_mxdatetime.c')
224 have_mxdatetime = True
225 version_flags.append('mx')
227 # check for python datetime package
228 if os.path.exists(os.path.join(get_python_inc(plat_specific=1),"datetime.h")):
229 define_macros.append(('HAVE_PYDATETIME','1'))
230 sources.append('adapter_datetime.c')
231 have_pydatetime = True
232 version_flags.append('dt')
234 # now decide which package will be the default for date/time typecasts
235 if have_pydatetime and use_pydatetime \
236 or have_pydatetime and not have_mxdatetime:
237 define_macros.append(('PSYCOPG_DEFAULT_PYDATETIME','1'))
238 elif have_mxdatetime:
239 define_macros.append(('PSYCOPG_DEFAULT_MXDATETIME','1'))
242 sys.stderr.write("error: " + msg + "\n")
243 e("psycopg requires a datetime module:")
244 e(" mx.DateTime module not found")
245 e(" python datetime module not found")
246 e("Note that psycopg needs the module headers and not just the module")
247 e("itself. If you installed Python or mx.DateTime from a binary package")
248 e("you probably need to install its companion -dev or -devel package.")
251 # generate a nice version string to avoid confusion when users report bugs
252 for have in parser.get('build_ext', 'define').split(','):
253 if have == 'PSYCOPG_EXTENSIONS':
254 version_flags.append('ext')
255 elif have == 'HAVE_PQPROTOCOL3':
256 version_flags.append('pq3')
258 PSYCOPG_VERSION_EX = PSYCOPG_VERSION + " (%s)" % ' '.join(version_flags)
260 PSYCOPG_VERSION_EX = PSYCOPG_VERSION
262 if sys.platform != 'win32':
263 define_macros.append(('PSYCOPG_VERSION', '"'+PSYCOPG_VERSION_EX+'"'))
265 define_macros.append(('PSYCOPG_VERSION', '\\"'+PSYCOPG_VERSION_EX+'\\"'))
267 # build the extension
269 sources = map(lambda x: os.path.join('psycopg', x), sources)
271 ext.append(Extension("psycopg2._psycopg", sources,
272 define_macros=define_macros,
273 include_dirs=include_dirs,
276 setup(name="psycopg2",
277 version=PSYCOPG_VERSION,
278 maintainer="Federico Di Gregorio",
279 maintainer_email="fog@initd.org",
280 author="Federico Di Gregorio",
281 author_email="fog@initd.org",
282 url="http://initd.org/tracker/psycopg",
283 download_url = "http://initd.org/pub/software/psycopg2",
284 license="GPL with exceptions or ZPL",
286 description=__doc__.split("\n")[0],
287 long_description="\n".join(__doc__.split("\n")[2:]),
288 classifiers=filter(None, classifiers.split("\n")),
289 data_files=data_files,
290 package_dir={'psycopg2':'lib'},
291 packages=['psycopg2'],
292 cmdclass={ 'build_ext': psycopg_build_ext },