aboutsummaryrefslogtreecommitdiffstats
path: root/setuptools/command
diff options
context:
space:
mode:
Diffstat (limited to 'setuptools/command')
-rwxr-xr-xsetuptools/command/easy_install.py177
1 files changed, 126 insertions, 51 deletions
diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py
index 8b88cd1d..cf4402a5 100755
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -22,6 +22,8 @@ import re
import stat
import random
import platform
+import textwrap
+import warnings
from glob import glob
from distutils import log, dir_util
@@ -1780,57 +1782,130 @@ def fix_jython_executable(executable, options):
return executable
-def get_script_args(dist, executable=sys_executable, wininst=False):
- """Yield write_script() argument tuples for a distribution's entrypoints"""
- spec = str(dist.as_requirement())
- header = get_script_header("", executable, wininst)
- for group in 'console_scripts', 'gui_scripts':
- for name, ep in dist.get_entry_map(group).items():
- script_text = (
- "# EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r\n"
- "__requires__ = %(spec)r\n"
- "import sys\n"
- "from pkg_resources import load_entry_point\n"
- "\n"
- "if __name__ == '__main__':"
- "\n"
- " sys.exit(\n"
- " load_entry_point(%(spec)r, %(group)r, %(name)r)()\n"
- " )\n"
- ) % locals()
- if sys.platform=='win32' or wininst:
- # On Windows/wininst, add a .py extension and an .exe launcher
- if group=='gui_scripts':
- launcher_type = 'gui'
- ext = '-script.pyw'
- old = ['.pyw']
- new_header = re.sub('(?i)python.exe','pythonw.exe',header)
- else:
- launcher_type = 'cli'
- ext = '-script.py'
- old = ['.py','.pyc','.pyo']
- new_header = re.sub('(?i)pythonw.exe','python.exe',header)
- if os.path.exists(new_header[2:-1].strip('"')) or sys.platform!='win32':
- hdr = new_header
- else:
- hdr = header
- yield (name+ext, hdr+script_text, 't', [name+x for x in old])
- yield (
- name+'.exe', get_win_launcher(launcher_type),
- 'b' # write in binary mode
- )
- if not is_64bit():
- # install a manifest for the launcher to prevent Windows
- # from detecting it as an installer (which it will for
- # launchers like easy_install.exe). Consider only
- # adding a manifest for launchers detected as installers.
- # See Distribute #143 for details.
- m_name = name + '.exe.manifest'
- yield (m_name, load_launcher_manifest(name), 't')
- else:
- # On other platforms, we assume the right thing to do is to
- # just write the stub with no extension.
- yield (name, header+script_text)
+class ScriptWriter(object):
+ """
+ Encapsulates behavior around writing entry point scripts for console and
+ gui apps.
+ """
+
+ template = textwrap.dedent("""
+ # EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r
+ __requires__ = %(spec)r
+ import sys
+ from pkg_resources import load_entry_point
+
+ if __name__ == '__main__':
+ sys.exit(
+ load_entry_point(%(spec)r, %(group)r, %(name)r)()
+ )
+ """).lstrip()
+
+ @classmethod
+ def get_script_args(cls, dist, executable=sys_executable, wininst=False):
+ """
+ Yield write_script() argument tuples for a distribution's entrypoints
+ """
+ gen_class = cls.get_writer(wininst)
+ spec = str(dist.as_requirement())
+ header = get_script_header("", executable, wininst)
+ for type_ in 'console', 'gui':
+ group = type_ + '_scripts'
+ for name, ep in dist.get_entry_map(group).items():
+ script_text = gen_class.template % locals()
+ for res in gen_class._get_script_args(type_, name, header,
+ script_text):
+ yield res
+
+ @classmethod
+ def get_writer(cls, force_windows):
+ if force_windows or sys.platform=='win32':
+ return WindowsScriptWriter.get_writer()
+ return cls
+
+ @classmethod
+ def _get_script_args(cls, type_, name, header, script_text):
+ # Simply write the stub with no extension.
+ yield (name, header+script_text)
+
+
+class WindowsScriptWriter(ScriptWriter):
+ @classmethod
+ def get_writer(cls):
+ """
+ Get a script writer suitable for Windows
+ """
+ # for compatibility, return the writer that creates exe launchers
+ # unless the SETUPTOOLS_USE_PYLAUNCHER is set, indicating
+ # future behavior.
+ use_legacy = 'SETUPTOOLS_USE_PYLAUNCHER' not in os.environ
+ if use_legacy:
+ return WindowsLauncherScriptWriter
+ return cls
+
+ @classmethod
+ def _get_script_args(cls, type_, name, header, script_text):
+ "For Windows, add a .py extension"
+ ext = dict(console='.pya', gui='.pyw')[type_]
+ if ext not in os.environ['PATHEXT'].lower().split(';'):
+ warnings.warn("%s not listed in PATHEXT; scripts will not be "
+ "recognized as executables." % ext, UserWarning)
+ old = ['.pya', '.py', '-script.py', '.pyc', '.pyo', '.pyw', '.exe']
+ old.remove(ext)
+ header = cls._adjust_header(type_, header)
+ blockers = [name+x for x in old]
+ yield name+ext, header+script_text, 't', blockers
+
+ @staticmethod
+ def _adjust_header(type_, orig_header):
+ """
+ Make sure 'pythonw' is used for gui and and 'python' is used for
+ console (regardless of what sys.executable is).
+ """
+ pattern = 'pythonw.exe'
+ repl = 'python.exe'
+ if type_ == 'gui':
+ pattern, repl = repl, pattern
+ pattern_ob = re.compile(re.escape(pattern), re.IGNORECASE)
+ new_header = pattern_ob.sub(string=orig_header, repl=repl)
+ clean_header = new_header[2:-1].strip('"')
+ if sys.platform == 'win32' and not os.path.exists(clean_header):
+ # the adjusted version doesn't exist, so return the original
+ return orig_header
+ return new_header
+
+
+class WindowsLauncherScriptWriter(WindowsScriptWriter):
+ @classmethod
+ def _get_script_args(cls, type_, name, header, script_text):
+ """
+ For Windows, add a .py extension and an .exe launcher
+ """
+ if type_=='gui':
+ launcher_type = 'gui'
+ ext = '-script.pyw'
+ old = ['.pyw']
+ else:
+ launcher_type = 'cli'
+ ext = '-script.py'
+ old = ['.py','.pyc','.pyo']
+ hdr = cls._adjust_header(type_, header)
+ blockers = [name+x for x in old]
+ yield (name+ext, hdr+script_text, 't', blockers)
+ yield (
+ name+'.exe', get_win_launcher(launcher_type),
+ 'b' # write in binary mode
+ )
+ if not is_64bit():
+ # install a manifest for the launcher to prevent Windows
+ # from detecting it as an installer (which it will for
+ # launchers like easy_install.exe). Consider only
+ # adding a manifest for launchers detected as installers.
+ # See Distribute #143 for details.
+ m_name = name + '.exe.manifest'
+ yield (m_name, load_launcher_manifest(name), 't')
+
+# for backward-compatibility
+get_script_args = ScriptWriter.get_script_args
def get_win_launcher(type):
"""