Repository: conda/conda

Issue:
conda update .. --no-deps wants to remove dependencies
Using conda 4.4rc, when trying to update a single package with `--no-deps`, it actually wants to remove a whole lot of (unrelated) packages:

```
joris@joris-XPS-13-9350:~/scipy$ conda update shapely --no-deps
Solving environment: done

## Package Plan ##

  environment location: /home/joris/miniconda3

  added / updated specs: 
    - shapely


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    shapely-1.6.2              |           py35_1         703 KB  conda-forge

The following packages will be REMOVED:

    bottleneck:    1.2.1-np113py35_0                 conda-forge
    fiona:         1.7.9-py35_0                      conda-forge
    geos:          3.5.1-1                           conda-forge
    h5py:          2.7.0-np113py35_1                 conda-forge
    libgdal:       2.1.4-2                           conda-forge
    libspatialite: 4.3.0a-15                         conda-forge
    mahotas:       1.4.3-np113py35_1                 conda-forge
    numba:         0.34.0-np113py35_0                           
    numexpr:       2.6.2-np113py35_0                 conda-forge
    numpy:         1.13.1-py35_blas_openblas_200     conda-forge [blas_openblas]
    opencv:        3.2.0-np113py35_blas_openblas_204 conda-forge [blas_openblas]
    pytables:      3.4.2-np113py35_1                 conda-forge
    pywavelets:    0.5.2-np113py35_0                 conda-forge
    statsmodels:   0.8.0-np113py35_0                 conda-forge
    turbodbc:      2.2.0-np113py35_0                 conda-forge

The following packages will be UPDATED:

    shapely:       1.6.0-py35_0                      conda-forge --> 1.6.2-py35_1 conda-forge

Proceed ([y]/n)?
```

I don't see this behaviour when downgrading conda to 4.3

