Support generating .pyw/.exe wrappers for Windows GUI scripts, and
"normal" #! wrappers for GUI scripts on other platforms. --HG-- branch : setuptools extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041254
This commit is contained in:
parent
9159d6d847
commit
ad0eebab21
32
launcher.c
32
launcher.c
|
@ -12,7 +12,8 @@
|
|||
|
||||
To build/rebuild with mingw32, do this in the setuptools project directory:
|
||||
|
||||
gcc -mno-cygwin -O -s -o setuptools/launcher.exe launcher.c
|
||||
gcc -DGUI=0 -mno-cygwin -O -s -o setuptools/cli.exe launcher.c
|
||||
gcc -DGUI=1 -mwindows -mno-cygwin -O -s -o setuptools/gui.exe launcher.c
|
||||
|
||||
It links to msvcrt.dll, but this shouldn't be a problem since it doesn't
|
||||
actually run Python in the same process. Note that using 'exec' instead
|
||||
|
@ -32,14 +33,13 @@
|
|||
int fail(char *format, char *data) {
|
||||
/* Print error message to stderr and return 1 */
|
||||
fprintf(stderr, format, data);
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int run(int argc, char **argv, int is_gui) {
|
||||
|
||||
char python[256]; /* python executable's filename*/
|
||||
char script[256]; /* the script's filename */
|
||||
|
@ -55,7 +55,7 @@ int main(int argc, char **argv) {
|
|||
end = script + strlen(script);
|
||||
while( end>script && *end != '.')
|
||||
*end-- = '\0';
|
||||
strcat(script, "py");
|
||||
strcat(script, (GUI ? "pyw" : "py"));
|
||||
|
||||
/* figure out the target python executable */
|
||||
|
||||
|
@ -102,22 +102,22 @@ int main(int argc, char **argv) {
|
|||
newargs[argc+1] = NULL;
|
||||
|
||||
/* printf("args 0: %s\nargs 1: %s\n", newargs[0], newargs[1]); */
|
||||
|
||||
if (is_gui) {
|
||||
/* Use exec, we don't need to wait for the GUI to finish */
|
||||
execv(newargs[0], (const char * const *)(newargs));
|
||||
return fail("Could not exec %s", python); /* shouldn't get here! */
|
||||
}
|
||||
/* We *do* need to wait for a CLI to finish, so use spawn */
|
||||
return spawnv(P_WAIT, newargs[0], (const char * const *)(newargs));
|
||||
}
|
||||
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hI, HINSTANCE hP, LPSTR lpCmd, int nShow) {
|
||||
return run(__argc, __argv, GUI);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm
|
|||
rotate = setuptools.command.rotate:rotate
|
||||
develop = setuptools.command.develop:develop
|
||||
setopt = setuptools.command.setopt:setopt
|
||||
build_py = setuptools.command.build_py:build_py
|
||||
saveopts = setuptools.command.saveopts:saveopts
|
||||
egg_info = setuptools.command.egg_info:egg_info
|
||||
upload = setuptools.command.upload:upload
|
||||
|
|
|
@ -39,8 +39,9 @@ Feature Highlights:
|
|||
without needing to create a ``MANIFEST.in`` file, and without having to force
|
||||
regeneration of the ``MANIFEST`` file when your source tree changes.
|
||||
|
||||
* Automatically generate wrapper scripts or Windows (console) .exe files for
|
||||
any number of "main" functions in your project.
|
||||
* Automatically generate wrapper scripts or Windows (console and GUI) .exe
|
||||
files for any number of "main" functions in your project. (Note: this is not
|
||||
a py2exe replacement; the .exe files rely on the local Python installation.)
|
||||
|
||||
* Transparent Pyrex support, so that your setup.py can list ``.pyx`` files and
|
||||
still work even when the end-user doesn't have Pyrex installed (as long as
|
||||
|
@ -314,8 +315,8 @@ for you with the correct extension, and on Windows it will even create an
|
|||
``.exe`` file so that users don't have to change their ``PATHEXT`` settings.
|
||||
The way to use this feature is to define "entry points" in your setup script
|
||||
that indicate what function the generated script should import and run. For
|
||||
example, to create two scripts called ``foo`` and ``bar``, you might do
|
||||
something like this::
|
||||
example, to create two console scripts called ``foo`` and ``bar``, and a GUI
|
||||
script called ``baz``, you might do something like this::
|
||||
|
||||
setup(
|
||||
# other arguments here...
|
||||
|
@ -323,23 +324,31 @@ something like this::
|
|||
'console_scripts': [
|
||||
'foo = my_package.some_module:main_func',
|
||||
'bar = other_module:some_func',
|
||||
],
|
||||
'gui_scripts': [
|
||||
'baz = my_package_gui.start_func',
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
When this project is installed on non-Windows platforms (using "setup.py
|
||||
install", "setup.py develop", or by using EasyInstall), a pair of ``foo`` and
|
||||
``bar`` scripts will be installed that import ``main_func`` and ``some_func``
|
||||
from the specified modules. The functions you specify are called with no
|
||||
arguments, and their return value is passed to ``sys.exit()``, so you can
|
||||
return an errorlevel or message to print to stderr.
|
||||
install", "setup.py develop", or by using EasyInstall), a set of ``foo``,
|
||||
``bar``, and ``baz`` scripts will be installed that import ``main_func`` and
|
||||
``some_func`` from the specified modules. The functions you specify are called
|
||||
with no arguments, and their return value is passed to ``sys.exit()``, so you
|
||||
can return an errorlevel or message to print to stderr.
|
||||
|
||||
You may define as many "console script" entry points as you like, and each one
|
||||
can optionally specify "extras" that it depends on, and that will be added to
|
||||
``sys.path`` when the script is run. For more information on "extras", see
|
||||
section below on `Declaring Extras`_. For more information on "entry points"
|
||||
in general, see the section below on `Dynamic Discovery of Services and
|
||||
Plugins`_.
|
||||
On Windows, a set of ``foo.exe``, ``bar.exe``, and ``baz.exe`` launchers are
|
||||
created, alongside a set of ``foo.py``, ``bar.py``, and ``baz.pyw`` files. The
|
||||
``.exe`` wrappers find and execute the right version of Python to run the
|
||||
``.py`` or ``.pyw`` file.
|
||||
|
||||
You may define as many "console script" and "gui script" entry points as you
|
||||
like, and each one can optionally specify "extras" that it depends on, that
|
||||
will be added to ``sys.path`` when the script is run. For more information on
|
||||
"extras", see the section below on `Declaring Extras`_. For more information
|
||||
on "entry points" in general, see the section below on `Dynamic Discovery of
|
||||
Services and Plugins`_.
|
||||
|
||||
|
||||
Declaring Dependencies
|
||||
|
@ -1848,6 +1857,11 @@ XXX
|
|||
Release Notes/Change History
|
||||
----------------------------
|
||||
|
||||
0.6a3
|
||||
* Added ``gui_scripts`` entry point group to allow installing GUI scripts
|
||||
on Windows and other platforms. (The special handling is only for Windows;
|
||||
other platforms are treated the same as for ``console_scripts``.)
|
||||
|
||||
0.6a2
|
||||
* Added ``console_scripts`` entry point group to allow installing scripts
|
||||
without the need to create separate script files. On Windows, console
|
||||
|
|
Binary file not shown.
|
@ -103,7 +103,7 @@ class develop(easy_install):
|
|||
# create wrapper scripts in the script dir, pointing to dist.scripts
|
||||
|
||||
# new-style...
|
||||
self.install_console_scripts(dist)
|
||||
self.install_wrapper_scripts(dist)
|
||||
|
||||
# ...and old-style
|
||||
for script_name in self.distribution.scripts or []:
|
||||
|
|
|
@ -10,7 +10,7 @@ file, or visit the `EasyInstall home page`__.
|
|||
__ http://peak.telecommunity.com/DevCenter/EasyInstall
|
||||
"""
|
||||
|
||||
import sys, os.path, zipimport, shutil, tempfile, zipfile
|
||||
import sys, os.path, zipimport, shutil, tempfile, zipfile, re
|
||||
from glob import glob
|
||||
from setuptools import Command
|
||||
from setuptools.sandbox import run_setup
|
||||
|
@ -247,7 +247,7 @@ class easy_install(Command):
|
|||
def install_egg_scripts(self, dist):
|
||||
"""Write all the scripts for `dist`, unless scripts are excluded"""
|
||||
|
||||
self.install_console_scripts(dist)
|
||||
self.install_wrapper_scripts(dist)
|
||||
if self.exclude_scripts or not dist.metadata_isdir('scripts'):
|
||||
return
|
||||
|
||||
|
@ -440,52 +440,52 @@ class easy_install(Command):
|
|||
return dst
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def install_console_scripts(self, dist):
|
||||
"""Write new-style console scripts, unless excluded"""
|
||||
|
||||
def install_wrapper_scripts(self, dist):
|
||||
if self.exclude_scripts:
|
||||
return
|
||||
for group in 'console_scripts', 'gui_scripts':
|
||||
for name,ep in dist.get_entry_map(group).items():
|
||||
self._install_wrapper_script(dist, group, name, ep)
|
||||
|
||||
|
||||
|
||||
def _install_wrapper_script(self, dist, group, name, entry_point):
|
||||
"""Write new-style console scripts, unless excluded"""
|
||||
|
||||
spec = str(dist.as_requirement())
|
||||
group = 'console_scripts'
|
||||
header = get_script_header("")
|
||||
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"
|
||||
"sys.exit(\n"
|
||||
" load_entry_point(%(spec)r, %(group)r, %(name)r)()\n"
|
||||
")\n"
|
||||
) % locals()
|
||||
|
||||
for name,ep in dist.get_entry_map(group).items():
|
||||
|
||||
script_text = get_script_header("") + (
|
||||
"# 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"
|
||||
"sys.exit(\n"
|
||||
" load_entry_point(%(spec)r, %(group)r, %(name)r)()\n"
|
||||
")\n"
|
||||
) % locals()
|
||||
|
||||
if sys.platform=='win32':
|
||||
# On Windows, add a .py extension and an .exe launcher
|
||||
self.write_script(name+'.py', script_text)
|
||||
self.write_script(
|
||||
name+'.exe', resource_string('setuptools','launcher.exe'),
|
||||
'b' # write in binary mode
|
||||
)
|
||||
if sys.platform=='win32':
|
||||
# On Windows, add a .py extension and an .exe launcher
|
||||
if group=='gui_scripts':
|
||||
ext, launcher = '.pyw', 'gui.exe'
|
||||
new_header = re.sub('(?i)python.exe','pythonw.exe',header)
|
||||
else:
|
||||
# On other platforms, we assume the right thing to do is to
|
||||
# write the stub with no extension.
|
||||
self.write_script(name, script_text)
|
||||
|
||||
|
||||
ext, launcher = '.py', 'cli.exe'
|
||||
new_header = re.sub('(?i)pythonw.exe','pythonw.exe',header)
|
||||
|
||||
if os.path.exists(new_header[2:-1]):
|
||||
header = new_header
|
||||
|
||||
self.write_script(name+ext, header+script_text)
|
||||
self.write_script(
|
||||
name+'.exe', resource_string('setuptools', launcher),
|
||||
'b' # write in binary mode
|
||||
)
|
||||
else:
|
||||
# On other platforms, we assume the right thing to do is to just
|
||||
# write the stub with no extension.
|
||||
self.write_script(name, header+script_text)
|
||||
|
||||
|
||||
|
||||
|
@ -495,7 +495,7 @@ class easy_install(Command):
|
|||
spec = str(dist.as_requirement())
|
||||
|
||||
if dev_path:
|
||||
script_text = get_script_header(script_text) + (
|
||||
script_text = get_script_header(script_text) + (
|
||||
"# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r\n"
|
||||
"__requires__ = %(spec)r\n"
|
||||
"from pkg_resources import require; require(%(spec)r)\n"
|
||||
|
@ -504,7 +504,7 @@ class easy_install(Command):
|
|||
"execfile(__file__)\n"
|
||||
) % locals()
|
||||
else:
|
||||
script_text = get_script_header(script_text) + (
|
||||
script_text = get_script_header(script_text) + (
|
||||
"# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r\n"
|
||||
"__requires__ = %(spec)r\n"
|
||||
"import pkg_resources\n"
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue