Repository: conda/conda

Issue:
Conda is installing unrequested feature
This seems to be a regression in `conda` 4.0.

I have created two test packages just to check this. They are empty and have just the `meta.yaml`:

test-release:

``` yaml
package:
  name: test
  version: "1.0"

build:
  number: 0
  features:
```

test-debug:

``` yaml
package:
  name: test
  version: "1.0"

build:
  number: 1
  features:
    - debug

requirements:
  run:
    - debug
```

(`debug` is the anaconda metapackage that only tracks the `debug` feature.)

Now, when creating a new environment with only the `test` package, it tries to install the `debug` version:

``` sh
$ conda create -n test-pkg test=1.0
Fetching package metadata: ......
Solving package specifications: .........

Package plan for installation in environment D:\Miniconda\envs\test-pkg:

The following NEW packages will be INSTALLED:

    debug: 1.0-0
    test:  1.0-debug_1 [debug]

Proceed ([y]/n)?
```



Discussion:
What happens if you use the same build number for both?

Then it won't try to install `debug`. It only happens when the build number of the package with the feature is higher.

Quick question: you say 4.0, but are you using the latest version  (4.0.5), or truly just 4.0?

Sorry, it is 4.0.5. I just assumed the regression was on the change from 3 to 4, since it seems the dependency solving was overhauled.

Any news on this?
We are having to work on a "brittle" version of conda here --'.
Thanks!

I think that this might be related to #4624.
Regarding this one, I think I now understand what's going on.

When performing the command `conda create -n test-pkg test=1.0`, conda's _first_ priority is to obtain the latest version and build of the packages specified on the command line. In this case, that means it is going to favor `test-1.0-1`. Since the only version of the package with this version and build number is the debug version, it _must_ install that one. 

The bug here is that features are never supposed to be pulled in involuntarily. So conda shouldn't be allowed to select the feature in that case.

Now, if you give both packages the _same_ build number, `conda create -n test-pkg test=1.0` now has a choice. There are two packages with the same version and build number, one with the `debug` feature, and one without. In this case, conda _always_ picks the one with the fewest features. So the non-debug version wins. Again, that's correct behavior.

If you want to force the debug feature in that second case, you must do `conda create -n test-pkg test=1.0 debug`. That will guarantee that the `debug` version of the package is installed. 

So the lesson here is that for now, if you want to avoid strange behavior, the build numbers need to line up.

However, I can understand why that would be confusing. Frankly, features _are_ confusing, and brittle, and I would prefer we not use them, and find other ways to implement our requirements.
Agreed, @SylvainCorlay, this may indeed be related. Do you use the exact same build numbers for your `cling` builds?
Yes I did! Thanks for looking into this.

On Feb 14, 2017 8:49 PM, "Michael C. Grant" <notifications@github.com>
wrote:

> Agreed, @SylvainCorlay <https://github.com/SylvainCorlay>, this may
> indeed be related. Do you use the exact same build numbers for your cling
> builds?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/conda/conda/issues/2384#issuecomment-279815579>, or mute
> the thread
> <https://github.com/notifications/unsubscribe-auth/ACSXFkV6G3JPcv5Vvls7-1MzAGqXnLATks5rcgU1gaJpZM4IL-YC>
> .
>

Looks like we have a resolution and understanding at least if this particular issue. 
Well, if @SylvainCorlay is using the same build numbers there's still something else going on. I'm not sure that either this issue or his other issue should be closed, because neither has really been solved.

Resolving patch:
diff --git a/conda/resolve.py b/conda/resolve.py
--- a/conda/resolve.py
+++ b/conda/resolve.py
@@ -875,11 +875,10 @@ def mysat(specs, add_if=False):
             solution, obj7 = C.minimize(eq_optional_c, solution)
             log.debug('Package removal metric: %d', obj7)
 
-            # Requested packages: maximize versions, then builds
+            # Requested packages: maximize versions
             eq_req_v, eq_req_b = r2.generate_version_metrics(C, specr)
             solution, obj3 = C.minimize(eq_req_v, solution)
-            solution, obj4 = C.minimize(eq_req_b, solution)
-            log.debug('Initial package version/build metrics: %d/%d', obj3, obj4)
+            log.debug('Initial package version metric: %d', obj3)
 
             # Track features: minimize feature count
             eq_feature_count = r2.generate_feature_count(C)
@@ -892,7 +891,11 @@ def mysat(specs, add_if=False):
             obj2 = ftotal - obj2
             log.debug('Package feature count: %d', obj2)
 
-            # Dependencies: minimize the number that need upgrading
+            # Requested packages: maximize builds
+            solution, obj4 = C.minimize(eq_req_b, solution)
+            log.debug('Initial package build metric: %d', obj4)
+
+            # Dependencies: minimize the number of packages that need upgrading
             eq_u = r2.generate_update_count(C, speca)
             solution, obj50 = C.minimize(eq_u, solution)
             log.debug('Dependency update count: %d', obj50)


Test patch: