Skip to content

Commit 292734e

Browse files
committed
Adds --upgrade-recursive option, makes -U non-recursive by default.
refs pypa#304
1 parent 854574f commit 292734e

File tree

2 files changed

+55
-30
lines changed

2 files changed

+55
-30
lines changed

pip/commands/install.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,12 @@ def __init__(self):
114114
'-U', '--upgrade',
115115
dest='upgrade',
116116
action='store_true',
117-
help='Upgrade all packages to the newest available version')
117+
help='Upgrade packages to the latest version, but not dependencies')
118+
self.parser.add_option(
119+
'-R', '--upgrade-recursive',
120+
dest='upgrade_recursive',
121+
action='store_true',
122+
help='Upgrade packages to the latest version, including dependencies')
118123
self.parser.add_option(
119124
'--force-reinstall',
120125
dest='force_reinstall',
@@ -216,23 +221,27 @@ def run(self, options, args):
216221

217222
finder = self._build_package_finder(options, index_urls)
218223

224+
upgrade = options.upgrade or options.upgrade_recursive
225+
219226
requirement_set = RequirementSet(
220227
build_dir=options.build_dir,
221228
src_dir=options.src_dir,
222229
download_dir=options.download_dir,
223230
download_cache=options.download_cache,
224-
upgrade=options.upgrade,
231+
upgrade=upgrade,
232+
upgrade_recursive=options.upgrade_recursive,
225233
as_egg=options.as_egg,
226234
ignore_installed=options.ignore_installed,
227235
ignore_dependencies=options.ignore_dependencies,
228236
force_reinstall=options.force_reinstall,
229237
use_user_site=options.use_user_site)
238+
230239
for name in args:
231240
requirement_set.add_requirement(
232-
InstallRequirement.from_line(name, None))
241+
InstallRequirement.from_line(name, None, upgrade=upgrade))
233242
for name in options.editables:
234243
requirement_set.add_requirement(
235-
InstallRequirement.from_editable(name, default_vcs=options.default_vcs))
244+
InstallRequirement.from_editable(name, default_vcs=options.default_vcs, upgrade=upgrade))
236245
for filename in options.requirements:
237246
for req in parse_requirements(filename, finder=finder, options=options):
238247
requirement_set.add_requirement(req)

pip/req.py

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
class InstallRequirement(object):
3939

4040
def __init__(self, req, comes_from, source_dir=None, editable=False,
41-
url=None, as_egg=False, update=True):
41+
url=None, as_egg=False, update=True, upgrade=False):
4242
self.extras = ()
4343
if isinstance(req, string_types):
4444
req = pkg_resources.Requirement.parse(req)
@@ -60,29 +60,32 @@ def __init__(self, req, comes_from, source_dir=None, editable=False,
6060
self._is_bundle = None
6161
# True if the editable should be updated:
6262
self.update = update
63+
# True if the requirement should be upgraded to the latest version
64+
self.upgrade = upgrade
6365
# Set to True after successful installation
6466
self.install_succeeded = None
6567
# UninstallPathSet of uninstalled distribution (for possible rollback)
6668
self.uninstalled = None
6769
self.use_user_site = False
6870

6971
@classmethod
70-
def from_editable(cls, editable_req, comes_from=None, default_vcs=None):
72+
def from_editable(cls, editable_req, comes_from=None, default_vcs=None, upgrade=False):
7173
name, url, extras_override = parse_editable(editable_req, default_vcs)
7274
if url.startswith('file:'):
7375
source_dir = url_to_path(url)
7476
else:
7577
source_dir = None
7678

77-
res = cls(name, comes_from, source_dir=source_dir, editable=True, url=url)
79+
res = cls(name, comes_from, source_dir=source_dir, editable=True,
80+
url=url, upgrade=upgrade)
7881

7982
if extras_override is not None:
8083
res.extras = extras_override
8184

8285
return res
8386

8487
@classmethod
85-
def from_line(cls, name, comes_from=None):
88+
def from_line(cls, name, comes_from=None, upgrade=False):
8689
"""Creates an InstallRequirement from a name, which might be a
8790
requirement, directory containing 'setup.py', filename, or URL.
8891
"""
@@ -116,7 +119,7 @@ def from_line(cls, name, comes_from=None):
116119
else:
117120
req = name
118121

119-
return cls(req, comes_from, url=url)
122+
return cls(req, comes_from, url=url, upgrade=upgrade)
120123

121124
def __str__(self):
122125
if self.req:
@@ -710,7 +713,7 @@ def is_bundle(self):
710713
or os.path.exists(os.path.join(base, 'pyinstall-manifest.txt')))
711714
return self._is_bundle
712715

