Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 321 lines (228 sloc) 11.145 kb
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
1 #!/usr/bin/python
2
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
3 import sys, os, re, platform
eb54575 @mkleehammer Issue 80: setup.py uses setuptools if available to allow building eggs
authored
4 from os.path import exists, abspath, dirname, join, isdir
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
5 from ConfigParser import SafeConfigParser
eb54575 @mkleehammer Issue 80: setup.py uses setuptools if available to allow building eggs
authored
6
7 try:
8 # Allow use of setuptools so eggs can be built.
9 from setuptools.core import setup, Command
10 except ImportError:
11 from distutils.core import setup, Command
12
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
13 from distutils.extension import Extension
14 from distutils.errors import *
15
16 OFFICIAL_BUILD = 9999
17
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
18
e82cb43 Added version command to setup.py
Michael Kleehammer authored
19 class VersionCommand(Command):
f89886e @mkleehammer Added description to setup version command
authored
20
a42975a @mkleehammer Ported setup tags command from v31 branch.
authored
21 description = "prints the pyodbc version, determined from git"
f89886e @mkleehammer Added description to setup version command
authored
22
e82cb43 Added version command to setup.py
Michael Kleehammer authored
23 user_options = []
24
25 def initialize_options(self):
26 self.verbose = 0
27
28 def finalize_options(self):
29 pass
30
31 def run(self):
32 version_str, version = get_version()
33 print version_str
34
35
a42975a @mkleehammer Ported setup tags command from v31 branch.
authored
36 class TagsCommand(Command):
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
37
a42975a @mkleehammer Ported setup tags command from v31 branch.
authored
38 description = 'runs etags'
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
39
a42975a @mkleehammer Ported setup tags command from v31 branch.
authored
40 user_options = []
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
41
a42975a @mkleehammer Ported setup tags command from v31 branch.
authored
42 def initialize_options(self):
43 pass
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
44
a42975a @mkleehammer Ported setup tags command from v31 branch.
authored
45 def finalize_options(self):
46 pass
47
48 def run(self):
49 # Windows versions of etag do not seem to expand wildcards (which Unix shells normally do for Unix utilities),
50 # so find all of the files ourselves.
51 files = [ join('src', f) for f in os.listdir('src') if f.endswith(('.h', '.cpp')) ]
52 cmd = 'etags %s' % ' '.join(files)
53 return os.system(cmd)
54
55
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
56
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
57 def main():
58
59 version_str, version = get_version()
60
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
61 settings = get_compiler_settings(version_str)
04d8111 @mkleehammer Added SQL Server 2008 date/time extensions support. Now caches connecti...
authored
62
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
63 files = [ abspath(join('src', f)) for f in os.listdir('src') if f.endswith('.cpp') ]
523aed0 @mkleehammer Issue 91: decimal fix; Completely reworked parameters; added leakcheck
authored
64
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
65 if exists('MANIFEST'):
66 os.remove('MANIFEST')
67
68 setup (name = "pyodbc",
69 version = version_str,
70 description = "DB API Module for ODBC",
71
72 long_description = ('A Python DB API 2 module for ODBC. This project provides an up-to-date, '
73 'convenient interface to ODBC using native data types like datetime and decimal.'),
74
75 maintainer = "Michael Kleehammer",
76 maintainer_email = "michael@kleehammer.com",
77
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
78 ext_modules = [Extension('pyodbc', files, **settings)],
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
79
1567234 eliminate gcc write-strings warnings; caused by Python declarations - no...
Michael Kleehammer authored
80 classifiers = ['Development Status :: 5 - Production/Stable',
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
81 'Intended Audience :: Developers',
82 'Intended Audience :: System Administrators',
83 'License :: OSI Approved :: MIT License',
84 'Operating System :: Microsoft :: Windows',
85 'Operating System :: POSIX',
86 'Programming Language :: Python',
87 'Topic :: Database',
1567234 eliminate gcc write-strings warnings; caused by Python declarations - no...
Michael Kleehammer authored
88 ],
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
89
47138be @mkleehammer Updated metadata to point to Google code hosting
authored
90 url = 'http://code.google.com/p/pyodbc',
e82cb43 Added version command to setup.py
Michael Kleehammer authored
91 download_url = 'http://code.google.com/p/pyodbc/downloads/list',
a42975a @mkleehammer Ported setup tags command from v31 branch.
authored
92 cmdclass = { 'version' : VersionCommand,
93 'tags' : TagsCommand })
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
94
95
04d8111 @mkleehammer Added SQL Server 2008 date/time extensions support. Now caches connecti...
authored
96
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
97 def get_compiler_settings(version_str):
98
99 settings = { 'libraries': [],
100 'define_macros' : [ ('PYODBC_VERSION', version_str) ] }
101
102 # This isn't the best or right way to do this, but I don't see how someone is supposed to sanely subclass the build
103 # command.
104 for option in ['assert', 'trace', 'leak-check']:
105 try:
106 sys.argv.remove('--%s' % option)
107 settings['define_macros'].append(('PYODBC_%s' % option.replace('-', '_'), 1))
108 except ValueError:
109 pass
110
111 if os.name == 'nt':
3c7a9e7 @mkleehammer Cleaned up compiler warnings
authored
112 settings['extra_compile_args'] = ['/Wall',
113 '/wd4668',
114 '/wd4820',
115 '/wd4711', # function selected for automatic inline expansion
116 '/wd4100', # unreferenced formal parameter
117 '/wd4127', # "conditional expression is constant" testing compilation constants
118 '/wd4191', # casts to PYCFunction, perhaps the extra parameters should be added
119 ]
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
120 settings['libraries'].append('odbc32')
eeede2f @mkleehammer Added pyodbc.drivers() for Windows builds.
authored
121 settings['libraries'].append('advapi32')
9dd144f @mkleehammer Added pyodbc.conf for preprocessor-time access to sizeof(SQLWCHAR)
authored
122
123 elif os.environ.get("OS", '').lower().startswith('windows'):
124 # Windows Cygwin (posix on windows)
125 # OS name not windows, but still on Windows
126 settings['libraries'].append('odbc32')
127
128 elif sys.platform == 'darwin':
129 # OS/X now ships with iODBC.
130 settings['libraries'].append('iodbc')
131
132 else:
133 # Other posix-like: Linux, Solaris, etc.
134
135 # Python functions take a lot of 'char *' that really should be const. gcc complains about this *a lot*
136 settings['extra_compile_args'] = ['-Wno-write-strings']
137
138 # What is the proper way to detect iODBC, MyODBC, unixODBC, etc.?
139 settings['libraries'].append('odbc')
140
141 get_config(settings, version_str)
142
143 return settings
144
145
146 def get_config(settings, version_str):
147 """
148 Adds configuration macros from pyodbc.conf to the compiler settings dictionary.
149
150 If pyodbc.conf does not exist, it will compile and run the pyodbcconf utility.
151
152 This is similar to what autoconf provides, but only uses the infrastructure provided by Python, which is important
153 for building on *nix and Windows.
154 """
155 filename = 'pyodbc.conf'
156
157 # If the file exists, make sure that the version in it is the same as the version we are compiling. Otherwise we
158 # might have added configuration items that aren't there.
159 if exists(filename):
160 try:
161 config = SafeConfigParser()
162 config.read(filename)
163
164 if (not config.has_option('define_macros', 'pyodbc_version') or
165 config.get('define_macros', 'pyodbc_version') != version_str):
166 print 'Recreating pyodbc.conf for new version'
167 os.remove(filename)
168
169 except:
170 config = None
171 # Assume the file has been corrupted. Delete and recreate
172 print 'Unable to read %s. Recreating' % filename
173 os.remove(filename)
174
175 if not exists('pyodbc.conf'):
176 # Doesn't exist, so build the pyodbcconf module and use it.
177
178 oldargv = sys.argv
179 sys.argv = [ oldargv[0], 'build' ]
180
181 setup(name="pyodbcconf",
182 ext_modules = [ Extension('pyodbcconf',
183 [join('utils', 'pyodbcconf', 'pyodbcconf.cpp')],
184 **settings) ])
185
186 sys.argv = oldargv
187
188 add_to_path()
189
190 import pyodbcconf
191 pyodbcconf.configure()
192
193 config = SafeConfigParser()
194 config.read(filename)
195
196 for section in config.sections():
197 for key, value in config.items(section):
198 settings[section].append( (key.upper(), value) )
199
200
201
202 def add_to_path():
203 """
204 Prepends the build directory to the path so pyodbcconf can be imported without installing it.
205 """
206 # Now run the utility
207
208 import imp
209 library_exts = [ t[0] for t in imp.get_suffixes() if t[-1] == imp.C_EXTENSION ]
210 library_names = [ 'pyodbcconf%s' % ext for ext in library_exts ]
211
212 # Only go into directories that match our version number.
213
214 dir_suffix = '-%s.%s' % (sys.version_info[0], sys.version_info[1])
215
216 build = join(dirname(abspath(__file__)), 'build')
217
218 for top, dirs, files in os.walk(build):
219 dirs = [ d for d in dirs if d.endswith(dir_suffix) ]
220 for name in library_names:
221 if name in files:
222 sys.path.insert(0, top)
223 return
224
225 raise SystemExit('Did not find pyodbcconf')
226
227
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
228 def get_version():
229 """
230 Returns the version of the product as (description, [major,minor,micro,beta]).
231
232 If the release is official, `beta` will be 9999 (OFFICIAL_BUILD).
233
234 1. If in a git repository, use the latest tag (git describe).
235 2. If in an unzipped source directory (from setup.py sdist),
236 read the version from the PKG-INFO file.
237 3. Use 2.1.0.0 and complain a lot.
238 """
239 # My goal is to (1) provide accurate tags for official releases but (2) not have to manage tags for every test
240 # release.
241 #
242 # Official versions are tagged using 3 numbers: major, minor, micro. A build of a tagged version should produce
243 # the version using just these pieces, such as 2.1.4.
244 #
245 # Unofficial versions are "working towards" the next version. So the next unofficial build after 2.1.4 would be a
246 # beta for 2.1.5. Using 'git describe' we can find out how many changes have been made after 2.1.4 and we'll use
247 # this count as the beta id (beta1, beta2, etc.)
248 #
c8c8fe1 fixed pyodbc.version for non-beta releases
Michael Kleehammer authored
249 # Since the 4 numbers are put into the Windows DLL, we want to make sure the beta versions sort *before* the
250 # official, so we set the official build number to 9999, but we don't show it.
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
251
252 name = None # branch/feature name. Should be None for official builds.
253 numbers = None # The 4 integers that make up the version.
254
255 # If this is a source release the version will have already been assigned and be in the PKG-INFO file.
256
257 name, numbers = _get_version_pkginfo()
258
259 # If not a source release, we should be in a git repository. Look for the latest tag.
260
261 if not numbers:
262 name, numbers = _get_version_git()
263
264 if not numbers:
265 print 'WARNING: Unable to determine version. Using 2.1.0.0'
266 name, numbers = '2.1.0-unsupported', [2,1,0,0]
267
268 return name, numbers
269
270
271 def _get_version_pkginfo():
272 filename = join(dirname(abspath(__file__)), 'PKG-INFO')
273 if exists(filename):
274 re_ver = re.compile(r'^Version: \s+ (\d+)\.(\d+)\.(\d+) (?: -beta(\d+))?', re.VERBOSE)
275 for line in open(filename):
276 match = re_ver.search(line)
277 if match:
278 name = line.split(':', 1)[1].strip()
9ff5342 @mkleehammer Issue 95: "beta0" added when building from source distribution.
authored
279 numbers = [int(n or 0) for n in match.groups()[:3]]
280 numbers.append(int(match.group(4) or OFFICIAL_BUILD)) # don't use 0 as a default for build
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
281 return name, numbers
282
283 return None, None
284
285
286 def _get_version_git():
9ff5342 @mkleehammer Issue 95: "beta0" added when building from source distribution.
authored
287 n, result = getoutput('git describe --tags --match 2.*')
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
288 if n:
289 print 'WARNING: git describe failed with: %s %s' % (n, result)
290 return None, None
291
292 match = re.match(r'(\d+).(\d+).(\d+) (?: -(\d+)-g[0-9a-z]+)?', result, re.VERBOSE)
293 if not match:
294 return None, None
295
1567234 eliminate gcc write-strings warnings; caused by Python declarations - no...
Michael Kleehammer authored
296 numbers = [int(n or OFFICIAL_BUILD) for n in match.groups()]
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
297 if numbers[-1] == OFFICIAL_BUILD:
298 name = '%s.%s.%s' % tuple(numbers[:3])
299 if numbers[-1] != OFFICIAL_BUILD:
300 # This is a beta of the next micro release, so increment the micro number to reflect this.
301 numbers[-2] += 1
691b6ba @mkleehammer Reworked Unicode; changed version format; more Py_ssize_t
authored
302 name = '%s.%s.%s-beta%02d' % tuple(numbers)
303
304 n, result = getoutput('git branch')
305 branch = re.search(r'\* (\w+)', result).group(1)
306 if branch != 'master' and not re.match('^v\d+$', branch):
307 name = branch + '-' + name
308
c3f6b46 @mkleehammer Import from Subversion 2.0.63; reworked versioning
authored
309 return name, numbers
310
311
312
313 def getoutput(cmd):
314 pipe = os.popen(cmd, 'r')
315 text = pipe.read().rstrip('\n')
316 status = pipe.close() or 0
317 return status, text
318
319 if __name__ == '__main__':
320 main()
Something went wrong with that request. Please try again.