prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Exit gracefully when misconfigured
  Currently if `mkdocs.yaml` does not exist or if `pages`/`project_name` are not set, we'll exit with an exception.  Really we should print a simple error to stderr and exit with an appropriate error code.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `mkdocs/config.py`
  Content:
  ```
  1 # coding: utf-8
  2 
  3 from mkdocs import utils
  4 from mkdocs.compat import urlparse
  5 import os
  6 import yaml
  7 
  8 DEFAULT_CONFIG = {
  9     'site_name': None,
  10     'pages': None,
  11 
  12     'site_url': None,
  13     'site_description': None,
  14     'site_author': None,
  15     'site_favicon': None,
  16 
  17     'theme': 'mkdocs',
  18     'docs_dir': 'docs',
  19     'site_dir': 'site',
  20     'theme_dir': None,
  21 
  22     'copyright': None,
  23     'google-analytics': None,
  24 
  25     # The address on which to serve the livereloading docs server.
  26     'dev_addr': '127.0.0.1:8000',
  27 
  28     # If `True`, use `<page_name>/index.hmtl` style files with hyperlinks to the directory.
  29     # If `False`, use `<page_name>.html style file with hyperlinks to the file.
  30     # True generates nicer URLs, but False is useful if browsing the output on a filesystem.
  31     'use_directory_urls': True,
  32 
  33     # Specify a link to the project source repo to be included
  34     # in the documentation pages.
  35     'repo_url': None,
  36 
  37     # A name to use for the link to the project source repo.
  38     # Default: If repo_url is unset then None, otherwise
  39     # "GitHub" or "Bitbucket" for known url or Hostname for unknown urls.
  40     'repo_name': None,
  41 
  42     # Specify which css or javascript files from the docs
  43     # directionary should be additionally included in the site.
  44     # Default: List of all .css and .js files in the docs dir.
  45     'extra_css': None,
  46     'extra_javascript': None,
  47 
  48     # Determine if the site should include the nav and next/prev elements.
  49     # Default: True if the site has more than one page, False otherwise.
  50     'include_nav': None,
  51     'include_next_prev': None,
  52 
  53     # PyMarkdown extension names.
  54     'markdown_extensions': (),
  55 
  56     # Determine if the site should generate a json search index and include
  57     # search elements in the theme. - TODO
  58     'include_search': False,
  59 
  60     # Determine if the site should include a 404.html page.
  61     # TODO: Implment this. Make this None, have it True if a 404.html
  62     # template exists in the theme or docs dir.
  63     'include_404': False,
  64 
  65     # Determine if the site should include a sitemap.xml page.
  66     # TODO: Implement this. Make this None, have it True if a sitemap.xml
  67     # template exists in the theme or docs dir.
  68     'include_sitemap': False,
  69 }
  70 
  71 
  72 def load_config(filename='mkdocs.yml', options=None):
  73     options = options or {}
  74     if 'config' in options:
  75         filename = options['config']
  76     assert os.path.exists(filename), "Config file '%s' does not exist." % filename
  77     with open(filename, 'r') as fp:
  78         user_config = yaml.load(fp)
  79     user_config.update(options)
  80     return validate_config(user_config)
  81 
  82 
  83 def validate_config(user_config):
  84     config = DEFAULT_CONFIG.copy()
  85     config.update(user_config)
  86 
  87     assert config['site_name'], "Config must contain 'site_name' setting."
  88 
  89     # If not specified, then the 'pages' config simply includes all
  90     # markdown files in the docs dir, without generating any header items
  91     # for them.
  92     pages = []
  93     extra_css = []
  94     extra_javascript = []
  95     for (dirpath, dirnames, filenames) in os.walk(config['docs_dir']):
  96         for filename in sorted(filenames):
  97             fullpath = os.path.join(dirpath, filename)
  98             relpath = os.path.relpath(fullpath, config['docs_dir'])
  99 
  100             if utils.is_markdown_file(filename):
  101                 # index pages should always be the first listed page.
  102                 if os.path.splitext(relpath)[0] == 'index':
  103                     pages.insert(0, relpath)
  104                 else:
  105                     pages.append(relpath)
  106             elif utils.is_css_file(filename):
  107                 extra_css.append(relpath)
  108             elif utils.is_javascript_file(filename):
  109                 extra_javascript.append(relpath)
  110 
  111     if config['pages'] is None:
  112         config['pages'] = pages
  113 
  114     if config['extra_css'] is None:
  115         config['extra_css'] = extra_css
  116 
  117     if config['extra_javascript'] is None:
  118         config['extra_javascript'] = extra_javascript
  119 
  120     package_dir = os.path.dirname(__file__)
  121     theme_dir = [os.path.join(package_dir, 'themes', config['theme'])]
  122 
  123     if config['theme_dir'] is not None:
  124         theme_dir.insert(0, config['theme_dir'])
  125 
  126     config['theme_dir'] = theme_dir
  127 
  128     if config['repo_url'] is not None and config['repo_name'] is None:
  129         repo_host = urlparse(config['repo_url']).netloc.lower()
  130         if repo_host == 'github.com':
  131             config['repo_name'] = 'GitHub'
  132         elif repo_host == 'bitbucket.com':
  133             config['repo_name'] = 'Bitbucket'
  134         else:
  135             config['repo_name'] = repo_host.split('.')[0].title()
  136 
  137     if config['include_next_prev'] is None:
  138         config['include_next_prev'] = len(config['pages']) > 1
  139 
  140     if config['include_nav'] is None:
  141         config['include_nav'] = len(config['pages']) > 1
  142 
  143     # To Do:
  144 
  145     # The docs dir must exist.
  146     # The theme dir must exist.
  147     # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'
  148     # A homepage 'index' must exist.
  149     # The theme 'base.html' file must exist.
  150     # Cannot set repo_name without setting repo_url.
  151     # Cannot set 'include_next_prev: true' when only one page exists.
  152     # Cannot set 'include_nav: true' when only one page exists.
  153     # Error if any config keys provided that are not in the DEFAULT_CONFIG.
  154 
  155     return config
  156
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/mkdocs/config.py b/mkdocs/config.py
  --- a/mkdocs/config.py
  +++ b/mkdocs/config.py
  @@ -2,7 +2,9 @@
   
   from mkdocs import utils
   from mkdocs.compat import urlparse
  +import errno
   import os
  +import sys
   import yaml
   
   DEFAULT_CONFIG = {
  @@ -73,7 +75,9 @@
       options = options or {}
       if 'config' in options:
           filename = options['config']
  -    assert os.path.exists(filename), "Config file '%s' does not exist." % filename
  +    if not os.path.exists(filename):
  +        sys.stderr.write("Config file '%s' does not exist." % filename)
  +        sys.exit(errno.ENOENT)
       with open(filename, 'r') as fp:
           user_config = yaml.load(fp)
       user_config.update(options)
  @@ -84,7 +88,9 @@
       config = DEFAULT_CONFIG.copy()
       config.update(user_config)
   
  -    assert config['site_name'], "Config must contain 'site_name' setting."
  +    if not config['site_name']:
  +        sys.stderr.write("Config must contain 'site_name' setting.")
  +        sys.exit(errno.EINVAL)
   
       # If not specified, then the 'pages' config simply includes all
       # markdown files in the docs dir, without generating any header items
  
verification_info: {"golden_diff": "diff --git a/mkdocs/config.py b/mkdocs/config.py\n--- a/mkdocs/config.py\n+++ b/mkdocs/config.py\n@@ -2,7 +2,9 @@\n \n from mkdocs import utils\n from mkdocs.compat import urlparse\n+import errno\n import os\n+import sys\n import yaml\n \n DEFAULT_CONFIG = {\n@@ -73,7 +75,9 @@\n     options = options or {}\n     if 'config' in options:\n         filename = options['config']\n-    assert os.path.exists(filename), \"Config file '%s' does not exist.\" % filename\n+    if not os.path.exists(filename):\n+        sys.stderr.write(\"Config file '%s' does not exist.\" % filename)\n+        sys.exit(errno.ENOENT)\n     with open(filename, 'r') as fp:\n         user_config = yaml.load(fp)\n     user_config.update(options)\n@@ -84,7 +88,9 @@\n     config = DEFAULT_CONFIG.copy()\n     config.update(user_config)\n \n-    assert config['site_name'], \"Config must contain 'site_name' setting.\"\n+    if not config['site_name']:\n+        sys.stderr.write(\"Config must contain 'site_name' setting.\")\n+        sys.exit(errno.EINVAL)\n \n     # If not specified, then the 'pages' config simply includes all\n     # markdown files in the docs dir, without generating any header items\n", "issue": "Exit gracefully when misconfigured\nCurrently if `mkdocs.yaml` does not exist or if `pages`/`project_name` are not set, we'll exit with an exception.  Really we should print a simple error to stderr and exit with an appropriate error code.\n\n", "before_files": [{"content": "# coding: utf-8\n\nfrom mkdocs import utils\nfrom mkdocs.compat import urlparse\nimport os\nimport yaml\n\nDEFAULT_CONFIG = {\n    'site_name': None,\n    'pages': None,\n\n    'site_url': None,\n    'site_description': None,\n    'site_author': None,\n    'site_favicon': None,\n\n    'theme': 'mkdocs',\n    'docs_dir': 'docs',\n    'site_dir': 'site',\n    'theme_dir': None,\n\n    'copyright': None,\n    'google-analytics': None,\n\n    # The address on which to serve the livereloading docs server.\n    'dev_addr': '127.0.0.1:8000',\n\n    # If `True`, use `<page_name>/index.hmtl` style files with hyperlinks to the directory.\n    # If `False`, use `<page_name>.html style file with hyperlinks to the file.\n    # True generates nicer URLs, but False is useful if browsing the output on a filesystem.\n    'use_directory_urls': True,\n\n    # Specify a link to the project source repo to be included\n    # in the documentation pages.\n    'repo_url': None,\n\n    # A name to use for the link to the project source repo.\n    # Default: If repo_url is unset then None, otherwise\n    # \"GitHub\" or \"Bitbucket\" for known url or Hostname for unknown urls.\n    'repo_name': None,\n\n    # Specify which css or javascript files from the docs\n    # directionary should be additionally included in the site.\n    # Default: List of all .css and .js files in the docs dir.\n    'extra_css': None,\n    'extra_javascript': None,\n\n    # Determine if the site should include the nav and next/prev elements.\n    # Default: True if the site has more than one page, False otherwise.\n    'include_nav': None,\n    'include_next_prev': None,\n\n    # PyMarkdown extension names.\n    'markdown_extensions': (),\n\n    # Determine if the site should generate a json search index and include\n    # search elements in the theme. - TODO\n    'include_search': False,\n\n    # Determine if the site should include a 404.html page.\n    # TODO: Implment this. Make this None, have it True if a 404.html\n    # template exists in the theme or docs dir.\n    'include_404': False,\n\n    # Determine if the site should include a sitemap.xml page.\n    # TODO: Implement this. Make this None, have it True if a sitemap.xml\n    # template exists in the theme or docs dir.\n    'include_sitemap': False,\n}\n\n\ndef load_config(filename='mkdocs.yml', options=None):\n    options = options or {}\n    if 'config' in options:\n        filename = options['config']\n    assert os.path.exists(filename), \"Config file '%s' does not exist.\" % filename\n    with open(filename, 'r') as fp:\n        user_config = yaml.load(fp)\n    user_config.update(options)\n    return validate_config(user_config)\n\n\ndef validate_config(user_config):\n    config = DEFAULT_CONFIG.copy()\n    config.update(user_config)\n\n    assert config['site_name'], \"Config must contain 'site_name' setting.\"\n\n    # If not specified, then the 'pages' config simply includes all\n    # markdown files in the docs dir, without generating any header items\n    # for them.\n    pages = []\n    extra_css = []\n    extra_javascript = []\n    for (dirpath, dirnames, filenames) in os.walk(config['docs_dir']):\n        for filename in sorted(filenames):\n            fullpath = os.path.join(dirpath, filename)\n            relpath = os.path.relpath(fullpath, config['docs_dir'])\n\n            if utils.is_markdown_file(filename):\n                # index pages should always be the first listed page.\n                if os.path.splitext(relpath)[0] == 'index':\n                    pages.insert(0, relpath)\n                else:\n                    pages.append(relpath)\n            elif utils.is_css_file(filename):\n                extra_css.append(relpath)\n            elif utils.is_javascript_file(filename):\n                extra_javascript.append(relpath)\n\n    if config['pages'] is None:\n        config['pages'] = pages\n\n    if config['extra_css'] is None:\n        config['extra_css'] = extra_css\n\n    if config['extra_javascript'] is None:\n        config['extra_javascript'] = extra_javascript\n\n    package_dir = os.path.dirname(__file__)\n    theme_dir = [os.path.join(package_dir, 'themes', config['theme'])]\n\n    if config['theme_dir'] is not None:\n        theme_dir.insert(0, config['theme_dir'])\n\n    config['theme_dir'] = theme_dir\n\n    if config['repo_url'] is not None and config['repo_name'] is None:\n        repo_host = urlparse(config['repo_url']).netloc.lower()\n        if repo_host == 'github.com':\n            config['repo_name'] = 'GitHub'\n        elif repo_host == 'bitbucket.com':\n            config['repo_name'] = 'Bitbucket'\n        else:\n            config['repo_name'] = repo_host.split('.')[0].title()\n\n    if config['include_next_prev'] is None:\n        config['include_next_prev'] = len(config['pages']) > 1\n\n    if config['include_nav'] is None:\n        config['include_nav'] = len(config['pages']) > 1\n\n    # To Do:\n\n    # The docs dir must exist.\n    # The theme dir must exist.\n    # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'\n    # A homepage 'index' must exist.\n    # The theme 'base.html' file must exist.\n    # Cannot set repo_name without setting repo_url.\n    # Cannot set 'include_next_prev: true' when only one page exists.\n    # Cannot set 'include_nav: true' when only one page exists.\n    # Error if any config keys provided that are not in the DEFAULT_CONFIG.\n\n    return config\n", "path": "mkdocs/config.py"}], "after_files": [{"content": "# coding: utf-8\n\nfrom mkdocs import utils\nfrom mkdocs.compat import urlparse\nimport errno\nimport os\nimport sys\nimport yaml\n\nDEFAULT_CONFIG = {\n    'site_name': None,\n    'pages': None,\n\n    'site_url': None,\n    'site_description': None,\n    'site_author': None,\n    'site_favicon': None,\n\n    'theme': 'mkdocs',\n    'docs_dir': 'docs',\n    'site_dir': 'site',\n    'theme_dir': None,\n\n    'copyright': None,\n    'google-analytics': None,\n\n    # The address on which to serve the livereloading docs server.\n    'dev_addr': '127.0.0.1:8000',\n\n    # If `True`, use `<page_name>/index.hmtl` style files with hyperlinks to the directory.\n    # If `False`, use `<page_name>.html style file with hyperlinks to the file.\n    # True generates nicer URLs, but False is useful if browsing the output on a filesystem.\n    'use_directory_urls': True,\n\n    # Specify a link to the project source repo to be included\n    # in the documentation pages.\n    'repo_url': None,\n\n    # A name to use for the link to the project source repo.\n    # Default: If repo_url is unset then None, otherwise\n    # \"GitHub\" or \"Bitbucket\" for known url or Hostname for unknown urls.\n    'repo_name': None,\n\n    # Specify which css or javascript files from the docs\n    # directionary should be additionally included in the site.\n    # Default: List of all .css and .js files in the docs dir.\n    'extra_css': None,\n    'extra_javascript': None,\n\n    # Determine if the site should include the nav and next/prev elements.\n    # Default: True if the site has more than one page, False otherwise.\n    'include_nav': None,\n    'include_next_prev': None,\n\n    # PyMarkdown extension names.\n    'markdown_extensions': (),\n\n    # Determine if the site should generate a json search index and include\n    # search elements in the theme. - TODO\n    'include_search': False,\n\n    # Determine if the site should include a 404.html page.\n    # TODO: Implment this. Make this None, have it True if a 404.html\n    # template exists in the theme or docs dir.\n    'include_404': False,\n\n    # Determine if the site should include a sitemap.xml page.\n    # TODO: Implement this. Make this None, have it True if a sitemap.xml\n    # template exists in the theme or docs dir.\n    'include_sitemap': False,\n}\n\n\ndef load_config(filename='mkdocs.yml', options=None):\n    options = options or {}\n    if 'config' in options:\n        filename = options['config']\n    if not os.path.exists(filename):\n        sys.stderr.write(\"Config file '%s' does not exist.\" % filename)\n        sys.exit(errno.ENOENT)\n    with open(filename, 'r') as fp:\n        user_config = yaml.load(fp)\n    user_config.update(options)\n    return validate_config(user_config)\n\n\ndef validate_config(user_config):\n    config = DEFAULT_CONFIG.copy()\n    config.update(user_config)\n\n    if not config['site_name']:\n        sys.stderr.write(\"Config must contain 'site_name' setting.\")\n        sys.exit(errno.EINVAL)\n\n    # If not specified, then the 'pages' config simply includes all\n    # markdown files in the docs dir, without generating any header items\n    # for them.\n    pages = []\n    extra_css = []\n    extra_javascript = []\n    for (dirpath, dirnames, filenames) in os.walk(config['docs_dir']):\n        for filename in sorted(filenames):\n            fullpath = os.path.join(dirpath, filename)\n            relpath = os.path.relpath(fullpath, config['docs_dir'])\n\n            if utils.is_markdown_file(filename):\n                # index pages should always be the first listed page.\n                if os.path.splitext(relpath)[0] == 'index':\n                    pages.insert(0, relpath)\n                else:\n                    pages.append(relpath)\n            elif utils.is_css_file(filename):\n                extra_css.append(relpath)\n            elif utils.is_javascript_file(filename):\n                extra_javascript.append(relpath)\n\n    if config['pages'] is None:\n        config['pages'] = pages\n\n    if config['extra_css'] is None:\n        config['extra_css'] = extra_css\n\n    if config['extra_javascript'] is None:\n        config['extra_javascript'] = extra_javascript\n\n    package_dir = os.path.dirname(__file__)\n    theme_dir = [os.path.join(package_dir, 'themes', config['theme'])]\n\n    if config['theme_dir'] is not None:\n        theme_dir.insert(0, config['theme_dir'])\n\n    config['theme_dir'] = theme_dir\n\n    if config['repo_url'] is not None and config['repo_name'] is None:\n        repo_host = urlparse(config['repo_url']).netloc.lower()\n        if repo_host == 'github.com':\n            config['repo_name'] = 'GitHub'\n        elif repo_host == 'bitbucket.com':\n            config['repo_name'] = 'Bitbucket'\n        else:\n            config['repo_name'] = repo_host.split('.')[0].title()\n\n    if config['include_next_prev'] is None:\n        config['include_next_prev'] = len(config['pages']) > 1\n\n    if config['include_nav'] is None:\n        config['include_nav'] = len(config['pages']) > 1\n\n    # To Do:\n\n    # The docs dir must exist.\n    # The theme dir must exist.\n    # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'\n    # A homepage 'index' must exist.\n    # The theme 'base.html' file must exist.\n    # Cannot set repo_name without setting repo_url.\n    # Cannot set 'include_next_prev: true' when only one page exists.\n    # Cannot set 'include_nav: true' when only one page exists.\n    # Error if any config keys provided that are not in the DEFAULT_CONFIG.\n\n    return config\n", "path": "mkdocs/config.py"}]}