def test_split_linkarg(self): for arg, res in [ ('w3-1.2-0', ('w3-1.2-0', pkgs_dirs[0], LINK_HARD)), ('w3-1.2-0 /opt/pkgs 1', ('w3-1.2-0', '/opt/pkgs', 1)), (' w3-1.2-0 /opt/pkgs 1 ', ('w3-1.2-0', '/opt/pkgs', 1)), (r'w3-1.2-0 C:\A B\pkgs 2', ('w3-1.2-0', r'C:\A B\pkgs', 2))]: self.assertEqual(inst.split_linkarg(arg), res)
def test_split_linkarg(self): for args, res in [ (['w3-1.2-0'], ('w3-1.2-0', pkgs_dirs[0], LINK_HARD)), (['w3-1.2-0', '/opt/pkgs', 1], ('w3-1.2-0', '/opt/pkgs', 1)), (['w3-1.2-0', '/opt/pkgs', 1], ('w3-1.2-0', '/opt/pkgs', 1)), ([r'w3-1.2-0', 'C:\A B\pkgs', 2], ('w3-1.2-0', r'C:\A B\pkgs', 2))]: self.assertEqual(inst.split_linkarg(args), res)
def test_split_linkarg(self): for arg, res in [ ("w3-1.2-0", ("w3-1.2-0", 1)), ("w3-1.2-0 1", ("w3-1.2-0", 1)), ("w3-1.2-0 1 True", ("w3-1.2-0", 1)), ]: self.assertEqual(inst.split_linkarg(arg), res)
def test_split_linkarg(self): for arg, res in [ ("w3-1.2-0", ("w3-1.2-0", pkgs_dirs[0], LINK_HARD)), ("w3-1.2-0 /opt/pkgs 1", ("w3-1.2-0", "/opt/pkgs", 1)), (" w3-1.2-0 /opt/pkgs 1 ", ("w3-1.2-0", "/opt/pkgs", 1)), (r"w3-1.2-0 C:\A B\pkgs 2", ("w3-1.2-0", r"C:\A B\pkgs", 2)), ]: self.assertEqual(inst.split_linkarg(arg), res)
def install(args, parser, command='install'): """ conda install, conda update, and conda create """ newenv = bool(command == 'create') if newenv: common.ensure_name_or_prefix(args, command) prefix = common.get_prefix(args, search=not newenv) if newenv: check_prefix(prefix, json=args.json) if config.force_32bit and plan.is_root_prefix(prefix): common.error_and_exit("cannot use CONDA_FORCE_32BIT=1 in root env") if command == 'update': if args.all: if args.packages: common.error_and_exit("""--all cannot be used with packages""", json=args.json, error_type="ValueError") elif not args.file: if len(args.packages) == 0: common.error_and_exit("""no package names supplied # If you want to update to a newer version of Anaconda, type: # # $ conda update --prefix %s anaconda """ % prefix, json=args.json, error_type="ValueError") if command == 'update': linked = ci.linked(prefix) for name in args.packages: common.arg2spec(name, json=args.json) if '=' in name: common.error_and_exit("Invalid package name: '%s'" % (name), json=args.json, error_type="ValueError") if name not in set(ci.name_dist(d) for d in linked): common.error_and_exit("package '%s' is not installed in %s" % (name, prefix), json=args.json, error_type="ValueError") if newenv and not args.no_default_packages: default_packages = config.create_default_packages[:] # Override defaults if they are specified at the command line for default_pkg in config.create_default_packages: if any(pkg.split('=')[0] == default_pkg for pkg in args.packages): default_packages.remove(default_pkg) args.packages.extend(default_packages) else: default_packages = [] common.ensure_override_channels_requires_channel(args) channel_urls = args.channel or () specs = [] if args.file: for fpath in args.file: specs.extend(common.specs_from_url(fpath, json=args.json)) elif getattr(args, 'all', False): linked = ci.linked(prefix) if not linked: common.error_and_exit("There are no packages installed in the " "prefix %s" % prefix) for pkg in linked: name, ver, build = pkg.rsplit('-', 2) if name in getattr(args, '_skip', ['anaconda']): continue if name == 'python' and ver.startswith('2'): # Oh Python 2... specs.append('%s >=%s,<3' % (name, ver)) else: specs.append('%s' % name) specs.extend(common.specs_from_args(args.packages, json=args.json)) if command == 'install' and args.revision: get_revision(args.revision, json=args.json) elif not (newenv and args.clone): common.check_specs(prefix, specs, json=args.json, create=(command == 'create')) num_cp = sum(s.endswith('.tar.bz2') for s in args.packages) if num_cp: if num_cp == len(args.packages): depends = misc.install_local_packages(prefix, args.packages, verbose=not args.quiet) if args.no_deps: depends = [] specs = list(set(depends)) args.unknown = True else: common.error_and_exit( "cannot mix specifications with conda package filenames", json=args.json, error_type="ValueError") # handle tar file containing conda packages if len(args.packages) == 1: tar_path = args.packages[0] if tar_path.endswith('.tar'): depends = install_tar(prefix, tar_path, verbose=not args.quiet) if args.no_deps: depends = [] specs = list(set(depends)) args.unknown = True if args.use_local: from conda.fetch import fetch_index from conda.utils import url_path try: from conda_build.config import croot except ImportError: common.error_and_exit( "you need to have 'conda-build >= 1.7.1' installed" " to use the --use-local option", json=args.json, error_type="RuntimeError") # remove the cache such that a refetch is made, # this is necessary because we add the local build repo URL fetch_index.cache = {} if exists(croot): channel_urls = [url_path(croot)] + list(channel_urls) index = common.get_index_trap(channel_urls=channel_urls, prepend=not args.override_channels, use_cache=args.use_index_cache, unknown=args.unknown, json=args.json, offline=args.offline) if newenv and args.clone: if set(args.packages) - set(default_packages): common.error_and_exit('did not expect any arguments for --clone', json=args.json, error_type="ValueError") clone(args.clone, prefix, json=args.json, quiet=args.quiet, index=index) misc.append_env(prefix) misc.touch_nonadmin(prefix) if not args.json: print_activate(args.name if args.name else prefix) return # Don't update packages that are already up-to-date if command == 'update' and not (args.all or args.force): r = Resolve(index) orig_packages = args.packages[:] for name in orig_packages: installed_metadata = [ci.is_linked(prefix, dist) for dist in linked] vers_inst = [dist.rsplit('-', 2)[1] for dist in linked if dist.rsplit('-', 2)[0] == name] build_inst = [m['build_number'] for m in installed_metadata if m['name'] == name] try: assert len(vers_inst) == 1, name assert len(build_inst) == 1, name except AssertionError as e: if args.json: common.exception_and_exit(e, json=True) else: raise pkgs = sorted(r.get_pkgs(MatchSpec(name))) if not pkgs: # Shouldn't happen? continue latest = pkgs[-1] if (latest.version == vers_inst[0] and latest.build_number == build_inst[0]): args.packages.remove(name) if not args.packages: from conda.cli.main_list import print_packages if not args.json: regex = '^(%s)$' % '|'.join(orig_packages) print('# All requested packages already installed.') print_packages(prefix, regex) else: common.stdout_json_success( message='All requested packages already installed.') return if args.force: args.no_deps = True spec_names = set(s.split()[0] for s in specs) if args.no_deps: only_names = spec_names else: only_names = None if not isdir(prefix) and not newenv: if args.mkdir: try: os.makedirs(prefix) except OSError: common.error_and_exit("Error: could not create directory: %s" % prefix, json=args.json, error_type="OSError") else: common.error_and_exit("""\ environment does not exist: %s # # Use 'conda create' to create an environment before installing packages # into it. #""" % prefix, json=args.json, error_type="NoEnvironmentFound") try: if command == 'install' and args.revision: actions = plan.revert_actions(prefix, get_revision(args.revision)) else: with common.json_progress_bars(json=args.json and not args.quiet): actions = plan.install_actions(prefix, index, specs, force=args.force, only_names=only_names, pinned=args.pinned, minimal_hint=args.alt_hint) if args.copy: new_link = [] for pkg in actions["LINK"]: dist, pkgs_dir, lt = inst.split_linkarg(pkg) lt = ci.LINK_COPY new_link.append("%s %s %d" % (dist, pkgs_dir, lt)) actions["LINK"] = new_link except NoPackagesFound as e: error_message = e.args[0] if command == 'update' and args.all: # Packages not found here just means they were installed but # cannot be found any more. Just skip them. if not args.json: print("Warning: %s, skipping" % error_message) else: # Not sure what to do here pass args._skip = getattr(args, '_skip', ['anaconda']) for pkg in e.pkgs: p = pkg.split()[0] if p in args._skip: # Avoid infinite recursion. This can happen if a spec # comes from elsewhere, like --file raise args._skip.append(p) return install(args, parser, command=command) else: packages = {index[fn]['name'] for fn in index} for pkg in e.pkgs: close = get_close_matches(pkg, packages, cutoff=0.7) if close: error_message += ("\n\nDid you mean one of these?" "\n\n %s" % (', '.join(close))) error_message += '\n\nYou can search for this package on anaconda.org with' error_message += '\n\n anaconda search -t conda %s' % pkg if len(e.pkgs) > 1: # Note this currently only happens with dependencies not found error_message += '\n\n (and similarly for the other packages)' if not find_executable('anaconda', include_others=False): error_message += '\n\nYou may need to install the anaconda-client command line client with' error_message += '\n\n conda install anaconda-client' pinned_specs = plan.get_pinned_specs(prefix) if pinned_specs: error_message += "\n\nNote that you have pinned specs in %s:" % join(prefix, 'conda-meta', 'pinned') error_message += "\n\n %r" % pinned_specs common.error_and_exit(error_message, json=args.json) except SystemExit as e: # Unsatisfiable package specifications/no such revision/import error error_type = 'UnsatisfiableSpecifications' if e.args and 'could not import' in e.args[0]: error_type = 'ImportError' common.exception_and_exit(e, json=args.json, newline=True, error_text=False, error_type=error_type) if plan.nothing_to_do(actions): from conda.cli.main_list import print_packages if not args.json: regex = '^(%s)$' % '|'.join(spec_names) print('\n# All requested packages already installed.') print_packages(prefix, regex) else: common.stdout_json_success( message='All requested packages already installed.') return if not args.json: print() print("Package plan for installation in environment %s:" % prefix) plan.display_actions(actions, index) if command in {'install', 'update'}: common.check_write(command, prefix) if not args.json: common.confirm_yn(args) elif args.dry_run: common.stdout_json_success(actions=actions, dry_run=True) sys.exit(0) with common.json_progress_bars(json=args.json and not args.quiet): try: plan.execute_actions(actions, index, verbose=not args.quiet) if not (command == 'update' and args.all): try: with open(join(prefix, 'conda-meta', 'history'), 'a') as f: f.write('# %s specs: %s\n' % (command, specs)) except IOError as e: if e.errno == errno.EACCES: log.debug("Can't write the history file") else: raise except RuntimeError as e: if len(e.args) > 0 and "LOCKERROR" in e.args[0]: error_type = "AlreadyLocked" else: error_type = "RuntimeError" common.exception_and_exit(e, error_type=error_type, json=args.json) except SystemExit as e: common.exception_and_exit(e, json=args.json) if newenv: misc.append_env(prefix) misc.touch_nonadmin(prefix) if not args.json: print_activate(args.name if args.name else prefix) if args.json: common.stdout_json_success(actions=actions)
def test_split_linkarg(self): for arg, res in [ ('w3-1.2-0', ('w3-1.2-0', LINK_HARD)), ('w3-1.2-0 1', ('w3-1.2-0', 1)), ('w3-1.2-0 1 True', ('w3-1.2-0', 1))]: self.assertEqual(inst.split_linkarg(arg), res)
def install(args, parser, command='install'): """ conda install, conda update, and conda create """ newenv = bool(command == 'create') if newenv: common.ensure_name_or_prefix(args, command) prefix = common.get_prefix(args, search=not newenv) if newenv: check_prefix(prefix, json=args.json) if config.force_32bit and plan.is_root_prefix(prefix): common.error_and_exit("cannot use CONDA_FORCE_32BIT=1 in root env") if command == 'update': if not args.file: if not args.all and len(args.packages) == 0: common.error_and_exit("""no package names supplied # If you want to update to a newer version of Anaconda, type: # # $ conda update --prefix %s anaconda """ % prefix, json=args.json, error_type="ValueError") if command == 'update' and not args.all: linked = ci.linked(prefix) for name in args.packages: common.arg2spec(name, json=args.json) if '=' in name: common.error_and_exit("Invalid package name: '%s'" % (name), json=args.json, error_type="ValueError") if name not in set(ci.name_dist(d) for d in linked): common.error_and_exit("package '%s' is not installed in %s" % (name, prefix), json=args.json, error_type="ValueError") if newenv and not args.no_default_packages: default_packages = config.create_default_packages[:] # Override defaults if they are specified at the command line for default_pkg in config.create_default_packages: if any(pkg.split('=')[0] == default_pkg for pkg in args.packages): default_packages.remove(default_pkg) args.packages.extend(default_packages) else: default_packages = [] common.ensure_override_channels_requires_channel(args) channel_urls = args.channel or () specs = [] if args.file: for fpath in args.file: specs.extend(common.specs_from_url(fpath, json=args.json)) elif getattr(args, 'all', False): linked = ci.linked(prefix) if not linked: common.error_and_exit("There are no packages installed in the " "prefix %s" % prefix) for pkg in linked: name, ver, build = pkg.rsplit('-', 2) if name in getattr(args, '_skip', ['anaconda']): continue if name == 'python' and ver.startswith('2'): # Oh Python 2... specs.append('%s >=%s,<3' % (name, ver)) else: specs.append('%s' % name) specs.extend(common.specs_from_args(args.packages, json=args.json)) if command == 'install' and args.revision: get_revision(args.revision, json=args.json) elif not (newenv and args.clone): common.check_specs(prefix, specs, json=args.json, create=(command == 'create')) num_cp = sum(s.endswith('.tar.bz2') for s in args.packages) if num_cp: if num_cp == len(args.packages): depends = misc.install_local_packages(prefix, args.packages, verbose=not args.quiet) if args.no_deps: depends = [] specs = list(set(depends)) args.unknown = True else: common.error_and_exit( "cannot mix specifications with conda package filenames", json=args.json, error_type="ValueError") # handle tar file containing conda packages if len(args.packages) == 1: tar_path = args.packages[0] if tar_path.endswith('.tar'): depends = install_tar(prefix, tar_path, verbose=not args.quiet) if args.no_deps: depends = [] specs = list(set(depends)) args.unknown = True if args.use_local: from conda.fetch import fetch_index from conda.utils import url_path try: from conda_build.config import croot except ImportError: common.error_and_exit( "you need to have 'conda-build >= 1.7.1' installed" " to use the --use-local option", json=args.json, error_type="RuntimeError") # remove the cache such that a refetch is made, # this is necessary because we add the local build repo URL fetch_index.cache = {} if exists(croot): channel_urls = [url_path(croot)] + list(channel_urls) index = common.get_index_trap(channel_urls=channel_urls, prepend=not args.override_channels, use_cache=args.use_index_cache, unknown=args.unknown, json=args.json, offline=args.offline) if newenv and args.clone: if set(args.packages) - set(default_packages): common.error_and_exit('did not expect any arguments for --clone', json=args.json, error_type="ValueError") clone(args.clone, prefix, json=args.json, quiet=args.quiet, index=index) misc.append_env(prefix) misc.touch_nonadmin(prefix) if not args.json: print_activate(args.name if args.name else prefix) return # Don't update packages that are already up-to-date if command == 'update' and not (args.all or args.force): r = Resolve(index) orig_packages = args.packages[:] for name in orig_packages: installed_metadata = [ci.is_linked(prefix, dist) for dist in linked] vers_inst = [dist.rsplit('-', 2)[1] for dist in linked if dist.rsplit('-', 2)[0] == name] build_inst = [m['build_number'] for m in installed_metadata if m['name'] == name] try: assert len(vers_inst) == 1, name assert len(build_inst) == 1, name except AssertionError as e: if args.json: common.exception_and_exit(e, json=True) else: raise pkgs = sorted(r.get_pkgs(MatchSpec(name))) if not pkgs: # Shouldn't happen? continue latest = pkgs[-1] if (latest.version == vers_inst[0] and latest.build_number == build_inst[0]): args.packages.remove(name) if not args.packages: from conda.cli.main_list import print_packages if not args.json: regex = '^(%s)$' % '|'.join(orig_packages) print('# All requested packages already installed.') print_packages(prefix, regex) else: common.stdout_json_success( message='All requested packages already installed.') return if args.force: args.no_deps = True spec_names = set(s.split()[0] for s in specs) if args.no_deps: only_names = spec_names else: only_names = None if not isdir(prefix) and not newenv: if args.mkdir: try: os.makedirs(prefix) except OSError: common.error_and_exit("Error: could not create directory: %s" % prefix, json=args.json, error_type="OSError") else: common.error_and_exit("""\ environment does not exist: %s # # Use 'conda create' to create an environment before installing packages # into it. #""" % prefix, json=args.json, error_type="NoEnvironmentFound") try: if command == 'install' and args.revision: actions = plan.revert_actions(prefix, get_revision(args.revision)) else: with common.json_progress_bars(json=args.json and not args.quiet): actions = plan.install_actions(prefix, index, specs, force=args.force, only_names=only_names, pinned=args.pinned, minimal_hint=args.alt_hint, update_deps=args.update_deps) if config.always_copy or args.copy: new_link = [] for pkg in actions["LINK"]: dist, pkgs_dir, lt = inst.split_linkarg(pkg) lt = ci.LINK_COPY new_link.append("%s %s %d" % (dist, pkgs_dir, lt)) actions["LINK"] = new_link except NoPackagesFound as e: error_message = e.args[0] if command == 'update' and args.all: # Packages not found here just means they were installed but # cannot be found any more. Just skip them. if not args.json: print("Warning: %s, skipping" % error_message) else: # Not sure what to do here pass args._skip = getattr(args, '_skip', ['anaconda']) for pkg in e.pkgs: p = pkg.split()[0] if p in args._skip: # Avoid infinite recursion. This can happen if a spec # comes from elsewhere, like --file raise args._skip.append(p) return install(args, parser, command=command) else: packages = {index[fn]['name'] for fn in index} for pkg in e.pkgs: close = get_close_matches(pkg, packages, cutoff=0.7) if close: error_message += ("\n\nDid you mean one of these?" "\n\n %s" % (', '.join(close))) error_message += '\n\nYou can search for this package on anaconda.org with' error_message += '\n\n anaconda search -t conda %s' % pkg if len(e.pkgs) > 1: # Note this currently only happens with dependencies not found error_message += '\n\n (and similarly for the other packages)' if not find_executable('anaconda', include_others=False): error_message += '\n\nYou may need to install the anaconda-client command line client with' error_message += '\n\n conda install anaconda-client' pinned_specs = plan.get_pinned_specs(prefix) if pinned_specs: error_message += "\n\nNote that you have pinned specs in %s:" % join(prefix, 'conda-meta', 'pinned') error_message += "\n\n %r" % pinned_specs common.error_and_exit(error_message, json=args.json) except SystemExit as e: # Unsatisfiable package specifications/no such revision/import error error_type = 'UnsatisfiableSpecifications' if e.args and 'could not import' in e.args[0]: error_type = 'ImportError' common.exception_and_exit(e, json=args.json, newline=True, error_text=False, error_type=error_type) if plan.nothing_to_do(actions): from conda.cli.main_list import print_packages if not args.json: regex = '^(%s)$' % '|'.join(spec_names) print('\n# All requested packages already installed.') print_packages(prefix, regex) else: common.stdout_json_success( message='All requested packages already installed.') return if not args.json: print() print("Package plan for installation in environment %s:" % prefix) plan.display_actions(actions, index, show_channel_urls=args.show_channel_urls) if command in {'install', 'update'}: common.check_write(command, prefix) if not args.json: common.confirm_yn(args) elif args.dry_run: common.stdout_json_success(actions=actions, dry_run=True) sys.exit(0) with common.json_progress_bars(json=args.json and not args.quiet): try: plan.execute_actions(actions, index, verbose=not args.quiet) if not (command == 'update' and args.all): try: with open(join(prefix, 'conda-meta', 'history'), 'a') as f: f.write('# %s specs: %s\n' % (command, specs)) except IOError as e: if e.errno == errno.EACCES: log.debug("Can't write the history file") else: raise except RuntimeError as e: if len(e.args) > 0 and "LOCKERROR" in e.args[0]: error_type = "AlreadyLocked" else: error_type = "RuntimeError" common.exception_and_exit(e, error_type=error_type, json=args.json) except SystemExit as e: common.exception_and_exit(e, json=args.json) if newenv: misc.append_env(prefix) misc.touch_nonadmin(prefix) if not args.json: print_activate(args.name if args.name else prefix) if args.json: common.stdout_json_success(actions=actions)
def display_actions(actions, index, show_channel_urls=None): if show_channel_urls is None: show_channel_urls = config.show_channel_urls if actions.get(inst.FETCH): print("\nThe following packages will be downloaded:\n") disp_lst = [] for dist in actions[inst.FETCH]: info = index[dist + '.tar.bz2'] extra = '%15s' % human_bytes(info['size']) if show_channel_urls: extra += ' %s' % config.canonical_channel_name( info.get('channel')) disp_lst.append((dist, extra)) print_dists(disp_lst) if index and len(actions[inst.FETCH]) > 1: print(' ' * 4 + '-' * 60) print(" " * 43 + "Total: %14s" % human_bytes(sum(index[dist + '.tar.bz2']['size'] for dist in actions[inst.FETCH]))) # package -> [oldver-oldbuild, newver-newbuild] packages = defaultdict(lambda: list(('', ''))) features = defaultdict(lambda: list(('', ''))) # This assumes each package will appear in LINK no more than once. Packages = {} linktypes = {} for arg in actions.get(inst.LINK, []): dist, pkgs_dir, lt = inst.split_linkarg(arg) pkg, ver, build = dist.rsplit('-', 2) packages[pkg][1] = ver + '-' + build Packages[dist] = Package(dist + '.tar.bz2', index[dist + '.tar.bz2']) linktypes[pkg] = lt features[pkg][1] = index[dist + '.tar.bz2'].get('features', '') for arg in actions.get(inst.UNLINK, []): dist, pkgs_dir, lt = inst.split_linkarg(arg) pkg, ver, build = dist.rsplit('-', 2) packages[pkg][0] = ver + '-' + build # If the package is not in the index (e.g., an installed # package that is not in the index any more), we just have to fake the metadata. info = index.get(dist + '.tar.bz2', dict(name=pkg, version=ver, build_number=int(build) if build.isdigit() else 0, build=build, channel=None)) Packages[dist] = Package(dist + '.tar.bz2', info) features[pkg][0] = info.get('features', '') # Put a minimum length here---. .--For the : # v v maxpkg = max(len(max(packages or [''], key=len)), 0) + 1 maxoldver = len(max(packages.values() or [['']], key=lambda i: len(i[0]))[0]) maxnewver = len(max(packages.values() or [['', '']], key=lambda i: len(i[1]))[1]) maxoldfeatures = len(max(features.values() or [['']], key=lambda i: len(i[0]))[0]) maxnewfeatures = len(max(features.values() or [['', '']], key=lambda i: len(i[1]))[1]) maxoldchannel = len(max([config.canonical_channel_name(Packages[p + '-' + packages[p][0]].channel) for p in packages if packages[p][0]] or [''], key=len)) maxnewchannel = len(max([config.canonical_channel_name(Packages[p + '-' + packages[p][1]].channel) for p in packages if packages[p][1]] or [''], key=len)) new = {p for p in packages if not packages[p][0]} removed = {p for p in packages if not packages[p][1]} updated = set() downgraded = set() oldfmt = {} newfmt = {} for pkg in packages: # That's right. I'm using old-style string formatting to generate a # string with new-style string formatting. oldfmt[pkg] = '{pkg:<%s} {vers[0]:<%s}' % (maxpkg, maxoldver) if show_channel_urls: oldfmt[pkg] += ' {channel[0]:<%s}' % maxoldchannel if packages[pkg][0]: newfmt[pkg] = '{vers[1]:<%s}' % maxnewver else: newfmt[pkg] = '{pkg:<%s} {vers[1]:<%s}' % (maxpkg, maxnewver) if show_channel_urls: newfmt[pkg] += ' {channel[1]:<%s}' % maxnewchannel # TODO: Should we also care about the old package's link type? if pkg in linktypes and linktypes[pkg] != install.LINK_HARD: newfmt[pkg] += ' (%s)' % install.link_name_map[linktypes[pkg]] if features[pkg][0]: oldfmt[pkg] += ' [{features[0]:<%s}]' % maxoldfeatures if features[pkg][1]: newfmt[pkg] += ' [{features[1]:<%s}]' % maxnewfeatures if pkg in new or pkg in removed: continue P0 = Packages[pkg + '-' + packages[pkg][0]] P1 = Packages[pkg + '-' + packages[pkg][1]] try: # <= here means that unchanged packages will be put in updated newer = (P0.name, P0.norm_version, P0.build_number) <= (P1.name, P1.norm_version, P1.build_number) except TypeError: newer = (P0.name, P0.version, P0.build_number) <= (P1.name, P1.version, P1.build_number) if newer: updated.add(pkg) else: downgraded.add(pkg) arrow = ' --> ' lead = ' ' * 4 def format(s, pkg): channel = ['', ''] for i in range(2): if packages[pkg][i]: channel[i] = config.canonical_channel_name(Packages[pkg + '-' + packages[pkg][i]].channel) return lead + s.format(pkg=pkg + ':', vers=packages[pkg], channel=channel, features=features[pkg]) if new: print("\nThe following NEW packages will be INSTALLED:\n") for pkg in sorted(new): print(format(newfmt[pkg], pkg)) if removed: print("\nThe following packages will be REMOVED:\n") for pkg in sorted(removed): print(format(oldfmt[pkg], pkg)) if updated: print("\nThe following packages will be UPDATED:\n") for pkg in sorted(updated): print(format(oldfmt[pkg] + arrow + newfmt[pkg], pkg)) if downgraded: print("\nThe following packages will be DOWNGRADED:\n") for pkg in sorted(downgraded): print(format(oldfmt[pkg] + arrow + newfmt[pkg], pkg)) print()
def test_split_linkarg(self): for arg, res in [('w3-1.2-0', ('w3-1.2-0', LINK_HARD)), ('w3-1.2-0 1', ('w3-1.2-0', 1))]: self.assertEqual(inst.split_linkarg(arg), res)
def display_actions(actions, index, show_channel_urls=None): if show_channel_urls is None: show_channel_urls = config_show_channel_urls def channel_str(s): if s is None: return '' if show_channel_urls is None: return '' if s == 'defaults' else s return s if show_channel_urls else '' def channel_len(s): return len(channel_str(s)) if actions.get(inst.FETCH): print("\nThe following packages will be downloaded:\n") disp_lst = [] for dist in actions[inst.FETCH]: info = index[dist + '.tar.bz2'] extra = '%15s' % human_bytes(info['size']) schannel = channel_str(info.get('schannel', '<unknown>')) if schannel: extra += ' ' + schannel disp_lst.append((dist, extra)) print_dists(disp_lst) if index and len(actions[inst.FETCH]) > 1: num_bytes = sum(index[dist + '.tar.bz2']['size'] for dist in actions[inst.FETCH]) print(' ' * 4 + '-' * 60) print(" " * 43 + "Total: %14s" % human_bytes(num_bytes)) # package -> [oldver-oldbuild, newver-newbuild] packages = defaultdict(lambda: list(('', ''))) features = defaultdict(lambda: list(('', ''))) # This assumes each package will appear in LINK no more than once. Packages = {} linktypes = {} for arg in actions.get(inst.LINK, []): dist, lt = inst.split_linkarg(arg) rec = index[dist + '.tar.bz2'] pkg = rec['name'] packages[pkg][1] = rec['version'] + '-' + rec['build'] dist = pkg + '-' + packages[pkg][1] Packages[dist] = Package(dist + '.tar.bz2', rec) linktypes[pkg] = lt features[pkg][1] = rec.get('features', '') for arg in actions.get(inst.UNLINK, []): dist, lt = inst.split_linkarg(arg) rec = index.get(dist + '.tar.bz2') if rec is None: pkg, ver, build, schannel = dist2quad(dist) rec = dict(name=pkg, version=ver, build=build, channel=None, schannel='<unknown>', build_number=int(build) if build.isdigit() else 0) pkg = rec['name'] packages[pkg][0] = rec['version'] + '-' + rec['build'] dist = pkg + '-' + packages[pkg][0] Packages[dist] = Package(dist + '.tar.bz2', rec) features[pkg][0] = rec.get('features', '') # Put a minimum length here---. .--For the : # v v maxpkg = max(len(max(packages or [''], key=len)), 0) + 1 maxoldver = len(max(packages.values() or [['']], key=lambda i: len(i[0]))[0]) maxnewver = len(max(packages.values() or [['', '']], key=lambda i: len(i[1]))[1]) maxoldfeatures = len(max(features.values() or [['']], key=lambda i: len(i[0]))[0]) maxnewfeatures = len(max(features.values() or [['', '']], key=lambda i: len(i[1]))[1]) maxoldchannel = max([channel_len(Packages[p + '-' + packages[p][0]].schannel) for p in packages if packages[p][0]] or [0]) maxnewchannel = max([channel_len(Packages[p + '-' + packages[p][1]].schannel) for p in packages if packages[p][1]] or [0]) new = {p for p in packages if not packages[p][0]} removed = {p for p in packages if not packages[p][1]} updated = set() downgraded = set() oldfmt = {} newfmt = {} for pkg in packages: # That's right. I'm using old-style string formatting to generate a # string with new-style string formatting. oldfmt[pkg] = '{pkg:<%s} {vers[0]:<%s}' % (maxpkg, maxoldver) if maxoldchannel: oldfmt[pkg] += ' {channel[0]:<%s}' % maxoldchannel if packages[pkg][0]: newfmt[pkg] = '{vers[1]:<%s}' % maxnewver else: newfmt[pkg] = '{pkg:<%s} {vers[1]:<%s}' % (maxpkg, maxnewver) if maxnewchannel: newfmt[pkg] += ' {channel[1]:<%s}' % maxnewchannel # TODO: Should we also care about the old package's link type? if pkg in linktypes and linktypes[pkg] != install.LINK_HARD: newfmt[pkg] += ' (%s)' % install.link_name_map[linktypes[pkg]] if features[pkg][0]: oldfmt[pkg] += ' [{features[0]:<%s}]' % maxoldfeatures if features[pkg][1]: newfmt[pkg] += ' [{features[1]:<%s}]' % maxnewfeatures if pkg in new or pkg in removed: continue P0 = Packages[pkg + '-' + packages[pkg][0]] P1 = Packages[pkg + '-' + packages[pkg][1]] try: # <= here means that unchanged packages will be put in updated newer = ((P0.name, P0.norm_version, P0.build_number) <= (P1.name, P1.norm_version, P1.build_number)) except TypeError: newer = ((P0.name, P0.version, P0.build_number) <= (P1.name, P1.version, P1.build_number)) if newer or str(P1.version) == 'custom': updated.add(pkg) else: downgraded.add(pkg) arrow = ' --> ' lead = ' ' * 4 def format(s, pkg): channel = ['', ''] for i in range(2): if packages[pkg][i]: channel[i] = channel_str(Packages[pkg + '-' + packages[pkg][i]].schannel) return lead + s.format(pkg=pkg + ':', vers=packages[pkg], channel=channel, features=features[pkg]) if new: print("\nThe following NEW packages will be INSTALLED:\n") for pkg in sorted(new): print(format(newfmt[pkg], pkg)) if removed: print("\nThe following packages will be REMOVED:\n") for pkg in sorted(removed): print(format(oldfmt[pkg], pkg)) if updated: print("\nThe following packages will be UPDATED:\n") for pkg in sorted(updated): print(format(oldfmt[pkg] + arrow + newfmt[pkg], pkg)) if downgraded: print("\nThe following packages will be DOWNGRADED:\n") for pkg in sorted(downgraded): print(format(oldfmt[pkg] + arrow + newfmt[pkg], pkg)) print()
def display_actions(actions, index): if actions.get(inst.FETCH): print("\nThe following packages will be downloaded:\n") disp_lst = [] for dist in actions[inst.FETCH]: info = index[dist + '.tar.bz2'] extra = '%15s' % human_bytes(info['size']) if config.show_channel_urls: extra += ' %s' % config.canonical_channel_name( info.get('channel')) disp_lst.append((dist, extra)) print_dists(disp_lst) if index and len(actions[inst.FETCH]) > 1: print(' ' * 4 + '-' * 60) print(" " * 43 + "Total: %14s" % human_bytes(sum(index[dist + '.tar.bz2']['size'] for dist in actions[inst.FETCH]))) # package -> [oldver-oldbuild, newver-newbuild] packages = defaultdict(lambda: list(('', ''))) features = defaultdict(lambda: list(('', ''))) # This assumes each package will appear in LINK no more than once. Packages = {} linktypes = {} for arg in actions.get(inst.LINK, []): dist, pkgs_dir, lt = inst.split_linkarg(arg) pkg, ver, build = dist.rsplit('-', 2) packages[pkg][1] = ver + '-' + build Packages[dist] = Package(dist + '.tar.bz2', index[dist + '.tar.bz2']) linktypes[pkg] = lt features[pkg][1] = index[dist + '.tar.bz2'].get('features', '') for arg in actions.get(inst.UNLINK, []): dist, pkgs_dir, lt = inst.split_linkarg(arg) pkg, ver, build = dist.rsplit('-', 2) packages[pkg][0] = ver + '-' + build # If the package is not in the index (e.g., an installed # package that is not in the index any more), we just have to fake the metadata. info = index.get(dist + '.tar.bz2', dict(name=pkg, version=ver, build_number=int(build) if build.isdigit() else 0, build=build, channel=None)) Packages[dist] = Package(dist + '.tar.bz2', info) features[pkg][0] = info.get('features', '') # Put a minimum length here---. .--For the : # v v maxpkg = max(len(max(packages or [''], key=len)), 0) + 1 maxoldver = len(max(packages.values() or [['']], key=lambda i: len(i[0]))[0]) maxnewver = len(max(packages.values() or [['', '']], key=lambda i: len(i[1]))[1]) maxoldfeatures = len(max(features.values() or [['']], key=lambda i: len(i[0]))[0]) maxnewfeatures = len(max(features.values() or [['', '']], key=lambda i: len(i[1]))[1]) maxoldchannel = len(max([config.canonical_channel_name(Packages[p + '-' + packages[p][0]].channel) for p in packages if packages[p][0]] or [''], key=len)) maxnewchannel = len(max([config.canonical_channel_name(Packages[p + '-' + packages[p][1]].channel) for p in packages if packages[p][1]] or [''], key=len)) new = {p for p in packages if not packages[p][0]} removed = {p for p in packages if not packages[p][1]} updated = set() downgraded = set() oldfmt = {} newfmt = {} for pkg in packages: # That's right. I'm using old-style string formatting to generate a # string with new-style string formatting. oldfmt[pkg] = '{pkg:<%s} {vers[0]:<%s}' % (maxpkg, maxoldver) if config.show_channel_urls: oldfmt[pkg] += ' {channel[0]:<%s}' % maxoldchannel if packages[pkg][0]: newfmt[pkg] = '{vers[1]:<%s}' % maxnewver else: newfmt[pkg] = '{pkg:<%s} {vers[1]:<%s}' % (maxpkg, maxnewver) if config.show_channel_urls: newfmt[pkg] += ' {channel[1]:<%s}' % maxnewchannel # TODO: Should we also care about the old package's link type? if pkg in linktypes and linktypes[pkg] != install.LINK_HARD: newfmt[pkg] += ' (%s)' % install.link_name_map[linktypes[pkg]] if features[pkg][0]: oldfmt[pkg] += ' [{features[0]:<%s}]' % maxoldfeatures if features[pkg][1]: newfmt[pkg] += ' [{features[1]:<%s}]' % maxnewfeatures if pkg in new or pkg in removed: continue P0 = Packages[pkg + '-' + packages[pkg][0]] P1 = Packages[pkg + '-' + packages[pkg][1]] try: # <= here means that unchanged packages will be put in updated newer = (P0.name, P0.norm_version, P0.build_number) <= (P1.name, P1.norm_version, P1.build_number) except TypeError: newer = (P0.name, P0.version, P0.build_number) <= (P1.name, P1.version, P1.build_number) if newer: updated.add(pkg) else: downgraded.add(pkg) arrow = ' --> ' lead = ' ' * 4 def format(s, pkg): channel = ['', ''] for i in range(2): if packages[pkg][i]: channel[i] = config.canonical_channel_name(Packages[pkg + '-' + packages[pkg][i]].channel) return lead + s.format(pkg=pkg + ':', vers=packages[pkg], channel=channel, features=features[pkg]) if new: print("\nThe following NEW packages will be INSTALLED:\n") for pkg in sorted(new): print(format(newfmt[pkg], pkg)) if removed: print("\nThe following packages will be REMOVED:\n") for pkg in sorted(removed): print(format(oldfmt[pkg], pkg)) if updated: print("\nThe following packages will be UPDATED:\n") for pkg in sorted(updated): print(format(oldfmt[pkg] + arrow + newfmt[pkg], pkg)) if downgraded: print("\nThe following packages will be DOWNGRADED:\n") for pkg in sorted(downgraded): print(format(oldfmt[pkg] + arrow + newfmt[pkg], pkg)) print()
def display_actions(actions, index, show_channel_urls=None): if show_channel_urls is None: show_channel_urls = config_show_channel_urls def channel_str(s): if s is None: return '' if show_channel_urls is None: return '' if s == 'defaults' else s return s if show_channel_urls else '' def channel_len(s): return len(channel_str(s)) if actions.get(inst.FETCH): print("\nThe following packages will be downloaded:\n") disp_lst = [] for dist in actions[inst.FETCH]: info = index[dist + '.tar.bz2'] extra = '%15s' % human_bytes(info['size']) schannel = channel_str(info.get('schannel', '<unknown>')) if schannel: extra += ' ' + schannel disp_lst.append((dist, extra)) print_dists(disp_lst) if index and len(actions[inst.FETCH]) > 1: num_bytes = sum(index[dist + '.tar.bz2']['size'] for dist in actions[inst.FETCH]) print(' ' * 4 + '-' * 60) print(" " * 43 + "Total: %14s" % human_bytes(num_bytes)) # package -> [oldver-oldbuild, newver-newbuild] packages = defaultdict(lambda: list(('', ''))) features = defaultdict(lambda: list(('', ''))) # This assumes each package will appear in LINK no more than once. Packages = {} linktypes = {} for arg in actions.get(inst.LINK, []): dist, lt = inst.split_linkarg(arg) rec = index[dist + '.tar.bz2'] pkg = rec['name'] packages[pkg][1] = rec['version'] + '-' + rec['build'] dist = pkg + '-' + packages[pkg][1] Packages[dist] = Package(dist + '.tar.bz2', rec) linktypes[pkg] = lt features[pkg][1] = rec.get('features', '') for arg in actions.get(inst.UNLINK, []): dist, lt = inst.split_linkarg(arg) rec = index.get(dist + '.tar.bz2') if rec is None: pkg, ver, build = dist.split('::', 2)[-1].rsplit('-', 2) rec = dict(name=pkg, version=ver, build=build, channel=None, schannel='<unknown>', build_number=int(build) if build.isdigit() else 0) pkg = rec['name'] packages[pkg][0] = rec['version'] + '-' + rec['build'] dist = pkg + '-' + packages[pkg][0] Packages[dist] = Package(dist + '.tar.bz2', rec) features[pkg][0] = rec.get('features', '') # Put a minimum length here---. .--For the : # v v maxpkg = max(len(max(packages or [''], key=len)), 0) + 1 maxoldver = len( max(packages.values() or [['']], key=lambda i: len(i[0]))[0]) maxnewver = len( max(packages.values() or [['', '']], key=lambda i: len(i[1]))[1]) maxoldfeatures = len( max(features.values() or [['']], key=lambda i: len(i[0]))[0]) maxnewfeatures = len( max(features.values() or [['', '']], key=lambda i: len(i[1]))[1]) maxoldchannel = max([ channel_len(Packages[p + '-' + packages[p][0]].schannel) for p in packages if packages[p][0] ] or [0]) maxnewchannel = max([ channel_len(Packages[p + '-' + packages[p][1]].schannel) for p in packages if packages[p][1] ] or [0]) new = {p for p in packages if not packages[p][0]} removed = {p for p in packages if not packages[p][1]} updated = set() downgraded = set() oldfmt = {} newfmt = {} for pkg in packages: # That's right. I'm using old-style string formatting to generate a # string with new-style string formatting. oldfmt[pkg] = '{pkg:<%s} {vers[0]:<%s}' % (maxpkg, maxoldver) if maxoldchannel: oldfmt[pkg] += ' {channel[0]:<%s}' % maxoldchannel if packages[pkg][0]: newfmt[pkg] = '{vers[1]:<%s}' % maxnewver else: newfmt[pkg] = '{pkg:<%s} {vers[1]:<%s}' % (maxpkg, maxnewver) if maxnewchannel: newfmt[pkg] += ' {channel[1]:<%s}' % maxnewchannel # TODO: Should we also care about the old package's link type? if pkg in linktypes and linktypes[pkg] != install.LINK_HARD: newfmt[pkg] += ' (%s)' % install.link_name_map[linktypes[pkg]] if features[pkg][0]: oldfmt[pkg] += ' [{features[0]:<%s}]' % maxoldfeatures if features[pkg][1]: newfmt[pkg] += ' [{features[1]:<%s}]' % maxnewfeatures if pkg in new or pkg in removed: continue P0 = Packages[pkg + '-' + packages[pkg][0]] P1 = Packages[pkg + '-' + packages[pkg][1]] try: # <= here means that unchanged packages will be put in updated newer = ((P0.name, P0.norm_version, P0.build_number) <= (P1.name, P1.norm_version, P1.build_number)) except TypeError: newer = ((P0.name, P0.version, P0.build_number) <= (P1.name, P1.version, P1.build_number)) if newer or str(P1.version) == 'custom': updated.add(pkg) else: downgraded.add(pkg) arrow = ' --> ' lead = ' ' * 4 def format(s, pkg): channel = ['', ''] for i in range(2): if packages[pkg][i]: channel[i] = channel_str(Packages[pkg + '-' + packages[pkg][i]].schannel) return lead + s.format(pkg=pkg + ':', vers=packages[pkg], channel=channel, features=features[pkg]) if new: print("\nThe following NEW packages will be INSTALLED:\n") for pkg in sorted(new): print(format(newfmt[pkg], pkg)) if removed: print("\nThe following packages will be REMOVED:\n") for pkg in sorted(removed): print(format(oldfmt[pkg], pkg)) if updated: print("\nThe following packages will be UPDATED:\n") for pkg in sorted(updated): print(format(oldfmt[pkg] + arrow + newfmt[pkg], pkg)) if downgraded: print("\nThe following packages will be DOWNGRADED:\n") for pkg in sorted(downgraded): print(format(oldfmt[pkg] + arrow + newfmt[pkg], pkg)) print()