summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2013-08-10 09:04:34 -0400
committerJason R. Coombs <jaraco@jaraco.com>2013-08-10 09:04:34 -0400
commitf6f1221d96577a7ca99170df4fac572e2093f07e (patch)
treeca256c797a9bec897082a33006e63b1c69c99426
parent183efcc46f5d13eafe67c5ad7853916c7c147673 (diff)
downloadpython-setuptools-bitbucket-f6f1221d96577a7ca99170df4fac572e2093f07e.tar.gz
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.
-rw-r--r--CHANGES.txt7
-rw-r--r--docs/easy_install.txt9
-rwxr-xr-xsetuptools/command/easy_install.py63
3 files changed, 60 insertions, 19 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index b9a53a0c..c45b793b 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -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
diff --git a/docs/easy_install.txt b/docs/easy_install.txt
index 12bc73ea..92e770b7 100644
--- a/docs/easy_install.txt
+++ b/docs/easy_install.txt
@@ -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
diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py
index 5be48bb1..6a45e596 100755
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -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
@@ -1829,6 +1829,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):
"""
For Windows, add a .py extension and an .exe launcher
@@ -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