We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
CATEGORIES_URL doesn't honor it's default value
First of all, thanks for this great software. But, when I'm using the variable CATEGORIES_URL in templates (category.html), it doesn't have it's default value (as said on the documentation: CATEGORIES_URL ('categories/')). I need to explicitly set this value in pelican.conf. I'm using Pelican 3.3.0

Thanks


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pelican/settings.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 from __future__ import unicode_literals, print_function
3 import six
4 
5 import copy
6 import inspect
7 import os
8 import locale
9 import logging
10 
11 try:
12     # SourceFileLoader is the recommended way in 3.3+
13     from importlib.machinery import SourceFileLoader
14     load_source = lambda name, path: SourceFileLoader(name, path).load_module()
15 except ImportError:
16     # but it does not exist in 3.2-, so fall back to imp
17     import imp
18     load_source = imp.load_source
19 
20 from os.path import isabs
21 
22 
23 logger = logging.getLogger(__name__)
24 
25 
26 DEFAULT_THEME = os.path.join(os.path.dirname(os.path.abspath(__file__)),
27                              'themes', 'notmyidea')
28 DEFAULT_CONFIG = {
29     'PATH': os.curdir,
30     'ARTICLE_DIR': '',
31     'ARTICLE_EXCLUDES': ('pages',),
32     'PAGE_DIR': 'pages',
33     'PAGE_EXCLUDES': (),
34     'THEME': DEFAULT_THEME,
35     'OUTPUT_PATH': 'output',
36     'READERS': {},
37     'STATIC_PATHS': ['images', ],
38     'THEME_STATIC_DIR': 'theme',
39     'THEME_STATIC_PATHS': ['static', ],
40     'FEED_ALL_ATOM': os.path.join('feeds', 'all.atom.xml'),
41     'CATEGORY_FEED_ATOM': os.path.join('feeds', '%s.atom.xml'),
42     'TRANSLATION_FEED_ATOM': os.path.join('feeds', 'all-%s.atom.xml'),
43     'FEED_MAX_ITEMS': '',
44     'SITEURL': '',
45     'SITENAME': 'A Pelican Blog',
46     'DISPLAY_PAGES_ON_MENU': True,
47     'DISPLAY_CATEGORIES_ON_MENU': True,
48     'OUTPUT_SOURCES': False,
49     'OUTPUT_SOURCES_EXTENSION': '.text',
50     'USE_FOLDER_AS_CATEGORY': True,
51     'DEFAULT_CATEGORY': 'misc',
52     'WITH_FUTURE_DATES': True,
53     'CSS_FILE': 'main.css',
54     'NEWEST_FIRST_ARCHIVES': True,
55     'REVERSE_CATEGORY_ORDER': False,
56     'DELETE_OUTPUT_DIRECTORY': False,
57     'OUTPUT_RETENTION': (),
58     'ARTICLE_URL': '{slug}.html',
59     'ARTICLE_SAVE_AS': '{slug}.html',
60     'ARTICLE_LANG_URL': '{slug}-{lang}.html',
61     'ARTICLE_LANG_SAVE_AS': '{slug}-{lang}.html',
62     'PAGE_URL': 'pages/{slug}.html',
63     'PAGE_SAVE_AS': os.path.join('pages', '{slug}.html'),
64     'PAGE_LANG_URL': 'pages/{slug}-{lang}.html',
65     'PAGE_LANG_SAVE_AS': os.path.join('pages', '{slug}-{lang}.html'),
66     'STATIC_URL': '{path}',
67     'STATIC_SAVE_AS': '{path}',
68     'PDF_GENERATOR': False,
69     'PDF_STYLE_PATH': '',
70     'PDF_STYLE': 'twelvepoint',
71     'CATEGORY_URL': 'category/{slug}.html',
72     'CATEGORY_SAVE_AS': os.path.join('category', '{slug}.html'),
73     'TAG_URL': 'tag/{slug}.html',
74     'TAG_SAVE_AS': os.path.join('tag', '{slug}.html'),
75     'AUTHOR_URL': 'author/{slug}.html',
76     'AUTHOR_SAVE_AS': os.path.join('author', '{slug}.html'),
77     'PAGINATION_PATTERNS': [
78         (0, '{name}{number}.html', '{name}{number}.html'),
79     ],
80     'YEAR_ARCHIVE_SAVE_AS': False,
81     'MONTH_ARCHIVE_SAVE_AS': False,
82     'DAY_ARCHIVE_SAVE_AS': False,
83     'RELATIVE_URLS': False,
84     'DEFAULT_LANG': 'en',
85     'TAG_CLOUD_STEPS': 4,
86     'TAG_CLOUD_MAX_ITEMS': 100,
87     'DIRECT_TEMPLATES': ('index', 'tags', 'categories', 'authors', 'archives'),
88     'EXTRA_TEMPLATES_PATHS': [],
89     'PAGINATED_DIRECT_TEMPLATES': ('index', ),
90     'PELICAN_CLASS': 'pelican.Pelican',
91     'DEFAULT_DATE_FORMAT': '%a %d %B %Y',
92     'DATE_FORMATS': {},
93     'ASCIIDOC_OPTIONS': [],
94     'MD_EXTENSIONS': ['codehilite(css_class=highlight)', 'extra'],
95     'JINJA_EXTENSIONS': [],
96     'JINJA_FILTERS': {},
97     'LOCALE': [''],  # defaults to user locale
98     'DEFAULT_PAGINATION': False,
99     'DEFAULT_ORPHANS': 0,
100     'DEFAULT_METADATA': (),
101     'FILENAME_METADATA': '(?P<date>\d{4}-\d{2}-\d{2}).*',
102     'PATH_METADATA': '',
103     'EXTRA_PATH_METADATA': {},
104     'DEFAULT_STATUS': 'published',
105     'ARTICLE_PERMALINK_STRUCTURE': '',
106     'TYPOGRIFY': False,
107     'SUMMARY_MAX_LENGTH': 50,
108     'PLUGIN_PATH': '',
109     'PLUGINS': [],
110     'PYGMENTS_RST_OPTIONS': {},
111     'TEMPLATE_PAGES': {},
112     'IGNORE_FILES': ['.#*'],
113     'SLUG_SUBSTITUTIONS': (),
114     'INTRASITE_LINK_REGEX': '[{|](?P<what>.*?)[|}]',
115     }
116 
117 PYGMENTS_RST_OPTIONS = None
118 
119 
120 def read_settings(path=None, override=None):
121     if path:
122         local_settings = get_settings_from_file(path)
123         # Make the paths relative to the settings file
124         for p in ['PATH', 'OUTPUT_PATH', 'THEME', 'PLUGIN_PATH']:
125             if p in local_settings and local_settings[p] is not None \
126                     and not isabs(local_settings[p]):
127                 absp = os.path.abspath(os.path.normpath(os.path.join(
128                     os.path.dirname(path), local_settings[p])))
129                 if p not in ('THEME', 'PLUGIN_PATH') or os.path.exists(absp):
130                     local_settings[p] = absp
131     else:
132         local_settings = copy.deepcopy(DEFAULT_CONFIG)
133 
134     if override:
135         local_settings.update(override)
136 
137     parsed_settings = configure_settings(local_settings)
138     # This is because there doesn't seem to be a way to pass extra
139     # parameters to docutils directive handlers, so we have to have a
140     # variable here that we'll import from within Pygments.run (see
141     # rstdirectives.py) to see what the user defaults were.
142     global PYGMENTS_RST_OPTIONS
143     PYGMENTS_RST_OPTIONS = parsed_settings.get('PYGMENTS_RST_OPTIONS', None)
144     return parsed_settings
145 
146 
147 def get_settings_from_module(module=None, default_settings=DEFAULT_CONFIG):
148     """Loads settings from a module, returns a dictionary."""
149 
150     context = copy.deepcopy(default_settings)
151     if module is not None:
152         context.update(
153             (k, v) for k, v in inspect.getmembers(module) if k.isupper())
154     return context
155 
156 
157 def get_settings_from_file(path, default_settings=DEFAULT_CONFIG):
158     """Loads settings from a file path, returning a dict."""
159 
160     name, ext = os.path.splitext(os.path.basename(path))
161     module = load_source(name, path)
162     return get_settings_from_module(module, default_settings=default_settings)
163 
164 
165 def configure_settings(settings):
166     """Provide optimizations, error checking and warnings for the given
167     settings.
168 
169     """
170     if not 'PATH' in settings or not os.path.isdir(settings['PATH']):
171         raise Exception('You need to specify a path containing the content'
172                         ' (see pelican --help for more information)')
173 
174     # lookup the theme in "pelican/themes" if the given one doesn't exist
175     if not os.path.isdir(settings['THEME']):
176         theme_path = os.path.join(
177             os.path.dirname(os.path.abspath(__file__)),
178             'themes',
179             settings['THEME'])
180         if os.path.exists(theme_path):
181             settings['THEME'] = theme_path
182         else:
183             raise Exception("Could not find the theme %s"
184                             % settings['THEME'])
185 
186     # standardize strings to lowercase strings
187     for key in [
188             'DEFAULT_LANG',
189             ]:
190         if key in settings:
191             settings[key] = settings[key].lower()
192 
193     # standardize strings to lists
194     for key in [
195             'LOCALE',
196             ]:
197         if key in settings and isinstance(settings[key], six.string_types):
198             settings[key] = [settings[key]]
199 
200     # check settings that must be a particular type
201     for key, types in [
202             ('OUTPUT_SOURCES_EXTENSION', six.string_types),
203             ('FILENAME_METADATA', six.string_types),
204             ]:
205         if key in settings and not isinstance(settings[key], types):
206             value = settings.pop(key)
207             logger.warn(
208                 'Detected misconfigured {} ({}), '
209                 'falling back to the default ({})'.format(
210                     key, value, DEFAULT_CONFIG[key]))
211 
212     # try to set the different locales, fallback on the default.
213     locales = settings.get('LOCALE', DEFAULT_CONFIG['LOCALE'])
214 
215     for locale_ in locales:
216         try:
217             locale.setlocale(locale.LC_ALL, str(locale_))
218             break  # break if it is successful
219         except locale.Error:
220             pass
221     else:
222         logger.warning("LOCALE option doesn't contain a correct value")
223 
224     if ('SITEURL' in settings):
225         # If SITEURL has a trailing slash, remove it and provide a warning
226         siteurl = settings['SITEURL']
227         if (siteurl.endswith('/')):
228             settings['SITEURL'] = siteurl[:-1]
229             logger.warning("Removed extraneous trailing slash from SITEURL.")
230         # If SITEURL is defined but FEED_DOMAIN isn't,
231         # set FEED_DOMAIN to SITEURL
232         if not 'FEED_DOMAIN' in settings:
233             settings['FEED_DOMAIN'] = settings['SITEURL']
234 
235     # Warn if feeds are generated with both SITEURL & FEED_DOMAIN undefined
236     feed_keys = [
237         'FEED_ATOM', 'FEED_RSS',
238         'FEED_ALL_ATOM', 'FEED_ALL_RSS',
239         'CATEGORY_FEED_ATOM', 'CATEGORY_FEED_RSS',
240         'TAG_FEED_ATOM', 'TAG_FEED_RSS',
241         'TRANSLATION_FEED_ATOM', 'TRANSLATION_FEED_RSS',
242     ]
243 
244     if any(settings.get(k) for k in feed_keys):
245         if not settings.get('SITEURL'):
246             logger.warning('Feeds generated without SITEURL set properly may'
247                            ' not be valid')
248 
249     if not 'TIMEZONE' in settings:
250         logger.warning(
251             'No timezone information specified in the settings. Assuming'
252             ' your timezone is UTC for feed generation. Check '
253             'http://docs.getpelican.com/en/latest/settings.html#timezone '
254             'for more information')
255 
256     # fix up pagination rules
257     from pelican.paginator import PaginationRule
258     pagination_rules = [
259         PaginationRule(*r) for r in settings.get(
260             'PAGINATION_PATTERNS',
261             DEFAULT_CONFIG['PAGINATION_PATTERNS'],
262         )
263     ]
264     settings['PAGINATION_PATTERNS'] = sorted(
265         pagination_rules,
266         key=lambda r: r[0],
267     )
268 
269     # Save people from accidentally setting a string rather than a list
270     path_keys = (
271         'ARTICLE_EXCLUDES',
272         'DEFAULT_METADATA',
273         'DIRECT_TEMPLATES',
274         'EXTRA_TEMPLATES_PATHS',
275         'FILES_TO_COPY',
276         'IGNORE_FILES',
277         'JINJA_EXTENSIONS',
278         'PAGINATED_DIRECT_TEMPLATES',
279         'PLUGINS',
280         'STATIC_PATHS',
281         'THEME_STATIC_PATHS',
282     )
283     for PATH_KEY in filter(lambda k: k in settings, path_keys):
284             if isinstance(settings[PATH_KEY], six.string_types):
285                 logger.warning("Detected misconfiguration with %s setting "
286                                "(must be a list), falling back to the default"
287                                % PATH_KEY)
288                 settings[PATH_KEY] = DEFAULT_CONFIG[PATH_KEY]
289 
290     for old, new, doc in [
291             ('LESS_GENERATOR', 'the Webassets plugin', None),
292             ('FILES_TO_COPY', 'STATIC_PATHS and EXTRA_PATH_METADATA',
293              'https://github.com/getpelican/pelican/blob/master/docs/settings.rst#path-metadata'),
294             ]:
295         if old in settings:
296             message = 'The {} setting has been removed in favor of {}'.format(
297                 old, new)
298             if doc:
299                 message += ', see {} for details'.format(doc)
300             logger.warning(message)
301 
302     return settings
303
```
--- 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()

```

