def test_match(self): for spec, res in [ ('numpy 1.7*', True), ('numpy 1.7.1', True), ('numpy 1.7', False), ('numpy 1.5*', False), ('numpy >=1.5', True), ('numpy >=1.5,<2', True), ('numpy >=1.8,<1.9', False), ('numpy >1.5,<2,!=1.7.1', False), ('numpy >1.8,<2|==1.7', False), ('numpy >1.8,<2|>=1.7.1', True), ('numpy >=1.8|1.7*', True), ('numpy ==1.7', False), ('numpy >=1.5,>1.6', True), ('numpy ==1.7.1', True), ('numpy 1.6*|1.7*', True), ('numpy 1.6*|1.8*', False), ('numpy 1.6.2|1.7*', True), ('numpy 1.6.2|1.7.1', True), ('numpy 1.6.2|1.7.0', False), ('numpy 1.7.1 py27_0', True), ('numpy 1.7.1 py26_0', False), ('python', False), ]: m = MatchSpec(spec) self.assertEqual(m.match('numpy-1.7.1-py27_0.tar.bz2'), res)
def solve(specs: List[str], r: Resolve) -> Union[bool, Iterable[str]]: features = set() # type: Set for spec in specs: if conda.config.platform == 'win32' and spec == 'python': continue # XXX: This does not work when a spec only contains the name, # and different versions of the package have different features. ms = MatchSpec(spec) for pkg in r.get_pkgs(ms, max_only=False): fn = pkg.fn features.update(r.track_features(fn)) for spec in specs: for pkg in r.get_pkgs(MatchSpec(spec), max_only=False): fn = pkg.fn r.update_with_features(fn, features) print("Solving package specifications: ", end='') try: return r.explicit(specs) or r.solve2(specs, features, installed=(), minimal_hint=False, guess=False, unsat_only=True) except RuntimeError: print('\n') return False
def execute(args, parser): import re import conda.install as install from conda.api import get_index from conda.resolve import MatchSpec, Resolve if args.regex: pat = re.compile(args.regex, re.I) else: pat = None prefix = common.get_prefix(args) if not args.canonical: linked = install.linked(prefix) # XXX: Make this work with more than one platform platform = args.platform or '' common.ensure_override_channels_requires_channel(args, dashc=False) channel_urls = args.channel or () index = get_index(channel_urls=channel_urls, prepend=not args.override_channels, platform=args.platform) r = Resolve(index) for name in sorted(r.groups): disp_name = name if pat and pat.search(name) is None: continue 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 pkgs = sorted(r.get_pkgs(MatchSpec(name))) if not pkgs: continue latest = pkgs[-1] if latest.version == vers_inst[0]: continue for pkg in sorted(r.get_pkgs(MatchSpec(name))): dist = pkg.fn[:-8] if args.canonical: print(dist) continue inst = '*' if dist in linked else ' ' print('%-25s %s %-15s %15s %-15s %s' % ( disp_name, inst, pkg.version, r.index[pkg.fn]['build'], canonical_channel_name(pkg.channel), common.disp_features(r.features(pkg.fn)), )) disp_name = ''
def handle_config_version(ms, ver, dep_type='run'): """ 'ms' is an instance of MatchSpec, and 'ver' is the version from the configuration, e.g. for ms.name == 'python', ver = 26 or None, return a (sometimes new) MatchSpec object """ if ms.strictness == 3: return ms if ms.strictness == 2: if ms.spec.split()[1] == 'x.x': if ver is None: raise RuntimeError("'%s' requires external setting" % ms.spec) # (no return here - proceeds below) else: # regular version return ms # If we don't have a configured version, or we are dealing with a simple # numpy runtime dependency; just use "numpy"/the name of the package as # the specification. In practice this means that a recipe which just # defines numpy as a runtime dependency will match any version of numpy # at install time. if ver is None or (dep_type == 'run' and ms.strictness == 1 and ms.name == 'numpy'): return MatchSpec(ms.name) ver = text_type(ver) if '.' not in ver: if ms.name == 'numpy': ver = '%s.%s' % (ver[0], ver[1:]) else: ver = '.'.join(ver) return MatchSpec('%s %s*' % (ms.name, ver))
def add_defaults_to_specs(r, linked, specs, update=False): # TODO: This should use the pinning mechanism. But don't change the API: # cas uses it. if r.explicit(specs): return log.debug('H0 specs=%r' % specs) linked = [fn if fn.endswith('.tar.bz2') else fn + '.tar.bz2' for fn in linked] names_linked = {r.index[fn]['name']: fn for fn in linked} names_ms = {MatchSpec(s).name: MatchSpec(s) for s in specs} for name, def_ver in [('python', default_python), # Default version required, but only used for Python ('lua', None)]: ms = names_ms.get(name) if ms and not ms.is_simple(): # if any of the specifications mention the Python/Numpy version, # we don't need to add the default spec log.debug('H1 %s' % name) continue any_depends_on = any(ms2.name == name for spec in specs for fn in r.find_matches(spec) for ms2 in r.ms_depends(fn)) log.debug('H2 %s %s' % (name, any_depends_on)) if not any_depends_on and name not in names_ms: # if nothing depends on Python/Numpy AND the Python/Numpy is not # specified, we don't need to add the default spec log.debug('H2A %s' % name) continue if (any_depends_on and len(specs) >= 1 and MatchSpec(specs[0]).is_exact()): # if something depends on Python/Numpy, but the spec is very # explicit, we also don't need to add the default spec log.debug('H2B %s' % name) continue if name in names_linked: # if Python/Numpy is already linked, we add that instead of the # default log.debug('H3 %s' % name) fkey = names_linked[name] info = r.index[fkey] ver = '.'.join(info['version'].split('.', 2)[:2]) spec = '%s %s*' % (info['name'], ver) if update: spec += ' (target=%s)' % fkey specs.append(spec) continue if (name, def_ver) in [('python', '3.3'), ('python', '3.4'), ('python', '3.5')]: # Don't include Python 3 in the specs if this is the Python 3 # version of conda. continue specs.append('%s %s*' % (name, def_ver)) log.debug('HF specs=%r' % specs)
def test_match(self): for spec, res in [ ('numpy 1.7*', True), ('numpy 1.7.1', True), ('numpy 1.7', False), ('numpy 1.5*', False), ('numpy >=1.5', True), ('numpy >=1.5,<2', True), ('numpy >=1.8,<1.9', False), ('numpy >1.5,<2,!=1.7.1', False), ('numpy >1.8,<2|==1.7', False),('numpy >1.8,<2|>=1.7.1', True), ('numpy >=1.8|1.7*', True), ('numpy ==1.7', False), ('numpy >=1.5,>1.6', True), ('numpy ==1.7.1', True), ('numpy >=1,*.7.*', True), ('numpy *.7.*,>=1', True), ('numpy >=1,*.8.*', False), ('numpy >=2,*.7.*', False), ('numpy 1.6*|1.7*', True), ('numpy 1.6*|1.8*', False), ('numpy 1.6.2|1.7*', True), ('numpy 1.6.2|1.7.1', True), ('numpy 1.6.2|1.7.0', False), ('numpy 1.7.1 py27_0', True), ('numpy 1.7.1 py26_0', False), ('numpy >1.7.1a', True), ('python', False), ]: m = MatchSpec(spec) self.assertEqual(m.match('numpy-1.7.1-py27_0.tar.bz2'), res) # both version numbers conforming to PEP 440 self.assertFalse(MatchSpec('numpy >=1.0.1').match('numpy-1.0.1a-0.tar.bz2')) # both version numbers non-conforming to PEP 440 self.assertFalse(MatchSpec('numpy >=1.0.1.vc11').match('numpy-1.0.1a.vc11-0.tar.bz2')) self.assertTrue(MatchSpec('numpy >=1.0.1*.vc11').match('numpy-1.0.1a.vc11-0.tar.bz2')) # one conforming, other non-conforming to PEP 440 self.assertTrue(MatchSpec('numpy <1.0.1').match('numpy-1.0.1.vc11-0.tar.bz2')) self.assertTrue(MatchSpec('numpy <1.0.1').match('numpy-1.0.1a.vc11-0.tar.bz2')) self.assertFalse(MatchSpec('numpy >=1.0.1.vc11').match('numpy-1.0.1a-0.tar.bz2')) self.assertTrue(MatchSpec('numpy >=1.0.1a').match('numpy-1.0.1z-0.tar.bz2'))
def ms_depends(self, typ='run'): res = [] name_ver_list = [('python', CONDA_PY), ('numpy', CONDA_NPY), ('perl', CONDA_PERL)] for spec in self.get_value('requirements/' + typ, []): try: ms = MatchSpec(spec) except AssertionError: raise RuntimeError("Invalid package specification: %r" % spec) for name, ver in name_ver_list: if ms.name == name: if ms.strictness != 1: sys.exit("""Error: You cannot specify a version for package '%s' in the requirements. Please use the environment variables CONDA_PY, CONDA_NPY, or CONDA_PERL. """ % name) str_ver = str(ver) if '.' not in str_ver: str_ver = '.'.join(str_ver) ms = MatchSpec('%s %s*' % (name, str_ver)) for c in '=!@#$%^&*:;"\'\\|<>?/': if c in ms.name: sys.exit("Error: bad character '%s' in package name " "dependency '%s'" % (c, ms.name)) res.append(ms) return res
def setUp(self): self.res = generate_mocked_resolve([ ("ranenv", "test-spec", "rando_chnl", "1"), (None, "test-spec", "defaults", "5"), ("test1", "test-spec2", "defaults", "1") ]) self.specs = [MatchSpec("test-spec"), MatchSpec("test-spec2")]
def test_match(self): for spec, res in [ ('numpy 1.7*', True), ('numpy 1.7.1', True), ('numpy 1.7', False), ('numpy 1.5*', False), ('numpy >=1.5', True), ('numpy >=1.5,<2', True), ('numpy >=1.8,<1.9', False), ('numpy >1.5,<2,!=1.7.1', False), ('numpy >1.8,<2|==1.7', False),('numpy >1.8,<2|>=1.7.1', True), ('numpy >=1.8|1.7*', True), ('numpy ==1.7', False), ('numpy >=1.5,>1.6', True), ('numpy ==1.7.1', True), ('numpy >=1,*.7.*', True), ('numpy *.7.*,>=1', True), ('numpy >=1,*.8.*', False), ('numpy >=2,*.7.*', False), ('numpy 1.6*|1.7*', True), ('numpy 1.6*|1.8*', False), ('numpy 1.6.2|1.7*', True), ('numpy 1.6.2|1.7.1', True), ('numpy 1.6.2|1.7.0', False), ('numpy 1.7.1 py27_0', True), ('numpy 1.7.1 py26_0', False), ('numpy >1.7.1a', True), ('python', False), ]: m = MatchSpec(spec) self.assertEqual(m.match('numpy-1.7.1-py27_0.tar.bz2'), res) # both version numbers conforming to PEP 440 self.assertFalse(MatchSpec('numpy >=1.0.1').match('numpy-1.0.1a-0.tar.bz2')) # both version numbers non-conforming to PEP 440 self.assertFalse(MatchSpec('numpy >=1.0.1.vc11').match('numpy-1.0.1a.vc11-0.tar.bz2')) self.assertTrue(MatchSpec('numpy >=1.0.1*.vc11').match('numpy-1.0.1a.vc11-0.tar.bz2')) # one conforming, other non-conforming to PEP 440 self.assertTrue(MatchSpec('numpy <1.0.1').match('numpy-1.0.1.vc11-0.tar.bz2')) self.assertTrue(MatchSpec('numpy <1.0.1').match('numpy-1.0.1a.vc11-0.tar.bz2')) self.assertFalse(MatchSpec('numpy >=1.0.1.vc11').match('numpy-1.0.1a-0.tar.bz2')) self.assertTrue(MatchSpec('numpy >=1.0.1a').match('numpy-1.0.1z-0.tar.bz2'))
def test_to_filename(self): ms = MatchSpec('foo 1.7 52') self.assertEqual(ms.to_filename(), 'foo-1.7-52.tar.bz2') for spec in 'bitarray', 'pycosat 0.6.0', 'numpy 1.6*': ms = MatchSpec(spec) self.assertEqual(ms.to_filename(), None)
def test_to_filename(self): ms = MatchSpec("foo 1.7 52") self.assertEqual(ms.to_filename(), "foo-1.7-52.tar.bz2") for spec in "bitarray", "pycosat 0.6.0", "numpy 1.6*": ms = MatchSpec(spec) self.assertEqual(ms.to_filename(), None)
def remove_actions(prefix, specs, index=None, pinned=True): linked = install.linked(prefix) mss = [MatchSpec(spec) for spec in specs] if index: r = Resolve(index) else: r = None pinned_specs = get_pinned_specs(prefix) actions = defaultdict(list) actions[inst.PREFIX] = prefix for dist in sorted(linked): fn = dist + '.tar.bz2' if any(ms.match(fn) for ms in mss): if pinned and any(MatchSpec(spec).match('%s.tar.bz2' % dist) for spec in pinned_specs): raise RuntimeError("Cannot remove %s because it is pinned. Use --no-pin to override." % dist) actions[inst.UNLINK].append(dist) if r and fn in index and r.track_features(fn): features_actions = remove_features_actions(prefix, index, r.track_features(fn)) for action in features_actions: if isinstance(actions[action], list): for item in features_actions[action]: if item not in actions[action]: actions[action].append(item) else: assert actions[action] == features_actions[action] return actions
def parse_specifications(requirements): """ Parse a list of specifications, turning multi-line specifications into a single specification. """ requirement_specs = defaultdict(list) # Generate a list of requirements for each spec name to ensure that # multi-line specs are handled. for spec in requirements: spec_details = spec.split(None, 1) if len(spec_details) == 2: # Package name and version spec were given, append the # version spec. requirement_specs[MatchSpec(spec).name].append(spec_details[1]) elif spec_details[0] not in requirement_specs: # Only package name given (e.g. 'numpy'), and the package name is # not in the requirements yet, so add an empty list. requirement_specs[MatchSpec(spec).name] = [] # Combine multi-line specs into a single line by assuming the requirements # should be and-ed. for spec_name, spec_list in requirement_specs.items(): requirement_specs[spec_name] = ','.join(spec_list) # Turn these into MatchSpecs. requirement_specs = { name: MatchSpec(' '.join([name, spec]).strip()) for name, spec in requirement_specs.items() } return requirement_specs
def test_match(self): for spec, res in [ ("numpy 1.7*", True), ("numpy 1.7.1", True), ("numpy 1.7", False), ("numpy 1.5*", False), ("numpy >=1.5", True), ("numpy >=1.5,<2", True), ("numpy >=1.8,<1.9", False), ("numpy >1.5,<2,!=1.7.1", False), ("numpy >1.8,<2|==1.7", False), ("numpy >1.8,<2|>=1.7.1", True), ("numpy >=1.8|1.7*", True), ("numpy ==1.7", False), ("numpy >=1.5,>1.6", True), ("numpy ==1.7.1", True), ("numpy >=1,*.7.*", True), ("numpy *.7.*,>=1", True), ("numpy >=1,*.8.*", False), ("numpy >=2,*.7.*", False), ("numpy 1.6*|1.7*", True), ("numpy 1.6*|1.8*", False), ("numpy 1.6.2|1.7*", True), ("numpy 1.6.2|1.7.1", True), ("numpy 1.6.2|1.7.0", False), ("numpy 1.7.1 py27_0", True), ("numpy 1.7.1 py26_0", False), ("python", False), ]: m = MatchSpec(spec) self.assertEqual(m.match("numpy-1.7.1-py27_0.tar.bz2"), res)
def handle_config_version(ms, ver): """ 'ms' is an instance of MatchSpec, and 'ver' is the version from the configuration, e.g. for ms.name == 'python', ver = 26 or None, return a (sometimes new) MatchSpec object """ if ms.strictness == 3: return ms if ms.strictness == 2: if ms.spec.split()[1] == 'x.x': if ver is None: raise RuntimeError("'%s' requires external setting" % ms.spec) # (no return here - proceeds below) else: # regular version return ms if ver is None or (ms.strictness == 1 and ms.name == 'numpy'): return MatchSpec(ms.name) ver = text_type(ver) if '.' not in ver: if ms.name == 'numpy': ver = '%s.%s' % (ver[0], ver[1:]) else: ver = '.'.join(ver) return MatchSpec('%s %s*' % (ms.name, ver))
def test_hash(self): a, b = MatchSpec('numpy 1.7*'), MatchSpec('numpy 1.7*') self.assertTrue(a is not b) self.assertEqual(a, b) self.assertEqual(hash(a), hash(b)) c, d = MatchSpec('python'), MatchSpec('python 2.7.4') self.assertNotEqual(a, c) self.assertNotEqual(hash(a), hash(c))
def setUp(self): pkgs = [(None, "test-spec", "default", "1"), ("ranenv", "test-spec", "default", "5"), ("test1", "test-spec2", "default", "1")] self.res = generate_mocked_resolve(pkgs) self.specs = [MatchSpec("test-spec"), MatchSpec("test-spec2")] self.context = generate_mocked_context( "some/prefix", "some/prefix", ["some/prefix/envs", "some/prefix/envs/_pre_"])
def add_defaults_to_specs(r, linked, specs, update=False): # TODO: This should use the pinning mechanism. But don't change the API: # cas uses it. if r.explicit(specs): return log.debug('H0 specs=%r' % specs) names_linked = {install.name_dist(dist): dist for dist in linked} names_ms = {MatchSpec(s).name: MatchSpec(s) for s in specs} for name, def_ver in [ ('python', config.default_python), # Default version required, but only used for Python ('lua', None) ]: ms = names_ms.get(name) if ms and ms.strictness > 1: # if any of the specifications mention the Python/Numpy version, # we don't need to add the default spec log.debug('H1 %s' % name) continue any_depends_on = any(ms2.name == name for spec in specs for fn in r.find_matches(spec) for ms2 in r.ms_depends(fn)) log.debug('H2 %s %s' % (name, any_depends_on)) if not any_depends_on and name not in names_ms: # if nothing depends on Python/Numpy AND the Python/Numpy is not # specified, we don't need to add the default spec log.debug('H2A %s' % name) continue if (any_depends_on and len(specs) >= 1 and MatchSpec(specs[0]).strictness == 3): # if something depends on Python/Numpy, but the spec is very # explicit, we also don't need to add the default spec log.debug('H2B %s' % name) continue if name in names_linked: # if Python/Numpy is already linked, we add that instead of the # default log.debug('H3 %s' % name) spec = dist2spec3v(names_linked[name]) if update: spec = '%s (target=%s.tar.bz2)' % (spec, names_linked[name]) specs.append(spec) continue if (name, def_ver) in [('python', '3.3'), ('python', '3.4'), ('python', '3.5')]: # Don't include Python 3 in the specs if this is the Python 3 # version of conda. continue specs.append('%s %s*' % (name, def_ver)) log.debug('HF specs=%r' % specs)
def test_match(self): for spec, res in [ ('numpy 1.7*', True), ('numpy 1.7.1', True), ('numpy 1.7', False), ('numpy 1.5*', False), ('numpy >=1.5', True), ('numpy >=1.5,<2', True), ('numpy >=1.8,<1.9', False), ('numpy >1.5,<2,!=1.7.1', False), ('numpy >1.8,<2|==1.7', False),('numpy >1.8,<2|>=1.7.1', True), ('numpy >=1.8|1.7*', True), ('numpy ==1.7', False), ('numpy >=1.5,>1.6', True), ('numpy ==1.7.1', True), ('numpy >=1,*.7.*', True), ('numpy *.7.*,>=1', True), ('numpy >=1,*.8.*', False), ('numpy >=2,*.7.*', False), ('numpy 1.6*|1.7*', True), ('numpy 1.6*|1.8*', False), ('numpy 1.6.2|1.7*', True), ('numpy 1.6.2|1.7.1', True), ('numpy 1.6.2|1.7.0', False), ('numpy 1.7.1 py27_0', True), ('numpy 1.7.1 py26_0', False), ('numpy >1.7.1a', True), ('python', False), ]: m = MatchSpec(spec) self.assertEqual(m.match(Dist('numpy-1.7.1-py27_0.tar.bz2')), res) # both version numbers conforming to PEP 440 self.assertFalse(MatchSpec('numpy >=1.0.1').match(Dist('numpy-1.0.1a-0.tar.bz2'))) # both version numbers non-conforming to PEP 440 self.assertFalse(MatchSpec('numpy >=1.0.1.vc11').match(Dist('numpy-1.0.1a.vc11-0.tar.bz2'))) self.assertTrue(MatchSpec('numpy >=1.0.1*.vc11').match(Dist('numpy-1.0.1a.vc11-0.tar.bz2'))) # one conforming, other non-conforming to PEP 440 self.assertTrue(MatchSpec('numpy <1.0.1').match(Dist('numpy-1.0.1.vc11-0.tar.bz2'))) self.assertTrue(MatchSpec('numpy <1.0.1').match(Dist('numpy-1.0.1a.vc11-0.tar.bz2'))) self.assertFalse(MatchSpec('numpy >=1.0.1.vc11').match(Dist('numpy-1.0.1a-0.tar.bz2'))) self.assertTrue(MatchSpec('numpy >=1.0.1a').match(Dist('numpy-1.0.1z-0.tar.bz2'))) self.assertTrue(MatchSpec('numpy >=1.0.1a py27*').match(Dist('numpy-1.0.1z-py27_1.tar.bz2'))) self.assertTrue(MatchSpec('blas * openblas').match(Dist('blas-1.0-openblas.tar.bz2'))) self.assertTrue(MatchSpec('blas').is_simple()) self.assertFalse(MatchSpec('blas').is_exact()) self.assertFalse(MatchSpec('blas 1.0').is_simple()) self.assertFalse(MatchSpec('blas 1.0').is_exact()) self.assertFalse(MatchSpec('blas 1.0 1').is_simple()) self.assertTrue(MatchSpec('blas 1.0 1').is_exact()) self.assertFalse(MatchSpec('blas 1.0 *').is_exact()) m = MatchSpec('blas 1.0', optional=True) m2 = MatchSpec(m, optional=False) m3 = MatchSpec(m2, target='blas-1.0-0.tar.bz2') m4 = MatchSpec(m3, target=None, optional=True) self.assertTrue(m.spec == m2.spec and m.optional != m2.optional) self.assertTrue(m2.spec == m3.spec and m2.optional == m3.optional and m2.target != m3.target) self.assertTrue(m == m4) self.assertRaises(ValueError, MatchSpec, 'blas (optional') self.assertRaises(ValueError, MatchSpec, 'blas (optional,test)')
def add_defaults_to_specs(r, linked, specs): if r.explicit(specs): return log.debug('H0 specs=%r' % specs) names_linked = {install.name_dist(dist): dist for dist in linked} names_ms = {MatchSpec(s).name: MatchSpec(s) for s in specs} for name, def_ver in [ ('python', config.default_python), ]: #('numpy', config.default_numpy)]: ms = names_ms.get(name) if ms and ms.strictness > 1: # if any of the specifications mention the Python/Numpy version, # we don't need to add the default spec log.debug('H1 %s' % name) continue any_depends_on = any(ms2.name == name for spec in specs for fn in r.get_max_dists(MatchSpec(spec)) for ms2 in r.ms_depends(fn)) log.debug('H2 %s %s' % (name, any_depends_on)) if not any_depends_on and name not in names_ms: # if nothing depends on Python/Numpy AND the Python/Numpy is not # specified, we don't need to add the default spec log.debug('H2A %s' % name) continue if (any_depends_on and len(specs) >= 1 and MatchSpec(specs[0]).strictness == 3): # if something depends on Python/Numpy, but the spec is very # explicit, we also don't need to add the default spec log.debug('H2B %s' % name) continue if name in names_linked: # if Python/Numpy is already linked, we add that instead of the # default log.debug('H3 %s' % name) specs.append(dist2spec3v(names_linked[name])) continue if (name, def_ver) == ('python', '3.3'): # Don't include Python 3 in the specs if this is the Python 3 # version of conda. continue specs.append('%s %s*' % (name, def_ver)) log.debug('HF specs=%r' % specs)
def test_match(self): for spec, res in [('numpy 1.7*', True), ('numpy 1.7.1', True), ('numpy 1.7', False), ('numpy 1.5*', False), ('numpy 1.6*|1.7*', True), ('numpy 1.6*|1.8*', False), ('numpy 1.6.2|1.7*', True), ('numpy 1.6.2|1.7.1', True), ('numpy 1.6.2|1.7.0', False), ('numpy 1.7.1 py27_0', True), ('numpy 1.7.1 py26_0', False), ('python', False)]: m = MatchSpec(spec) self.assertEqual(m.match('numpy-1.7.1-py27_0.tar.bz2'), res)
def test_match(self): for spec, res in [('numpy 1.7*', True), ('numpy 1.7.1', True), ('numpy 1.7', False), ('numpy 1.5*', False), ('numpy 1.6*|1.7*', True), ('numpy 1.6*|1.8*', False), ('numpy 1.6.2|1.7*', True), ('numpy 1.6.2|1.7.1', True), ('numpy 1.6.2|1.7.0', False), ('numpy 1.7.1 py27_0', True), ('numpy 1.7.1 py26_0', False), ('python', False)]: m = MatchSpec(spec) self.assertEqual(m.match('numpy-1.7.1-py27_0.tar.bz2'), res)
def test_hash(self): a, b = MatchSpec('numpy 1.7*'), MatchSpec('numpy 1.7*') # optional should not change the hash d = MatchSpec('numpy 1.7* (optional)') self.assertTrue(a is not b) self.assertTrue(a is not d) self.assertEqual(a, b) self.assertNotEqual(a, d) self.assertEqual(hash(a), hash(b)) self.assertEqual(hash(a), hash(d)) c, d = MatchSpec('python'), MatchSpec('python 2.7.4') self.assertNotEqual(a, c) self.assertNotEqual(hash(a), hash(c)) self.assertNotEqual(c, d) self.assertNotEqual(hash(c), hash(d))
def test_numpy(self): for spec, ver, res_spec in [ ('numpy', None, 'numpy'), ('numpy', 18, 'numpy'), ('numpy', 110, 'numpy'), ('numpy x.x', 17, 'numpy 1.7*'), ('numpy x.x', 110, 'numpy 1.10*'), ('numpy 1.9.1', 18, 'numpy 1.9.1'), ('numpy 1.9.0 py27_2', None, 'numpy 1.9.0 py27_2'), ]: ms = MatchSpec(spec) self.assertEqual(handle_config_version(ms, ver), MatchSpec(res_spec)) self.assertRaises(RuntimeError, handle_config_version, MatchSpec('numpy x.x'), None)
def get_package_versions(package): index = get_index() r = Resolve(index) if package in r.groups: return r.get_pkgs(MatchSpec(package)) else: return []
def arg2spec(arg, json=False, update=False): try: spec = MatchSpec(spec_from_line(arg)) except: error_and_exit('invalid package specification: %s' % arg, json=json, error_type="ValueError") name = spec.name if name in config.disallow: error_and_exit("specification '%s' is disallowed" % name, json=json, error_type="ValueError") if spec.strictness > 1 and update: error_and_exit("""version specifications not allowed with 'update'; use conda update %s%s or conda install %s""" % (name, ' ' * (len(arg) - len(name)), arg), json=json, error_type="ValueError") if spec.strictness != 2: return str(spec) ver = spec.vspecs.spec if isinstance(ver, tuple) or ver.startswith( ('=', '>', '<', '!')) or ver.endswith('*'): return str(spec) elif ver.endswith('.0'): return '%s %s|%s*' % (name, ver[:-2], ver) else: return '%s %s*' % (name, ver)
def test_circular_dependencies(): index2 = index.copy() index2['package1-1.0-0.tar.bz2'] = { 'build': '0', 'build_number': 0, 'depends': ['package2'], 'name': 'package1', 'requires': ['package2'], 'version': '1.0', } index2['package2-1.0-0.tar.bz2'] = { 'build': '0', 'build_number': 0, 'depends': ['package1'], 'name': 'package2', 'requires': ['package1'], 'version': '1.0', } r = Resolve(index2) assert set(r.find_matches(MatchSpec('package1'))) == { 'package1-1.0-0.tar.bz2', } assert set(r.get_dists(['package1']).keys()) == { 'package1-1.0-0.tar.bz2', 'package2-1.0-0.tar.bz2', } assert r.solve(['package1']) == r.solve(['package2']) == \ r.solve(['package1', 'package2']) == [ 'package1-1.0-0.tar.bz2', 'package2-1.0-0.tar.bz2', ]
def test_match(self): for spec, res in [ ('numpy 1.7*', True), ('numpy 1.7.1', True), ('numpy 1.7', False), ('numpy 1.5*', False), ('numpy >=1.5', True), ('numpy >=1.5,<2', True), ('numpy >=1.8,<1.9', False), ('numpy >1.5,<2,!=1.7.1', False), ('numpy >1.8,<2|==1.7', False),('numpy >1.8,<2|>=1.7.1', True), ('numpy >=1.8|1.7*', True), ('numpy ==1.7', False), ('numpy >=1.5,>1.6', True), ('numpy ==1.7.1', True), ('numpy 1.6*|1.7*', True), ('numpy 1.6*|1.8*', False), ('numpy 1.6.2|1.7*', True), ('numpy 1.6.2|1.7.1', True), ('numpy 1.6.2|1.7.0', False), ('numpy 1.7.1 py27_0', True), ('numpy 1.7.1 py26_0', False), ('python', False), ]: m = MatchSpec(spec) self.assertEqual(m.match('numpy-1.7.1-py27_0.tar.bz2'), res)
def create_rpm_installer(target, config, python_spec='python'): rpm_prefix = config['rpm']['prefix'] index = conda.api.get_index() matches = Resolve(index).get_pkgs(MatchSpec(python_spec)) if not matches: raise RuntimeError('No python found in the channels.') # Pick the latest Python match. pkg_info = sorted(matches)[-1].info dist_name = '{}-{}-{}'.format(pkg_info['name'], pkg_info['version'], pkg_info['build']) pkg_cache = os.path.join(target, 'SOURCES') if not conda_install.is_fetched(pkg_cache, dist_name): print('Fetching {}'.format(dist_name)) conda.fetch.fetch_pkg(pkg_info, pkg_cache) installer_source = os.path.join(os.path.dirname(__file__), 'install.py') installer_target = os.path.join(pkg_cache, 'install.py') shutil.copyfile(installer_source, installer_target) spec_dir = os.path.join(target, 'SPECS') if not os.path.exists(spec_dir): os.makedirs(spec_dir) specfile = os.path.join(spec_dir, '{}-installer.spec'.format(rpm_prefix)) with open(specfile, 'w') as fh: fh.write(generate.render_installer(pkg_info, config))
def filter_cases(cases, index, extra_specs): """ cases might look like: cases = ([('python', '2.7'), ('numpy', '1.8')], [('python', '2.7'), ('numpy', '1.9')], [('python', '3.5'), ('numpy', '1.8')], ) Typically extra_specs comes from the environment specification. """ """ cases might look like: cases = ([('python', '2.7'), ('numpy', '1.8')], [('python', '2.7'), ('numpy', '1.9')], [('python', '3.5'), ('numpy', '1.8')], ) Typically extra_specs comes from the environment specification. """ specs = [MatchSpec(spec) for spec in extra_specs] for case in cases: cases_by_pkg_name = {name: '{}-{}.0-0.tar.bz2'.format(name, version) for name, version in case} match = [] for spec in specs: if spec.name in cases_by_pkg_name: match.append(bool(spec.match(cases_by_pkg_name[spec.name]))) if all(match): yield case
def test_llvm(self): ms = MatchSpec('llvm') pkgs = [Package(fn, r.index[Dist(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 filter_cases(cases, extra_specs): """ cases might look like: cases = ([('python', '2.7'), ('numpy', '1.8')], [('python', '2.7'), ('numpy', '1.9')], [('python', '3.5'), ('numpy', '1.8')], ) Typically extra_specs comes from the environment specification. """ specs = [MatchSpec(spec) for spec in extra_specs] for case in cases: # Invent a sensible "tar.bz2" name which we can use to invoke conda's # MatchSpec matching. cases_by_pkg_name = { name: '{}-{}.0-0.tar.bz2'.format(name, version) for name, version in case } match = [] for spec in specs: # Only run the filter on the packages in cases. if spec.name in cases_by_pkg_name: match.append(bool(spec.match(cases_by_pkg_name[spec.name]))) if all(match): yield case
def warn_on_old_conda_build(index): root_linked = linked(cc.root_dir) vers_inst = [ dist.rsplit('-', 2)[1] for dist in root_linked if dist.rsplit('-', 2)[0] == 'conda-build' ] if not len(vers_inst) == 1: print("WARNING: Could not detect installed version of conda-build", file=sys.stderr) return r = Resolve(index) try: pkgs = sorted(r.get_pkgs(MatchSpec('conda-build'))) except NoPackagesFound: print( "WARNING: Could not find any versions of conda-build in the channels", file=sys.stderr) return if pkgs[-1].version != vers_inst[0]: print(""" WARNING: conda-build appears to be out of date. You have version %s but the latest version is %s. Run conda update -n root conda-build to get the latest version. """ % (vers_inst[0], pkgs[-1].version), file=sys.stderr)
def test_circular_dependencies(): index2 = index.copy() index2['package1-1.0-0.tar.bz2'] = IndexRecord(**{ 'build': '0', 'build_number': 0, 'depends': ['package2'], 'name': 'package1', 'requires': ['package2'], 'version': '1.0', }) index2['package2-1.0-0.tar.bz2'] = IndexRecord(**{ 'build': '0', 'build_number': 0, 'depends': ['package1'], 'name': 'package2', 'requires': ['package1'], 'version': '1.0', }) index2 = {Dist(key): value for key, value in iteritems(index2)} r = Resolve(index2) assert set(r.find_matches(MatchSpec('package1'))) == { Dist('package1-1.0-0.tar.bz2'), } assert set(r.get_reduced_index(['package1']).keys()) == { Dist('package1-1.0-0.tar.bz2'), Dist('package2-1.0-0.tar.bz2'), } assert r.install(['package1']) == r.install(['package2']) == \ r.install(['package1', 'package2']) == [ Dist('package1-1.0-0.tar.bz2'), Dist('package2-1.0-0.tar.bz2'), ]
def test_explicit1(self): self.assertEqual(r.explicit(['pycosat 0.6.0 py27_0']), None) self.assertEqual(r.explicit(['zlib']), None) self.assertEqual(r.explicit(['zlib 1.2.7']), None) # because zlib has no dependencies it is also explicit exp_result = r.explicit([MatchSpec('zlib 1.2.7 0', schannel='defaults')]) self.assertEqual(exp_result, [Dist('defaults::zlib-1.2.7-0.tar.bz2')])
def arg2spec(arg, json=False, update=False): try: spec = MatchSpec(spec_from_line(arg), normalize=True) except: error_and_exit('invalid package specification: %s' % arg, json=json, error_type="ValueError") name = spec.name if name in disallow: error_and_exit("specification '%s' is disallowed" % name, json=json, error_type="ValueError") if not spec.is_simple() and update: error_and_exit("""version specifications not allowed with 'update'; use conda update %s%s or conda install %s""" % (name, ' ' * (len(arg)-len(name)), arg), json=json, error_type="ValueError") return str(spec)
def test_match(self): for spec, res in [ ("numpy 1.7*", True), ("numpy 1.7.1", True), ("numpy 1.7", False), ("numpy 1.5*", False), ("numpy 1.6*|1.7*", True), ("numpy 1.6*|1.8*", False), ("numpy 1.6.2|1.7*", True), ("numpy 1.6.2|1.7.1", True), ("numpy 1.6.2|1.7.0", False), ("numpy 1.7.1 py27_0", True), ("numpy 1.7.1 py26_0", False), ("python", False), ]: m = MatchSpec(spec) self.assertEqual(m.match("numpy-1.7.1-py27_0.tar.bz2"), res)
def test_python(self): for spec, ver, res_spec in [ ('python', '3.4', 'python 3.4*'), ('python 2.7.8', '2.7', 'python 2.7.8'), ('python 2.7.8', '3.5', 'python 2.7.8'), ('python 2.7.8', None, 'python 2.7.8'), ('python', None, 'python'), ('python x.x', '2.7', 'python 2.7*'), ('python', '27', 'python 2.7*'), ('python', 27, 'python 2.7*'), ]: ms = MatchSpec(spec) self.assertEqual(handle_config_version(ms, ver), MatchSpec(res_spec)) self.assertRaises(RuntimeError, handle_config_version, MatchSpec('python x.x'), None)
def test_match(self): for spec, res in [ ("numpy 1.7*", True), ("numpy 1.7.1", True), ("numpy 1.7", False), ("numpy 1.5*", False), ("numpy >=1.5", True), ("numpy >=1.5,<2", True), ("numpy >=1.8,<1.9", False), ("numpy >1.5,<2,!=1.7.1", False), ("numpy >1.8,<2|==1.7", False), ("numpy >1.8,<2|>=1.7.1", True), ("numpy >=1.8|1.7*", True), ("numpy ==1.7", False), ("numpy >=1.5,>1.6", True), ("numpy ==1.7.1", True), ("numpy >=1,*.7.*", True), ("numpy *.7.*,>=1", True), ("numpy >=1,*.8.*", False), ("numpy >=2,*.7.*", False), ("numpy 1.6*|1.7*", True), ("numpy 1.6*|1.8*", False), ("numpy 1.6.2|1.7*", True), ("numpy 1.6.2|1.7.1", True), ("numpy 1.6.2|1.7.0", False), ("numpy 1.7.1 py27_0", True), ("numpy 1.7.1 py26_0", False), ("numpy >1.7.1a", True), ("python", False), ]: m = MatchSpec(spec) self.assertEqual(m.match("numpy-1.7.1-py27_0.tar.bz2"), res) # both version numbers conforming to PEP 440 self.assertFalse(MatchSpec("numpy >=1.0.1").match("numpy-1.0.1a-0.tar.bz2")) # both version numbers non-conforming to PEP 440 self.assertFalse(MatchSpec("numpy >=1.0.1.vc11").match("numpy-1.0.1a.vc11-0.tar.bz2")) self.assertTrue(MatchSpec("numpy >=1.0.1*.vc11").match("numpy-1.0.1a.vc11-0.tar.bz2")) # one conforming, other non-conforming to PEP 440 self.assertTrue(MatchSpec("numpy <1.0.1").match("numpy-1.0.1.vc11-0.tar.bz2")) self.assertTrue(MatchSpec("numpy <1.0.1").match("numpy-1.0.1a.vc11-0.tar.bz2")) self.assertFalse(MatchSpec("numpy >=1.0.1.vc11").match("numpy-1.0.1a-0.tar.bz2")) self.assertTrue(MatchSpec("numpy >=1.0.1a").match("numpy-1.0.1z-0.tar.bz2"))
print repo r = Resolve(repo['packages']) r.solve(env_lts['packages'], features=set()) r.solve2(env_lts['packages'], features=set()) # conda.api.fetch_repodata is the underlying index loader. #index = get_index(channel_urls=channel_urls, # prepend=not args.override_channels, # use_cache=args.use_index_cache, # unknown=args.unknown, # json=args.json, # offline=args.offline) from conda.resolve import MatchSpec fn = 'numpy-1.8.3-py27_0.tar.bz2' ms = MatchSpec('numpy >=1.7,<1.9') print ms.match(fn) #for name in orig_packages: # pkgs = sorted(r.get_pkgs(MatchSpec(name)))