[Distutils] Disabling --single-version-externally-managed

Phillip J. Eby pje at telecommunity.com
Mon Sep 3 00:50:10 CEST 2007

At 01:12 PM 9/2/2007 -0700, Toshio Kuratomi wrote:
>What is the real way to allow people to do quick and dirty scripting and
>experimentation from the interpreter shell in this environment?


1. Select the desired default version using "easy_install package==version", or
2. Have *no* default version, and always use require() (or 
automatically-managed dependencies declared via a setup.py script).

>And once again, we are *not* creating and packaging scripts that use
>__require__.  We are packaging multiple versions of modules with a

And once again, this won't work.  Either you must not have a default 
version, or you must deal with the potential conflict in your scripts.

The supported way of doing that is to generate the scripts using 
easy_install.  If you are packaging something that doesn't use 
setuptools explicitly, you'll just have to patch it to declare its 
dependencies.  You're already patching the .spec file; heck, if it 
would make it more palatable, perhaps we could add a way to specify 
the requirements via the command line.  (Alternately, you could just 
create a requires.txt in the .egg-info directory.)

>   We need to have instructions for end-users who want to do
>quick and dirty scripting or experiment in the interpreter shell how to
>select the version that they wish.

easy_install package==version will change the default version, and 
require() will work if there is no default version.  Those are the 
supported ways of doing this.

>Once again, *we are not creating any system level python scripts that
>make use of a specific, non-default version*.

I'm saying that even your programs that use the default version, 
should explicitly specify what version they use.  If you're going to 
support multiple versions, then declare *all* the dependencies, or at 
least the ones that would otherwise have conflicts.

>B) For projects
>that have not been ported to a new version of the module.  We have no
>control over how those upstream scripts are written -- whether they use
>easy_install, hand code __requires__, or munge sys.path themselves.

The correct instructions are for them to use setuptools and declare 
their dependencies, or live with whatever the status quo is.

>This is true.  But it's not going to change until all upstreams have
>moved to using setuptools.  We provide a set of packages that work
>together.  And we provide a means for the user to shoot themselves in
>the foot.  But this is nothing new, they've had access to PYTHONPATH,
>su, rm -rf, etc in the past.
>What we can do is make as much of what they expect to work work as it
>used to.  And where it differs, we offer a standard, logical, and simple
>method to get the behaviour they want.

Right - and the single simplest solution for all of this is to simply 
use setuptools as it was designed: select a default version using 
easy_install, and declare dependencies for everything 
else.  Alternatively, don't install *anything* as the default 
version, and declare *all* dependencies.

If your goal is to have simple and consistent behavior, the second is 
the best choice.  If you want the greatest backward-compatibility, 
the first is the best choice.

Note that it isn't really possible for users *now* to choose a 
different package version at runtime, so requiring the use of 
easy_install to switch default versions doesn't seem like a big 
deal.  They already have to make this choice by what RPMs they 
install, and it's just as global a choice -- except that this way, 
they can do it without breaking anything.

>If you feel that __requires__ is a private method that shouldn't be used
>then we'd respect that.  But between that and your teelling us that
>pkg_resources.require() isn't meant to work like that, it means that
>there's simply no method for making setuptools do what we need it to and
>we'll have to find some other method to accomplish this.

There are *two* ways to accomplish it: have a default (and use 
easy_install to change it when desired), or don't have a default.

Either way, you are going to ultimately end up at a place where 
everything needs to declare its dependencies, preferably in a 
setup.py.  Having a default version may be useful for the transition 
period, but the best way to encourage people to actually transition 
is to have some *benefit* for declaring their dependencies -- like 
being able to use the non-default versions.

This is why I even discourage direct use of require(), as it says in the docs:

"""In general, it should not be necessary for you to call this method 
directly. It's intended more for use in quick-and-dirty scripting and 
interactive interpreter hacking than for production use. If you're 
creating an actual library or application, it's strongly recommended 
that you create a "setup.py" script using setuptools, and declare all 
your requirements there. That way, tools like EasyInstall can 
automatically detect what requirements your package has, and deal 
with them accordingly."""

More information about the Distutils-SIG mailing list