diff --git a/pelican/settings.py b/pelican/settings.py
--- a/pelican/settings.py
+++ b/pelican/settings.py
@@ -68,6 +68,8 @@
     'PDF_GENERATOR': False,
     'PDF_STYLE_PATH': '',
     'PDF_STYLE': 'twelvepoint',
+    'CATEGORIES_URL': 'categories.html',
+    'CATEGORIES_SAVE_AS': 'categories.html',
     'CATEGORY_URL': 'category/{slug}.html',
     'CATEGORY_SAVE_AS': os.path.join('category', '{slug}.html'),
     'TAG_URL': 'tag/{slug}.html',

{"golden_diff": "diff --git a/pelican/settings.py b/pelican/settings.py\n--- a/pelican/settings.py\n+++ b/pelican/settings.py\n@@ -68,6 +68,8 @@\n     'PDF_GENERATOR': False,\n     'PDF_STYLE_PATH': '',\n     'PDF_STYLE': 'twelvepoint',\n+    'CATEGORIES_URL': 'categories.html',\n+    'CATEGORIES_SAVE_AS': 'categories.html',\n     'CATEGORY_URL': 'category/{slug}.html',\n     'CATEGORY_SAVE_AS': os.path.join('category', '{slug}.html'),\n     'TAG_URL': 'tag/{slug}.html',\n", "issue": "CATEGORIES_URL doesn't honor it's default value\nFirst of all, thanks for this great software. But, when I'm using the variable CATEGORIES_URL in templates (category.html), it doesn't have it's default value (as said on the documentation: CATEGORIES_URL ('categories/')). I need to explicitly set this value in pelican.conf. I'm using Pelican 3.3.0\n\nThanks\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nfrom __future__ import unicode_literals, print_function\nimport six\n\nimport copy\nimport inspect\nimport os\nimport locale\nimport logging\n\ntry:\n    # SourceFileLoader is the recommended way in 3.3+\n    from importlib.machinery import SourceFileLoader\n    load_source = lambda name, path: SourceFileLoader(name, path).load_module()\nexcept ImportError:\n    # but it does not exist in 3.2-, so fall back to imp\n    import imp\n    load_source = imp.load_source\n\nfrom os.path import isabs\n\n\nlogger = logging.getLogger(__name__)\n\n\nDEFAULT_THEME = os.path.join(os.path.dirname(os.path.abspath(__file__)),\n                             'themes', 'notmyidea')\nDEFAULT_CONFIG = {\n    'PATH': os.curdir,\n    'ARTICLE_DIR': '',\n    'ARTICLE_EXCLUDES': ('pages',),\n    'PAGE_DIR': 'pages',\n    'PAGE_EXCLUDES': (),\n    'THEME': DEFAULT_THEME,\n    'OUTPUT_PATH': 'output',\n    'READERS': {},\n    'STATIC_PATHS': ['images', ],\n    'THEME_STATIC_DIR': 'theme',\n    'THEME_STATIC_PATHS': ['static', ],\n    'FEED_ALL_ATOM': os.path.join('feeds', 'all.atom.xml'),\n    'CATEGORY_FEED_ATOM': os.path.join('feeds', '%s.atom.xml'),\n    'TRANSLATION_FEED_ATOM': os.path.join('feeds', 'all-%s.atom.xml'),\n    'FEED_MAX_ITEMS': '',\n    'SITEURL': '',\n    'SITENAME': 'A Pelican Blog',\n    'DISPLAY_PAGES_ON_MENU': True,\n    'DISPLAY_CATEGORIES_ON_MENU': True,\n    'OUTPUT_SOURCES': False,\n    'OUTPUT_SOURCES_EXTENSION': '.text',\n    'USE_FOLDER_AS_CATEGORY': True,\n    'DEFAULT_CATEGORY': 'misc',\n    'WITH_FUTURE_DATES': True,\n    'CSS_FILE': 'main.css',\n    'NEWEST_FIRST_ARCHIVES': True,\n    'REVERSE_CATEGORY_ORDER': False,\n    'DELETE_OUTPUT_DIRECTORY': False,\n    'OUTPUT_RETENTION': (),\n    'ARTICLE_URL': '{slug}.html',\n    'ARTICLE_SAVE_AS': '{slug}.html',\n    'ARTICLE_LANG_URL': '{slug}-{lang}.html',\n    'ARTICLE_LANG_SAVE_AS': '{slug}-{lang}.html',\n    'PAGE_URL': 'pages/{slug}.html',\n    'PAGE_SAVE_AS': os.path.join('pages', '{slug}.html'),\n    'PAGE_LANG_URL': 'pages/{slug}-{lang}.html',\n    'PAGE_LANG_SAVE_AS': os.path.join('pages', '{slug}-{lang}.html'),\n    'STATIC_URL': '{path}',\n    'STATIC_SAVE_AS': '{path}',\n    'PDF_GENERATOR': False,\n    'PDF_STYLE_PATH': '',\n    'PDF_STYLE': 'twelvepoint',\n    'CATEGORY_URL': 'category/{slug}.html',\n    'CATEGORY_SAVE_AS': os.path.join('category', '{slug}.html'),\n    'TAG_URL': 'tag/{slug}.html',\n    'TAG_SAVE_AS': os.path.join('tag', '{slug}.html'),\n    'AUTHOR_URL': 'author/{slug}.html',\n    'AUTHOR_SAVE_AS': os.path.join('author', '{slug}.html'),\n    'PAGINATION_PATTERNS': [\n        (0, '{name}{number}.html', '{name}{number}.html'),\n    ],\n    'YEAR_ARCHIVE_SAVE_AS': False,\n    'MONTH_ARCHIVE_SAVE_AS': False,\n    'DAY_ARCHIVE_SAVE_AS': False,\n    'RELATIVE_URLS': False,\n    'DEFAULT_LANG': 'en',\n    'TAG_CLOUD_STEPS': 4,\n    'TAG_CLOUD_MAX_ITEMS': 100,\n    'DIRECT_TEMPLATES': ('index', 'tags', 'categories', 'authors', 'archives'),\n    'EXTRA_TEMPLATES_PATHS': [],\n    'PAGINATED_DIRECT_TEMPLATES': ('index', ),\n    'PELICAN_CLASS': 'pelican.Pelican',\n    'DEFAULT_DATE_FORMAT': '%a %d %B %Y',\n    'DATE_FORMATS': {},\n    'ASCIIDOC_OPTIONS': [],\n    'MD_EXTENSIONS': ['codehilite(css_class=highlight)', 'extra'],\n    'JINJA_EXTENSIONS': [],\n    'JINJA_FILTERS': {},\n    'LOCALE': [''],  # defaults to user locale\n    'DEFAULT_PAGINATION': False,\n    'DEFAULT_ORPHANS': 0,\n    'DEFAULT_METADATA': (),\n    'FILENAME_METADATA': '(?P<date>\\d{4}-\\d{2}-\\d{2}).*',\n    'PATH_METADATA': '',\n    'EXTRA_PATH_METADATA': {},\n    'DEFAULT_STATUS': 'published',\n    'ARTICLE_PERMALINK_STRUCTURE': '',\n    'TYPOGRIFY': False,\n    'SUMMARY_MAX_LENGTH': 50,\n    'PLUGIN_PATH': '',\n    'PLUGINS': [],\n    'PYGMENTS_RST_OPTIONS': {},\n    'TEMPLATE_PAGES': {},\n    'IGNORE_FILES': ['.#*'],\n    'SLUG_SUBSTITUTIONS': (),\n    'INTRASITE_LINK_REGEX': '[{|](?P<what>.*?)[|}]',\n    }\n\nPYGMENTS_RST_OPTIONS = None\n\n\ndef read_settings(path=None, override=None):\n    if path:\n        local_settings = get_settings_from_file(path)\n        # Make the paths relative to the settings file\n        for p in ['PATH', 'OUTPUT_PATH', 'THEME', 'PLUGIN_PATH']:\n            if p in local_settings and local_settings[p] is not None \\\n                    and not isabs(local_settings[p]):\n                absp = os.path.abspath(os.path.normpath(os.path.join(\n                    os.path.dirname(path), local_settings[p])))\n                if p not in ('THEME', 'PLUGIN_PATH') or os.path.exists(absp):\n                    local_settings[p] = absp\n    else:\n        local_settings = copy.deepcopy(DEFAULT_CONFIG)\n\n    if override:\n        local_settings.update(override)\n\n    parsed_settings = configure_settings(local_settings)\n    # This is because there doesn't seem to be a way to pass extra\n    # parameters to docutils directive handlers, so we have to have a\n    # variable here that we'll import from within Pygments.run (see\n    # rstdirectives.py) to see what the user defaults were.\n    global PYGMENTS_RST_OPTIONS\n    PYGMENTS_RST_OPTIONS = parsed_settings.get('PYGMENTS_RST_OPTIONS', None)\n    return parsed_settings\n\n\ndef get_settings_from_module(module=None, default_settings=DEFAULT_CONFIG):\n    \"\"\"Loads settings from a module, returns a dictionary.\"\"\"\n\n    context = copy.deepcopy(default_settings)\n    if module is not None:\n        context.update(\n            (k, v) for k, v in inspect.getmembers(module) if k.isupper())\n    return context\n\n\ndef get_settings_from_file(path, default_settings=DEFAULT_CONFIG):\n    \"\"\"Loads settings from a file path, returning a dict.\"\"\"\n\n    name, ext = os.path.splitext(os.path.basename(path))\n    module = load_source(name, path)\n    return get_settings_from_module(module, default_settings=default_settings)\n\n\ndef configure_settings(settings):\n    \"\"\"Provide optimizations, error checking and warnings for the given\n    settings.\n\n    \"\"\"\n    if not 'PATH' in settings or not os.path.isdir(settings['PATH']):\n        raise Exception('You need to specify a path containing the content'\n                        ' (see pelican --help for more information)')\n\n    # lookup the theme in \"pelican/themes\" if the given one doesn't exist\n    if not os.path.isdir(settings['THEME']):\n        theme_path = os.path.join(\n            os.path.dirname(os.path.abspath(__file__)),\n            'themes',\n            settings['THEME'])\n        if os.path.exists(theme_path):\n            settings['THEME'] = theme_path\n        else:\n            raise Exception(\"Could not find the theme %s\"\n                            % settings['THEME'])\n\n    # standardize strings to lowercase strings\n    for key in [\n            'DEFAULT_LANG',\n            ]:\n        if key in settings:\n            settings[key] = settings[key].lower()\n\n    # standardize strings to lists\n    for key in [\n            'LOCALE',\n            ]:\n        if key in settings and isinstance(settings[key], six.string_types):\n            settings[key] = [settings[key]]\n\n    # check settings that must be a particular type\n    for key, types in [\n            ('OUTPUT_SOURCES_EXTENSION', six.string_types),\n            ('FILENAME_METADATA', six.string_types),\n            ]:\n        if key in settings and not isinstance(settings[key], types):\n            value = settings.pop(key)\n            logger.warn(\n                'Detected misconfigured {} ({}), '\n                'falling back to the default ({})'.format(\n                    key, value, DEFAULT_CONFIG[key]))\n\n    # try to set the different locales, fallback on the default.\n    locales = settings.get('LOCALE', DEFAULT_CONFIG['LOCALE'])\n\n    for locale_ in locales:\n        try:\n            locale.setlocale(locale.LC_ALL, str(locale_))\n            break  # break if it is successful\n        except locale.Error:\n            pass\n    else:\n        logger.warning(\"LOCALE option doesn't contain a correct value\")\n\n    if ('SITEURL' in settings):\n        # If SITEURL has a trailing slash, remove it and provide a warning\n        siteurl = settings['SITEURL']\n        if (siteurl.endswith('/')):\n            settings['SITEURL'] = siteurl[:-1]\n            logger.warning(\"Removed extraneous trailing slash from SITEURL.\")\n        # If SITEURL is defined but FEED_DOMAIN isn't,\n        # set FEED_DOMAIN to SITEURL\n        if not 'FEED_DOMAIN' in settings:\n            settings['FEED_DOMAIN'] = settings['SITEURL']\n\n    # Warn if feeds are generated with both SITEURL & FEED_DOMAIN undefined\n    feed_keys = [\n        'FEED_ATOM', 'FEED_RSS',\n        'FEED_ALL_ATOM', 'FEED_ALL_RSS',\n        'CATEGORY_FEED_ATOM', 'CATEGORY_FEED_RSS',\n        'TAG_FEED_ATOM', 'TAG_FEED_RSS',\n        'TRANSLATION_FEED_ATOM', 'TRANSLATION_FEED_RSS',\n    ]\n\n    if any(settings.get(k) for k in feed_keys):\n        if not settings.get('SITEURL'):\n            logger.warning('Feeds generated without SITEURL set properly may'\n                           ' not be valid')\n\n    if not 'TIMEZONE' in settings:\n        logger.warning(\n            'No timezone information specified in the settings. Assuming'\n            ' your timezone is UTC for feed generation. Check '\n            'http://docs.getpelican.com/en/latest/settings.html#timezone '\n            'for more information')\n\n    # fix up pagination rules\n    from pelican.paginator import PaginationRule\n    pagination_rules = [\n        PaginationRule(*r) for r in settings.get(\n            'PAGINATION_PATTERNS',\n            DEFAULT_CONFIG['PAGINATION_PATTERNS'],\n        )\n    ]\n    settings['PAGINATION_PATTERNS'] = sorted(\n        pagination_rules,\n        key=lambda r: r[0],\n    )\n\n    # Save people from accidentally setting a string rather than a list\n    path_keys = (\n        'ARTICLE_EXCLUDES',\n        'DEFAULT_METADATA',\n        'DIRECT_TEMPLATES',\n        'EXTRA_TEMPLATES_PATHS',\n        'FILES_TO_COPY',\n        'IGNORE_FILES',\n        'JINJA_EXTENSIONS',\n        'PAGINATED_DIRECT_TEMPLATES',\n        'PLUGINS',\n        'STATIC_PATHS',\n        'THEME_STATIC_PATHS',\n    )\n    for PATH_KEY in filter(lambda k: k in settings, path_keys):\n            if isinstance(settings[PATH_KEY], six.string_types):\n                logger.warning(\"Detected misconfiguration with %s setting \"\n                               \"(must be a list), falling back to the default\"\n                               % PATH_KEY)\n                settings[PATH_KEY] = DEFAULT_CONFIG[PATH_KEY]\n\n    for old, new, doc in [\n            ('LESS_GENERATOR', 'the Webassets plugin', None),\n            ('FILES_TO_COPY', 'STATIC_PATHS and EXTRA_PATH_METADATA',\n             'https://github.com/getpelican/pelican/blob/master/docs/settings.rst#path-metadata'),\n            ]:\n        if old in settings:\n            message = 'The {} setting has been removed in favor of {}'.format(\n                old, new)\n            if doc:\n                message += ', see {} for details'.format(doc)\n            logger.warning(message)\n\n    return settings\n", "path": "pelican/settings.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nfrom __future__ import unicode_literals, print_function\nimport six\n\nimport copy\nimport inspect\nimport os\nimport locale\nimport logging\n\ntry:\n    # SourceFileLoader is the recommended way in 3.3+\n    from importlib.machinery import SourceFileLoader\n    load_source = lambda name, path: SourceFileLoader(name, path).load_module()\nexcept ImportError:\n    # but it does not exist in 3.2-, so fall back to imp\n    import imp\n    load_source = imp.load_source\n\nfrom os.path import isabs\n\n\nlogger = logging.getLogger(__name__)\n\n\nDEFAULT_THEME = os.path.join(os.path.dirname(os.path.abspath(__file__)),\n                             'themes', 'notmyidea')\nDEFAULT_CONFIG = {\n    'PATH': os.curdir,\n    'ARTICLE_DIR': '',\n    'ARTICLE_EXCLUDES': ('pages',),\n    'PAGE_DIR': 'pages',\n    'PAGE_EXCLUDES': (),\n    'THEME': DEFAULT_THEME,\n    'OUTPUT_PATH': 'output',\n    'READERS': {},\n    'STATIC_PATHS': ['images', ],\n    'THEME_STATIC_DIR': 'theme',\n    'THEME_STATIC_PATHS': ['static', ],\n    'FEED_ALL_ATOM': os.path.join('feeds', 'all.atom.xml'),\n    'CATEGORY_FEED_ATOM': os.path.join('feeds', '%s.atom.xml'),\n    'TRANSLATION_FEED_ATOM': os.path.join('feeds', 'all-%s.atom.xml'),\n    'FEED_MAX_ITEMS': '',\n    'SITEURL': '',\n    'SITENAME': 'A Pelican Blog',\n    'DISPLAY_PAGES_ON_MENU': True,\n    'DISPLAY_CATEGORIES_ON_MENU': True,\n    'OUTPUT_SOURCES': False,\n    'OUTPUT_SOURCES_EXTENSION': '.text',\n    'USE_FOLDER_AS_CATEGORY': True,\n    'DEFAULT_CATEGORY': 'misc',\n    'WITH_FUTURE_DATES': True,\n    'CSS_FILE': 'main.css',\n    'NEWEST_FIRST_ARCHIVES': True,\n    'REVERSE_CATEGORY_ORDER': False,\n    'DELETE_OUTPUT_DIRECTORY': False,\n    'OUTPUT_RETENTION': (),\n    'ARTICLE_URL': '{slug}.html',\n    'ARTICLE_SAVE_AS': '{slug}.html',\n    'ARTICLE_LANG_URL': '{slug}-{lang}.html',\n    'ARTICLE_LANG_SAVE_AS': '{slug}-{lang}.html',\n    'PAGE_URL': 'pages/{slug}.html',\n    'PAGE_SAVE_AS': os.path.join('pages', '{slug}.html'),\n    'PAGE_LANG_URL': 'pages/{slug}-{lang}.html',\n    'PAGE_LANG_SAVE_AS': os.path.join('pages', '{slug}-{lang}.html'),\n    'STATIC_URL': '{path}',\n    'STATIC_SAVE_AS': '{path}',\n    'PDF_GENERATOR': False,\n    'PDF_STYLE_PATH': '',\n    'PDF_STYLE': 'twelvepoint',\n    'CATEGORIES_URL': 'categories.html',\n    'CATEGORIES_SAVE_AS': 'categories.html',\n    'CATEGORY_URL': 'category/{slug}.html',\n    'CATEGORY_SAVE_AS': os.path.join('category', '{slug}.html'),\n    'TAG_URL': 'tag/{slug}.html',\n    'TAG_SAVE_AS': os.path.join('tag', '{slug}.html'),\n    'AUTHOR_URL': 'author/{slug}.html',\n    'AUTHOR_SAVE_AS': os.path.join('author', '{slug}.html'),\n    'PAGINATION_PATTERNS': [\n        (0, '{name}{number}.html', '{name}{number}.html'),\n    ],\n    'YEAR_ARCHIVE_SAVE_AS': False,\n    'MONTH_ARCHIVE_SAVE_AS': False,\n    'DAY_ARCHIVE_SAVE_AS': False,\n    'RELATIVE_URLS': False,\n    'DEFAULT_LANG': 'en',\n    'TAG_CLOUD_STEPS': 4,\n    'TAG_CLOUD_MAX_ITEMS': 100,\n    'DIRECT_TEMPLATES': ('index', 'tags', 'categories', 'authors', 'archives'),\n    'EXTRA_TEMPLATES_PATHS': [],\n    'PAGINATED_DIRECT_TEMPLATES': ('index', ),\n    'PELICAN_CLASS': 'pelican.Pelican',\n    'DEFAULT_DATE_FORMAT': '%a %d %B %Y',\n    'DATE_FORMATS': {},\n    'ASCIIDOC_OPTIONS': [],\n    'MD_EXTENSIONS': ['codehilite(css_class=highlight)', 'extra'],\n    'JINJA_EXTENSIONS': [],\n    'JINJA_FILTERS': {},\n    'LOCALE': [''],  # defaults to user locale\n    'DEFAULT_PAGINATION': False,\n    'DEFAULT_ORPHANS': 0,\n    'DEFAULT_METADATA': (),\n    'FILENAME_METADATA': '(?P<date>\\d{4}-\\d{2}-\\d{2}).*',\n    'PATH_METADATA': '',\n    'EXTRA_PATH_METADATA': {},\n    'DEFAULT_STATUS': 'published',\n    'ARTICLE_PERMALINK_STRUCTURE': '',\n    'TYPOGRIFY': False,\n    'SUMMARY_MAX_LENGTH': 50,\n    'PLUGIN_PATH': '',\n    'PLUGINS': [],\n    'PYGMENTS_RST_OPTIONS': {},\n    'TEMPLATE_PAGES': {},\n    'IGNORE_FILES': ['.#*'],\n    'SLUG_SUBSTITUTIONS': (),\n    'INTRASITE_LINK_REGEX': '[{|](?P<what>.*?)[|}]',\n    }\n\nPYGMENTS_RST_OPTIONS = None\n\n\ndef read_settings(path=None, override=None):\n    if path:\n        local_settings = get_settings_from_file(path)\n        # Make the paths relative to the settings file\n        for p in ['PATH', 'OUTPUT_PATH', 'THEME', 'PLUGIN_PATH']:\n            if p in local_settings and local_settings[p] is not None \\\n                    and not isabs(local_settings[p]):\n                absp = os.path.abspath(os.path.normpath(os.path.join(\n                    os.path.dirname(path), local_settings[p])))\n                if p not in ('THEME', 'PLUGIN_PATH') or os.path.exists(absp):\n                    local_settings[p] = absp\n    else:\n        local_settings = copy.deepcopy(DEFAULT_CONFIG)\n\n    if override:\n        local_settings.update(override)\n\n    parsed_settings = configure_settings(local_settings)\n    # This is because there doesn't seem to be a way to pass extra\n    # parameters to docutils directive handlers, so we have to have a\n    # variable here that we'll import from within Pygments.run (see\n    # rstdirectives.py) to see what the user defaults were.\n    global PYGMENTS_RST_OPTIONS\n    PYGMENTS_RST_OPTIONS = parsed_settings.get('PYGMENTS_RST_OPTIONS', None)\n    return parsed_settings\n\n\ndef get_settings_from_module(module=None, default_settings=DEFAULT_CONFIG):\n    \"\"\"Loads settings from a module, returns a dictionary.\"\"\"\n\n    context = copy.deepcopy(default_settings)\n    if module is not None:\n        context.update(\n            (k, v) for k, v in inspect.getmembers(module) if k.isupper())\n    return context\n\n\ndef get_settings_from_file(path, default_settings=DEFAULT_CONFIG):\n    \"\"\"Loads settings from a file path, returning a dict.\"\"\"\n\n    name, ext = os.path.splitext(os.path.basename(path))\n    module = load_source(name, path)\n    return get_settings_from_module(module, default_settings=default_settings)\n\n\ndef configure_settings(settings):\n    \"\"\"Provide optimizations, error checking and warnings for the given\n    settings.\n\n    \"\"\"\n    if not 'PATH' in settings or not os.path.isdir(settings['PATH']):\n        raise Exception('You need to specify a path containing the content'\n                        ' (see pelican --help for more information)')\n\n    # lookup the theme in \"pelican/themes\" if the given one doesn't exist\n    if not os.path.isdir(settings['THEME']):\n        theme_path = os.path.join(\n            os.path.dirname(os.path.abspath(__file__)),\n            'themes',\n            settings['THEME'])\n        if os.path.exists(theme_path):\n            settings['THEME'] = theme_path\n        else:\n            raise Exception(\"Could not find the theme %s\"\n                            % settings['THEME'])\n\n    # standardize strings to lowercase strings\n    for key in [\n            'DEFAULT_LANG',\n            ]:\n        if key in settings:\n            settings[key] = settings[key].lower()\n\n    # standardize strings to lists\n    for key in [\n            'LOCALE',\n            ]:\n        if key in settings and isinstance(settings[key], six.string_types):\n            settings[key] = [settings[key]]\n\n    # check settings that must be a particular type\n    for key, types in [\n            ('OUTPUT_SOURCES_EXTENSION', six.string_types),\n            ('FILENAME_METADATA', six.string_types),\n            ]:\n        if key in settings and not isinstance(settings[key], types):\n            value = settings.pop(key)\n            logger.warn(\n                'Detected misconfigured {} ({}), '\n                'falling back to the default ({})'.format(\n                    key, value, DEFAULT_CONFIG[key]))\n\n    # try to set the different locales, fallback on the default.\n    locales = settings.get('LOCALE', DEFAULT_CONFIG['LOCALE'])\n\n    for locale_ in locales:\n        try:\n            locale.setlocale(locale.LC_ALL, str(locale_))\n            break  # break if it is successful\n        except locale.Error:\n            pass\n    else:\n        logger.warning(\"LOCALE option doesn't contain a correct value\")\n\n    if ('SITEURL' in settings):\n        # If SITEURL has a trailing slash, remove it and provide a warning\n        siteurl = settings['SITEURL']\n        if (siteurl.endswith('/')):\n            settings['SITEURL'] = siteurl[:-1]\n            logger.warning(\"Removed extraneous trailing slash from SITEURL.\")\n        # If SITEURL is defined but FEED_DOMAIN isn't,\n        # set FEED_DOMAIN to SITEURL\n        if not 'FEED_DOMAIN' in settings:\n            settings['FEED_DOMAIN'] = settings['SITEURL']\n\n    # Warn if feeds are generated with both SITEURL & FEED_DOMAIN undefined\n    feed_keys = [\n        'FEED_ATOM', 'FEED_RSS',\n        'FEED_ALL_ATOM', 'FEED_ALL_RSS',\n        'CATEGORY_FEED_ATOM', 'CATEGORY_FEED_RSS',\n        'TAG_FEED_ATOM', 'TAG_FEED_RSS',\n        'TRANSLATION_FEED_ATOM', 'TRANSLATION_FEED_RSS',\n    ]\n\n    if any(settings.get(k) for k in feed_keys):\n        if not settings.get('SITEURL'):\n            logger.warning('Feeds generated without SITEURL set properly may'\n                           ' not be valid')\n\n    if not 'TIMEZONE' in settings:\n        logger.warning(\n            'No timezone information specified in the settings. Assuming'\n            ' your timezone is UTC for feed generation. Check '\n            'http://docs.getpelican.com/en/latest/settings.html#timezone '\n            'for more information')\n\n    # fix up pagination rules\n    from pelican.paginator import PaginationRule\n    pagination_rules = [\n        PaginationRule(*r) for r in settings.get(\n            'PAGINATION_PATTERNS',\n            DEFAULT_CONFIG['PAGINATION_PATTERNS'],\n        )\n    ]\n    settings['PAGINATION_PATTERNS'] = sorted(\n        pagination_rules,\n        key=lambda r: r[0],\n    )\n\n    # Save people from accidentally setting a string rather than a list\n    path_keys = (\n        'ARTICLE_EXCLUDES',\n        'DEFAULT_METADATA',\n        'DIRECT_TEMPLATES',\n        'EXTRA_TEMPLATES_PATHS',\n        'FILES_TO_COPY',\n        'IGNORE_FILES',\n        'JINJA_EXTENSIONS',\n        'PAGINATED_DIRECT_TEMPLATES',\n        'PLUGINS',\n        'STATIC_PATHS',\n        'THEME_STATIC_PATHS',\n    )\n    for PATH_KEY in filter(lambda k: k in settings, path_keys):\n            if isinstance(settings[PATH_KEY], six.string_types):\n                logger.warning(\"Detected misconfiguration with %s setting \"\n                               \"(must be a list), falling back to the default\"\n                               % PATH_KEY)\n                settings[PATH_KEY] = DEFAULT_CONFIG[PATH_KEY]\n\n    for old, new, doc in [\n            ('LESS_GENERATOR', 'the Webassets plugin', None),\n            ('FILES_TO_COPY', 'STATIC_PATHS and EXTRA_PATH_METADATA',\n             'https://github.com/getpelican/pelican/blob/master/docs/settings.rst#path-metadata'),\n            ]:\n        if old in settings:\n            message = 'The {} setting has been removed in favor of {}'.format(\n                old, new)\n            if doc:\n                message += ', see {} for details'.format(doc)\n            logger.warning(message)\n\n    return settings\n", "path": "pelican/settings.py"}]}