~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to setup.py

  • Committer: John Arbash Meinel
  • Date: 2010-08-13 19:08:57 UTC
  • mto: (5050.17.7 2.2)
  • mto: This revision was merged to the branch mainline in revision 5379.
  • Revision ID: john@arbash-meinel.com-20100813190857-mvzwnimrxvm0zimp
Lots of documentation updates.

We had a lot of http links pointing to the old domain. They should
all now be properly updated to the new domain. (only bazaar-vcs.org
entry left is for pqm, which seems to still reside at the old url.)

Also removed one 'TODO' doc entry about switching to binary xdelta, since
we basically did just that with groupcompress.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
import os
10
10
import os.path
11
11
import sys
 
12
import copy
12
13
 
13
14
if sys.version_info < (2, 4):
14
15
    sys.stderr.write("[ERROR] Not a supported Python version. Need 2.4+\n")
37
38
    'version':      bzrlib.__version__,
38
39
    'author':       'Canonical Ltd',
39
40
    'author_email': 'bazaar@lists.canonical.com',
40
 
    'url':          'http://www.bazaar-vcs.org/',
 
41
    'url':          'http://bazaar.canonical.com/',
41
42
    'description':  'Friendly distributed version control system',
42
43
    'license':      'GNU GPL v2',
43
 
    'download_url': 'http://bazaar-vcs.org/Download',
 
44
    'download_url': 'https://launchpad.net/bzr/+download',
44
45
    'long_description': get_long_description(),
45
46
    'classifiers': [
46
47
        'Development Status :: 6 - Mature',
65
66
            'package_data': {'bzrlib': ['doc/api/*.txt',
66
67
                                        'tests/test_patches_data/*',
67
68
                                        'help_topics/en/*.txt',
 
69
                                        'tests/ssl_certs/server_without_pass.key',
 
70
                                        'tests/ssl_certs/server_with_pass.key',
 
71
                                        'tests/ssl_certs/server.crt'
68
72
                                       ]},
69
73
           }
70
74
 
93
97
BZRLIB['packages'] = get_bzrlib_packages()
94
98
 
95
99
 
 
100
from distutils import log
96
101
from distutils.core import setup
97
102
from distutils.command.install_scripts import install_scripts
98
103
from distutils.command.install_data import install_data
121
126
                f = file(batch_path, "w")
122
127
                f.write(batch_str)
123
128
                f.close()
124
 
                print "Created:", batch_path
125
 
            except Exception, e:
126
 
                print "ERROR: Unable to create %s: %s" % (batch_path, e)
 
129
                print("Created: %s" % batch_path)
 
130
            except Exception:
 
131
                e = sys.exc_info()[1]
 
132
                print("ERROR: Unable to create %s: %s" % (batch_path, e))
127
133
 
128
134
    def _quoted_path(self, path):
129
135
        if ' ' in path:
163
169
from distutils.extension import Extension
164
170
ext_modules = []
165
171
try:
166
 
    from Pyrex.Distutils import build_ext
 
172
    try:
 
173
        from Pyrex.Distutils import build_ext
 
174
        from Pyrex.Compiler.Version import version as pyrex_version
 
175
    except ImportError:
 
176
        print("No Pyrex, trying Cython...")
 
177
        from Cython.Distutils import build_ext
 
178
        from Cython.Compiler.Version import version as pyrex_version
167
179
except ImportError:
168
180
    have_pyrex = False
169
181
    # try to build the extension from the prior generated source.
170
 
    print
171
 
    print ("The python package 'Pyrex' is not available."
172
 
           " If the .c files are available,")
173
 
    print ("they will be built,"
174
 
           " but modifying the .pyx files will not rebuild them.")
175
 
    print
 
182
    print("")
 
183
    print("The python package 'Pyrex' is not available."
 
184
          " If the .c files are available,")
 
185
    print("they will be built,"
 
186
          " but modifying the .pyx files will not rebuild them.")
 
187
    print("")
176
188
    from distutils.command.build_ext import build_ext
177
189
else:
178
190
    have_pyrex = True
179
 
    from Pyrex.Compiler.Version import version as pyrex_version
 
191
    pyrex_version_info = tuple(map(int, pyrex_version.split('.')))
180
192
 
181
193
 
182
194
class build_ext_if_possible(build_ext):
194
206
    def run(self):
195
207
        try:
196
208
            build_ext.run(self)