(see also discussion on gitter: https://gitter.im/conda/conda?at=5a01863532e080696e74a5aa)

I am using conda-forge as default channel:

```
joris@joris-XPS-13-9350:~/scipy$ conda info

     active environment : None
            shell level : 0
       user config file : /home/joris/.condarc
 populated config files : /home/joris/.condarc
          conda version : 4.4.0rc1
    conda-build version : 3.0.1
         python version : 3.5.4.final.0
       base environment : /home/joris/miniconda3  (writable)
           channel URLs : https://conda.anaconda.org/conda-canary/linux-64
                          https://conda.anaconda.org/conda-canary/noarch
                          https://conda.anaconda.org/conda-forge/linux-64
                          https://conda.anaconda.org/conda-forge/noarch
                          https://repo.continuum.io/pkgs/free/linux-64
                          https://repo.continuum.io/pkgs/free/noarch
                          https://repo.continuum.io/pkgs/r/linux-64
                          https://repo.continuum.io/pkgs/r/noarch
                          https://repo.continuum.io/pkgs/pro/linux-64
                          https://repo.continuum.io/pkgs/pro/noarch
          package cache : /home/joris/miniconda3/pkgs
                          /home/joris/.conda/pkgs
       envs directories : /home/joris/miniconda3/envs
                          /home/joris/.conda/envs
               platform : linux-64
             user-agent : conda/4.4.0rc1 requests/2.13.0 CPython/3.5.4 Linux/4.4.0-97-generic ubuntu/16.04 glibc/2.23
                UID:GID : 1000:1000
             netrc file : None
           offline mode : False
```


Discussion:
The original reason I tried `--no-deps` is because without that it actually tried to downgrade numpy and a bunch of depending packages (that might be the actual problem actually):

```
joris@joris-XPS-13-9350:~/scipy$ conda update shapely
Solving environment: done

## Package Plan ##

  environment location: /home/joris/miniconda3

  added / updated specs: 
    - shapely


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    numexpr-2.6.4              |           py35_0         426 KB  conda-forge
    geos-3.6.2                 |                0        19.9 MB  conda-forge
    fiona-1.7.0                |      np111py35_0         1.1 MB  conda-forge
    libgdal-2.0.0              |                1        47.0 MB
    numba-0.34.0               |      np111py35_0         2.5 MB
    shapely-1.6.2              |           py35_1         703 KB  conda-forge
    gdal-2.0.0                 |           py35_1         1.4 MB
    opencv-3.3.0               |py35_blas_openblas_200        49.2 MB  conda-forge
    numpy-1.11.3               |py35_blas_openblas_202         7.5 MB  conda-forge
    turbodbc-2.4.1             |           py35_1         9.0 MB  conda-forge
    mahotas-1.4.4              |           py35_0         4.1 MB  conda-forge
    pywavelets-0.5.2           |           py35_1         5.6 MB  conda-forge
    pytables-3.4.2             |           py35_5         7.0 MB  conda-forge
    libspatialite-4.3.0a       |               16         4.6 MB  conda-forge
    ------------------------------------------------------------
                                           Total:       160.1 MB

The following NEW packages will be INSTALLED:

    gdal:          2.0.0-py35_1                                 

The following packages will be UPDATED:

    bottleneck:    1.2.1-np113py35_0                 conda-forge --> 1.2.1-py35_1                  conda-forge
    geos:          3.5.1-1                           conda-forge --> 3.6.2-0                       conda-forge
    h5py:          2.7.0-np113py35_1                 conda-forge --> 2.7.1-py35_1                  conda-forge
    libspatialite: 4.3.0a-15                         conda-forge --> 4.3.0a-16                     conda-forge
    mahotas:       1.4.3-np113py35_1                 conda-forge --> 1.4.4-py35_0                  conda-forge
    numba:         0.34.0-np113py35_0                            --> 0.34.0-np111py35_0                       
    numexpr:       2.6.2-np113py35_0                 conda-forge --> 2.6.4-py35_0                  conda-forge
    opencv:        3.2.0-np113py35_blas_openblas_204 conda-forge [blas_openblas] --> 3.3.0-py35_blas_openblas_200  conda-forge [blas_openblas]
    pytables:      3.4.2-np113py35_1                 conda-forge --> 3.4.2-py35_5                  conda-forge
    pywavelets:    0.5.2-np113py35_0                 conda-forge --> 0.5.2-py35_1                  conda-forge
    shapely:       1.6.0-py35_0                      conda-forge --> 1.6.2-py35_1                  conda-forge
    statsmodels:   0.8.0-np113py35_0                 conda-forge --> 0.8.0-py35_0                  conda-forge
    turbodbc:      2.2.0-np113py35_0                 conda-forge --> 2.4.1-py35_1                  conda-forge

The following packages will be DOWNGRADED:

    fiona:         1.7.9-py35_0                      conda-forge --> 1.7.0-np111py35_0             conda-forge
    libgdal:       2.1.4-2                           conda-forge --> 2.0.0-1                                  
    numpy:         1.13.1-py35_blas_openblas_200     conda-forge [blas_openblas] --> 1.11.3-py35_blas_openblas_202 conda-forge [blas_openblas]

Proceed ([y]/n)? n
```

So this might also be a problem with the shapely package (although it seems to correctly specify only lower bound for numpy https://github.com/conda-forge/shapely-feedstock/blob/master/recipe/meta.yaml#L26)

Thanks for the report.  This is probably a bug.  I'll add it to the list to investigate.
Has there been any update on this?  I came to this via #6281 .  My conda installation is essentially unusable now for installing anything, as trying to install anything results in conda wanting to downgrade unrelated packages and upgrade even more unrelated packages.
@BrenBarn this issue is for conda 4.4, not conda 4.3 as in #6281.

Resolving patch:
diff --git a/conda/base/context.py b/conda/base/context.py
--- a/conda/base/context.py
+++ b/conda/base/context.py
@@ -575,7 +575,6 @@ def list_parameters(self):
             'ignore_pinned',
             'max_shlvl',
             'migrated_custom_channels',
-            'no_dependencies',
             'only_dependencies',
             'prune',
             'root_prefix',
@@ -763,6 +762,10 @@ def get_help_dict():
             A list of previously-used channel_alias values, useful for example when switching
             between different Anaconda Repository instances.
             """),
+        'no_dependencies': dals("""
+            Do not install, update, remove, or change dependencies. This WILL lead to broken
+            environments and inconsistent behavior. Use at your own risk.
+            """),
         'non_admin_enabled': dals("""
             Allows completion of conda's create, install, update, and remove operations, for
             non-privileged (non-root or non-administrator) users.
diff --git a/conda/cli/conda_argparse.py b/conda/cli/conda_argparse.py
--- a/conda/cli/conda_argparse.py
+++ b/conda/cli/conda_argparse.py
@@ -987,7 +987,8 @@ def add_parser_create_install_update(p):
     p.add_argument(
         "--no-deps",
         action="store_true",
-        help="Do not install dependencies.",
+        help="Do not install, update, remove, or change dependencies. This WILL lead "
+             "to broken environments and inconsistent behavior. Use at your own risk.",
     )
     p.add_argument(
         "--only-deps",
diff --git a/conda/core/solve.py b/conda/core/solve.py
--- a/conda/core/solve.py
+++ b/conda/core/solve.py
@@ -298,7 +298,6 @@ def solve_final_state(self, deps_modifier=NULL, prune=NULL, ignore_pinned=NULL,
         if log.isEnabledFor(DEBUG):
             log.debug("final specs to add: %s",
                       dashlist(sorted(text_type(s) for s in final_environment_specs)))
-        pre_solution = solution
         solution = r.solve(tuple(final_environment_specs))  # return value is List[dist]
 
         # add back inconsistent packages to solution
@@ -312,13 +311,25 @@ def solve_final_state(self, deps_modifier=NULL, prune=NULL, ignore_pinned=NULL,
         # Special case handling for various DepsModifer flags. Maybe this block could be pulled
         # out into its own non-public helper method?
         if deps_modifier == DepsModifier.NO_DEPS:
-            # In the NO_DEPS case we're just filtering out packages from the solution.
-            dont_add_packages = []
-            new_packages = set(solution) - set(pre_solution)
-            for dist in new_packages:
-                if not any(spec.match(index[dist]) for spec in specs_to_add):
-                    dont_add_packages.append(dist)
-            solution = tuple(rec for rec in solution if rec not in dont_add_packages)
+            # In the NO_DEPS case, we need to start with the original list of packages in the
+            # environment, and then only modify packages that match specs_to_add or
+            # specs_to_remove.
+            _no_deps_solution = IndexedSet(Dist(rec) for rec in prefix_data.iter_records())
+            only_remove_these = set(dist
+                                    for spec in specs_to_remove
+                                    for dist in _no_deps_solution
+                                    if spec.match(index[dist]))
+            _no_deps_solution -= only_remove_these
+
+            only_add_these = set(dist
+                                 for spec in specs_to_add
+                                 for dist in solution
+                                 if spec.match(index[dist]))
+            remove_before_adding_back = set(dist.name for dist in only_add_these)
+            _no_deps_solution = IndexedSet(dist for dist in _no_deps_solution
+                                           if dist.name not in remove_before_adding_back)
+            _no_deps_solution |= only_add_these
+            solution = _no_deps_solution
         elif deps_modifier == DepsModifier.ONLY_DEPS:
             # Using a special instance of the DAG to remove leaf nodes that match the original
             # specs_to_add.  It's important to only remove leaf nodes, because a typical use


Test patch: