Index: setuptools/tests/test_resources.py =================================================================== --- setuptools/tests/test_resources.py (revision 66050) +++ setuptools/tests/test_resources.py (working copy) @@ -1,6 +1,11 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# NOTE: the shebang line is for ScriptHeaderTests from unittest import TestCase, makeSuite from pkg_resources import * -import pkg_resources, sys +from setuptools.command.easy_install import get_script_header, is_sh +import os, pkg_resources, sys +from StringIO import StringIO try: frozenset except NameError: @@ -491,3 +496,48 @@ +class ScriptHeaderTests(TestCase): + + non_ascii_exe = '/Users/José/bin/python' + + def test_get_script_header(self): + if sys.platform.startswith('java') and is_sh(sys.executable): + # Tested below + return + + self.assertEqual(get_script_header('#!/usr/local/bin/python'), + '#!%s\n' % os.path.normpath(sys.executable)) + self.assertEqual(get_script_header('#!/usr/bin/python -x'), + '#!%s -x\n' % os.path.normpath(sys.executable)) + self.assertEqual(get_script_header('#!/usr/bin/python', + executable=self.non_ascii_exe), + '#!%s -x\n' % self.non_ascii_exe) + + def test_get_script_header_jython_workaround(self): + platform = sys.platform + sys.platform = 'java1.5.0_13' + stderr = sys.stderr + try: + # A mock sys.executable that uses a shebang line (this file) + exe = os.path.normpath(os.path.splitext(__file__)[0] + '.py') + + self.assertEqual(get_script_header('#!/usr/local/bin/python', + executable=exe), + '#!/usr/bin/env %s\n' % exe) + + # Ensure we generate what is basically a broken shebang line + # when there's options, with a warning emitted + sys.stderr = StringIO() + self.assertEqual(get_script_header('#!/usr/bin/python -x', + executable=exe), + '#!%s -x\n' % exe) + self.assert_('Unable to adapt shebang line' in sys.stderr.getvalue()) + + sys.stderr = StringIO() + self.assertEqual(get_script_header('#!/usr/bin/python', + executable=self.non_ascii_exe), + '#!%s -x\n' % self.non_ascii_exe) + self.assert_('Unable to adapt shebang line' in sys.stderr.getvalue()) + finally: + sys.platform = platform + sys.stderr = stderr Index: setuptools/command/easy_install.py =================================================================== --- setuptools/command/easy_install.py (revision 66050) +++ setuptools/command/easy_install.py (working copy) @@ -1421,8 +1421,11 @@ executable = "python.exe" else: executable = nt_quote_arg(executable) + hdr = "#!%(executable)s%(options)s\n" % locals() - if unicode(hdr,'ascii','ignore').encode('ascii') != hdr: + non_ascii_hdr = unicode(hdr,'ascii','ignore').encode('ascii') != hdr + + if non_ascii_hdr: # Non-ascii path to sys.executable, use -x to prevent warnings if options: if options.strip().startswith('-'): @@ -1430,7 +1433,20 @@ # else: punt, we can't do it, let the warning happen anyway else: options = ' -x' - hdr = "#!%(executable)s%(options)s\n" % locals() + + if sys.platform.startswith('java') and is_sh(executable): + # Workaround Jython's sys.executable being a .sh (an invalid + # shebang line interpreter) + if options: + # Can't apply the workaround, leave it broken + print >> sys.stderr, \ + ("WARNING: Unable to adapt shebang line for Jython, " + "the following script is NOT executable\n see " + "http://bugs.jython.org/issue1112 for more information.") + else: + executable = '/usr/bin/env %s' % executable + + hdr = "#!%(executable)s%(options)s\n" % locals() return hdr def auto_chmod(func, arg, exc): @@ -1637,6 +1653,17 @@ import setuptools; argv0 = os.path.dirname(setuptools.__path__[0]) sys.argv[0] = argv0; sys.argv.append(argv0); main() +def is_sh(executable): + """Determine if the specified executable is a .sh (contains a + shebang line) + """ + try: + fp = open(executable) + magic = fp.read(2) + fp.close() + except (OSError,IOError): + return executable + return magic == '#!' def main(argv=None, **kw): from setuptools import setup