Repository: mkdocs/mkdocs

Issue:
Allow mkdocs.yaml config file (.yaml extension)
Even though `.yml` is commonly used, `.yaml` is actually preferred:

https://yaml.org/faq.html

> Is there an official extension for YAML files?
>
> Please use ".yaml" when possible.

It would therefore be great if you would allow `mkdocs.yaml`.

Somewhat related t #2164

Allow mkdocs.yaml when '--config' is not passed
We wanted to give our colleagues to possibility to build docs automatically when they put a `mkdocs.yml` in the docs folder of their repository. But it happened often, that they used `.yaml` instead the `.yml`.

When this PR is accepted, it will look first look for `mkdocs.yml` when `--config` is not provided. If this file is not present, it will try to find `mkdocs.yaml`.
When both are not present, it behaves like before.
When both are present, it behaves like before.
If only the `.yaml` version it present, this one will be used as the config file.


Discussion:

Resolving patch:
diff --git a/mkdocs/config/base.py b/mkdocs/config/base.py
--- a/mkdocs/config/base.py
+++ b/mkdocs/config/base.py
@@ -156,24 +156,34 @@ def _open_config_file(config_file):
 
     # Default to the standard config filename.
     if config_file is None:
-        config_file = os.path.abspath('mkdocs.yml')
-
-    # If closed file descriptor, get file path to reopen later.
-    if hasattr(config_file, 'closed') and config_file.closed:
-        config_file = config_file.name
-
-    log.debug(f"Loading configuration file: {config_file}")
-
+        paths_to_try = ['mkdocs.yml', 'mkdocs.yaml']
     # If it is a string, we can assume it is a path and attempt to open it.
-    if isinstance(config_file, str):
-        if os.path.exists(config_file):
-            config_file = open(config_file, 'rb')
+    elif isinstance(config_file, str):
+        paths_to_try = [config_file]
+    # If closed file descriptor, get file path to reopen later.
+    elif getattr(config_file, 'closed', False):
+        paths_to_try = [config_file.name]
+    else:
+        paths_to_try = None
+
+    if paths_to_try:
+        # config_file is not a file descriptor, so open it as a path.
+        for path in paths_to_try:
+            path = os.path.abspath(path)
+            log.debug(f"Loading configuration file: {path}")
+            try:
+                config_file = open(path, 'rb')
+                break
+            except FileNotFoundError:
+                continue
         else:
             raise exceptions.ConfigurationError(
-                f"Config file '{config_file}' does not exist.")
+                f"Config file '{paths_to_try[0]}' does not exist.")
+    else:
+        log.debug(f"Loading configuration file: {config_file}")
+        # Ensure file descriptor is at begining
+        config_file.seek(0)
 
-    # Ensure file descriptor is at begining
-    config_file.seek(0)
     try:
         yield config_file
     finally:


Test patch:
diff --git a/mkdocs/tests/config/base_tests.py b/mkdocs/tests/config/base_tests.py
--- a/mkdocs/tests/config/base_tests.py
+++ b/mkdocs/tests/config/base_tests.py
@@ -55,7 +55,76 @@ def test_load_from_file(self):
             self.assertTrue(isinstance(cfg, base.Config))
             self.assertEqual(cfg['site_name'], 'MkDocs Test')
         finally:
-            os.remove(config_file.name)
+            temp_dir.cleanup()
+
+    def test_load_default_file(self):
+        """
+        test that `mkdocs.yml` will be loaded when '--config' is not set.
+        """
+
+        temp_dir = TemporaryDirectory()
+        config_file = open(os.path.join(temp_dir.name, 'mkdocs.yml'), 'w')
+        os.mkdir(os.path.join(temp_dir.name, 'docs'))
+        old_dir = os.getcwd()
+        try:
+            os.chdir(temp_dir.name)
+            config_file.write("site_name: MkDocs Test\n")
+            config_file.flush()
+            config_file.close()
+
+            cfg = base.load_config(config_file=None)
+            self.assertTrue(isinstance(cfg, base.Config))
+            self.assertEqual(cfg['site_name'], 'MkDocs Test')
+        finally:
+            os.chdir(old_dir)
+            temp_dir.cleanup()
+
+    def test_load_default_file_with_yaml(self):
+        """
+        test that `mkdocs.yml` will be loaded when '--config' is not set.
+        """
+
+        temp_dir = TemporaryDirectory()
+        config_file = open(os.path.join(temp_dir.name, 'mkdocs.yaml'), 'w')
+        os.mkdir(os.path.join(temp_dir.name, 'docs'))
+        old_dir = os.getcwd()
+        try:
+            os.chdir(temp_dir.name)
+            config_file.write("site_name: MkDocs Test\n")
+            config_file.flush()
+            config_file.close()
+
+            cfg = base.load_config(config_file=None)
+            self.assertTrue(isinstance(cfg, base.Config))
+            self.assertEqual(cfg['site_name'], 'MkDocs Test')
+        finally:
+            os.chdir(old_dir)
+            temp_dir.cleanup()
+
+    def test_load_default_file_prefer_yml(self):
+        """
+        test that `mkdocs.yml` will be loaded when '--config' is not set.
+        """
+
+        temp_dir = TemporaryDirectory()
+        config_file1 = open(os.path.join(temp_dir.name, 'mkdocs.yml'), 'w')
+        config_file2 = open(os.path.join(temp_dir.name, 'mkdocs.yaml'), 'w')
+        os.mkdir(os.path.join(temp_dir.name, 'docs'))
+        old_dir = os.getcwd()
+        try:
+            os.chdir(temp_dir.name)
+            config_file1.write("site_name: MkDocs Test1\n")
+            config_file1.flush()
+            config_file1.close()
+            config_file2.write("site_name: MkDocs Test2\n")
+            config_file2.flush()
+            config_file2.close()
+
+            cfg = base.load_config(config_file=None)
+            self.assertTrue(isinstance(cfg, base.Config))
+            self.assertEqual(cfg['site_name'], 'MkDocs Test1')
+        finally:
+            os.chdir(old_dir)
             temp_dir.cleanup()
 
     def test_load_from_missing_file(self):