/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to setup.py

  • Committer: John Arbash Meinel
  • Date: 2011-04-20 14:27:19 UTC
  • mto: This revision was merged to the branch mainline in revision 5837.
  • Revision ID: john@arbash-meinel.com-20110420142719-advs1k5vztqzbrgv
Fix bug #767177. Be more agressive with file.close() calls.

Our test suite gets a number of thread leaks and failures because it happens to get async
SFTPFile.close() calls. (if an SFTPFile closes due to __del__ it is done as an async request,
while if you call SFTPFile.close() it is done as a synchronous request.)
We have a couple other cases, probably. Namely SFTPTransport.get() also does an async
prefetch of the content, so if you don't .read() you'll also leak threads that think they
are doing work that you want.

The biggest change here, though, is using a try/finally in a generator, which is not 
python2.4 compatible.

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")
65
66
            'package_data': {'bzrlib': ['doc/api/*.txt',
66
67
                                        'tests/test_patches_data/*',
67
68
                                        'help_topics/en/*.txt',
 
69
                                        'tests/ssl_certs/ca.crt',
68
70
                                        'tests/ssl_certs/server_without_pass.key',
69
71
                                        'tests/ssl_certs/server_with_pass.key',
70
72
                                        'tests/ssl_certs/server.crt'
125
127
                f = file(batch_path, "w")
126
128
                f.write(batch_str)
127
129
                f.close()
128
 
                print "Created:", batch_path
129
 
            except Exception, e:
130
 
                print "ERROR: Unable to create %s: %s" % (batch_path, e)
 
130
                print("Created: %s" % batch_path)
 
131
            except Exception:
 
132
                e = sys.exc_info()[1]
 
133
                print("ERROR: Unable to create %s: %s" % (batch_path, e))
131
134
 
132
135
    def _quoted_path(self, path):
133
136
        if ' ' in path:
171
174
        from Pyrex.Distutils import build_ext
172
175
        from Pyrex.Compiler.Version import version as pyrex_version
173
176
    except ImportError:
174
 
        print "No Pyrex, trying Cython..."
 
177
        print("No Pyrex, trying Cython...")
175
178
        from Cython.Distutils import build_ext
176
179
        from Cython.Compiler.Version import version as pyrex_version
177
180
except ImportError:
178
181
    have_pyrex = False
179
182
    # try to build the extension from the prior generated source.
180
 
    print
181
 
    print ("The python package 'Pyrex' is not available."
182
 
           " If the .c files are available,")
183
 
    print ("they will be built,"
184
 
           " but modifying the .pyx files will not rebuild them.")
185
 
    print
 
183
    print("")
 
184
    print("The python package 'Pyrex' is not available."
 
185
          " If the .c files are available,")
 
186
    print("they will be built,"
 
187
          " but modifying the .pyx files will not rebuild them.")
 
188
    print("")
186
189
    from distutils.command.build_ext import build_ext
187
190
else:
188
191
    have_pyrex = True
204
207
    def run(self):
205
208
        try:
206
209
            build_ext.run(self)
207
 
        except DistutilsPlatformError, e:
 
210
        except DistutilsPlatformError:
 
211
            e = sys.exc_info()[1]
208
212
            if not self.allow_python_fallback:
209
213
                log.warn('\n  Cannot build extensions.\n'
210
214
                         '  Use "build_ext --allow-python-fallback" to use'
281
285
    add_pyrex_extension('bzrlib._dirstate_helpers_pyx',
282
286
                        libraries=['Ws2_32'])
283
287
    add_pyrex_extension('bzrlib._walkdirs_win32')
284
 
    z_lib = 'zdll'
285
288
else:
286
289
    if have_pyrex and pyrex_version_info[:3] == (0,9,4):
287
290
        # Pyrex 0.9.4.1 fails to compile this extension correctly
288
291
        # The code it generates re-uses a "local" pointer and
289
292
        # calls "PY_DECREF" after having set it to NULL. (It mixes PY_XDECREF
290
293
        # which is NULL safe with PY_DECREF which is not.)
291
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/449372>
292
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/276868>
293
 
        print 'Cannot build extension "bzrlib._dirstate_helpers_pyx" using'
294
 
        print 'your version of pyrex "%s". Please upgrade your pyrex' % (
295
 
            pyrex_version,)
296
 
        print 'install. For now, the non-compiled (python) version will'
297
 
        print 'be used instead.'
 
294
        # <https://bugs.launchpad.net/bzr/+bug/449372>
 
295
        # <https://bugs.launchpad.net/bzr/+bug/276868>
 
296
        print('Cannot build extension "bzrlib._dirstate_helpers_pyx" using')
 
297
        print('your version of pyrex "%s". Please upgrade your pyrex'
 
298
              % (pyrex_version,))
 
299
        print('install. For now, the non-compiled (python) version will')
 
300
        print('be used instead.')
298
301
    else:
299
302
        add_pyrex_extension('bzrlib._dirstate_helpers_pyx')
300
303
    add_pyrex_extension('bzrlib._readdir_pyx')
301
 
    z_lib = 'z'
302
 
add_pyrex_extension('bzrlib._chk_map_pyx', libraries=[z_lib])
 
304
add_pyrex_extension('bzrlib._chk_map_pyx')
303
305
ext_modules.append(Extension('bzrlib._patiencediff_c',
304
306
                             ['bzrlib/_patiencediff_c.c']))
305
307
if have_pyrex and pyrex_version_info < (0, 9, 6, 3):
306
 
    print
307
 
    print 'Your Pyrex/Cython version %s is too old to build the simple_set' % (
308
 
        pyrex_version)
309
 
    print 'and static_tuple extensions.'
310
 
    print 'Please upgrade to at least Pyrex 0.9.6.3'
311
 
    print
 
308
    print("")
 
309
    print('Your Pyrex/Cython version %s is too old to build the simple_set' % (
 
310
        pyrex_version))
 
311
    print('and static_tuple extensions.')
 
312
    print('Please upgrade to at least Pyrex 0.9.6.3')
 
313
    print("")
312
314
    # TODO: Should this be a fatal error?
313
315
else:
314
316
    # We only need 0.9.6.3 to build _simple_set_pyx, but static_tuple depends
320
322
 
321
323
 
322
324
if unavailable_files:
323
 
    print 'C extension(s) not found:'
324
 
    print '   %s' % ('\n  '.join(unavailable_files),)
325
 
    print 'The python versions will be used instead.'
326
 
    print
 
325
    print('C extension(s) not found:')
 
326
    print('   %s' % ('\n  '.join(unavailable_files),))
 
327
    print('The python versions will be used instead.')
 
328
    print("")
327
329
 
328
330
 
329
331
def get_tbzr_py2exe_info(includes, excludes, packages, console_targets,
393
395
    # ditto for the tbzrcommand tool
394
396
    tbzrcommand = dict(
395
397
        script = os.path.join(tbzr_root, "scripts", "tbzrcommand.py"),
396
 
        icon_resources = [(0,'bzr.ico')],
 
398
        icon_resources = icon_resources,
 
399
        other_resources = other_resources,
397
400
    )
398
401
    console_targets.append(tbzrcommand)
399
402
    tbzrcommandw = tbzrcommand.copy()
413
416
 
414
417
def get_qbzr_py2exe_info(includes, excludes, packages, data_files):
415
418
    # PyQt4 itself still escapes the plugin detection code for some reason...
416
 
    packages.append('PyQt4')
417
 
    excludes.append('PyQt4.elementtree.ElementTree')
418
 
    excludes.append('PyQt4.uic.port_v3')
 
419
    includes.append('PyQt4.QtCore')
 
420
    includes.append('PyQt4.QtGui')
419
421
    includes.append('sip') # extension module required for Qt.
420
422
    packages.append('pygments') # colorizer for qbzr
421
423
    packages.append('docutils') # html formatting
422
424
    includes.append('win32event')  # for qsubprocess stuff
423
 
    # but we can avoid many Qt4 Dlls.
424
 
    dll_excludes.extend(
425
 
        """QtAssistantClient4.dll QtCLucene4.dll QtDesigner4.dll
426
 
        QtHelp4.dll QtNetwork4.dll QtOpenGL4.dll QtScript4.dll
427
 
        QtSql4.dll QtTest4.dll QtWebKit4.dll QtXml4.dll
428
 
        qscintilla2.dll""".split())
429
425
    # the qt binaries might not be on PATH...
430
426
    # They seem to install to a place like C:\Python25\PyQt4\*
431
427
    # Which is not the same as C:\Python25\Lib\site-packages\PyQt4
534
530
            install_data.run(self)
535
531
 
536
532
            py2exe = self.distribution.get_command_obj('py2exe', False)
537
 
            optimize = py2exe.optimize
 
533
            # GZ 2010-04-19: Setup has py2exe.optimize as 2, but give plugins
 
534
            #                time before living with docstring stripping
 
535
            optimize = 1
538
536
            compile_names = [f for f in self.outfiles if f.endswith('.py')]
 
537
            # Round mtime to nearest even second so that installing on a FAT
 
538
            # filesystem bytecode internal and script timestamps will match
 
539
            for f in compile_names:
 
540
                mtime = os.stat(f).st_mtime
 
541
                remainder = mtime % 2
 
542
                if remainder:
 
543
                    mtime -= remainder
 
544
                    os.utime(f, (mtime, mtime))
539
545
            byte_compile(compile_names,
540
546
                         optimize=optimize,
541
547
                         force=self.force, prefix=self.install_dir,
542
548
                         dry_run=self.dry_run)
543
 
            if optimize:
544
 
                suffix = 'o'
545
 
            else:
546
 
                suffix = 'c'
547
 
            self.outfiles.extend([f + suffix for f in compile_names])
 
549
            self.outfiles.extend([f + 'o' for f in compile_names])
548
550
    # end of class install_data_with_bytecompile
549
551
 
550
552
    target = py2exe.build_exe.Target(script = "bzr",
558
560
                                     company_name = "Canonical Ltd.",
559
561
                                     comments = META_INFO['description'],
560
562
                                    )
 
563
    gui_target = copy.copy(target)
 
564
    gui_target.dest_base = "bzrw"
561
565
 
562
566
    packages = BZRLIB['packages']
563
567
    packages.remove('bzrlib')
648
652
    console_targets = [target,
649
653
                       'tools/win32/bzr_postinstall.py',
650
654
                       ]
651
 
    gui_targets = []
 
655
    gui_targets = [gui_target]
652
656
    data_files = topics_files + plugins_files
653
657
 
654
658
    if 'qbzr' in plugins:
681
685
        # print this warning to stderr as output is redirected, so it is seen
682
686
        # at build time.  Also to stdout so it appears in the log
683
687
        for f in (sys.stderr, sys.stdout):
684
 
            print >> f, \
685
 
                "Skipping TBZR binaries - please set TBZR to a directory to enable"
 
688
            f.write("Skipping TBZR binaries - "
 
689
                "please set TBZR to a directory to enable\n")
686
690
 
687
691
    # MSWSOCK.dll is a system-specific library, which py2exe accidentally pulls
688
692
    # in on Vista.
689
 
    dll_excludes.extend(["MSWSOCK.dll", "MSVCP60.dll", "powrprof.dll"])
 
693
    dll_excludes.extend(["MSWSOCK.dll",
 
694
                         "MSVCP60.dll",
 
695
                         "MSVCP90.dll",
 
696
                         "powrprof.dll",
 
697
                         "SHFOLDER.dll"])
690
698
    options_list = {"py2exe": {"packages": packages + list(additional_packages),
691
699
                               "includes": includes,
692
700
                               "excludes": excludes,
693
701
                               "dll_excludes": dll_excludes,
694
702
                               "dist_dir": "win32_bzr.exe",
695
 
                               "optimize": 1,
 
703
                               "optimize": 2,
 
704
                               "custom_boot_script":
 
705
                                        "tools/win32/py2exe_boot_common.py",
696
706
                              },
697
707
                   }
698
708
 
699
 
    setup(options=options_list,
700
 
          console=console_targets,
701
 
          windows=gui_targets,
702
 
          zipfile='lib/library.zip',
703
 
          data_files=data_files,
704
 
          cmdclass={'install_data': install_data_with_bytecompile},
705
 
          )
 
709
    # We want the libaray.zip to have optimize = 2, but the exe to have
 
710
    # optimize = 1, so that .py files that get compilied at run time
 
711
    # (e.g. user installed plugins) dont have their doc strings removed.
 
712
    class py2exe_no_oo_exe(py2exe.build_exe.py2exe):
 
713
        def build_executable(self, *args, **kwargs):
 
714
            self.optimize = 1
 
715
            py2exe.build_exe.py2exe.build_executable(self, *args, **kwargs)
 
716
            self.optimize = 2
 
717
 
 
718
    if __name__ == '__main__':
 
719
        setup(options=options_list,
 
720
              console=console_targets,
 
721
              windows=gui_targets,
 
722
              zipfile='lib/library.zip',
 
723
              data_files=data_files,
 
724
              cmdclass={'install_data': install_data_with_bytecompile,
 
725
                        'py2exe': py2exe_no_oo_exe},
 
726
              )
706
727
 
707
728
else:
708
729
    # ad-hoc for easy_install
712
733
        # easy_install one
713
734
        DATA_FILES = [('man/man1', ['bzr.1'])]
714
735
 
715
 
    if sys.platform != 'win32':
716
 
        # see https://wiki.kubuntu.org/Apport/DeveloperHowTo
717
 
        #
718
 
        # checking the paths and hardcoding the check for root is a bit gross,
719
 
        # but I don't see a cleaner way to find out the locations in a way
720
 
        # that's going to align with the hardcoded paths in apport.
721
 
        if os.geteuid() == 0:
722
 
            DATA_FILES += [
723
 
                ('/usr/share/apport/package-hooks',
724
 
                    ['apport/source_bzr.py']),
725
 
                ('/etc/apport/crashdb.conf.d/',
726
 
                    ['apport/bzr-crashdb.conf']),]
727
 
 
728
736
    # std setup
729
737
    ARGS = {'scripts': ['bzr'],
730
738
            'data_files': DATA_FILES,
736
744
    ARGS.update(BZRLIB)
737
745
    ARGS.update(PKG_DATA)
738
746
 
739
 
    setup(**ARGS)
 
747
    if __name__ == '__main__':
 
748
        setup(**ARGS)