def list_packages(prefix, installed, regex=None, format='human', show_channel_urls=show_channel_urls): res = 1 result = [] for dist in get_packages(installed, regex): res = 0 if format == 'canonical': result.append(dist) continue if format == 'export': result.append('='.join(dist2quad(dist)[:3])) continue try: # Returns None if no meta-file found (e.g. pip install) info = install.is_linked(prefix, dist) features = set(info.get('features', '').split()) disp = '%(name)-25s %(version)-15s %(build)15s' % info disp += ' %s' % common.disp_features(features) schannel = info.get('schannel') if show_channel_urls or show_channel_urls is None and schannel != 'defaults': disp += ' %s' % schannel result.append(disp) except (AttributeError, IOError, KeyError, ValueError) as e: log.debug(str(e)) result.append('%-25s %-15s %s' % dist2quad(dist)[:3]) return res, result
def match(self, info): if type(info) is dict: name = info.get('name') version = info.get('version') build = info.get('build') else: name, version, build, schannel = dist2quad(info[:-8]) if name != self.name: return False return self.match_fast(version, build)
def print_dists(dists_extras): fmt = " %-27s|%17s" print(fmt % ('package', 'build')) print(fmt % ('-' * 27, '-' * 17)) for dist, extra in dists_extras: dist = dist2quad(dist) line = fmt % (dist[0]+'-'+dist[1], dist[2]) if extra: line += extra print(line)
def test_dist2quad(): assert dist2quad('python-2.7.11-0') == ('python', '2.7.11', '0', 'defaults') assert dist2quad('python-2.7.11-0.tar.bz2') == ('python', '2.7.11', '0', 'defaults') assert dist2quad('test::python-2.7.11-0') == ('python', '2.7.11', '0', 'test') assert dist2quad('test::python-2.7.11-0.tar.bz2') == ('python', '2.7.11', '0', 'test') assert dist2quad('python-test-2.7.11-0') == ('python-test', '2.7.11', '0', 'defaults') assert _dist2pair('python-2.7.11-0') == ('defaults', 'python-2.7.11-0') assert _dist2pair('python-2.7.11-0.tar.bz2') == ('defaults', 'python-2.7.11-0') assert _dist2pair('test::python-2.7.11-0') == ('test', 'python-2.7.11-0') assert _dist2pair('test::python-2.7.11-0.tar.bz2') == ('test', 'python-2.7.11-0') assert _dist2pair('python-test-2.7.11-0') == ('defaults', 'python-test-2.7.11-0') assert _dist2filename('python-2.7.11-0') == 'python-2.7.11-0.tar.bz2' assert _dist2filename('python-2.7.11-0.tar.bz2') == 'python-2.7.11-0.tar.bz2' assert _dist2filename('test::python-2.7.11-0') == 'python-2.7.11-0.tar.bz2' assert _dist2filename('test::python-2.7.11-0.tar.bz2') == 'python-2.7.11-0.tar.bz2' assert _dist2filename('python-test-2.7.11-0') == 'python-test-2.7.11-0.tar.bz2' assert name_dist('python-2.7.11-0') == 'python' assert name_dist('python-2.7.11-0.tar.bz2') == 'python' assert name_dist('test::python-2.7.11-0') == 'python' assert name_dist('test::python-2.7.11-0.tar.bz2') == 'python' assert name_dist('python-test-2.7.11-0') == 'python-test'
def _get_items(self): # TODO: Include .tar.bz2 files for local installs. from conda.api import get_index args = self.parsed_args call_dict = dict(channel_urls=args.channel or (), use_cache=True, prepend=not args.override_channels, unknown=args.unknown, offline=args.offline) if hasattr(args, 'platform'): # in search call_dict['platform'] = args.platform index = get_index(**call_dict) return [dist2quad(i)[0] for i in index]
def object_log(self): result = [] for i, (date, content, unused_com) in enumerate(self.parse()): # Based on Mateusz's code; provides more details about the # history event event = { 'date': date, 'rev': i, 'install': [], 'remove': [], 'upgrade': [], 'downgrade': [] } added = {} removed = {} if is_diff(content): for pkg in content: name, version, build, channel = dist2quad(pkg[1:]) if pkg.startswith('+'): added[name.lower()] = (version, build, channel) elif pkg.startswith('-'): removed[name.lower()] = (version, build, channel) changed = set(added) & set(removed) for name in sorted(changed): old = removed[name] new = added[name] details = { 'old': '-'.join((name, ) + old), 'new': '-'.join((name, ) + new) } if new > old: event['upgrade'].append(details) else: event['downgrade'].append(details) for name in sorted(set(removed) - changed): event['remove'].append('-'.join((name, ) + removed[name])) for name in sorted(set(added) - changed): event['install'].append('-'.join((name, ) + added[name])) else: for pkg in sorted(content): event['install'].append(pkg) result.append(event) return result
def object_log(self): result = [] for i, (date, content, unused_com) in enumerate(self.parse()): # Based on Mateusz's code; provides more details about the # history event event = { 'date': date, 'rev': i, 'install': [], 'remove': [], 'upgrade': [], 'downgrade': [] } added = {} removed = {} if is_diff(content): for pkg in content: name, version, build, channel = dist2quad(pkg[1:]) if pkg.startswith('+'): added[name.lower()] = (version, build, channel) elif pkg.startswith('-'): removed[name.lower()] = (version, build, channel) changed = set(added) & set(removed) for name in sorted(changed): old = removed[name] new = added[name] details = { 'old': '-'.join((name,) + old), 'new': '-'.join((name,) + new) } if new > old: event['upgrade'].append(details) else: event['downgrade'].append(details) for name in sorted(set(removed) - changed): event['remove'].append('-'.join((name,) + removed[name])) for name in sorted(set(added) - changed): event['install'].append('-'.join((name,) + added[name])) else: for pkg in sorted(content): event['install'].append(pkg) result.append(event) return result
def pretty_diff(diff): added = {} removed = {} for s in diff: fn = s[1:] name, version, unused_build = dist2quad(fn, channel=False) if s.startswith('-'): removed[name.lower()] = version elif s.startswith('+'): added[name.lower()] = version changed = set(added) & set(removed) for name in sorted(changed): yield ' %s {%s -> %s}' % (name, removed[name], added[name]) for name in sorted(set(removed) - changed): yield '-%s-%s' % (name, removed[name]) for name in sorted(set(added) - changed): yield '+%s-%s' % (name, added[name])
def test_dist2(): for name in ('python', 'python-hyphen', ''): for version in ('2.7.0', '2.7.0rc1', ''): for build in ('0', 'py27_0', 'py35_0+g34fe21', ''): for channel in ('defaults', 'test', 'test-hyphen', 'http://bremen', 'https://anaconda.org/mcg', '<unknown>'): dist_noprefix = name + '-' + version + '-' + build quad = (name, version, build, channel) dist = dist_noprefix if channel == 'defaults' else channel + '::' + dist_noprefix for suffix in ('', '.tar.bz2', '[debug]', '.tar.bz2[debug]'): test = dist + suffix assert dist2quad(test) == quad assert dist2pair(test) == (channel, dist_noprefix) assert dist2name(test) == name assert name_dist(test) == name assert dist2dirname(test) == dist_noprefix assert dist2filename(test) == dist_noprefix + '.tar.bz2' assert dist2filename(test, '') == dist_noprefix
def pretty_diff(diff): added = {} removed = {} for s in diff: fn = s[1:] name, version, _, channel = dist2quad(fn) if channel != 'defaults': version += ' (%s)' % channel if s.startswith('-'): removed[name.lower()] = version elif s.startswith('+'): added[name.lower()] = version changed = set(added) & set(removed) for name in sorted(changed): yield ' %s {%s -> %s}' % (name, removed[name], added[name]) for name in sorted(set(removed) - changed): yield '-%s-%s' % (name, removed[name]) for name in sorted(set(added) - changed): yield '+%s-%s' % (name, added[name])
def find_substitute(self, installed, features, fn): """ Find a substitute package for `fn` (given `installed` packages) which does *NOT* have `features`. If found, the substitute will have the same package name and version and its dependencies will match the installed packages as closely as possible. If no substitute is found, None is returned. """ name, version, unused_build, schannel = dist2quad(fn) candidates = {} for pkg in self.get_pkgs(MatchSpec(name + ' ' + version)): fn1 = pkg.fn if self.features(fn1).intersection(features): continue key = sum(self.sum_matches(fn1, fn2) for fn2 in installed) candidates[key] = fn1 if candidates: maxkey = max(candidates) return candidates[maxkey] else: return None
def test_dist2(): for name in ("python", "python-hyphen", ""): for version in ("2.7.0", "2.7.0rc1", ""): for build in ("0", "py27_0", "py35_0+g34fe21", ""): for channel in ( "defaults", "test", "test-hyphen", "http://bremen", "https://anaconda.org/mcg", "<unknown>", ): dist_noprefix = name + "-" + version + "-" + build quad = (name, version, build, channel) dist = dist_noprefix if channel == "defaults" else channel + "::" + dist_noprefix for suffix in ("", ".tar.bz2", "[debug]", ".tar.bz2[debug]"): test = dist + suffix assert dist2quad(test) == quad assert dist2pair(test) == (channel, dist_noprefix) assert dist2name(test) == name assert name_dist(test) == name assert dist2dirname(test) == dist_noprefix assert dist2filename(test) == dist_noprefix + ".tar.bz2" assert dist2filename(test, "") == dist_noprefix
def _get_items(self): import conda.install packages = conda.install.linked(get_prefix(self.parsed_args)) return [dist2quad(i)[0] for i in packages]
def package_quad(self, fkey): rec = self.index.get(fkey, None) if rec is None: return dist2quad(fkey.rsplit('[', 1)[0].rsplit('/', 1)[-1]) return (rec['name'], rec['version'], rec['build'], rec.get('schannel', 'defaults'))
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()