197
 
        except DistutilsPlatformError, e:
 
209
        except DistutilsPlatformError:
 
210
            e = sys.exc_info()[1]
198
211
            if not self.allow_python_fallback:
199
212
                log.warn('\n  Cannot build extensions.\n'
200
213
                         '  Use "build_ext --allow-python-fallback" to use'
261
274
 
262
275
add_pyrex_extension('bzrlib._annotator_pyx')
263
276
add_pyrex_extension('bzrlib._bencode_pyx')
264
 
add_pyrex_extension('bzrlib._btree_serializer_pyx')
265
277
add_pyrex_extension('bzrlib._chunks_to_lines_pyx')
266
278
add_pyrex_extension('bzrlib._groupcompress_pyx',
267
279
                    extra_source=['bzrlib/diff-delta.c'])
272
284
    add_pyrex_extension('bzrlib._dirstate_helpers_pyx',
273
285
                        libraries=['Ws2_32'])
274
286
    add_pyrex_extension('bzrlib._walkdirs_win32')
275
 
    z_lib = 'zdll'
276
287
else:
277
 
    if have_pyrex and pyrex_version == '0.9.4.1':
 
288
    if have_pyrex and pyrex_version_info[:3] == (0,9,4):
278
289
        # Pyrex 0.9.4.1 fails to compile this extension correctly
279
290
        # The code it generates re-uses a "local" pointer and
280
291
        # calls "PY_DECREF" after having set it to NULL. (It mixes PY_XDECREF
281
292
        # which is NULL safe with PY_DECREF which is not.)
282
 
        print 'Cannot build extension "bzrlib._dirstate_helpers_pyx" using'
283
 
        print 'your version of pyrex "%s". Please upgrade your pyrex' % (
284
 
            pyrex_version,)
285
 
        print 'install. For now, the non-compiled (python) version will'
286
 
        print 'be used instead.'
 
293
        # <https://bugs.edge.launchpad.net/bzr/+bug/449372>
 
294
        # <https://bugs.edge.launchpad.net/bzr/+bug/276868>
 
295
        print('Cannot build extension "bzrlib._dirstate_helpers_pyx" using')
 
296
        print('your version of pyrex "%s". Please upgrade your pyrex' % (
 
297
            pyrex_version,))
 
298
        print('install. For now, the non-compiled (python) version will')
 
299
        print('be used instead.')
287
300
    else:
288
301
        add_pyrex_extension('bzrlib._dirstate_helpers_pyx')
289
302
    add_pyrex_extension('bzrlib._readdir_pyx')
290
 
    z_lib = 'z'
291
 
add_pyrex_extension('bzrlib._chk_map_pyx', libraries=[z_lib])
 
303
add_pyrex_extension('bzrlib._chk_map_pyx')
292
304
ext_modules.append(Extension('bzrlib._patiencediff_c',
293
305
                             ['bzrlib/_patiencediff_c.c']))
 
306
if have_pyrex and pyrex_version_info < (0, 9, 6, 3):
 
307
    print("")
 
308
    print('Your Pyrex/Cython version %s is too old to build the simple_set' % (
 
309
        pyrex_version))
 
310
    print('and static_tuple extensions.')
 
311
    print('Please upgrade to at least Pyrex 0.9.6.3')
 
312
    print("")
 
313
    # TODO: Should this be a fatal error?
 
314
else:
 
315
    # We only need 0.9.6.3 to build _simple_set_pyx, but static_tuple depends
 
316
    # on simple_set
 
317
    add_pyrex_extension('bzrlib._simple_set_pyx')
 
318
    ext_modules.append(Extension('bzrlib._static_tuple_c',
 
319
                                 ['bzrlib/_static_tuple_c.c']))
 
320
add_pyrex_extension('bzrlib._btree_serializer_pyx')
294
321
 
295
322
 
296
323
if unavailable_files:
297
 
    print 'C extension(s) not found:'
298
 
    print '   %s' % ('\n  '.join(unavailable_files),)
299
 
    print 'The python versions will be used instead.'
300
 
    print
 
324
    print('C extension(s) not found:')
 
325
    print('   %s' % ('\n  '.join(unavailable_files),))
 
326
    print('The python versions will be used instead.')
 
327
    print("")
301
328
 
302
329
 
303
330
def get_tbzr_py2exe_info(includes, excludes, packages, console_targets,
323
350
    # Ensure tbzrlib itself is on sys.path
324
351
    sys.path.append(tbzr_root)
325
352
 
326
 
    # Ensure our COM "entry-point" is on sys.path
327
 
    sys.path.append(os.path.join(tbzr_root, "shellext", "python"))
328
 
 
329
353
    packages.append("tbzrlib")
330
354
 
331
355
    # collect up our icons.
353
377
    excludes.extend("""pywin pywin.dialogs pywin.dialogs.list
354
378
                       win32ui crawler.Crawler""".split())
355
379
 
356
 
    # NOTE: We still create a DLL version of the Python implemented shell
357
 
    # extension for testing purposes - but it is *not* registered by
358
 
    # default - our C++ one is instead.  To discourage people thinking
359
 
    # this DLL is still necessary, its called 'tbzr_old.dll'
360
 
    tbzr = dict(
361
 
        modules=["tbzr"],
362
 
        create_exe = False, # we only want a .dll
363
 
        dest_base = 'tbzr_old',
364
 
    )
365
 
    com_targets.append(tbzr)
366
 
 
367
380
    # tbzrcache executables - a "console" version for debugging and a
368
381
    # GUI version that is generally used.
369
382
    tbzrcache = dict(
394
407
    console_targets.append(tracer)
395
408
 
396
409
    # The C++ implemented shell extensions.
397
 
    dist_dir = os.path.join(tbzr_root, "shellext", "cpp", "tbzrshellext",
398
 
                            "build", "dist")
 
410
    dist_dir = os.path.join(tbzr_root, "shellext", "build")
399
411
    data_files.append(('', [os.path.join(dist_dir, 'tbzrshellext_x86.dll')]))
400
412
    data_files.append(('', [os.path.join(dist_dir, 'tbzrshellext_x64.dll')]))
401
413
 
402
414
 
403
 
def get_qbzr_py2exe_info(includes, excludes, packages):
 
415
def get_qbzr_py2exe_info(includes, excludes, packages, data_files):
404
416
    # PyQt4 itself still escapes the plugin detection code for some reason...
405
 
    packages.append('PyQt4')
406
 
    excludes.append('PyQt4.elementtree.ElementTree')
 
417
    includes.append('PyQt4.QtCore')
 
418
    includes.append('PyQt4.QtGui')
407
419
    includes.append('sip') # extension module required for Qt.
408
420
    packages.append('pygments') # colorizer for qbzr
409
421
    packages.append('docutils') # html formatting
410
 
    # but we can avoid many Qt4 Dlls.
411
 
    dll_excludes.extend(
412
 
        """QtAssistantClient4.dll QtCLucene4.dll QtDesigner4.dll
413
 
        QtHelp4.dll QtNetwork4.dll QtOpenGL4.dll QtScript4.dll
414
 
        QtSql4.dll QtTest4.dll QtWebKit4.dll QtXml4.dll
415
 
        qscintilla2.dll""".split())
 
422
    includes.append('win32event')  # for qsubprocess stuff
416
423
    # the qt binaries might not be on PATH...
417
 
    qt_dir = os.path.join(sys.prefix, "PyQt4", "bin")
418
 
    path = os.environ.get("PATH","")
419
 
    if qt_dir.lower() not in [p.lower() for p in path.split(os.pathsep)]:
420
 
        os.environ["PATH"] = path + os.pathsep + qt_dir
 
424
    # They seem to install to a place like C:\Python25\PyQt4\*
 
425
    # Which is not the same as C:\Python25\Lib\site-packages\PyQt4
 
426
    pyqt_dir = os.path.join(sys.prefix, "PyQt4")
 
427
    pyqt_bin_dir = os.path.join(pyqt_dir, "bin")
 
428
    if os.path.isdir(pyqt_bin_dir):
 
429
        path = os.environ.get("PATH", "")
 
430
        if pyqt_bin_dir.lower() not in [p.lower() for p in path.split(os.pathsep)]:
 
431
            os.environ["PATH"] = path + os.pathsep + pyqt_bin_dir
 
432
    # also add all imageformat plugins to distribution
 
433
    # We will look in 2 places, dirname(PyQt4.__file__) and pyqt_dir
 
434
    base_dirs_to_check = []
 
435
    if os.path.isdir(pyqt_dir):
 
436
        base_dirs_to_check.append(pyqt_dir)
 
437
    try:
 
438
        import PyQt4
 
439
    except ImportError:
 
440
        pass
 
441
    else:
 
442
        pyqt4_base_dir = os.path.dirname(PyQt4.__file__)
 
443
        if pyqt4_base_dir != pyqt_dir:
 
444
            base_dirs_to_check.append(pyqt4_base_dir)
 
445
    if not base_dirs_to_check:
 
446
        log.warn("Can't find PyQt4 installation -> not including imageformat"
 
447
                 " plugins")
 
448
    else:
 
449
        files = []
 
450
        for base_dir in base_dirs_to_check:
 
451
            plug_dir = os.path.join(base_dir, 'plugins', 'imageformats')
 
452
            if os.path.isdir(plug_dir):
 
453
                for fname in os.listdir(plug_dir):
 
454
                    # Include plugin dlls, but not debugging dlls
 
455
                    fullpath = os.path.join(plug_dir, fname)
 
456
                    if fname.endswith('.dll') and not fname.endswith('d4.dll'):
 
457
                        files.append(fullpath)
 
458
        if files:
 
459
            data_files.append(('imageformats', files))
 
460
        else:
 
461
            log.warn('PyQt4 was found, but we could not find any imageformat'
 
462
                     ' plugins. Are you sure your configuration is correct?')
421
463
 
422
464
 
423
465
def get_svn_py2exe_info(includes, excludes, packages):
424
466
    packages.append('subvertpy')
 
467
    packages.append('sqlite3')
425
468
 
426
469
 
427
470
if 'bdist_wininst' in sys.argv:
485
528
            install_data.run(self)
486
529
 
487
530
            py2exe = self.distribution.get_command_obj('py2exe', False)
488
 
            optimize = py2exe.optimize
 
531
            # GZ 2010-04-19: Setup has py2exe.optimize as 2, but give plugins
 
532
            #                time before living with docstring stripping
 
533
            optimize = 1
489
534
            compile_names = [f for f in self.outfiles if f.endswith('.py')]
 
535
            # Round mtime to nearest even second so that installing on a FAT
 
536
            # filesystem bytecode internal and script timestamps will match
 
537
            for f in compile_names:
 
538
                mtime = os.stat(f).st_mtime
 
539
                remainder = mtime % 2
 
540
                if remainder:
 
541
                    mtime -= remainder
 
542
                    os.utime(f, (mtime, mtime))
490
543
            byte_compile(compile_names,
491
544
                         optimize=optimize,
492
545
                         force=self.force, prefix=self.install_dir,
493
546
                         dry_run=self.dry_run)
494
 
            if optimize:
495
 
                suffix = 'o'
496
 
            else:
497
 
                suffix = 'c'
498
 
            self.outfiles.extend([f + suffix for f in compile_names])
 
547
            self.outfiles.extend([f + 'o' for f in compile_names])
499
548
    # end of class install_data_with_bytecompile
500
549
 
501
550
    target = py2exe.build_exe.Target(script = "bzr",
505
554
                                     version = version_str,
506
555
                                     description = META_INFO['description'],
507
556
                                     author = META_INFO['author'],
508
 
                                     copyright = "(c) Canonical Ltd, 2005-2007",
 
557
                                     copyright = "(c) Canonical Ltd, 2005-2010",
509
558
                                     company_name = "Canonical Ltd.",
510
559
                                     comments = META_INFO['description'],
511
560
                                    )
 
561
    gui_target = copy.copy(target)
 
562
    gui_target.dest_base = "bzrw"
512
563
 
513
564
    packages = BZRLIB['packages']
514
565
    packages.remove('bzrlib')
524
575
    if sys.version.startswith('2.4'):
525
576
        # adding elementtree package
526
577
        additional_packages.add('elementtree')
527
 
    elif sys.version.startswith('2.5'):
 
578
    elif sys.version.startswith('2.6') or sys.version.startswith('2.5'):
528
579
        additional_packages.add('xml.etree')
529
580
    else:
530
581
        import warnings
576
627
            excludes.extend(["bzrlib.plugins." + d for d in dirs])
577
628
        x = []
578
629
        for i in files:
579
 
            if os.path.splitext(i)[1] not in [".py", ".pyd", ".dll", ".mo"]:
 
630
            # Throw away files we don't want packaged. Note that plugins may
 
631
            # have data files with all sorts of extensions so we need to
 
632
            # be conservative here about what we ditch.
 
633
            ext = os.path.splitext(i)[1]
 
634
            if ext.endswith('~') or ext in [".pyc", ".swp"]:
580
635
                continue
581
636
            if i == '__init__.py' and root == 'bzrlib/plugins':
582
637
                continue
595
650
    console_targets = [target,
596
651
                       'tools/win32/bzr_postinstall.py',
597
652
                       ]
598
 
    gui_targets = []
599
 
    com_targets = []
 
653
    gui_targets = [gui_target]
600
654
    data_files = topics_files + plugins_files
601
655
 
602
656
    if 'qbzr' in plugins:
603
 
        get_qbzr_py2exe_info(includes, excludes, packages)
 
657
        get_qbzr_py2exe_info(includes, excludes, packages, data_files)
604
658
 
605
659
    if 'svn' in plugins:
606
660
        get_svn_py2exe_info(includes, excludes, packages)
629
683
        # print this warning to stderr as output is redirected, so it is seen
630
684
        # at build time.  Also to stdout so it appears in the log
631
685
        for f in (sys.stderr, sys.stdout):
632
 
            print >> f, \
633
 
                "Skipping TBZR binaries - please set TBZR to a directory to enable"
 
686
            f.write("Skipping TBZR binaries - "
 
687
                "please set TBZR to a directory to enable\n")
634
688
 
635
689
    # MSWSOCK.dll is a system-specific library, which py2exe accidentally pulls
636
690
    # in on Vista.
640
694
                               "excludes": excludes,
641
695
                               "dll_excludes": dll_excludes,
642
696
                               "dist_dir": "win32_bzr.exe",
643
 
                               "optimize": 1,
 
697
                               "optimize": 2,
 
698
                               "custom_boot_script":
 
699
                                        "tools/win32/py2exe_boot_common.py",
644
700
                              },
645
701
                   }
646
702
 
647
 
    setup(options=options_list,
648
 
          console=console_targets,
649
 
          windows=gui_targets,
650
 
          com_server=com_targets,
651
 
          zipfile='lib/library.zip',
652
 
          data_files=data_files,
653
 
          cmdclass={'install_data': install_data_with_bytecompile},
654
 
          )
 
703
    # We want the libaray.zip to have optimize = 2, but the exe to have
 
704
    # optimize = 1, so that .py files that get compilied at run time
 
705
    # (e.g. user installed plugins) dont have their doc strings removed.
 
706
    class py2exe_no_oo_exe(py2exe.build_exe.py2exe):
 
707
        def build_executable(self, *args, **kwargs):
 
708
            self.optimize = 1
 
709
            py2exe.build_exe.py2exe.build_executable(self, *args, **kwargs)
 
710
            self.optimize = 2
 
711
 
 
712
    if __name__ == '__main__':
 
713
        setup(options=options_list,
 
714
              console=console_targets,
 
715
              windows=gui_targets,
 
716
              zipfile='lib/library.zip',
 
717
              data_files=data_files,
 
718
              cmdclass={'install_data': install_data_with_bytecompile,
 
719
                        'py2exe': py2exe_no_oo_exe},
 
720
              )
655
721
 
656
722
else:
657
723
    # ad-hoc for easy_install
661
727
        # easy_install one
662
728
        DATA_FILES = [('man/man1', ['bzr.1'])]
663
729
 
 
730
    if sys.platform != 'win32':
 
731
        # see https://wiki.kubuntu.org/Apport/DeveloperHowTo
 
732
        #
 
733
        # checking the paths and hardcoding the check for root is a bit gross,
 
734
        # but I don't see a cleaner way to find out the locations in a way
 
735
        # that's going to align with the hardcoded paths in apport.
 
736
        if os.geteuid() == 0:
 
737
            DATA_FILES += [
 
738
                ('/usr/share/apport/package-hooks',
 
739
                    ['apport/source_bzr.py']),
 
740
                ('/etc/apport/crashdb.conf.d/',
 
741
                    ['apport/bzr-crashdb.conf']),]
 
742
 
664
743
    # std setup
665
744
    ARGS = {'scripts': ['bzr'],
666
745
            'data_files': DATA_FILES,
672
751
    ARGS.update(BZRLIB)
673
752
    ARGS.update(PKG_DATA)
674
753
 
675
 
    setup(**ARGS)
 
754
    if __name__ == '__main__':
 
755
        setup(**ARGS)