We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Feeds generate malformed urls (with double slash)
When setting a site url that ends with a slash (like http://feldboris.alwaysdata.net/blog/), pelican will generate url in feeds with double slash (like http://feldboris.alwaysdata.net/blog//feeds/all.atom.xml) just after site url. W3C feeds validator show a warning with these double slashs.

It's maybe the cause of a rss problem (my rss client show old feeds entries as unread) as post fields also contains double slash now.


--- 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 import os
3 import locale
4 import logging
5 
6 from os.path import isabs
7 
8 
9 logger = logging.getLogger(__name__)
10 
11 
12 DEFAULT_THEME = os.sep.join([os.path.dirname(os.path.abspath(__file__)),
13                               "themes/notmyidea"])
14 _DEFAULT_CONFIG = {'PATH': '.',
15                    'ARTICLE_DIR': '',
16                    'ARTICLE_EXCLUDES': ('pages',),
17                    'PAGE_DIR': 'pages',
18                    'PAGE_EXCLUDES': (),
19                    'THEME': DEFAULT_THEME,
20                    'OUTPUT_PATH': 'output/',
21                    'MARKUP': ('rst', 'md'),
22                    'STATIC_PATHS': ['images', ],
23                    'THEME_STATIC_PATHS': ['static', ],
24                    'FEED': 'feeds/all.atom.xml',
25                    'FEED_MAIN_URL': 'feeds/all.atom.xml',
26                    'CATEGORY_FEED': 'feeds/%s.atom.xml',
27                    'TRANSLATION_FEED': 'feeds/all-%s.atom.xml',
28                    'FEED_MAX_ITEMS': '',
29                    'SITENAME': 'A Pelican Blog',
30                    'DISPLAY_PAGES_ON_MENU': True,
31                    'PDF_GENERATOR': False,
32                    'DEFAULT_CATEGORY': 'misc',
33                    'FALLBACK_ON_FS_DATE': True,
34                    'WITH_FUTURE_DATES': True,
35                    'CSS_FILE': 'main.css',
36                    'REVERSE_ARCHIVE_ORDER': False,
37                    'REVERSE_CATEGORY_ORDER': False,
38                    'DELETE_OUTPUT_DIRECTORY': False,
39                    'ARTICLE_URL': '{slug}.html',
40                    'ARTICLE_SAVE_AS': '{slug}.html',
41                    'ARTICLE_LANG_URL': '{slug}-{lang}.html',
42                    'ARTICLE_LANG_SAVE_AS': '{slug}-{lang}.html',
43                    'PAGE_URL': 'pages/{slug}.html',
44                    'PAGE_SAVE_AS': 'pages/{slug}.html',
45                    'PAGE_LANG_URL': 'pages/{slug}-{lang}.html',
46                    'PAGE_LANG_SAVE_AS': 'pages/{slug}-{lang}.html',
47                    'CATEGORY_URL': 'category/{name}.html',
48                    'CATEGORY_SAVE_AS': 'category/{name}.html',
49                    'TAG_URL': 'tag/{slug}.html',
50                    'TAG_SAVE_AS': 'tag/{slug}.html',
51                    'AUTHOR_URL': u'author/{slug}.html',
52                    'AUTHOR_SAVE_AS': u'author/{slug}.html',
53                    'RELATIVE_URLS': True,
54                    'DEFAULT_LANG': 'en',
55                    'TAG_CLOUD_STEPS': 4,
56                    'TAG_CLOUD_MAX_ITEMS': 100,
57                    'DIRECT_TEMPLATES': ('index', 'tags', 'categories', 'archives'),
58                    'PAGINATED_DIRECT_TEMPLATES': ('index', ),
59                    'PELICAN_CLASS': 'pelican.Pelican',
60                    'DEFAULT_DATE_FORMAT': '%a %d %B %Y',
61                    'DATE_FORMATS': {},
62                    'JINJA_EXTENSIONS': [],
63                    'LOCALE': '',  # default to user locale
64                    'DEFAULT_PAGINATION': False,
65                    'DEFAULT_ORPHANS': 0,
66                    'DEFAULT_METADATA': (),
67                    'FILES_TO_COPY': (),
68                    'DEFAULT_STATUS': 'published',
69                    'ARTICLE_PERMALINK_STRUCTURE': '',
70                    'TYPOGRIFY': False,
71                    }
72 
73 
74 def read_settings(filename=None):
75     if filename:
76         local_settings = get_settings_from_file(filename)
77     else:
78         local_settings = _DEFAULT_CONFIG
79     configured_settings = configure_settings(local_settings, None, filename)
80     return configured_settings
81 
82 
83 def get_settings_from_file(filename, default_settings=None):
84     """Load a Python file into a dictionary.
85     """
86     if default_settings == None:
87         default_settings = _DEFAULT_CONFIG
88     context = default_settings.copy()
89     if filename:
90         tempdict = {}
91         execfile(filename, tempdict)
92         for key in tempdict:
93             if key.isupper():
94                 context[key] = tempdict[key]
95     return context
96 
97 
98 def configure_settings(settings, default_settings=None, filename=None):
99     """Provide optimizations, error checking, and warnings for loaded settings"""
100     if default_settings is None:
101         default_settings = _DEFAULT_CONFIG
102 
103     # Make the paths relative to the settings file
104     if filename:
105         for path in ['PATH', 'OUTPUT_PATH']:
106             if path in settings:
107                 if settings[path] is not None and not isabs(settings[path]):
108                     settings[path] = os.path.abspath(os.path.normpath(
109                         os.path.join(os.path.dirname(filename), settings[path]))
110                     )
111 
112     # if locales is not a list, make it one
113     locales = settings['LOCALE']
114 
115     if isinstance(locales, basestring):
116         locales = [locales]
117 
118     # try to set the different locales, fallback on the default.
119     if not locales:
120         locales = _DEFAULT_CONFIG['LOCALE']
121 
122     for locale_ in locales:
123         try:
124             locale.setlocale(locale.LC_ALL, locale_)
125             break  # break if it is successfull
126         except locale.Error:
127             pass
128     else:
129         logger.warn("LOCALE option doesn't contain a correct value")
130 
131     # If SITEURL is defined but FEED_DOMAIN isn't, set FEED_DOMAIN = SITEURL
132     if ('SITEURL' in settings) and (not 'FEED_DOMAIN' in settings):
133         settings['FEED_DOMAIN'] = settings['SITEURL']
134 
135     # Warn if feeds are generated with both SITEURL & FEED_DOMAIN undefined
136     if (('FEED' in settings) or ('FEED_RSS' in settings)) and (not 'FEED_DOMAIN' in settings):
137         logger.warn("Since feed URLs should always be absolute, you should specify "
138                  "FEED_DOMAIN in your settings. (e.g., 'FEED_DOMAIN = "
139                  "http://www.example.com')")
140 
141     if not 'TIMEZONE' in settings:
142         logger.warn("No timezone information specified in the settings. Assuming"
143                  " your timezone is UTC for feed generation. Check "
144                  "http://docs.notmyidea.org/alexis/pelican/settings.html#timezone "
145                  "for more information")
146 
147     return settings
148
```
--- 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
@@ -128,9 +128,15 @@
     else:
         logger.warn("LOCALE option doesn't contain a correct value")
 
-    # If SITEURL is defined but FEED_DOMAIN isn't, set FEED_DOMAIN = SITEURL
-    if ('SITEURL' in settings) and (not 'FEED_DOMAIN' in settings):
-        settings['FEED_DOMAIN'] = settings['SITEURL']
+    if ('SITEURL' in settings):
+        # If SITEURL has a trailing slash, remove it and provide a warning
+        siteurl = settings['SITEURL']
+        if (siteurl[len(siteurl) - 1:] == '/'):
+            settings['SITEURL'] = siteurl[:-1]
+            logger.warn("Removed extraneous trailing slash from SITEURL.")
+        # If SITEURL is defined but FEED_DOMAIN isn't, set FEED_DOMAIN = SITEURL
+        if not 'FEED_DOMAIN' in settings:
+            settings['FEED_DOMAIN'] = settings['SITEURL']
 
     # Warn if feeds are generated with both SITEURL & FEED_DOMAIN undefined
     if (('FEED' in settings) or ('FEED_RSS' in settings)) and (not 'FEED_DOMAIN' in settings):

{"golden_diff": "diff --git a/pelican/settings.py b/pelican/settings.py\n--- a/pelican/settings.py\n+++ b/pelican/settings.py\n@@ -128,9 +128,15 @@\n     else:\n         logger.warn(\"LOCALE option doesn't contain a correct value\")\n \n-    # If SITEURL is defined but FEED_DOMAIN isn't, set FEED_DOMAIN = SITEURL\n-    if ('SITEURL' in settings) and (not 'FEED_DOMAIN' in settings):\n-        settings['FEED_DOMAIN'] = settings['SITEURL']\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[len(siteurl) - 1:] == '/'):\n+            settings['SITEURL'] = siteurl[:-1]\n+            logger.warn(\"Removed extraneous trailing slash from SITEURL.\")\n+        # If SITEURL is defined but FEED_DOMAIN isn't, set FEED_DOMAIN = 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     if (('FEED' in settings) or ('FEED_RSS' in settings)) and (not 'FEED_DOMAIN' in settings):\n", "issue": "Feeds generate malformed urls (with double slash)\nWhen setting a site url that ends with a slash (like http://feldboris.alwaysdata.net/blog/), pelican will generate url in feeds with double slash (like http://feldboris.alwaysdata.net/blog//feeds/all.atom.xml) just after site url. W3C feeds validator show a warning with these double slashs.\n\nIt's maybe the cause of a rss problem (my rss client show old feeds entries as unread) as post fields also contains double slash now.\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nimport os\nimport locale\nimport logging\n\nfrom os.path import isabs\n\n\nlogger = logging.getLogger(__name__)\n\n\nDEFAULT_THEME = os.sep.join([os.path.dirname(os.path.abspath(__file__)),\n                              \"themes/notmyidea\"])\n_DEFAULT_CONFIG = {'PATH': '.',\n                   'ARTICLE_DIR': '',\n                   'ARTICLE_EXCLUDES': ('pages',),\n                   'PAGE_DIR': 'pages',\n                   'PAGE_EXCLUDES': (),\n                   'THEME': DEFAULT_THEME,\n                   'OUTPUT_PATH': 'output/',\n                   'MARKUP': ('rst', 'md'),\n                   'STATIC_PATHS': ['images', ],\n                   'THEME_STATIC_PATHS': ['static', ],\n                   'FEED': 'feeds/all.atom.xml',\n                   'FEED_MAIN_URL': 'feeds/all.atom.xml',\n                   'CATEGORY_FEED': 'feeds/%s.atom.xml',\n                   'TRANSLATION_FEED': 'feeds/all-%s.atom.xml',\n                   'FEED_MAX_ITEMS': '',\n                   'SITENAME': 'A Pelican Blog',\n                   'DISPLAY_PAGES_ON_MENU': True,\n                   'PDF_GENERATOR': False,\n                   'DEFAULT_CATEGORY': 'misc',\n                   'FALLBACK_ON_FS_DATE': True,\n                   'WITH_FUTURE_DATES': True,\n                   'CSS_FILE': 'main.css',\n                   'REVERSE_ARCHIVE_ORDER': False,\n                   'REVERSE_CATEGORY_ORDER': False,\n                   'DELETE_OUTPUT_DIRECTORY': False,\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': 'pages/{slug}.html',\n                   'PAGE_LANG_URL': 'pages/{slug}-{lang}.html',\n                   'PAGE_LANG_SAVE_AS': 'pages/{slug}-{lang}.html',\n                   'CATEGORY_URL': 'category/{name}.html',\n                   'CATEGORY_SAVE_AS': 'category/{name}.html',\n                   'TAG_URL': 'tag/{slug}.html',\n                   'TAG_SAVE_AS': 'tag/{slug}.html',\n                   'AUTHOR_URL': u'author/{slug}.html',\n                   'AUTHOR_SAVE_AS': u'author/{slug}.html',\n                   'RELATIVE_URLS': True,\n                   'DEFAULT_LANG': 'en',\n                   'TAG_CLOUD_STEPS': 4,\n                   'TAG_CLOUD_MAX_ITEMS': 100,\n                   'DIRECT_TEMPLATES': ('index', 'tags', 'categories', 'archives'),\n                   'PAGINATED_DIRECT_TEMPLATES': ('index', ),\n                   'PELICAN_CLASS': 'pelican.Pelican',\n                   'DEFAULT_DATE_FORMAT': '%a %d %B %Y',\n                   'DATE_FORMATS': {},\n                   'JINJA_EXTENSIONS': [],\n                   'LOCALE': '',  # default to user locale\n                   'DEFAULT_PAGINATION': False,\n                   'DEFAULT_ORPHANS': 0,\n                   'DEFAULT_METADATA': (),\n                   'FILES_TO_COPY': (),\n                   'DEFAULT_STATUS': 'published',\n                   'ARTICLE_PERMALINK_STRUCTURE': '',\n                   'TYPOGRIFY': False,\n                   }\n\n\ndef read_settings(filename=None):\n    if filename:\n        local_settings = get_settings_from_file(filename)\n    else:\n        local_settings = _DEFAULT_CONFIG\n    configured_settings = configure_settings(local_settings, None, filename)\n    return configured_settings\n\n\ndef get_settings_from_file(filename, default_settings=None):\n    \"\"\"Load a Python file into a dictionary.\n    \"\"\"\n    if default_settings == None:\n        default_settings = _DEFAULT_CONFIG\n    context = default_settings.copy()\n    if filename:\n        tempdict = {}\n        execfile(filename, tempdict)\n        for key in tempdict:\n            if key.isupper():\n                context[key] = tempdict[key]\n    return context\n\n\ndef configure_settings(settings, default_settings=None, filename=None):\n    \"\"\"Provide optimizations, error checking, and warnings for loaded settings\"\"\"\n    if default_settings is None:\n        default_settings = _DEFAULT_CONFIG\n\n    # Make the paths relative to the settings file\n    if filename:\n        for path in ['PATH', 'OUTPUT_PATH']:\n            if path in settings:\n                if settings[path] is not None and not isabs(settings[path]):\n                    settings[path] = os.path.abspath(os.path.normpath(\n                        os.path.join(os.path.dirname(filename), settings[path]))\n                    )\n\n    # if locales is not a list, make it one\n    locales = settings['LOCALE']\n\n    if isinstance(locales, basestring):\n        locales = [locales]\n\n    # try to set the different locales, fallback on the default.\n    if not locales:\n        locales = _DEFAULT_CONFIG['LOCALE']\n\n    for locale_ in locales:\n        try:\n            locale.setlocale(locale.LC_ALL, locale_)\n            break  # break if it is successfull\n        except locale.Error:\n            pass\n    else:\n        logger.warn(\"LOCALE option doesn't contain a correct value\")\n\n    # If SITEURL is defined but FEED_DOMAIN isn't, set FEED_DOMAIN = SITEURL\n    if ('SITEURL' in settings) and (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    if (('FEED' in settings) or ('FEED_RSS' in settings)) and (not 'FEED_DOMAIN' in settings):\n        logger.warn(\"Since feed URLs should always be absolute, you should specify \"\n                 \"FEED_DOMAIN in your settings. (e.g., 'FEED_DOMAIN = \"\n                 \"http://www.example.com')\")\n\n    if not 'TIMEZONE' in settings:\n        logger.warn(\"No timezone information specified in the settings. Assuming\"\n                 \" your timezone is UTC for feed generation. Check \"\n                 \"http://docs.notmyidea.org/alexis/pelican/settings.html#timezone \"\n                 \"for more information\")\n\n    return settings\n", "path": "pelican/settings.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nimport os\nimport locale\nimport logging\n\nfrom os.path import isabs\n\n\nlogger = logging.getLogger(__name__)\n\n\nDEFAULT_THEME = os.sep.join([os.path.dirname(os.path.abspath(__file__)),\n                              \"themes/notmyidea\"])\n_DEFAULT_CONFIG = {'PATH': '.',\n                   'ARTICLE_DIR': '',\n                   'ARTICLE_EXCLUDES': ('pages',),\n                   'PAGE_DIR': 'pages',\n                   'PAGE_EXCLUDES': (),\n                   'THEME': DEFAULT_THEME,\n                   'OUTPUT_PATH': 'output/',\n                   'MARKUP': ('rst', 'md'),\n                   'STATIC_PATHS': ['images', ],\n                   'THEME_STATIC_PATHS': ['static', ],\n                   'FEED': 'feeds/all.atom.xml',\n                   'FEED_MAIN_URL': 'feeds/all.atom.xml',\n                   'CATEGORY_FEED': 'feeds/%s.atom.xml',\n                   'TRANSLATION_FEED': 'feeds/all-%s.atom.xml',\n                   'FEED_MAX_ITEMS': '',\n                   'SITENAME': 'A Pelican Blog',\n                   'DISPLAY_PAGES_ON_MENU': True,\n                   'PDF_GENERATOR': False,\n                   'DEFAULT_CATEGORY': 'misc',\n                   'FALLBACK_ON_FS_DATE': True,\n                   'WITH_FUTURE_DATES': True,\n                   'CSS_FILE': 'main.css',\n                   'REVERSE_ARCHIVE_ORDER': False,\n                   'REVERSE_CATEGORY_ORDER': False,\n                   'DELETE_OUTPUT_DIRECTORY': False,\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': 'pages/{slug}.html',\n                   'PAGE_LANG_URL': 'pages/{slug}-{lang}.html',\n                   'PAGE_LANG_SAVE_AS': 'pages/{slug}-{lang}.html',\n                   'CATEGORY_URL': 'category/{name}.html',\n                   'CATEGORY_SAVE_AS': 'category/{name}.html',\n                   'TAG_URL': 'tag/{slug}.html',\n                   'TAG_SAVE_AS': 'tag/{slug}.html',\n                   'AUTHOR_URL': u'author/{slug}.html',\n                   'AUTHOR_SAVE_AS': u'author/{slug}.html',\n                   'RELATIVE_URLS': True,\n                   'DEFAULT_LANG': 'en',\n                   'TAG_CLOUD_STEPS': 4,\n                   'TAG_CLOUD_MAX_ITEMS': 100,\n                   'DIRECT_TEMPLATES': ('index', 'tags', 'categories', 'archives'),\n                   'PAGINATED_DIRECT_TEMPLATES': ('index', ),\n                   'PELICAN_CLASS': 'pelican.Pelican',\n                   'DEFAULT_DATE_FORMAT': '%a %d %B %Y',\n                   'DATE_FORMATS': {},\n                   'JINJA_EXTENSIONS': [],\n                   'LOCALE': '',  # default to user locale\n                   'DEFAULT_PAGINATION': False,\n                   'DEFAULT_ORPHANS': 0,\n                   'DEFAULT_METADATA': (),\n                   'FILES_TO_COPY': (),\n                   'DEFAULT_STATUS': 'published',\n                   'ARTICLE_PERMALINK_STRUCTURE': '',\n                   'TYPOGRIFY': False,\n                   }\n\n\ndef read_settings(filename=None):\n    if filename:\n        local_settings = get_settings_from_file(filename)\n    else:\n        local_settings = _DEFAULT_CONFIG\n    configured_settings = configure_settings(local_settings, None, filename)\n    return configured_settings\n\n\ndef get_settings_from_file(filename, default_settings=None):\n    \"\"\"Load a Python file into a dictionary.\n    \"\"\"\n    if default_settings == None:\n        default_settings = _DEFAULT_CONFIG\n    context = default_settings.copy()\n    if filename:\n        tempdict = {}\n        execfile(filename, tempdict)\n        for key in tempdict:\n            if key.isupper():\n                context[key] = tempdict[key]\n    return context\n\n\ndef configure_settings(settings, default_settings=None, filename=None):\n    \"\"\"Provide optimizations, error checking, and warnings for loaded settings\"\"\"\n    if default_settings is None:\n        default_settings = _DEFAULT_CONFIG\n\n    # Make the paths relative to the settings file\n    if filename:\n        for path in ['PATH', 'OUTPUT_PATH']:\n            if path in settings:\n                if settings[path] is not None and not isabs(settings[path]):\n                    settings[path] = os.path.abspath(os.path.normpath(\n                        os.path.join(os.path.dirname(filename), settings[path]))\n                    )\n\n    # if locales is not a list, make it one\n    locales = settings['LOCALE']\n\n    if isinstance(locales, basestring):\n        locales = [locales]\n\n    # try to set the different locales, fallback on the default.\n    if not locales:\n        locales = _DEFAULT_CONFIG['LOCALE']\n\n    for locale_ in locales:\n        try:\n            locale.setlocale(locale.LC_ALL, locale_)\n            break  # break if it is successfull\n        except locale.Error:\n            pass\n    else:\n        logger.warn(\"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[len(siteurl) - 1:] == '/'):\n            settings['SITEURL'] = siteurl[:-1]\n            logger.warn(\"Removed extraneous trailing slash from SITEURL.\")\n        # If SITEURL is defined but FEED_DOMAIN isn't, set FEED_DOMAIN = 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    if (('FEED' in settings) or ('FEED_RSS' in settings)) and (not 'FEED_DOMAIN' in settings):\n        logger.warn(\"Since feed URLs should always be absolute, you should specify \"\n                 \"FEED_DOMAIN in your settings. (e.g., 'FEED_DOMAIN = \"\n                 \"http://www.example.com')\")\n\n    if not 'TIMEZONE' in settings:\n        logger.warn(\"No timezone information specified in the settings. Assuming\"\n                 \" your timezone is UTC for feed generation. Check \"\n                 \"http://docs.notmyidea.org/alexis/pelican/settings.html#timezone \"\n                 \"for more information\")\n\n    return settings\n", "path": "pelican/settings.py"}]}