Repository: conda/conda

Issue:
fix 'conda env create` using remote env file
Fix `conda env create  mfix/mfix-18.1.0-osx64` in master. Broken in https://github.com/conda/conda/pull/7385.

xref: https://github.com/conda/conda/issues/7111

Can also remove the deprecation warnings now (they were apparently placed in the wrong code location to begin with).


Discussion:

Resolving patch:
diff --git a/conda_env/specs/__init__.py b/conda_env/specs/__init__.py
--- a/conda_env/specs/__init__.py
+++ b/conda_env/specs/__init__.py
@@ -13,35 +13,42 @@
 
 
 def detect(**kwargs):
-    # Check file existence
     filename = kwargs.get('filename')
-    if filename and not os.path.isfile(filename):
-        raise EnvironmentFileNotFound(filename=filename)
+    remote_definition = kwargs.get('name')
 
     # Check extensions
     all_valid_exts = YamlFileSpec.extensions.union(RequirementsSpec.extensions)
     fname, ext = os.path.splitext(filename)
-    if ext == '' or ext not in all_valid_exts:
-        raise EnvironmentFileExtensionNotValid(filename)
-    elif ext in YamlFileSpec.extensions:
-        specs = [YamlFileSpec]
-    elif ext in RequirementsSpec.extensions:
-        specs = [RequirementsSpec]
+
+    # First check if file exists and test the known valid extension for specs
+    file_exists = filename and os.path.isfile(filename)
+    if file_exists:
+        if ext == '' or ext not in all_valid_exts:
+            raise EnvironmentFileExtensionNotValid(filename)
+        elif ext in YamlFileSpec.extensions:
+            specs = [YamlFileSpec]
+        elif ext in RequirementsSpec.extensions:
+            specs = [RequirementsSpec]
     else:
         specs = [NotebookSpec, BinstarSpec]
 
     # Check specifications
+    spec_instances = []
     for SpecClass in specs:
         spec = SpecClass(**kwargs)
+        spec_instances.append(spec)
         if spec.can_handle():
             return spec
 
-    raise SpecNotFound(build_message(specs))
+    if not file_exists and remote_definition is None:
+        raise EnvironmentFileNotFound(filename=filename)
+    else:
+        raise SpecNotFound(build_message(spec_instances))
 
 
-def build_message(specs):
-    binstar_spec = next((spec for spec in specs if isinstance(spec, BinstarSpec)), None)
+def build_message(spec_instances):
+    binstar_spec = next((s for s in spec_instances if isinstance(s, BinstarSpec)), None)
     if binstar_spec:
         return binstar_spec.msg
     else:
-        return "\n".join([s.msg for s in specs if s.msg is not None])
+        return "\n".join([s.msg for s in spec_instances if s.msg is not None])
diff --git a/conda_env/specs/binstar.py b/conda_env/specs/binstar.py
--- a/conda_env/specs/binstar.py
+++ b/conda_env/specs/binstar.py
@@ -43,10 +43,6 @@ def __init__(self, name=None, **kwargs):
 
     def can_handle(self):
         result = self._can_handle()
-        if result:
-            print("WARNING: Binstar environments are deprecated and scheduled to be "
-                  "removed in conda 4.5. See conda issue #5843 at "
-                  "https://github.com/conda/conda/pull/5843 for more information.")
         return result
 
     def _can_handle(self):
@@ -60,6 +56,7 @@ def _can_handle(self):
                 self.msg = ("Anaconda Client is required to interact with anaconda.org or an "
                             "Anaconda API. Please run `conda install anaconda-client`.")
                 return False
+
             return self.package is not None and self.valid_package()
         return False
 


Test patch:
diff --git a/tests/conda_env/test_cli.py b/tests/conda_env/test_cli.py
--- a/tests/conda_env/test_cli.py
+++ b/tests/conda_env/test_cli.py
@@ -50,6 +50,7 @@
 
 test_env_name_1 = "env-1"
 test_env_name_2 = "snowflakes"
+test_env_name_42 = "env-42"
 
 
 def escape_for_winpath(p):
@@ -86,16 +87,16 @@ def run_env_command(command, prefix, *arguments):
         command_line = "{0} -n {1} {2}".format(command, prefix, " ".join(arguments))
     elif command is Commands.ENV_CREATE: # CREATE
         if prefix :
-            command_line = "{0} -f {1}  {2}".format(command, prefix, " ".join(arguments))
+            command_line = "{0} -f {1} {2}".format(command, prefix, " ".join(arguments))
         else:
-            command_line = "{0} ".format(command)
+            command_line = "{0} {1}".format(command, " ".join(arguments))
     elif command is Commands.ENV_REMOVE:  # REMOVE
         command_line = "{0} --yes -n {1} {2}".format(command, prefix, " ".join(arguments))
     elif command is Commands.ENV_UPDATE:
         command_line = "{0} -n {1} {2}".format(command, prefix, " ".join(arguments))
     else:
         command_line = " --help "
-
+    print(command_line)
     args = p.parse_args(split(command_line))
     context._set_argparse_args(args)
 
@@ -155,6 +156,9 @@ def tearDown(self):
         if env_is_created(test_env_name_1):
             run_env_command(Commands.ENV_REMOVE, test_env_name_1)
 
+        if env_is_created(test_env_name_42):
+            run_env_command(Commands.ENV_REMOVE, test_env_name_42)
+
     def test_conda_env_create_no_file(self):
         '''
         Test `conda env create` without an environment.yml file
@@ -175,6 +179,17 @@ def test_conda_env_create_no_existent_file(self):
         except Exception as e:
             self.assertIsInstance(e, EnvironmentFileNotFound)
 
+    def test_create_valid_remote_env(self):
+        run_env_command(Commands.ENV_CREATE, None, 'goanpeca/env-42')
+        self.assertTrue(env_is_created(test_env_name_42))
+
+        o, e = run_conda_command(Commands.INFO, None, "--json")
+
+        parsed = json.loads(o)
+        self.assertNotEqual(
+            len([env for env in parsed['envs'] if env.endswith(test_env_name_42)]), 0
+        )
+
     def test_create_valid_env(self):
         '''
         Creates an environment.yml file and
@@ -203,12 +218,24 @@ def test_update(self):
         self.assertNotEqual(len(parsed), 0)
 
     def test_name(self):
+        """
         # smoke test for gh-254
+        Test that --name can overide the `name` key inside an environment.yml
+        """
         create_env(environment_1)
+        env_name = 'smoke-gh-254'
         try:
-            run_env_command(Commands.ENV_CREATE, test_env_name_1, "create")
+            run_env_command(Commands.ENV_CREATE, 'environment.yml', "-n",
+                            env_name)
         except Exception as e:
-            self.assertIsInstance(e, EnvironmentFileNotFound, str(e))
+            print(e)
+
+        o, e = run_conda_command(Commands.INFO, None, "--json")
+
+        parsed = json.loads(o)
+        self.assertNotEqual(
+            len([env for env in parsed['envs'] if env.endswith(env_name)]), 0
+        )
 
 
 def env_is_created(env_name):