713-
def bundle_requirements(self):
716+
def bundle_requirements(self, upgrade=False):
714717
for dest_dir in self._bundle_editable_dirs:
715718
package = os.path.basename(dest_dir)
716719
## FIXME: svnism:
@@ -730,13 +733,11 @@ def bundle_requirements(self):
730733
else:
731734
url = None
732735
yield InstallRequirement(
733-
package, self, editable=True, url=url,
734-
update=False, source_dir=dest_dir)
736+
package, self, editable=True, url=url, update=False,
737+
source_dir=dest_dir, upgrade=upgrade)
735738
for dest_dir in self._bundle_build_dirs:
736739
package = os.path.basename(dest_dir)
737-
yield InstallRequirement(
738-
package, self,
739-
source_dir=dest_dir)
740+
yield InstallRequirement(package, self, source_dir=dest_dir, upgrade=upgrade)
740741

741742
def move_bundle_files(self, dest_build_dir, dest_src_dir):
742743
base = self._temp_build_dir
@@ -812,13 +813,15 @@ def __repr__(self):
812813
class RequirementSet(object):
813814

814815
def __init__(self, build_dir, src_dir, download_dir, download_cache=None,
815-
upgrade=False, ignore_installed=False, as_egg=False,
816-
ignore_dependencies=False, force_reinstall=False, use_user_site=False):
816+
ignore_installed=False, as_egg=False, force_reinstall=False,
817+
ignore_dependencies=False, use_user_site=False, upgrade=False,
818+
upgrade_recursive=False):
817819
self.build_dir = build_dir
818820
self.src_dir = src_dir
819821
self.download_dir = download_dir
820822
self.download_cache = download_cache
821823
self.upgrade = upgrade
824+
self.upgrade_recursive = upgrade_recursive
822825
self.ignore_installed = ignore_installed
823826
self.force_reinstall = force_reinstall
824827
self.requirements = Requirements()
@@ -921,9 +924,13 @@ def locate_files(self):
921924
else:
922925
install_needed = False
923926
if req_to_install.satisfied_by:
927+
if self.upgrade and not self.upgrade_recursive:
928+
upgrade_cmd = '--upgrade-recursive'
929+
else:
930+
upgrade_cmd = '--upgrade'
924931
logger.notify('Requirement already satisfied '
925-
'(use --upgrade to upgrade): %s'
926-
% req_to_install)
932+
'(use %s to upgrade): %s'
933+
% (upgrade_cmd, req_to_install))
927934

928935
if req_to_install.editable:
929936
if req_to_install.source_dir is None:
@@ -953,11 +960,11 @@ def prepare_files(self, finder, force_root_egg_info=False, bundle=False):
953960
if not self.ignore_installed and not req_to_install.editable:
954961
req_to_install.check_if_exists()
955962
if req_to_install.satisfied_by:
956-
if self.upgrade:
963+
if req_to_install.upgrade:
957964
if not self.force_reinstall and not req_to_install.url:
958965
try:
959966
url = finder.find_requirement(
960-
req_to_install, self.upgrade)
967+
req_to_install, upgrade=True)
961968
except BestVersionAlreadyInstalled:
962969
best_installed = True
963970
install = False
@@ -979,9 +986,13 @@ def prepare_files(self, finder, force_root_egg_info=False, bundle=False):
979986
logger.notify('Requirement already up-to-date: %s'
980987
% req_to_install)
981988
else:
989+
if self.upgrade and not self.upgrade_recursive:
990+
upgrade_cmd = '--upgrade-recursive'
991+
else:
992+
upgrade_cmd = '--upgrade'
982993
logger.notify('Requirement already satisfied '
983-
'(use --upgrade to upgrade): %s'
984-
% req_to_install)
994+
'(use %s to upgrade): %s'
995+
% (upgrade_cmd, req_to_install))
985996
if req_to_install.editable:
986997
logger.notify('Obtaining %s' % req_to_install)
987998
elif install:
@@ -1023,7 +1034,7 @@ def prepare_files(self, finder, force_root_egg_info=False, bundle=False):
10231034
if req_to_install.url is None:
10241035
if not_found:
10251036
raise not_found
1026-
url = finder.find_requirement(req_to_install, upgrade=self.upgrade)
1037+
url = finder.find_requirement(req_to_install, upgrade=req_to_install.upgrade)
10271038
else:
10281039
## FIXME: should req_to_install.url already be a link?
10291040
url = Link(req_to_install.url)
@@ -1044,7 +1055,7 @@ def prepare_files(self, finder, force_root_egg_info=False, bundle=False):
10441055
is_bundle = req_to_install.is_bundle
10451056
if is_bundle:
10461057
req_to_install.move_bundle_files(self.build_dir, self.src_dir)
1047-
for subreq in req_to_install.bundle_requirements():
1058+
for subreq in req_to_install.bundle_requirements(upgrade=self.upgrade_recursive):
10481059
reqs.append(subreq)
10491060
self.add_requirement(subreq)
10501061
elif self.is_download:
@@ -1068,7 +1079,7 @@ def prepare_files(self, finder, force_root_egg_info=False, bundle=False):
10681079
# repeat check_if_exists to uninstall-on-upgrade (#14)
10691080
req_to_install.check_if_exists()
10701081
if req_to_install.satisfied_by:
1071-
if self.upgrade or self.ignore_installed:
1082+
if req_to_install.upgrade or self.ignore_installed:
10721083
#don't uninstall conflict if user install and and conflict is not user install
10731084
if not (self.use_user_site and not dist_in_usersite(req_to_install.satisfied_by)):
10741085
req_to_install.conflicts_with = req_to_install.satisfied_by
@@ -1092,7 +1103,7 @@ def prepare_files(self, finder, force_root_egg_info=False, bundle=False):
10921103
if self.has_requirement(name):
10931104
## FIXME: check for conflict
10941105
continue
1095-
subreq = InstallRequirement(req, req_to_install)
1106+
subreq = InstallRequirement(req, req_to_install, upgrade=self.upgrade_recursive)
10961107
reqs.append(subreq)
10971108
self.add_requirement(subreq)
10981109
if not self.has_requirement(req_to_install.name):
@@ -1344,16 +1355,21 @@ def parse_requirements(filename, finder=None, comes_from=None, options=None):
13441355
elif line.startswith('--no-index'):
13451356
finder.index_urls = []
13461357
else:
1358+
# Use getattr since uninstall doesn't set these options
1359+
upgrade = (getattr(options, 'upgrade', False)
1360+
or getattr(options, 'upgrade_recursive', False))
13471361
comes_from = '-r %s (line %s)' % (filename, line_number)
13481362
if line.startswith('-e') or line.startswith('--editable'):
13491363
if line.startswith('-e'):
13501364
line = line[2:].strip()
13511365
else:
13521366
line = line[len('--editable'):].strip().lstrip('=')
1353-
req = InstallRequirement.from_editable(
1354-
line, comes_from=comes_from, default_vcs=options.default_vcs)
1367+
req = InstallRequirement.from_editable(line,
1368+
comes_from=comes_from,
1369+
default_vcs=options.default_vcs,
1370+
upgrade=upgrade)
13551371
else:
1356-
req = InstallRequirement.from_line(line, comes_from)
1372+
req = InstallRequirement.from_line(line, comes_from, upgrade=upgrade)
13571373
yield req
13581374

13591375

0 commit comments

Comments
 (0)