Commit 3e6dd67c authored by Jason R. Coombs's avatar Jason R. Coombs

Issue 60: Implemented experimental opt-in support for using native launchers...

Issue 60: Implemented experimental opt-in support for using native launchers rather than installing launcher executables. My initial experience with this technique has been very positive.
parent da1761c8
......@@ -6,6 +6,13 @@ CHANGES
1.0
---
* On Windows, Setuptools supports deferring to Vinay Sajip's `pylauncher
<https://bitbucket.org/pypa/pylauncher>`_ (included with Python 3.3) to
launch console and GUI scripts and not install its own launcher
executables. This experimental functionality is currently only enabled if
the ``SETUPTOOLS_USE_PYLAUNCHER`` environment variable is set (to anything).
In the future, this behavior may become default, but only after it has
matured and seen substantial adoption.
* Issue #50: Normalized API of environment marker support. Specifically,
removed line number and filename from SyntaxErrors when returned from
`pkg_resources.invalid_marker`. Any clients depending on the specific
......
......@@ -96,6 +96,15 @@ sections below on `Command-Line Options`_ and `Configuration Files`_. You
can pass command line options (such as ``--script-dir``) to
``ez_setup.py`` to control where ``easy_install.exe`` will be installed.
Setuptools also supports deferring to an external launcher such as
`pylauncher <https://bitbucket.org/pypa/pylauncher>`_ for launching scripts.
Enable this experimental functionality by setting the
``SETUPTOOLS_USE_PYLAUNCHER`` environment variable. Setuptools will then not
install its own launcher executable, but will install scripts as simple
scripts with a .py (or .pyw) extension appended. If these extensions are
associated with the pylauncher and listed in the PATHEXT environment variable,
these scripts can then be invoked simply and directly just like any other
executable.
Downloading and Installing a Package
......
......@@ -1818,7 +1818,7 @@ class ScriptWriter(object):
@classmethod
def get_writer(cls, force_windows):
if force_windows or sys.platform=='win32':
return WindowsScriptWriter
return WindowsScriptWriter.get_writer()
return cls
@classmethod
......@@ -1828,6 +1828,49 @@ class ScriptWriter(object):
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='.py', gui='.pyw')[type_]
old = ['.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):
"""
......@@ -1857,24 +1900,6 @@ class WindowsScriptWriter(ScriptWriter):
m_name = name + '.exe.manifest'
yield (m_name, load_launcher_manifest(name), 't')
@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
# for backward-compatibility
get_script_args = ScriptWriter.get_script_args
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment