Repository: conda/conda

Issue:
NoPackagesFound does not work correctly for missing recursive dependencies



Discussion:

Resolving patch:
diff --git a/conda/resolve.py b/conda/resolve.py
--- a/conda/resolve.py
+++ b/conda/resolve.py
@@ -278,12 +278,25 @@ def all_deps(self, root_fn, max_only=False):
 
         def add_dependents(fn1, max_only=False):
             for ms in self.ms_depends(fn1):
+                found = False
+                notfound = []
                 for pkg2 in self.get_pkgs(ms, max_only=max_only):
                     if pkg2.fn in res:
+                        found = True
                         continue
-                    res[pkg2.fn] = pkg2
-                    if ms.strictness < 3:
-                        add_dependents(pkg2.fn, max_only=max_only)
+                    try:
+                        if ms.strictness < 3:
+                            add_dependents(pkg2.fn, max_only=max_only)
+                    except NoPackagesFound as e:
+                        if e.pkg not in notfound:
+                            notfound.append(e.pkg)
+                    else:
+                        found = True
+                        res[pkg2.fn] = pkg2
+
+                if not found:
+                    raise NoPackagesFound("Could not find some dependencies "
+                        "for %s: %s" % (ms, ', '.join(notfound)), str(ms))
 
         add_dependents(root_fn, max_only=max_only)
         return res
@@ -394,7 +407,7 @@ def get_dists(self, specs, max_only=False):
                     dists[pkg.fn] = pkg
                     found = True
             if not found:
-                raise NoPackagesFound("Could not find some dependencies for %s: %s" % (spec, ', '.join(notfound)), None)
+                raise NoPackagesFound("Could not find some dependencies for %s: %s" % (spec, ', '.join(notfound)), spec)
 
         return dists
 


Test patch:
diff --git a/tests/test_resolve.py b/tests/test_resolve.py
--- a/tests/test_resolve.py
+++ b/tests/test_resolve.py
@@ -696,6 +696,22 @@ def test_nonexistent_deps():
         'requires': ['nose 1.2.1', 'python 3.3'],
         'version': '1.1',
     }
+    index2['anotherpackage-1.0-py33_0.tar.bz2'] = {
+        'build': 'py33_0',
+        'build_number': 0,
+        'depends': ['nose', 'mypackage 1.1'],
+        'name': 'anotherpackage',
+        'requires': ['nose', 'mypackage 1.1'],
+        'version': '1.0',
+    }
+    index2['anotherpackage-2.0-py33_0.tar.bz2'] = {
+        'build': 'py33_0',
+        'build_number': 0,
+        'depends': ['nose', 'mypackage'],
+        'name': 'anotherpackage',
+        'requires': ['nose', 'mypackage'],
+        'version': '2.0',
+    }
     r = Resolve(index2)
 
     assert set(r.find_matches(MatchSpec('mypackage'))) == {
@@ -772,6 +788,32 @@ def test_nonexistent_deps():
     ]
     assert raises(NoPackagesFound, lambda: r.solve(['mypackage 1.0']))
 
+    assert r.solve(['anotherpackage 1.0']) == [
+        'anotherpackage-1.0-py33_0.tar.bz2',
+        'mypackage-1.1-py33_0.tar.bz2',
+        'nose-1.3.0-py33_0.tar.bz2',
+        'openssl-1.0.1c-0.tar.bz2',
+        'python-3.3.2-0.tar.bz2',
+        'readline-6.2-0.tar.bz2',
+        'sqlite-3.7.13-0.tar.bz2',
+        'system-5.8-1.tar.bz2',
+        'tk-8.5.13-0.tar.bz2',
+        'zlib-1.2.7-0.tar.bz2',
+    ]
+
+    assert r.solve(['anotherpackage']) == [
+        'anotherpackage-2.0-py33_0.tar.bz2',
+        'mypackage-1.1-py33_0.tar.bz2',
+        'nose-1.3.0-py33_0.tar.bz2',
+        'openssl-1.0.1c-0.tar.bz2',
+        'python-3.3.2-0.tar.bz2',
+        'readline-6.2-0.tar.bz2',
+        'sqlite-3.7.13-0.tar.bz2',
+        'system-5.8-1.tar.bz2',
+        'tk-8.5.13-0.tar.bz2',
+        'zlib-1.2.7-0.tar.bz2',
+    ]
+
     # This time, the latest version is messed up
     index3 = index.copy()
     index3['mypackage-1.1-py33_0.tar.bz2'] = {
@@ -790,6 +832,22 @@ def test_nonexistent_deps():
         'requires': ['nose 1.2.1', 'python 3.3'],
         'version': '1.0',
     }
+    index3['anotherpackage-1.0-py33_0.tar.bz2'] = {
+        'build': 'py33_0',
+        'build_number': 0,
+        'depends': ['nose', 'mypackage 1.0'],
+        'name': 'anotherpackage',
+        'requires': ['nose', 'mypackage 1.0'],
+        'version': '1.0',
+    }
+    index3['anotherpackage-2.0-py33_0.tar.bz2'] = {
+        'build': 'py33_0',
+        'build_number': 0,
+        'depends': ['nose', 'mypackage'],
+        'name': 'anotherpackage',
+        'requires': ['nose', 'mypackage'],
+        'version': '2.0',
+    }
     r = Resolve(index3)
 
     assert set(r.find_matches(MatchSpec('mypackage'))) == {
@@ -852,6 +910,35 @@ def test_nonexistent_deps():
     ]
     assert raises(NoPackagesFound, lambda: r.solve(['mypackage 1.1']))
 
+
+    assert r.solve(['anotherpackage 1.0']) == [
+        'anotherpackage-1.0-py33_0.tar.bz2',
+        'mypackage-1.0-py33_0.tar.bz2',
+        'nose-1.3.0-py33_0.tar.bz2',
+        'openssl-1.0.1c-0.tar.bz2',
+        'python-3.3.2-0.tar.bz2',
+        'readline-6.2-0.tar.bz2',
+        'sqlite-3.7.13-0.tar.bz2',
+        'system-5.8-1.tar.bz2',
+        'tk-8.5.13-0.tar.bz2',
+        'zlib-1.2.7-0.tar.bz2',
+    ]
+
+    # If recursive checking is working correctly, this will give
+    # anotherpackage 2.0, not anotherpackage 1.0
+    assert r.solve(['anotherpackage']) == [
+        'anotherpackage-2.0-py33_0.tar.bz2',
+        'mypackage-1.0-py33_0.tar.bz2',
+        'nose-1.3.0-py33_0.tar.bz2',
+        'openssl-1.0.1c-0.tar.bz2',
+        'python-3.3.2-0.tar.bz2',
+        'readline-6.2-0.tar.bz2',
+        'sqlite-3.7.13-0.tar.bz2',
+        'system-5.8-1.tar.bz2',
+        'tk-8.5.13-0.tar.bz2',
+        'zlib-1.2.7-0.tar.bz2',
+    ]
+
 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'])