Merge remote-tracking branch 'origin/pycurl' into planetlab-4_0-branch
[plcapi.git] / psycopg2 / setup.py
1 # setup.py - distutils packaging
2 #
3 # Copyright (C) 2003-2004 Federico Di Gregorio  <fog@debian.org>
4 #
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
8 # version.
9 #
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
13 # for more details.
14
15 """Python-PostgreSQL Database Adapter
16  
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.
22  
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
27 brave programmer.
28 """
29
30 classifiers = """\
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
38 Topic :: Database
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
44 """
45
46 import os
47 import sys
48 import popen2
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
54
55 PSYCOPG_VERSION = '2.0.5.1'
56 version_flags   = []
57
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
63
64 def get_pg_config(kind, pg_config="pg_config"):
65     p = popen2.popen3(pg_config + " --" + kind)
66     r = p[0].readline().strip()
67     if not r:
68         raise Warning(p[2].readline())
69     return r
70     
71 class psycopg_build_ext(build_ext):
72     """Conditionally complement the setup.cfg options file.
73     
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.
77     
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.
80     """
81     user_options = build_ext.user_options[:]
82     user_options.extend([
83         ('use-pydatetime', None,
84          "Use Python datatime objects for date and time representation."),    
85         ('pg-config=', None,
86           "The name of the pg_config binary and/or full path to find it"),
87         ('use-decimal', None,
88          "Use Decimal type even on Python 2.3 if the module is provided."),
89     ])
90     
91     boolean_options = build_ext.boolean_options[:]
92     boolean_options.extend(('use-pydatetime', 'use-decimal'))
93     
94     DEFAULT_PG_CONFIG = "pg_config"
95     
96     def initialize_options(self):
97         build_ext.initialize_options(self)
98         self.use_pg_dll = 1
99         self.pgdir = None
100         self.pg_config = self.DEFAULT_PG_CONFIG
101         self.mx_include_dir = None
102     
103     def get_compiler(self):
104         """Return the c compiler to compile extensions.
105
106         If a compiler was not explicitely set (on the command line, for
107         example), fall back on the default compiler.
108         """
109         return self.compiler or get_default_compiler()
110
111     def get_pg_config(self, kind):
112         return get_pg_config(kind, self.pg_config)
113
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')
121
122         build_ext.build_extensions(self)
123         
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")) 
136                     break
137  
138     def finalize_darwin(self):
139         """Finalize build system configuration on darwin platform."""
140         self.libraries.append('ssl')
141         self.libraries.append('crypto')
142         
143     def finalize_options(self):
144         """Complete the build system configuation."""
145         build_ext.finalize_options(self)
146
147         self.include_dirs.append(".")        
148         self.libraries.append("pq")
149         
150         try:
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"))
154             try:
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('.')
160             except:
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))
165         except Warning, w:
166             if self.pg_config == self.DEFAULT_PG_CONFIG:
167                 sys.stderr.write("Warning: %s" % str(w))
168             else:
169                 sys.stderr.write("Error: %s" % str(w))
170                 sys.exit(1)
171             
172         if hasattr(self, "finalize_" + sys.platform):
173             getattr(self, "finalize_" + sys.platform)()
174             
175 # let's start with macro definitions (the ones not already in setup.cfg)
176 define_macros = []
177 include_dirs = []
178
179 # python version
180 define_macros.append(('PY_MAJOR_VERSION', str(sys.version_info[0])))
181 define_macros.append(('PY_MINOR_VERSION', str(sys.version_info[1])))
182
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'))
186     
187 # gather information to build the extension module
188 ext = [] ; data_files = []
189
190 # sources
191
192 sources = [
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']
198
199 from ConfigParser import ConfigParser
200 parser = ConfigParser()
201 parser.read('setup.cfg')
202
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')
209
210 # Choose a datetime module
211 have_pydatetime = False
212 have_mxdatetime = False
213 use_pydatetime  = int(parser.get('build_ext', 'use_pydatetime'))
214
215 # check for mx package
216 if parser.has_option('build_ext', 'mx_include_dir'):
217     mxincludedir = parser.get('build_ext', 'mx_include_dir')
218 else:
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')
226
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')
233     
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'))
240 else:
241     def e(msg):
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.")
249     sys.exit(1)
250
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')
257 if version_flags:
258     PSYCOPG_VERSION_EX = PSYCOPG_VERSION + " (%s)" % ' '.join(version_flags)
259 else:
260     PSYCOPG_VERSION_EX = PSYCOPG_VERSION
261     
262 if sys.platform != 'win32':
263     define_macros.append(('PSYCOPG_VERSION', '"'+PSYCOPG_VERSION_EX+'"'))
264 else:
265     define_macros.append(('PSYCOPG_VERSION', '\\"'+PSYCOPG_VERSION_EX+'\\"'))
266
267 # build the extension
268
269 sources = map(lambda x: os.path.join('psycopg', x), sources)
270
271 ext.append(Extension("psycopg2._psycopg", sources,
272                      define_macros=define_macros,
273                      include_dirs=include_dirs,
274                      undef_macros=[]))
275
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",
285       platforms = ["any"],
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 },
293       ext_modules=ext)