diff options
-rwxr-xr-x | launcher.c | 28 | ||||
-rwxr-xr-x | setuptools.egg-info/entry_points.txt | 1 | ||||
-rwxr-xr-x | setuptools.txt | 44 | ||||
-rwxr-xr-x | setuptools/cli.exe | bin | 0 -> 5632 bytes | |||
-rwxr-xr-x | setuptools/command/develop.py | 2 | ||||
-rwxr-xr-x | setuptools/command/easy_install.py | 82 | ||||
-rwxr-xr-x | setuptools/gui.exe | bin | 0 -> 5632 bytes | |||
-rwxr-xr-x | setuptools/launcher.exe | bin | 5120 -> 0 bytes |
8 files changed, 86 insertions, 71 deletions
@@ -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,19 +102,19 @@ 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); +} diff --git a/setuptools.egg-info/entry_points.txt b/setuptools.egg-info/entry_points.txt index 3136631e..37a81910 100755 --- a/setuptools.egg-info/entry_points.txt +++ b/setuptools.egg-info/entry_points.txt @@ -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 diff --git a/setuptools.txt b/setuptools.txt index 956d84ea..264058a2 100755 --- a/setuptools.txt +++ b/setuptools.txt @@ -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 diff --git a/setuptools/cli.exe b/setuptools/cli.exe Binary files differnew file mode 100755 index 00000000..d4afdaec --- /dev/null +++ b/setuptools/cli.exe diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 24875467..f767ac4a 100755 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -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 []: diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index 6f73383b..302a28cf 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -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) - spec = str(dist.as_requirement()) - group = 'console_scripts' - 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() + def _install_wrapper_script(self, dist, group, name, entry_point): + """Write new-style console scripts, unless excluded""" - 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 - ) + spec = str(dist.as_requirement()) + 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() + + 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" diff --git a/setuptools/gui.exe b/setuptools/gui.exe Binary files differnew file mode 100755 index 00000000..4021a4e4 --- /dev/null +++ b/setuptools/gui.exe diff --git a/setuptools/launcher.exe b/setuptools/launcher.exe Binary files differdeleted file mode 100755 index f2f5dd5c..00000000 --- a/setuptools/launcher.exe +++ /dev/null |