setup.py revision 8fbefe28745f980579620147dd0c0fdef94374de
1# Autodetecting setup.py script for building the Python extensions
2#
3
4__version__ = "$Revision$"
5
6import sys, os, getopt, imp, re
7
8from distutils import log
9from distutils import sysconfig
10from distutils import text_file
11from distutils.errors import *
12from distutils.core import Extension, setup
13from distutils.command.build_ext import build_ext
14from distutils.command.install import install
15from distutils.command.install_lib import install_lib
16
17# This global variable is used to hold the list of modules to be disabled.
18disabled_module_list = []
19
20def add_dir_to_list(dirlist, dir):
21    """Add the directory 'dir' to the list 'dirlist' (at the front) if
22    1) 'dir' is not already in 'dirlist'
23    2) 'dir' actually exists, and is a directory."""
24    if dir is not None and os.path.isdir(dir) and dir not in dirlist:
25        dirlist.insert(0, dir)
26
27def find_file(filename, std_dirs, paths):
28    """Searches for the directory where a given file is located,
29    and returns a possibly-empty list of additional directories, or None
30    if the file couldn't be found at all.
31
32    'filename' is the name of a file, such as readline.h or libcrypto.a.
33    'std_dirs' is the list of standard system directories; if the
34        file is found in one of them, no additional directives are needed.
35    'paths' is a list of additional locations to check; if the file is
36        found in one of them, the resulting list will contain the directory.
37    """
38
39    # Check the standard locations
40    for dir in std_dirs:
41        f = os.path.join(dir, filename)
42        if os.path.exists(f): return []
43
44    # Check the additional directories
45    for dir in paths:
46        f = os.path.join(dir, filename)
47        if os.path.exists(f):
48            return [dir]
49
50    # Not found anywhere
51    return None
52
53def find_library_file(compiler, libname, std_dirs, paths):
54    result = compiler.find_library_file(std_dirs + paths, libname)
55    if result is None:
56        return None
57
58    # Check whether the found file is in one of the standard directories
59    dirname = os.path.dirname(result)
60    for p in std_dirs:
61        # Ensure path doesn't end with path separator
62        p = p.rstrip(os.sep)
63        if p == dirname:
64            return [ ]
65
66    # Otherwise, it must have been in one of the additional directories,
67    # so we have to figure out which one.
68    for p in paths:
69        # Ensure path doesn't end with path separator
70        p = p.rstrip(os.sep)
71        if p == dirname:
72            return [p]
73    else:
74        assert False, "Internal error: Path not found in std_dirs or paths"
75
76def module_enabled(extlist, modname):
77    """Returns whether the module 'modname' is present in the list
78    of extensions 'extlist'."""
79    extlist = [ext for ext in extlist if ext.name == modname]
80    return len(extlist)
81
82def find_module_file(module, dirlist):
83    """Find a module in a set of possible folders. If it is not found
84    return the unadorned filename"""
85    list = find_file(module, [], dirlist)
86    if not list:
87        return module
88    if len(list) > 1:
89        log.info("WARNING: multiple copies of %s found"%module)
90    return os.path.join(list[0], module)
91
92class PyBuildExt(build_ext):
93
94    def build_extensions(self):
95
96        # Detect which modules should be compiled
97        self.detect_modules()
98
99        # Remove modules that are present on the disabled list
100        self.extensions = [ext for ext in self.extensions
101                           if ext.name not in disabled_module_list]
102
103        # Fix up the autodetected modules, prefixing all the source files
104        # with Modules/ and adding Python's include directory to the path.
105        (srcdir,) = sysconfig.get_config_vars('srcdir')
106        if not srcdir:
107            # Maybe running on Windows but not using CYGWIN?
108            raise ValueError("No source directory; cannot proceed.")
109
110        # Figure out the location of the source code for extension modules
111        moddir = os.path.join(os.getcwd(), srcdir, 'Modules')
112        moddir = os.path.normpath(moddir)
113        srcdir, tail = os.path.split(moddir)
114        srcdir = os.path.normpath(srcdir)
115        moddir = os.path.normpath(moddir)
116
117        moddirlist = [moddir]
118        incdirlist = ['./Include']
119
120        # Platform-dependent module source and include directories
121        platform = self.get_platform()
122        if platform in ('darwin', 'mac'):
123            # Mac OS X also includes some mac-specific modules
124            macmoddir = os.path.join(os.getcwd(), srcdir, 'Mac/Modules')
125            moddirlist.append(macmoddir)
126            incdirlist.append('./Mac/Include')
127
128        alldirlist = moddirlist + incdirlist
129
130        # Fix up the paths for scripts, too
131        self.distribution.scripts = [os.path.join(srcdir, filename)
132                                     for filename in self.distribution.scripts]
133
134        for ext in self.extensions[:]:
135            ext.sources = [ find_module_file(filename, moddirlist)
136                            for filename in ext.sources ]
137            if ext.depends is not None:
138                ext.depends = [find_module_file(filename, alldirlist)
139                               for filename in ext.depends]
140            ext.include_dirs.append( '.' ) # to get config.h
141            for incdir in incdirlist:
142                ext.include_dirs.append( os.path.join(srcdir, incdir) )
143
144            # If a module has already been built statically,
145            # don't build it here
146            if ext.name in sys.builtin_module_names:
147                self.extensions.remove(ext)
148
149        if platform != 'mac':
150            # Parse Modules/Setup to figure out which modules are turned
151            # on in the file.
152            input = text_file.TextFile('Modules/Setup', join_lines=1)
153            remove_modules = []
154            while 1:
155                line = input.readline()
156                if not line: break
157                line = line.split()
158                remove_modules.append( line[0] )
159            input.close()
160
161            for ext in self.extensions[:]:
162                if ext.name in remove_modules:
163                    self.extensions.remove(ext)
164
165        # When you run "make CC=altcc" or something similar, you really want
166        # those environment variables passed into the setup.py phase.  Here's
167        # a small set of useful ones.
168        compiler = os.environ.get('CC')
169        linker_so = os.environ.get('LDSHARED')
170        args = {}
171        # unfortunately, distutils doesn't let us provide separate C and C++
172        # compilers
173        if compiler is not None:
174            (ccshared,opt,base) = sysconfig.get_config_vars('CCSHARED','OPT','BASECFLAGS')
175            args['compiler_so'] = compiler + ' ' + opt + ' ' + ccshared + ' ' + base
176        if linker_so is not None:
177            args['linker_so'] = linker_so
178        self.compiler.set_executables(**args)
179
180        build_ext.build_extensions(self)
181
182    def build_extension(self, ext):
183
184        try:
185            build_ext.build_extension(self, ext)
186        except (CCompilerError, DistutilsError), why:
187            self.announce('WARNING: building of extension "%s" failed: %s' %
188                          (ext.name, sys.exc_info()[1]))
189            return
190        # Workaround for Mac OS X: The Carbon-based modules cannot be
191        # reliably imported into a command-line Python
192        if 'Carbon' in ext.extra_link_args:
193            self.announce(
194                'WARNING: skipping import check for Carbon-based "%s"' %
195                ext.name)
196            return
197        # Workaround for Cygwin: Cygwin currently has fork issues when many
198        # modules have been imported
199        if self.get_platform() == 'cygwin':
200            self.announce('WARNING: skipping import check for Cygwin-based "%s"'
201                % ext.name)
202            return
203        ext_filename = os.path.join(
204            self.build_lib,
205            self.get_ext_filename(self.get_ext_fullname(ext.name)))
206        try:
207            imp.load_dynamic(ext.name, ext_filename)
208        except ImportError, why:
209            self.announce('*** WARNING: renaming "%s" since importing it'
210                          ' failed: %s' % (ext.name, why), level=3)
211            assert not self.inplace
212            basename, tail = os.path.splitext(ext_filename)
213            newname = basename + "_failed" + tail
214            if os.path.exists(newname):
215                os.remove(newname)
216            os.rename(ext_filename, newname)
217
218            # XXX -- This relies on a Vile HACK in
219            # distutils.command.build_ext.build_extension().  The
220            # _built_objects attribute is stored there strictly for
221            # use here.
222            # If there is a failure, _built_objects may not be there,
223            # so catch the AttributeError and move on.
224            try:
225                for filename in self._built_objects:
226                    os.remove(filename)
227            except AttributeError:
228                self.announce('unable to remove files (ignored)')
229        except:
230            exc_type, why, tb = sys.exc_info()
231            self.announce('*** WARNING: importing extension "%s" '
232                          'failed with %s: %s' % (ext.name, exc_type, why),
233                          level=3)
234
235    def get_platform(self):
236        # Get value of sys.platform
237        for platform in ['cygwin', 'beos', 'darwin', 'atheos', 'osf1']:
238            if sys.platform.startswith(platform):
239                return platform
240        return sys.platform
241
242    def detect_modules(self):
243        # Ensure that /usr/local is always used
244        add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
245        add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
246
247        # fink installs lots of goodies in /sw/... - make sure we
248        # check there
249        if sys.platform == "darwin":
250            add_dir_to_list(self.compiler.library_dirs, '/sw/lib')
251            add_dir_to_list(self.compiler.include_dirs, '/sw/include')
252
253        if os.path.normpath(sys.prefix) != '/usr':
254            add_dir_to_list(self.compiler.library_dirs,
255                            sysconfig.get_config_var("LIBDIR"))
256            add_dir_to_list(self.compiler.include_dirs,
257                            sysconfig.get_config_var("INCLUDEDIR"))
258
259        try:
260            have_unicode = unicode
261        except NameError:
262            have_unicode = 0
263
264        # lib_dirs and inc_dirs are used to search for files;
265        # if a file is found in one of those directories, it can
266        # be assumed that no additional -I,-L directives are needed.
267        lib_dirs = self.compiler.library_dirs + ['/lib', '/usr/lib', '/usr/lib/lib64']
268        inc_dirs = self.compiler.include_dirs + ['/usr/include']
269        exts = []
270
271        platform = self.get_platform()
272        (srcdir,) = sysconfig.get_config_vars('srcdir')
273
274        # Check for AtheOS which has libraries in non-standard locations
275        if platform == 'atheos':
276            lib_dirs += ['/system/libs', '/atheos/autolnk/lib']
277            lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep)
278            inc_dirs += ['/system/include', '/atheos/autolnk/include']
279            inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep)
280
281        # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
282        if platform in ['osf1', 'unixware7', 'openunix8']:
283            lib_dirs += ['/usr/ccs/lib']
284
285        # Check for MacOS X, which doesn't need libm.a at all
286        math_libs = ['m']
287        if platform in ['darwin', 'beos', 'mac']:
288            math_libs = []
289
290        # XXX Omitted modules: gl, pure, dl, SGI-specific modules
291
292        #
293        # The following modules are all pretty straightforward, and compile
294        # on pretty much any POSIXish platform.
295        #
296
297        # Some modules that are normally always on:
298        exts.append( Extension('regex', ['regexmodule.c', 'regexpr.c']) )
299
300        exts.append( Extension('_hotshot', ['_hotshot.c']) )
301        exts.append( Extension('_weakref', ['_weakref.c']) )
302        exts.append( Extension('xreadlines', ['xreadlinesmodule.c']) )
303
304        # array objects
305        exts.append( Extension('array', ['arraymodule.c']) )
306        # complex math library functions
307        exts.append( Extension('cmath', ['cmathmodule.c'],
308                               libraries=math_libs) )
309
310        # math library functions, e.g. sin()
311        exts.append( Extension('math',  ['mathmodule.c'],
312                               libraries=math_libs) )
313        # fast string operations implemented in C
314        exts.append( Extension('strop', ['stropmodule.c']) )
315        # time operations and variables
316        exts.append( Extension('time', ['timemodule.c'],
317                               libraries=math_libs) )
318        exts.append( Extension('datetime', ['datetimemodule.c', 'timemodule.c'],
319                               libraries=math_libs) )
320        # random number generator implemented in C
321        exts.append( Extension("_random", ["_randommodule.c"]) )
322        # fast iterator tools implemented in C
323        exts.append( Extension("itertools", ["itertoolsmodule.c"]) )
324        # high-performance collections
325        exts.append( Extension("collections", ["collectionsmodule.c"]) )
326        # bisect
327        exts.append( Extension("_bisect", ["_bisectmodule.c"]) )
328        # heapq
329        exts.append( Extension("_heapq", ["_heapqmodule.c"]) )
330        # operator.add() and similar goodies
331        exts.append( Extension('operator', ['operator.c']) )
332        # Python C API test module
333        exts.append( Extension('_testcapi', ['_testcapimodule.c']) )
334        # static Unicode character database
335        if have_unicode:
336            exts.append( Extension('unicodedata', ['unicodedata.c']) )
337        # access to ISO C locale support
338        data = open('pyconfig.h').read()
339        m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data)
340        if m is not None:
341            locale_libs = ['intl']
342        else:
343            locale_libs = []
344        if platform == 'darwin':
345            locale_extra_link_args = ['-framework', 'CoreFoundation']
346        else:
347            locale_extra_link_args = []
348
349
350        exts.append( Extension('_locale', ['_localemodule.c'],
351                               libraries=locale_libs,
352                               extra_link_args=locale_extra_link_args) )
353
354        # Modules with some UNIX dependencies -- on by default:
355        # (If you have a really backward UNIX, select and socket may not be
356        # supported...)
357
358        # fcntl(2) and ioctl(2)
359        exts.append( Extension('fcntl', ['fcntlmodule.c']) )
360        if platform not in ['mac']:
361                # pwd(3)
362            exts.append( Extension('pwd', ['pwdmodule.c']) )
363            # grp(3)
364            exts.append( Extension('grp', ['grpmodule.c']) )
365        # select(2); not on ancient System V
366        exts.append( Extension('select', ['selectmodule.c']) )
367
368        # The md5 module implements the RSA Data Security, Inc. MD5
369        # Message-Digest Algorithm, described in RFC 1321.  The
370        # necessary files md5c.c and md5.h are included here.
371        exts.append( Extension('md5', ['md5module.c', 'md5c.c']) )
372
373        # The sha module implements the SHA checksum algorithm.
374        # (NIST's Secure Hash Algorithm.)
375        exts.append( Extension('sha', ['shamodule.c']) )
376
377        # Helper module for various ascii-encoders
378        exts.append( Extension('binascii', ['binascii.c']) )
379
380        # Fred Drake's interface to the Python parser
381        exts.append( Extension('parser', ['parsermodule.c']) )
382
383        # cStringIO and cPickle
384        exts.append( Extension('cStringIO', ['cStringIO.c']) )
385        exts.append( Extension('cPickle', ['cPickle.c']) )
386
387        # Memory-mapped files (also works on Win32).
388        if platform not in ['atheos', 'mac']:
389            exts.append( Extension('mmap', ['mmapmodule.c']) )
390
391        # Lance Ellinghaus's modules:
392        # enigma-inspired encryption
393        exts.append( Extension('rotor', ['rotormodule.c']) )
394        if platform not in ['mac']:
395            # syslog daemon interface
396            exts.append( Extension('syslog', ['syslogmodule.c']) )
397
398        # George Neville-Neil's timing module:
399        exts.append( Extension('timing', ['timingmodule.c']) )
400
401        #
402        # Here ends the simple stuff.  From here on, modules need certain
403        # libraries, are platform-specific, or present other surprises.
404        #
405
406        # Multimedia modules
407        # These don't work for 64-bit platforms!!!
408        # These represent audio samples or images as strings:
409
410        # According to #993173, this one should actually work fine on
411        # 64-bit platforms.
412        exts.append( Extension('audioop', ['audioop.c']) )
413
414        # Disabled on 64-bit platforms
415        if sys.maxint != 9223372036854775807L:
416            # Operations on audio samples
417            # Operations on images
418            exts.append( Extension('imageop', ['imageop.c']) )
419            # Read SGI RGB image files (but coded portably)
420            exts.append( Extension('rgbimg', ['rgbimgmodule.c']) )
421
422        # readline
423        if self.compiler.find_library_file(lib_dirs, 'readline'):
424            readline_libs = ['readline']
425            if self.compiler.find_library_file(lib_dirs,
426                                                 'ncurses'):
427                readline_libs.append('ncurses')
428            elif self.compiler.find_library_file(lib_dirs, 'curses'):
429                readline_libs.append('curses')
430            elif self.compiler.find_library_file(lib_dirs +
431                                               ['/usr/lib/termcap'],
432                                               'termcap'):
433                readline_libs.append('termcap')
434            exts.append( Extension('readline', ['readline.c'],
435                                   library_dirs=['/usr/lib/termcap'],
436                                   libraries=readline_libs) )
437        if platform not in ['mac']:
438            # crypt module.
439
440            if self.compiler.find_library_file(lib_dirs, 'crypt'):
441                libs = ['crypt']
442            else:
443                libs = []
444            exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) )
445
446        # CSV files
447        exts.append( Extension('_csv', ['_csv.c']) )
448
449        # socket(2)
450        exts.append( Extension('_socket', ['socketmodule.c'],
451                               depends = ['socketmodule.h']) )
452        # Detect SSL support for the socket module (via _ssl)
453        ssl_incs = find_file('openssl/ssl.h', inc_dirs,
454                             ['/usr/local/ssl/include',
455                              '/usr/contrib/ssl/include/'
456                             ]
457                             )
458        if ssl_incs is not None:
459            krb5_h = find_file('krb5.h', inc_dirs,
460                               ['/usr/kerberos/include'])
461            if krb5_h:
462                ssl_incs += krb5_h
463        ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
464                                     ['/usr/local/ssl/lib',
465                                      '/usr/contrib/ssl/lib/'
466                                     ] )
467
468        if (ssl_incs is not None and
469            ssl_libs is not None):
470            exts.append( Extension('_ssl', ['_ssl.c'],
471                                   include_dirs = ssl_incs,
472                                   library_dirs = ssl_libs,
473                                   libraries = ['ssl', 'crypto'],
474                                   depends = ['socketmodule.h']), )
475
476        # Modules that provide persistent dictionary-like semantics.  You will
477        # probably want to arrange for at least one of them to be available on
478        # your machine, though none are defined by default because of library
479        # dependencies.  The Python module anydbm.py provides an
480        # implementation independent wrapper for these; dumbdbm.py provides
481        # similar functionality (but slower of course) implemented in Python.
482
483        # Sleepycat Berkeley DB interface.  http://www.sleepycat.com
484        #
485        # This requires the Sleepycat DB code. The earliest supported version
486        # of that library is 3.2, the latest supported version is 4.2.  A list
487        # of available releases can be found at
488        #
489        # http://www.sleepycat.com/update/index.html
490
491        # when sorted in reverse order, keys for this dict must appear in the
492        # order you wish to search - e.g., search for db4 before db3
493        db_try_this = {
494            'db4': {'libs': ('db-4.2', 'db42', 'db-4.1', 'db41', 'db-4.0', 'db4',),
495                    'libdirs': ('/usr/local/BerkeleyDB.4.2/lib',
496                                '/usr/local/BerkeleyDB.4.1/lib',
497                                '/usr/local/BerkeleyDB.4.0/lib',
498                                '/usr/local/lib',
499                                '/opt/sfw',
500                                '/sw/lib',
501                                ),
502                    'incdirs': ('/usr/local/BerkeleyDB.4.2/include',
503                                '/usr/local/include/db42',
504                                '/usr/local/BerkeleyDB.4.1/include',
505                                '/usr/local/include/db41',
506                                '/usr/local/BerkeleyDB.4.0/include',
507                                '/usr/local/include/db4',
508                                '/opt/sfw/include/db4',
509                                '/sw/include/db4',
510                                '/usr/include/db4',
511                                )},
512            'db3': {'libs': ('db-3.3', 'db-3.2', 'db3',),
513                    'libdirs': ('/usr/local/BerkeleyDB.3.3/lib',
514                                '/usr/local/BerkeleyDB.3.2/lib',
515                                '/usr/local/lib',
516                                '/opt/sfw/lib',
517                                '/sw/lib',
518                                ),
519                    'incdirs': ('/usr/local/BerkeleyDB.3.3/include',
520                                '/usr/local/BerkeleyDB.3.2/include',
521                                '/usr/local/include/db3',
522                                '/opt/sfw/include/db3',
523                                '/sw/include/db3',
524                                '/usr/include/db3',
525                                )},
526            }
527
528        db_search_order = db_try_this.keys()
529        db_search_order.sort()
530        db_search_order.reverse()
531
532        class found(Exception): pass
533        try:
534            # See whether there is a Sleepycat header in the standard
535            # search path.
536            std_dbinc = None
537            for d in inc_dirs:
538                f = os.path.join(d, "db.h")
539                if os.path.exists(f):
540                    f = open(f).read()
541                    m = re.search(r"#define\WDB_VERSION_MAJOR\W([1-9]+)", f)
542                    if m:
543                        std_dbinc = 'db' + m.group(1)
544            for dbkey in db_search_order:
545                dbd = db_try_this[dbkey]
546                for dblib in dbd['libs']:
547                    # Prefer version-specific includes over standard
548                    # include locations.
549                    db_incs = find_file('db.h', [], dbd['incdirs'])
550                    dblib_dir = find_library_file(self.compiler,
551                                                  dblib,
552                                                  lib_dirs,
553                                                  list(dbd['libdirs']))
554                    if (db_incs or dbkey == std_dbinc) and \
555                           dblib_dir is not None:
556                        dblibs = [dblib]
557                        raise found
558        except found:
559            dblibs = [dblib]
560            # A default source build puts Berkeley DB in something like
561            # /usr/local/Berkeley.3.3 and the lib dir under that isn't
562            # normally on ld.so's search path, unless the sysadmin has hacked
563            # /etc/ld.so.conf.  We add the directory to runtime_library_dirs
564            # so the proper -R/--rpath flags get passed to the linker.  This
565            # is usually correct and most trouble free, but may cause problems
566            # in some unusual system configurations (e.g. the directory is on
567            # an NFS server that goes away).
568            exts.append(Extension('_bsddb', ['_bsddb.c'],
569                                  library_dirs=dblib_dir,
570                                  runtime_library_dirs=dblib_dir,
571                                  include_dirs=db_incs,
572                                  libraries=dblibs))
573        else:
574            db_incs = None
575            dblibs = []
576            dblib_dir = None
577
578
579        # Look for Berkeley db 1.85.   Note that it is built as a different
580        # module name so it can be included even when later versions are
581        # available.  A very restrictive search is performed to avoid
582        # accidentally building this module with a later version of the
583        # underlying db library.  May BSD-ish Unixes incorporate db 1.85
584        # symbols into libc and place the include file in /usr/include.
585        f = "/usr/include/db.h"
586        if os.path.exists(f):
587            data = open(f).read()
588            m = re.search(r"#s*define\s+HASHVERSION\s+2\s*", data)
589            if m is not None:
590                # bingo - old version used hash file format version 2
591                ### XXX this should be fixed to not be platform-dependent
592                ### but I don't have direct access to an osf1 platform and
593                ### seemed to be muffing the search somehow
594                libraries = platform == "osf1" and ['db'] or None
595                if libraries is not None:
596                    exts.append(Extension('bsddb185', ['bsddbmodule.c'],
597                                          libraries=libraries))
598                else:
599                    exts.append(Extension('bsddb185', ['bsddbmodule.c']))
600
601        # The standard Unix dbm module:
602        if platform not in ['cygwin']:
603            if find_file("ndbm.h", inc_dirs, []) is not None:
604                # Some systems have -lndbm, others don't
605                if self.compiler.find_library_file(lib_dirs, 'ndbm'):
606                    ndbm_libs = ['ndbm']
607                else:
608                    ndbm_libs = []
609                exts.append( Extension('dbm', ['dbmmodule.c'],
610                                       define_macros=[('HAVE_NDBM_H',None)],
611                                       libraries = ndbm_libs ) )
612            elif (self.compiler.find_library_file(lib_dirs, 'gdbm')
613                  and find_file("gdbm/ndbm.h", inc_dirs, []) is not None):
614                exts.append( Extension('dbm', ['dbmmodule.c'],
615                                       define_macros=[('HAVE_GDBM_NDBM_H',None)],
616                                       libraries = ['gdbm'] ) )
617            elif db_incs is not None:
618                exts.append( Extension('dbm', ['dbmmodule.c'],
619                                       library_dirs=dblib_dir,
620                                       runtime_library_dirs=dblib_dir,
621                                       include_dirs=db_incs,
622                                       define_macros=[('HAVE_BERKDB_H',None),
623                                                      ('DB_DBM_HSEARCH',None)],
624                                       libraries=dblibs))
625
626        # Anthony Baxter's gdbm module.  GNU dbm(3) will require -lgdbm:
627        if (self.compiler.find_library_file(lib_dirs, 'gdbm')):
628            exts.append( Extension('gdbm', ['gdbmmodule.c'],
629                                   libraries = ['gdbm'] ) )
630
631        # The mpz module interfaces to the GNU Multiple Precision library.
632        # You need to ftp the GNU MP library.
633        # This was originally written and tested against GMP 1.2 and 1.3.2.
634        # It has been modified by Rob Hooft to work with 2.0.2 as well, but I
635        # haven't tested it recently, and it definitely doesn't work with
636        # GMP 4.0.  For more complete modules, refer to
637        # http://gmpy.sourceforge.net and
638        # http://www.egenix.com/files/python/mxNumber.html
639
640        # A compatible MP library unencumbered by the GPL also exists.  It was
641        # posted to comp.sources.misc in volume 40 and is widely available from
642        # FTP archive sites. One URL for it is:
643        # ftp://gatekeeper.dec.com/.b/usenet/comp.sources.misc/volume40/fgmp/part01.Z
644
645        if (self.compiler.find_library_file(lib_dirs, 'gmp')):
646            exts.append( Extension('mpz', ['mpzmodule.c'],
647                                   libraries = ['gmp'] ) )
648
649
650        # Unix-only modules
651        if platform not in ['mac', 'win32']:
652            # Steen Lumholt's termios module
653            exts.append( Extension('termios', ['termios.c']) )
654            # Jeremy Hylton's rlimit interface
655            if platform not in ['atheos']:
656                exts.append( Extension('resource', ['resource.c']) )
657
658            # Sun yellow pages. Some systems have the functions in libc.
659            if platform not in ['cygwin', 'atheos']:
660                if (self.compiler.find_library_file(lib_dirs, 'nsl')):
661                    libs = ['nsl']
662                else:
663                    libs = []
664                exts.append( Extension('nis', ['nismodule.c'],
665                                       libraries = libs) )
666
667        # Curses support, requiring the System V version of curses, often
668        # provided by the ncurses library.
669        if (self.compiler.find_library_file(lib_dirs, 'ncurses')):
670            curses_libs = ['ncurses']
671            exts.append( Extension('_curses', ['_cursesmodule.c'],
672                                   libraries = curses_libs) )
673        elif (self.compiler.find_library_file(lib_dirs, 'curses')
674              and platform != 'darwin'):
675                # OSX has an old Berkeley curses, not good enough for
676                # the _curses module.
677            if (self.compiler.find_library_file(lib_dirs, 'terminfo')):
678                curses_libs = ['curses', 'terminfo']
679            elif (self.compiler.find_library_file(lib_dirs, 'termcap')):
680                curses_libs = ['curses', 'termcap']
681            else:
682                curses_libs = ['curses']
683
684            exts.append( Extension('_curses', ['_cursesmodule.c'],
685                                   libraries = curses_libs) )
686
687        # If the curses module is enabled, check for the panel module
688        if (module_enabled(exts, '_curses') and
689            self.compiler.find_library_file(lib_dirs, 'panel')):
690            exts.append( Extension('_curses_panel', ['_curses_panel.c'],
691                                   libraries = ['panel'] + curses_libs) )
692
693
694        # Andrew Kuchling's zlib module.  Note that some versions of zlib
695        # 1.1.3 have security problems.  See CERT Advisory CA-2002-07:
696        # http://www.cert.org/advisories/CA-2002-07.html
697        #
698        # zlib 1.1.4 is fixed, but at least one vendor (RedHat) has decided to
699        # patch its zlib 1.1.3 package instead of upgrading to 1.1.4.  For
700        # now, we still accept 1.1.3, because we think it's difficult to
701        # exploit this in Python, and we'd rather make it RedHat's problem
702        # than our problem <wink>.
703        #
704        # You can upgrade zlib to version 1.1.4 yourself by going to
705        # http://www.gzip.org/zlib/
706        zlib_inc = find_file('zlib.h', [], inc_dirs)
707        if zlib_inc is not None:
708            zlib_h = zlib_inc[0] + '/zlib.h'
709            version = '"0.0.0"'
710            version_req = '"1.1.3"'
711            fp = open(zlib_h)
712            while 1:
713                line = fp.readline()
714                if not line:
715                    break
716                if line.startswith('#define ZLIB_VERSION'):
717                    version = line.split()[2]
718                    break
719            if version >= version_req:
720                if (self.compiler.find_library_file(lib_dirs, 'z')):
721                    exts.append( Extension('zlib', ['zlibmodule.c'],
722                                           libraries = ['z']) )
723
724        # Gustavo Niemeyer's bz2 module.
725        if (self.compiler.find_library_file(lib_dirs, 'bz2')):
726            exts.append( Extension('bz2', ['bz2module.c'],
727                                   libraries = ['bz2']) )
728
729        # Interface to the Expat XML parser
730        #
731        # Expat was written by James Clark and is now maintained by a
732        # group of developers on SourceForge; see www.libexpat.org for
733        # more information.  The pyexpat module was written by Paul
734        # Prescod after a prototype by Jack Jansen.  The Expat source
735        # is included in Modules/expat/.  Usage of a system
736        # shared libexpat.so/expat.dll is not advised.
737        #
738        # More information on Expat can be found at www.libexpat.org.
739        #
740        if sys.byteorder == "little":
741            xmlbo = "1234"
742        else:
743            xmlbo = "4321"
744        expatinc = os.path.join(os.getcwd(), srcdir, 'Modules', 'expat')
745        define_macros = [
746            ('XML_NS', '1'),
747            ('XML_DTD', '1'),
748            ('BYTEORDER', xmlbo),
749            ('XML_CONTEXT_BYTES','1024'),
750            ]
751        config_h = sysconfig.get_config_h_filename()
752        config_h_vars = sysconfig.parse_config_h(open(config_h))
753        for feature_macro in ['HAVE_MEMMOVE', 'HAVE_BCOPY']:
754            if config_h_vars.has_key(feature_macro):
755                define_macros.append((feature_macro, '1'))
756        exts.append(Extension('pyexpat',
757                              define_macros = define_macros,
758                              include_dirs = [expatinc],
759                              sources = ['pyexpat.c',
760                                         'expat/xmlparse.c',
761                                         'expat/xmlrole.c',
762                                         'expat/xmltok.c',
763                                         ],
764                              ))
765
766        # Hye-Shik Chang's CJKCodecs modules.
767        exts.append(Extension('_multibytecodec',
768                              ['cjkcodecs/multibytecodec.c']))
769        for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'):
770            exts.append(Extension('_codecs_' + loc,
771                                  ['cjkcodecs/_codecs_%s.c' % loc]))
772
773        # Dynamic loading module
774        if sys.maxint == 0x7fffffff:
775            # This requires sizeof(int) == sizeof(long) == sizeof(char*)
776            dl_inc = find_file('dlfcn.h', [], inc_dirs)
777            if (dl_inc is not None) and (platform not in ['atheos', 'darwin']):
778                exts.append( Extension('dl', ['dlmodule.c']) )
779
780        # Platform-specific libraries
781        if platform == 'linux2':
782            # Linux-specific modules
783            exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) )
784
785        if platform in ('linux2', 'freebsd4'):
786            exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) )
787
788        if platform == 'sunos5':
789            # SunOS specific modules
790            exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) )
791
792        if platform == 'darwin':
793            # Mac OS X specific modules.
794            exts.append( Extension('_CF', ['cf/_CFmodule.c', 'cf/pycfbridge.c'],
795                        extra_link_args=['-framework', 'CoreFoundation']) )
796
797            exts.append( Extension('ColorPicker', ['ColorPickermodule.c'],
798                        extra_link_args=['-framework', 'Carbon']) )
799            exts.append( Extension('autoGIL', ['autoGIL.c'],
800                        extra_link_args=['-framework', 'CoreFoundation']) )
801            exts.append( Extension('gestalt', ['gestaltmodule.c'],
802                        extra_link_args=['-framework', 'Carbon']) )
803            exts.append( Extension('MacOS', ['macosmodule.c'],
804                        extra_link_args=['-framework', 'Carbon']) )
805            exts.append( Extension('OSATerminology', ['OSATerminology.c'],
806                        extra_link_args=['-framework', 'Carbon']) )
807            exts.append( Extension('icglue', ['icgluemodule.c'],
808                        extra_link_args=['-framework', 'Carbon']) )
809            exts.append( Extension('_Res', ['res/_Resmodule.c'],
810                        extra_link_args=['-framework', 'Carbon']) )
811            exts.append( Extension('_Snd', ['snd/_Sndmodule.c'],
812                        extra_link_args=['-framework', 'Carbon']) )
813            exts.append( Extension('Nav', ['Nav.c'],
814                    extra_link_args=['-framework', 'Carbon']) )
815            exts.append( Extension('_AE', ['ae/_AEmodule.c'],
816                    extra_link_args=['-framework', 'Carbon']) )
817            exts.append( Extension('_AH', ['ah/_AHmodule.c'],
818                    extra_link_args=['-framework', 'Carbon']) )
819            exts.append( Extension('_App', ['app/_Appmodule.c'],
820                    extra_link_args=['-framework', 'Carbon']) )
821            exts.append( Extension('_CarbonEvt', ['carbonevt/_CarbonEvtmodule.c'],
822                    extra_link_args=['-framework', 'Carbon']) )
823            exts.append( Extension('_CG', ['cg/_CGmodule.c'],
824                    extra_link_args=['-framework', 'ApplicationServices']) )
825            exts.append( Extension('_Cm', ['cm/_Cmmodule.c'],
826                    extra_link_args=['-framework', 'Carbon']) )
827            exts.append( Extension('_Ctl', ['ctl/_Ctlmodule.c'],
828                    extra_link_args=['-framework', 'Carbon']) )
829            exts.append( Extension('_Dlg', ['dlg/_Dlgmodule.c'],
830                    extra_link_args=['-framework', 'Carbon']) )
831            exts.append( Extension('_Drag', ['drag/_Dragmodule.c'],
832                    extra_link_args=['-framework', 'Carbon']) )
833            exts.append( Extension('_Evt', ['evt/_Evtmodule.c'],
834                    extra_link_args=['-framework', 'Carbon']) )
835            exts.append( Extension('_File', ['file/_Filemodule.c'],
836                    extra_link_args=['-framework', 'Carbon']) )
837            exts.append( Extension('_Folder', ['folder/_Foldermodule.c'],
838                    extra_link_args=['-framework', 'Carbon']) )
839            exts.append( Extension('_Fm', ['fm/_Fmmodule.c'],
840                    extra_link_args=['-framework', 'Carbon']) )
841            exts.append( Extension('_Help', ['help/_Helpmodule.c'],
842                    extra_link_args=['-framework', 'Carbon']) )
843            exts.append( Extension('_Icn', ['icn/_Icnmodule.c'],
844                    extra_link_args=['-framework', 'Carbon']) )
845            exts.append( Extension('_IBCarbon', ['ibcarbon/_IBCarbon.c'],
846                    extra_link_args=['-framework', 'Carbon']) )
847            exts.append( Extension('_Launch', ['launch/_Launchmodule.c'],
848                    extra_link_args=['-framework', 'ApplicationServices']) )
849            exts.append( Extension('_List', ['list/_Listmodule.c'],
850                    extra_link_args=['-framework', 'Carbon']) )
851            exts.append( Extension('_Menu', ['menu/_Menumodule.c'],
852                    extra_link_args=['-framework', 'Carbon']) )
853            exts.append( Extension('_Mlte', ['mlte/_Mltemodule.c'],
854                    extra_link_args=['-framework', 'Carbon']) )
855            exts.append( Extension('_OSA', ['osa/_OSAmodule.c'],
856                    extra_link_args=['-framework', 'Carbon']) )
857            exts.append( Extension('_Qd', ['qd/_Qdmodule.c'],
858                    extra_link_args=['-framework', 'Carbon']) )
859            exts.append( Extension('_Qdoffs', ['qdoffs/_Qdoffsmodule.c'],
860                    extra_link_args=['-framework', 'Carbon']) )
861            exts.append( Extension('_Qt', ['qt/_Qtmodule.c'],
862                    extra_link_args=['-framework', 'QuickTime',
863                                     '-framework', 'Carbon']) )
864            exts.append( Extension('_Scrap', ['scrap/_Scrapmodule.c'],
865                    extra_link_args=['-framework', 'Carbon']) )
866            exts.append( Extension('_TE', ['te/_TEmodule.c'],
867                    extra_link_args=['-framework', 'Carbon']) )
868            # As there is no standardized place (yet) to put
869            # user-installed Mac libraries on OSX, we search for "waste"
870            # in parent directories of the Python source tree. You
871            # should put a symlink to your Waste installation in the
872            # same folder as your python source tree.  Or modify the
873            # next few lines:-)
874            waste_incs = find_file("WASTE.h", [],
875                    ['../'*n + 'waste/C_C++ Headers' for n in (0,1,2,3,4)])
876            waste_libs = find_library_file(self.compiler, "WASTE", [],
877                    ["../"*n + "waste/Static Libraries" for n in (0,1,2,3,4)])
878            if waste_incs != None and waste_libs != None:
879                (srcdir,) = sysconfig.get_config_vars('srcdir')
880                exts.append( Extension('waste',
881                               ['waste/wastemodule.c'] + [
882                                os.path.join(srcdir, d) for d in
883                                'Mac/Wastemods/WEObjectHandlers.c',
884                                'Mac/Wastemods/WETabHooks.c',
885                                'Mac/Wastemods/WETabs.c'
886                               ],
887                               include_dirs = waste_incs + [os.path.join(srcdir, 'Mac/Wastemods')],
888                               library_dirs = waste_libs,
889                               libraries = ['WASTE'],
890                               extra_link_args = ['-framework', 'Carbon'],
891                ) )
892            exts.append( Extension('_Win', ['win/_Winmodule.c'],
893                    extra_link_args=['-framework', 'Carbon']) )
894
895        self.extensions.extend(exts)
896
897        # Call the method for detecting whether _tkinter can be compiled
898        self.detect_tkinter(inc_dirs, lib_dirs)
899
900    def detect_tkinter_darwin(self, inc_dirs, lib_dirs):
901        # The _tkinter module, using frameworks. Since frameworks are quite
902        # different the UNIX search logic is not sharable.
903        from os.path import join, exists
904        framework_dirs = [
905            '/System/Library/Frameworks/',
906            '/Library/Frameworks',
907            join(os.getenv('HOME'), '/Library/Frameworks')
908        ]
909
910        # Find the directory that contains the Tcl.framwork and Tk.framework
911        # bundles.
912        # XXX distutils should support -F!
913        for F in framework_dirs:
914            # both Tcl.framework and Tk.framework should be present
915            for fw in 'Tcl', 'Tk':
916                if not exists(join(F, fw + '.framework')):
917                    break
918            else:
919                # ok, F is now directory with both frameworks. Continure
920                # building
921                break
922        else:
923            # Tk and Tcl frameworks not found. Normal "unix" tkinter search
924            # will now resume.
925            return 0
926
927        # For 8.4a2, we must add -I options that point inside the Tcl and Tk
928        # frameworks. In later release we should hopefully be able to pass
929        # the -F option to gcc, which specifies a framework lookup path.
930        #
931        include_dirs = [
932            join(F, fw + '.framework', H)
933            for fw in 'Tcl', 'Tk'
934            for H in 'Headers', 'Versions/Current/PrivateHeaders'
935        ]
936
937        # For 8.4a2, the X11 headers are not included. Rather than include a
938        # complicated search, this is a hard-coded path. It could bail out
939        # if X11 libs are not found...
940        include_dirs.append('/usr/X11R6/include')
941        frameworks = ['-framework', 'Tcl', '-framework', 'Tk']
942
943        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
944                        define_macros=[('WITH_APPINIT', 1)],
945                        include_dirs = include_dirs,
946                        libraries = [],
947                        extra_compile_args = frameworks,
948                        extra_link_args = frameworks,
949                        )
950        self.extensions.append(ext)
951        return 1
952
953
954    def detect_tkinter(self, inc_dirs, lib_dirs):
955        # The _tkinter module.
956
957        # Rather than complicate the code below, detecting and building
958        # AquaTk is a separate method. Only one Tkinter will be built on
959        # Darwin - either AquaTk, if it is found, or X11 based Tk.
960        platform = self.get_platform()
961        if platform == 'darwin' and \
962           self.detect_tkinter_darwin(inc_dirs, lib_dirs):
963            return
964
965        # Assume we haven't found any of the libraries or include files
966        # The versions with dots are used on Unix, and the versions without
967        # dots on Windows, for detection by cygwin.
968        tcllib = tklib = tcl_includes = tk_includes = None
969        for version in ['8.5', '85', '8.4', '84', '8.3', '83', '8.2',
970                        '82', '8.1', '81', '8.0', '80']:
971            tklib = self.compiler.find_library_file(lib_dirs, 'tk' + version)
972            tcllib = self.compiler.find_library_file(lib_dirs, 'tcl' + version)
973            if tklib and tcllib:
974                # Exit the loop when we've found the Tcl/Tk libraries
975                break
976
977        # Now check for the header files
978        if tklib and tcllib:
979            # Check for the include files on Debian and {Free,Open}BSD, where
980            # they're put in /usr/include/{tcl,tk}X.Y
981            dotversion = version
982            if '.' not in dotversion and "bsd" in sys.platform.lower():
983                # OpenBSD and FreeBSD use Tcl/Tk library names like libtcl83.a,
984                # but the include subdirs are named like .../include/tcl8.3.
985                dotversion = dotversion[:-1] + '.' + dotversion[-1]
986            tcl_include_sub = []
987            tk_include_sub = []
988            for dir in inc_dirs:
989                tcl_include_sub += [dir + os.sep + "tcl" + dotversion]
990                tk_include_sub += [dir + os.sep + "tk" + dotversion]
991            tk_include_sub += tcl_include_sub
992            tcl_includes = find_file('tcl.h', inc_dirs, tcl_include_sub)
993            tk_includes = find_file('tk.h', inc_dirs, tk_include_sub)
994
995        if (tcllib is None or tklib is None or
996            tcl_includes is None or tk_includes is None):
997            self.announce("INFO: Can't locate Tcl/Tk libs and/or headers", 2)
998            return
999
1000        # OK... everything seems to be present for Tcl/Tk.
1001
1002        include_dirs = [] ; libs = [] ; defs = [] ; added_lib_dirs = []
1003        for dir in tcl_includes + tk_includes:
1004            if dir not in include_dirs:
1005                include_dirs.append(dir)
1006
1007        # Check for various platform-specific directories
1008        if platform == 'sunos5':
1009            include_dirs.append('/usr/openwin/include')
1010            added_lib_dirs.append('/usr/openwin/lib')
1011        elif os.path.exists('/usr/X11R6/include'):
1012            include_dirs.append('/usr/X11R6/include')
1013            added_lib_dirs.append('/usr/X11R6/lib')
1014        elif os.path.exists('/usr/X11R5/include'):
1015            include_dirs.append('/usr/X11R5/include')
1016            added_lib_dirs.append('/usr/X11R5/lib')
1017        else:
1018            # Assume default location for X11
1019            include_dirs.append('/usr/X11/include')
1020            added_lib_dirs.append('/usr/X11/lib')
1021
1022        # If Cygwin, then verify that X is installed before proceeding
1023        if platform == 'cygwin':
1024            x11_inc = find_file('X11/Xlib.h', [], include_dirs)
1025            if x11_inc is None:
1026                return
1027
1028        # Check for BLT extension
1029        if self.compiler.find_library_file(lib_dirs + added_lib_dirs,
1030                                           'BLT8.0'):
1031            defs.append( ('WITH_BLT', 1) )
1032            libs.append('BLT8.0')
1033        elif self.compiler.find_library_file(lib_dirs + added_lib_dirs,
1034                                           'BLT'):
1035            defs.append( ('WITH_BLT', 1) )
1036            libs.append('BLT')
1037
1038        # Add the Tcl/Tk libraries
1039        libs.append('tk'+ version)
1040        libs.append('tcl'+ version)
1041
1042        if platform in ['aix3', 'aix4']:
1043            libs.append('ld')
1044
1045        # Finally, link with the X11 libraries (not appropriate on cygwin)
1046        if platform != "cygwin":
1047            libs.append('X11')
1048
1049        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1050                        define_macros=[('WITH_APPINIT', 1)] + defs,
1051                        include_dirs = include_dirs,
1052                        libraries = libs,
1053                        library_dirs = added_lib_dirs,
1054                        )
1055        self.extensions.append(ext)
1056
1057##         # Uncomment these lines if you want to play with xxmodule.c
1058##         ext = Extension('xx', ['xxmodule.c'])
1059##         self.extensions.append(ext)
1060
1061        # XXX handle these, but how to detect?
1062        # *** Uncomment and edit for PIL (TkImaging) extension only:
1063        #       -DWITH_PIL -I../Extensions/Imaging/libImaging  tkImaging.c \
1064        # *** Uncomment and edit for TOGL extension only:
1065        #       -DWITH_TOGL togl.c \
1066        # *** Uncomment these for TOGL extension only:
1067        #       -lGL -lGLU -lXext -lXmu \
1068
1069class PyBuildInstall(install):
1070    # Suppress the warning about installation into the lib_dynload
1071    # directory, which is not in sys.path when running Python during
1072    # installation:
1073    def initialize_options (self):
1074        install.initialize_options(self)
1075        self.warn_dir=0
1076
1077class PyBuildInstallLib(install_lib):
1078    # Do exactly what install_lib does but make sure correct access modes get
1079    # set on installed directories and files. All installed files with get
1080    # mode 644 unless they are a shared library in which case they will get
1081    # mode 755. All installed directories will get mode 755.
1082
1083    so_ext = sysconfig.get_config_var("SO")
1084
1085    def install(self):
1086        outfiles = install_lib.install(self)
1087        self.set_file_modes(outfiles, 0644, 0755)
1088        self.set_dir_modes(self.install_dir, 0755)
1089        return outfiles
1090
1091    def set_file_modes(self, files, defaultMode, sharedLibMode):
1092        if not self.is_chmod_supported(): return
1093        if not files: return
1094
1095        for filename in files:
1096            if os.path.islink(filename): continue
1097            mode = defaultMode
1098            if filename.endswith(self.so_ext): mode = sharedLibMode
1099            log.info("changing mode of %s to %o", filename, mode)
1100            if not self.dry_run: os.chmod(filename, mode)
1101
1102    def set_dir_modes(self, dirname, mode):
1103        if not self.is_chmod_supported(): return
1104        os.path.walk(dirname, self.set_dir_modes_visitor, mode)
1105
1106    def set_dir_modes_visitor(self, mode, dirname, names):
1107        if os.path.islink(dirname): return
1108        log.info("changing mode of %s to %o", dirname, mode)
1109        if not self.dry_run: os.chmod(dirname, mode)
1110
1111    def is_chmod_supported(self):
1112        return hasattr(os, 'chmod')
1113
1114SUMMARY = """
1115Python is an interpreted, interactive, object-oriented programming
1116language. It is often compared to Tcl, Perl, Scheme or Java.
1117
1118Python combines remarkable power with very clear syntax. It has
1119modules, classes, exceptions, very high level dynamic data types, and
1120dynamic typing. There are interfaces to many system calls and
1121libraries, as well as to various windowing systems (X11, Motif, Tk,
1122Mac, MFC). New built-in modules are easily written in C or C++. Python
1123is also usable as an extension language for applications that need a
1124programmable interface.
1125
1126The Python implementation is portable: it runs on many brands of UNIX,
1127on Windows, DOS, OS/2, Mac, Amiga... If your favorite system isn't
1128listed here, it may still be supported, if there's a C compiler for
1129it. Ask around on comp.lang.python -- or just try compiling Python
1130yourself.
1131"""
1132
1133CLASSIFIERS = """
1134Development Status :: 3 - Alpha
1135Development Status :: 6 - Mature
1136License :: OSI Approved :: Python Software Foundation License
1137Natural Language :: English
1138Programming Language :: C
1139Programming Language :: Python
1140Topic :: Software Development
1141"""
1142
1143def main():
1144    # turn off warnings when deprecated modules are imported
1145    import warnings
1146    warnings.filterwarnings("ignore",category=DeprecationWarning)
1147    setup(# PyPI Metadata (PEP 301)
1148          name = "Python",
1149          version = sys.version.split()[0],
1150          url = "http://www.python.org/%s" % sys.version[:3],
1151          maintainer = "Guido van Rossum and the Python community",
1152          maintainer_email = "python-dev@python.org",
1153          description = "A high-level object-oriented programming language",
1154          long_description = SUMMARY.strip(),
1155          license = "PSF license",
1156          classifiers = filter(None, CLASSIFIERS.split("\n")),
1157          platforms = ["Many"],
1158
1159          # Build info
1160          cmdclass = {'build_ext':PyBuildExt, 'install':PyBuildInstall,
1161                      'install_lib':PyBuildInstallLib},
1162          # The struct module is defined here, because build_ext won't be
1163          # called unless there's at least one extension module defined.
1164          ext_modules=[Extension('struct', ['structmodule.c'])],
1165
1166          # Scripts to install
1167          scripts = ['Tools/scripts/pydoc', 'Tools/scripts/idle',
1168                     'Lib/smtpd.py']
1169        )
1170
1171# --install-platlib
1172if __name__ == '__main__':
1173    main()
1174