def test_package_ordering(): sympy_071 = Package('sympy-0.7.1-py27_0.tar.bz2', r.index['sympy-0.7.1-py27_0.tar.bz2']) sympy_072 = Package('sympy-0.7.2-py27_0.tar.bz2', r.index['sympy-0.7.2-py27_0.tar.bz2']) python_275 = Package('python-2.7.5-0.tar.bz2', r.index['python-2.7.5-0.tar.bz2']) numpy = Package('numpy-1.7.1-py27_0.tar.bz2', r.index['numpy-1.7.1-py27_0.tar.bz2']) numpy_mkl = Package('numpy-1.7.1-py27_p0.tar.bz2', r.index['numpy-1.7.1-py27_p0.tar.bz2']) assert sympy_071 < sympy_072 assert not sympy_071 < sympy_071 assert not sympy_072 < sympy_071 raises(TypeError, lambda: sympy_071 < python_275) assert sympy_071 <= sympy_072 assert sympy_071 <= sympy_071 assert not sympy_072 <= sympy_071 assert raises(TypeError, lambda: sympy_071 <= python_275) assert sympy_071 == sympy_071 assert not sympy_071 == sympy_072 assert (sympy_071 == python_275) is False assert (sympy_071 == 1) is False assert not sympy_071 != sympy_071 assert sympy_071 != sympy_072 assert (sympy_071 != python_275) is True assert not sympy_071 > sympy_072 assert not sympy_071 > sympy_071 assert sympy_072 > sympy_071 raises(TypeError, lambda: sympy_071 > python_275) assert not sympy_071 >= sympy_072 assert sympy_071 >= sympy_071 assert sympy_072 >= sympy_071 assert raises(TypeError, lambda: sympy_071 >= python_275) # The first four are a bit arbitrary. For now, we just test that it # doesn't prefer the mkl version. assert not numpy > numpy_mkl assert not numpy >= numpy_mkl assert numpy < numpy_mkl assert numpy <= numpy_mkl assert (numpy != numpy_mkl) is True assert (numpy == numpy_mkl) is False
def test_llvm(self): ms = MatchSpec('llvm') pkgs = [Package(fn, r.index[fn]) for fn in r.find_matches(ms)] pkgs.sort() self.assertEqual( [p.fn for p in pkgs], ['llvm-3.1-0.tar.bz2', 'llvm-3.1-1.tar.bz2', 'llvm-3.2-0.tar.bz2'])
def app_get_index(all_version=False): """ return the index of available applications on the channels By default only the latest version of each app is included in the result, unless all_version is set to True. """ import sys pyxx = 'py%d%d' % sys.version_info[:2] def filter_build(build): return bool(pyxx in build) if 'py' in build else True index = {fn: info for fn, info in iteritems(get_index()) if info.get('type') == 'app' and filter_build(info['build'])} if all_version: return index d = defaultdict(list) # name -> list of Package objects for fn, info in iteritems(index): d[_name_fn(fn)].append(Package(fn, info)) res = {} for pkgs in itervalues(d): pkg = max(pkgs) res[pkg.fn] = index[pkg.fn] return res
def app_get_index(all_version=False): """ return the index of available applications on the channels By default only the latest version of each app is included in the result, unless all_version is set to True. """ index = {fn: info for fn, info in iteritems(get_index()) if info.get('type') == 'app'} if all_version: return index d = defaultdict(list) # name -> list of Package objects for fn, info in iteritems(index): d[_name_fn(fn)].append(Package(fn, info)) res = {} for pkgs in itervalues(d): pkg = max(pkgs) res[pkg.fn] = index[pkg.fn] return res
def display_actions(actions, index): if actions.get(FETCH): print("\nThe following packages will be downloaded:\n") disp_lst = [] for dist in actions[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[FETCH]) > 1: print(' ' * 4 + '-' * 60) print(" " * 43 + "Total: %14s" % human_bytes( sum(index[dist + '.tar.bz2']['size'] for dist in actions[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(LINK, []): dist, pkgs_dir, lt = 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(UNLINK, []): dist, pkgs_dir, lt = 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[pkg + '-' + packages[pkg][0]].channel) for pkg in packages if packages[pkg][0] ] or [''], key=len)) maxnewchannel = len( max([ config.canonical_channel_name( Packages[pkg + '-' + packages[pkg][1]].channel) for pkg in packages if packages[pkg][1] ] or [''], key=len)) new = {pkg for pkg in packages if not packages[pkg][0]} removed = {pkg for pkg in packages if not packages[pkg][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 test_different_names(self): pkgs = [Package(fn, r.index[fn]) for fn in [ 'llvm-3.1-1.tar.bz2', 'python-2.7.5-0.tar.bz2']] self.assertRaises(TypeError, pkgs.sort)
def execute_search(args, parser): import re from conda.resolve import Resolve if args.reverse_dependency: if not args.regex: parser.error("--reverse-dependency requires at least one package name") if args.spec: parser.error("--reverse-dependency does not work with --spec") pat = None ms = None if args.regex: if args.spec: ms = ' '.join(args.regex.split('=')) else: regex = args.regex if args.full_name: regex = r'^%s$' % regex try: pat = re.compile(regex, re.I) except re.error as e: common.error_and_exit( "'%s' is not a valid regex pattern (exception: %s)" % (regex, e), json=args.json, error_type="ValueError") prefix = common.get_prefix(args) import conda.config import conda.install linked = conda.install.linked(prefix) extracted = set() for pkgs_dir in conda.config.pkgs_dirs: extracted.update(conda.install.extracted(pkgs_dir)) # XXX: Make this work with more than one platform platform = args.platform or '' if platform and platform != config.subdir: args.unknown = False common.ensure_override_channels_requires_channel(args, dashc=False, json=args.json) channel_urls = args.channel or () 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, prefix=prefix, json=args.json, platform=args.platform, offline=args.offline) else: index = common.get_index_trap(channel_urls=channel_urls, prepend=not args.override_channels, platform=args.platform, use_cache=args.use_index_cache, prefix=prefix, unknown=args.unknown, json=args.json, offline=args.offline) r = Resolve(index) if args.canonical: json = [] else: json = {} names = [] for name in sorted(r.groups): if '@' in name: continue if args.reverse_dependency: ms_name = ms for pkg in r.groups[name]: for dep in r.ms_depends(pkg): if pat.search(dep.name): names.append((name, Package(pkg, r.index[pkg]))) else: if pat and pat.search(name) is None: continue if ms and name != ms.name: continue if ms: ms_name = ms else: ms_name = name pkgs = sorted(r.get_pkgs(ms_name)) names.append((name, pkgs)) if args.reverse_dependency: new_names = [] old = None for name, pkg in sorted(names, key=lambda x:(x[0], x[1].name, x[1])): if name == old: new_names[-1][1].append(pkg) else: new_names.append((name, [pkg])) old = name names = new_names for name, pkgs in names: if args.reverse_dependency: disp_name = pkgs[0].name else: disp_name = name if args.names_only and not args.outdated: print(name) continue if not args.canonical: json[name] = [] if args.outdated: vers_inst = [dist.rsplit('-', 2)[1] for dist in linked if dist.rsplit('-', 2)[0] == name] if not vers_inst: continue assert len(vers_inst) == 1, name if not pkgs: continue latest = pkgs[-1] if latest.version == vers_inst[0]: continue if args.names_only: print(name) continue for pkg in pkgs: dist = pkg.fn[:-8] if args.canonical: if not args.json: print(dist) else: json.append(dist) continue if platform and platform != config.subdir: inst = ' ' elif dist in linked: inst = '*' elif dist in extracted: inst = '.' else: inst = ' ' if not args.json: print('%-25s %s %-15s %15s %-15s %s' % ( disp_name, inst, pkg.version, pkg.build, config.canonical_channel_name(pkg.channel), common.disp_features(r.features(pkg.fn)), )) disp_name = '' else: data = {} data.update(pkg.info) data.update({ 'fn': pkg.fn, 'installed': inst == '*', 'extracted': inst in '*.', 'version': pkg.version, 'build': pkg.build, 'build_number': pkg.build_number, 'channel': config.canonical_channel_name(pkg.channel), 'full_channel': pkg.channel, 'features': list(r.features(pkg.fn)), 'license': pkg.info.get('license'), 'size': pkg.info.get('size'), 'depends': pkg.info.get('depends'), 'type': pkg.info.get('type') }) if data['type'] == 'app': data['icon'] = make_icon_url(pkg.info) json[name].append(data) if args.json: common.stdout_json(json)
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()