[Distutils] A plan for scripts (in EasyInstall)

Ian Bicking ianb at colorstudy.com
Mon Jun 6 18:00:24 CEST 2005


Phillip J. Eby wrote:
> Here's my semi-final plan for doing scripts with EasyInstall; please let me 
> know if you see any issues with it:
> 
> * Make bdist_egg stick the scripts under an EGG-INFO/scripts/ subdirectory 
> of the egg, by abusing the install_scripts command.  (Note: this does *not* 
> mean they will be copied to 'PackageName.egg-info', only that they will be 
> included in the built egg file.  Currently, subdirectories of .egg-info are 
> not included in the built egg, so this is completely separate.)
> 
> * Add 'metadata_isdir' and 'metadata_listdir' APIs to pkg_resources, to 
> allow inspecting the contents of EGG-INFO/scripts
> 
> * Add these options to the easy_install command:
> 
>    --exclude-scripts, -x     Don't install scripts
>    --scripts-to=DIR, -t DIR  Install scripts to DIR

Should these options match distutils?  Well, --install-scripts -- I 
don't think it has an --exclude-scripts.  I don't really see a need for 
the short form, but it doesn't really matter.

> The --scripts-to option would default to being the *same as the 
> installation directory*, unless you're installing to site-packages, in 
> which case they would go to the Python default location for installing scripts.
> 
> Why the installation directory?  Because if you run the scripts from there, 
> the egg(s) will be in a directory on sys.path, meaning that 'require()' 
> will then work.  In essence, I'm assuming that the normal use case for 
> specifying an install-dir is to create an "application directory" filled 
> with the eggs needed to run a specific application.  For example, on a 
> Unix-like system you might be installing to your ~/bin.
> 
> The downside to this assumption is that since the scripts are in the same 
> place, they might become importable when that's not intended.  So if you're 
> installing to a personal ~/lib/python, you will probably want to use -x or 
> -t to override.

How would they be importable?  Assuming you don't put __init__.py in 
scripts/, it shouldn't be a problem, right?  As for putting them in the 
installation direction, it's not a great place but at least they won't 
be lost.

> Anyway, if you are installing scripts, easy_install will just do what the 
> distutils does now to install them in their specified locations.  This 
> basically means giving them executable permissions and munging the #! line 
> if applicable.  On a multi-version install (-m or -i), it seems like we 
> should also add a line like:
> 
>    from pkg_resources import require; require("thispackage==version"); del 
> require
 >
> But, as I've pointed out before, it's a tricky modification, as it would 
> need to be inserted just before the first *executable* line of code in the 
> script, which is often not the first line.  Docstrings and __future__ 
> statements both have to be skipped, or else the script could be broken by 
> the modification.  Further, even a successful modification is going to 
> change the script's line numbering, which could have tech support 
> implications.  So, I'm somewhat reluctant to do this without a way to turn 
> it off (other than by skipping scripts).  There also needs to be a way to 
> verify that the script is in fact a Python script!  (Presumably by checking 
> for a .py/.pyw extension or a #! line containing "python".)
 >
> Also, adding such a 'require()' line might be more restrictive than 
> necessary; the script might include its own require() already!

Well, they certainly don't have require() lines yet, so you can set 
precedent now.  Personally I don't worry much about changing line 
numbers slightly -- in general it is easy and beneficial to make scripts 
very small, and I'd be worried about the generated code (which might be 
very useful to know for debugging) being obscured by tricky processes.

All the fiddling with a fake __main__ module and whatnot seems 
unnecessarily complicated, all to enable a crufty process.  In 
particular, I find __main__ annoying because of the double-import 
problem (the same module existing as __main__ and as its true name) -- 
it works okay for small utilities, but if I want to give the script any 
polish at all I'd want to get rid of __main__.

-- 
Ian Bicking  /  ianb at colorstudy.com  /  http://blog.ianbicking.org


More information about the Distutils-SIG mailing list