Issue139

Title pkg_resources.require can't deal with multiple installed versions if one is present in easy-install.pth
Priority bug Status chatting
Superseder Nosy List mbogosian, pje
Assigned To Keywords

Created on 2012-06-25.07:53:53 by mbogosian, last changed 2012-06-27.17:16:18 by pje.

Messages
msg662 (view) Author: pje Date: 2012-06-27.17:16:17
You can't do failover or fallback if there's a default version.
msg661 (view) Author: mbogosian Date: 2012-06-25.17:39:02
So failover/fallback would work like this?

- - - - - - - - %< - - - - - - - -

easy_install BeautifulSoup==3.0.8
# ...
easy_install -U BeautifulSoup # <- upgrades to >= 3.1.0
# ...
python <<EOF
try:
    __require__ = ( 'BeautifulSoup==3.0.8', )
    import pkg_resources
# Note: we can't catch pkg_resources.DistributionNotFound explicitly
# because we can't yet import pkg_resources; so we have to catch the
# generic Exception instead
except:
    __require__ = ( 'BeautifulSoup>=3.1.0', )
    import pkg_resources
EOF

- - - - - - - - >% - - - - - - - -

Correct me if I'm wrong, but the workaround in msg660 only works for *one* package. In other words, there's no workaround for something like this:

- - - - - - - - %< - - - - - - - -

easy_install mymodule==3.0
# ...
easy_install mymodule==2.0 # <- mymodule 2.0 now globally active version
# ...
easy_install hermodule==5.0
# ...
easy_install hermodule==4.0 # <- hermodule 4.0 now globally active version
# ...
python <<EOF
import pkg_resources

try:
    pkg_resources.require('mymodule==3.0')
except pkg_resources.DistributionNotFound:
    # Fallback to mymodule 2.0 if 3.0 is unavailable
    pkg_resources.require('mymodule==2.0')
    displayMyModuleMissingFeaturesWarning()

try:
    pkg_resources.require('hermodule==5.0')
except pkg_resources.DistributionNotFound:
    # Fallback to hermodule 4.0 if 5.0 is unavailable
    pkg_resources.require('hermodule==4.0')
    displayHerModuleMissingFeaturesWarning()
EOF

- - - - - - - - >% - - - - - - - -
msg660 (view) Author: pje Date: 2012-06-25.16:34:24
On Mon, Jun 25, 2012 at 3:53 AM, mbogosian <setuptools@bugs.python.org>wrote:

>
> Perhaps I have misunderstood the intended behavior, but I thought one
> should be able to do this:
>
> % easy_install BeautifulSoup==3.0.8
> ...
> % easy_install -U BeautifulSoup
> [installs 3.1.0.1]
> ...
> % python -c 'import pkg_resources ; print
> pkg_resources.require("BeautifulSoup==3.0.8")'
> Traceback (most recent call last):
> pkg_resources.VersionConflict: (BeautifulSoup 3.1.0.1
> (.../site-packages/BeautifulSoup-3.1.0.1-py2.5.egg),
> Requirement.parse('BeautifulSoup==3.0.8'))
>

Do this instead:

python -c '__requires__=['BeautifulSoup==3.0.8']; import pkg_resources;
import beautifulsoup'

That is, if the main script declares a __requires__ variable before
importing pkg_resources, pkg_resources will allow you to override what
would normally produce a VersionConflict due to a default version being
present on the command line.

This is an undocumented but supported workaround for the issue, as it's
used internally by the scripts easy_install generates.
msg659 (view) Author: mbogosian Date: 2012-06-25.07:53:53
Perhaps I have misunderstood the intended behavior, but I thought one should be able to do this:

- - - - - - - - %< - - - - - - - -

% easy_install BeautifulSoup==3.0.8
...
% easy_install -U BeautifulSoup
[installs 3.1.0.1]
...
% python -c 'import pkg_resources ; print pkg_resources.require("BeautifulSoup==3.0.8")'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".../site-packages/distribute-0.6.10-py2.5.egg/pkg_resources.py", line 648, in require
    needed = self.resolve(parse_requirements(requirements))
  File ".../site-packages/distribute-0.6.10-py2.5.egg/pkg_resources.py", line 550, in resolve
    raise VersionConflict(dist,req) # XXX put more info here
pkg_resources.VersionConflict: (BeautifulSoup 3.1.0.1 (.../site-packages/BeautifulSoup-3.1.0.1-py2.5.egg), Requirement.parse('BeautifulSoup==3.0.8'))

- - - - - - - - >% - - - - - - - -

If I use the '-m' tag (to keep it out of easy_install.pth), I have a different problem:

- - - - - - - - %< - - - - - - - -

% easy_install -m BeautifulSoup==3.0.8
...
% easy_install -U -m BeautifulSoup
[installs 3.1.0.1]
...
% python -c 'import pkg_resources ; print pkg_resources.require("BeautifulSoup==3.0.8")'
[BeautifulSoup 3.0.8 (.../site-packages/BeautifulSoup-3.0.8-py2.5.egg)]
% python -c 'import BeautifulSoup'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: No module named BeautifulSoup

- - - - - - - - >% - - - - - - - -

Can I not have my cake and eat it too? Meaning, can I not have multiple installed versions of a package with a default (i.e., an entry in easy-install.pth), but still be able to explicitly specify a previously installed version?
History
Date User Action Args
2012-06-27 17:16:18pjesetmessages: + msg662
2012-06-25 17:39:03mbogosiansetstatus: resolved -> chatting
messages: + msg661
2012-06-25 16:35:23pjesetstatus: chatting -> resolved
2012-06-25 16:35:10pjesetfiles: - unnamed
2012-06-25 16:34:24pjesetfiles: + unnamed
status: unread -> chatting
messages: + msg660
nosy: + pje
2012-06-25 07:53:53mbogosiancreate