diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2013-08-10 09:04:34 -0400 |
---|---|---|
committer | Jason R. Coombs <jaraco@jaraco.com> | 2013-08-10 09:04:34 -0400 |
commit | f6f1221d96577a7ca99170df4fac572e2093f07e (patch) | |
tree | ca256c797a9bec897082a33006e63b1c69c99426 | |
parent | 183efcc46f5d13eafe67c5ad7853916c7c147673 (diff) | |
download | python-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.txt | 7 | ||||
-rw-r--r-- | docs/easy_install.txt | 9 | ||||
-rwxr-xr-x | setuptools/command/easy_install.py | 63 |
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 |