Repository: facebookresearch/hydra

Issue:
[Bug] Cannot find configuration file if the file suffix is `.yml` instead of `.yaml`
# 🐛 Bug
## Description
<!-- A clear and concise description of what the bug is. -->

`.yml` is also a popular suffix for YAML file. However, the code doesn't handle it correctly and assumes that people will use `.yaml` suffix. Either this needs to be mentioned explicitly in the documentation to avoid confusion or the code has to be fixed. This is an excerpt from `hydra/plugins/config_source.py` showing how this currently is handled.

```python
@staticmethod
def _normalize_file_name(filename: str) -> str:
    if not any(filename.endswith(ext) for ext in [".yaml", ".yml"]):
        filename += ".yaml"
    return filename
```

The code above seems recognize that people use `.yml` suffix but assuming people will always use `.yaml` by appending to it? The [documentation](https://hydra.cc/docs/next/tutorials/basic/your_first_app/config_file) suggests that the users should omit the suffix.

## Checklist
- [x] I checked on the latest version of Hydra

## System information
- **Hydra Version** :  1.0.5
- **Python version** : 3.7.5



Discussion:
Supported config file extention is only .yaml.
The docs tells you that you should omit the suffix when referencing configs (config can be files, structured configs and other things).

The .yml is only supported for the primary config file, but to avoid confusion I am probably going to remove this support.

I think for new users like me that go through the docs in this flow: Tutorial -> Basic Tutorial -> Your first Hydra app -> Specifying a config file. They won't know that `.yaml` is the only supported extension as the docs doesn't say that. What I got from the docs so far is that hydra supports YAML file, as a habit, I use `.yml` and get the error.

I think one line in the docs mentioning about the config file should ended with `.yaml` extension will probably help lots of new users out there.
> I think for new users like me that go through the docs in this flow: Tutorial -> Basic Tutorial -> Your first Hydra app -> Specifying a config file. They won't know that `.yaml` is the only supported extension as the docs doesn't say that. What I got from the docs so far is that hydra supports YAML file, as a habit, I use `.yml` and get the error.
> 
> I think one line in the docs mentioning about the config file should ended with `.yaml` extension will probably help lots of new users out there.

Thank you for the suggestion! I will update our doc accordingly.

Resolving patch:
diff --git a/hydra/_internal/utils.py b/hydra/_internal/utils.py
--- a/hydra/_internal/utils.py
+++ b/hydra/_internal/utils.py
@@ -16,7 +16,7 @@
 
 from hydra._internal.config_search_path_impl import ConfigSearchPathImpl
 from hydra.core.config_search_path import ConfigSearchPath, SearchPathQuery
-from hydra.core.utils import get_valid_filename, split_config_path
+from hydra.core.utils import get_valid_filename, validate_config_path
 from hydra.errors import (
     CompactHydraException,
     InstantiationException,
@@ -310,10 +310,10 @@ def _run_hydra(
         task_name,
     ) = detect_calling_file_or_module_from_task_function(task_function)
 
-    config_dir, config_name = split_config_path(config_path, config_name)
+    validate_config_path(config_path)
 
     search_path = create_automatic_config_search_path(
-        calling_file, calling_module, config_dir
+        calling_file, calling_module, config_path
     )
 
     def add_conf_dir() -> None:
diff --git a/hydra/core/utils.py b/hydra/core/utils.py
--- a/hydra/core/utils.py
+++ b/hydra/core/utils.py
@@ -4,13 +4,13 @@
 import os
 import re
 import sys
-import warnings
 from contextlib import contextmanager
 from dataclasses import dataclass
 from datetime import datetime
-from os.path import basename, dirname, splitext
+from os.path import splitext
 from pathlib import Path
-from typing import Any, Dict, Optional, Sequence, Tuple, Union, cast
+from textwrap import dedent
+from typing import Any, Dict, Optional, Sequence, Union, cast
 
 from omegaconf import DictConfig, OmegaConf, open_dict, read_write
 
@@ -191,41 +191,17 @@ def set(self, key: str, value: Any) -> None:
         self.conf[key] = value
 
 
-def split_config_path(
-    config_path: Optional[str], config_name: Optional[str]
-) -> Tuple[Optional[str], Optional[str]]:
-    if config_path is None or config_path == "":
-        return None, config_name
-    split_file = splitext(config_path)
-    if split_file[1] in (".yaml", ".yml"):
-        # assuming dir/config.yaml form
-        config_file: Optional[str] = basename(config_path)
-        config_dir: Optional[str] = dirname(config_path)
-        # DEPRECATED: remove in 1.1
-        msg = (
-            "\nUsing config_path to specify the config name is deprecated, specify the config name via config_name"
-            "\nSee https://hydra.cc/docs/next/upgrades/0.11_to_1.0/config_path_changes"
-        )
-        warnings.warn(category=UserWarning, message=msg)
-    else:
-        # assuming dir form without a config file.
-        config_file = None
-        config_dir = config_path
-
-    if config_dir == "":
-        config_dir = None
-
-    if config_file == "":
-        config_file = None
-
-    if config_file is not None:
-        if config_name is not None:
-            raise ValueError(
-                "Config name should be specified in either normalized_config_path or config_name, but not both"
+def validate_config_path(config_path: Optional[str]) -> None:
+    if config_path is not None:
+        split_file = splitext(config_path)
+        if split_file[1] in (".yaml", ".yml"):
+            msg = dedent(
+                """\
+            Using config_path to specify the config name is not supported, specify the config name via config_name.
+            See https://hydra.cc/docs/next/upgrades/0.11_to_1.0/config_path_changes
+            """
             )
-        config_name = config_file
-
-    return config_dir, config_name
+            raise ValueError(msg)
 
 
 @contextmanager
diff --git a/hydra/plugins/config_source.py b/hydra/plugins/config_source.py
--- a/hydra/plugins/config_source.py
+++ b/hydra/plugins/config_source.py
@@ -1,4 +1,5 @@
 # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
+import warnings
 import re
 
 from abc import abstractmethod
@@ -116,6 +117,11 @@ def full_path(self) -> str:
 
     @staticmethod
     def _normalize_file_name(filename: str) -> str:
+        if filename.endswith(".yml"):
+            # DEPRECATED: remove in 1.2
+            warnings.warn(
+                "Support for .yml files is deprecated. Use .yaml extension for Hydra config files"
+            )
         if not any(filename.endswith(ext) for ext in [".yaml", ".yml"]):
             filename += ".yaml"
         return filename


Test patch:
diff --git a/hydra/test_utils/test_utils.py b/hydra/test_utils/test_utils.py
--- a/hydra/test_utils/test_utils.py
+++ b/hydra/test_utils/test_utils.py
@@ -23,7 +23,7 @@
 from hydra._internal.hydra import Hydra
 from hydra._internal.utils import detect_task_name
 from hydra.core.global_hydra import GlobalHydra
-from hydra.core.utils import JobReturn, split_config_path
+from hydra.core.utils import JobReturn, validate_config_path
 from hydra.types import TaskFunction
 
 
@@ -58,16 +58,14 @@ def __call__(self, cfg: DictConfig) -> Any:
 
     def __enter__(self) -> "TaskTestFunction":
         try:
-            config_dir, config_name = split_config_path(
-                self.config_path, self.config_name
-            )
+            validate_config_path(self.config_path)
 
             job_name = detect_task_name(self.calling_file, self.calling_module)
 
             self.hydra = Hydra.create_main_hydra_file_or_module(
                 calling_file=self.calling_file,
                 calling_module=self.calling_module,
-                config_path=config_dir,
+                config_path=self.config_path,
                 job_name=job_name,
                 strict=self.strict,
             )
@@ -76,7 +74,7 @@ def __enter__(self) -> "TaskTestFunction":
             assert overrides is not None
             overrides.append(f"hydra.run.dir={self.temp_dir}")
             self.job_ret = self.hydra.run(
-                config_name=config_name,
+                config_name=self.config_name,
                 task_function=self,
                 overrides=overrides,
                 with_log_configuration=self.configure_logging,
@@ -146,21 +144,19 @@ def __enter__(self) -> "SweepTaskFunction":
         overrides.append(f"hydra.sweep.dir={self.temp_dir}")
 
         try:
-            config_dir, config_name = split_config_path(
-                self.config_path, self.config_name
-            )
+            validate_config_path(self.config_path)
             job_name = detect_task_name(self.calling_file, self.calling_module)
 
             hydra_ = Hydra.create_main_hydra_file_or_module(
                 calling_file=self.calling_file,
                 calling_module=self.calling_module,
-                config_path=config_dir,
+                config_path=self.config_path,
                 job_name=job_name,
                 strict=self.strict,
             )
 
             self.returns = hydra_.multirun(
-                config_name=config_name,
+                config_name=self.config_name,
                 task_function=self,
                 overrides=overrides,
                 with_log_configuration=self.configure_logging,
diff --git a/tests/test_config_loader.py b/tests/test_config_loader.py
--- a/tests/test_config_loader.py
+++ b/tests/test_config_loader.py
@@ -202,9 +202,17 @@ def test_load_yml_file(self, path: str) -> None:
         config_loader = ConfigLoaderImpl(
             config_search_path=create_config_search_path(path)
         )
-        cfg = config_loader.load_configuration(
-            config_name="config.yml", overrides=[], strict=False, run_mode=RunMode.RUN
-        )
+        with pytest.warns(
+            UserWarning,
+            match="Support for .yml files is deprecated. Use .yaml extension for Hydra config files",
+        ):
+            cfg = config_loader.load_configuration(
+                config_name="config.yml",
+                overrides=[],
+                strict=False,
+                run_mode=RunMode.RUN,
+            )
+
         with open_dict(cfg):
             del cfg["hydra"]
 
diff --git a/tests/test_hydra.py b/tests/test_hydra.py
--- a/tests/test_hydra.py
+++ b/tests/test_hydra.py
@@ -186,12 +186,14 @@ def test_app_with_config_path_backward_compatibility(
     calling_file: str,
     calling_module: str,
 ) -> None:
-    msg = (
-        "\nUsing config_path to specify the config name is deprecated, specify the config name via config_name"
-        "\nSee https://hydra.cc/docs/next/upgrades/0.11_to_1.0/config_path_changes"
+    msg = dedent(
+        """\
+    Using config_path to specify the config name is not supported, specify the config name via config_name.
+    See https://hydra.cc/docs/next/upgrades/0.11_to_1.0/config_path_changes
+    """
     )
 
-    with pytest.warns(expected_warning=UserWarning, match=re.escape(msg)):
+    with pytest.raises(ValueError, match=re.escape(msg)):
         task = hydra_task_runner(
             calling_file=calling_file,
             calling_module=calling_module,