We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Pagination fails when files don't have an extension
The pagination process assumes that files will have extensions (i.e. usually ".html"). This fails if the URL scheme for the site uses extension-less names. My settings.py has:

```
ARTICLE_URL = '{slug}'
ARTICLE_SAVE_AS = '{slug}'
AUTHOR_URL = 'author/{name}.html'
CATEGORY_URL = 'category/{name}'
CATEGORY_SAVE_AS = 'category/{name}'
TAG_URL = 'tag/{name}'
TAG_SAVE_AS = 'tag/{name}'
```

This means that, for example, the linux tag is listed at `http://example.com/tag/linux` -- note: no extension. Using commit  1580f7f (current master as of this writing), only the final page of tags is generated, because the same file is rewritten for each page because the name doesn't change.

I have a patch for this and will submit a PR.


--- 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/writers.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 from __future__ import with_statement
3 
4 import os
5 import re
6 import locale
7 import logging
8 
9 from codecs import open
10 from functools import partial
11 from feedgenerator import Atom1Feed, Rss201rev2Feed
12 from jinja2 import Markup
13 from pelican.paginator import Paginator
14 from pelican.utils import get_relative_path, set_date_tzinfo
15 
16 logger = logging.getLogger(__name__)
17 
18 
19 class Writer(object):
20 
21     def __init__(self, output_path, settings=None):
22         self.output_path = output_path
23         self.reminder = dict()
24         self.settings = settings or {}
25 
26     def _create_new_feed(self, feed_type, context):
27         feed_class = Rss201rev2Feed if feed_type == 'rss' else Atom1Feed
28         sitename = Markup(context['SITENAME']).striptags()
29         feed = feed_class(
30             title=sitename,
31             link=(self.site_url + '/'),
32             feed_url=self.feed_url,
33             description=context.get('SITESUBTITLE', ''))
34         return feed
35 
36     def _add_item_to_the_feed(self, feed, item):
37 
38         title = Markup(item.title).striptags()
39         feed.add_item(
40             title=title,
41             link='%s/%s' % (self.site_url, item.url),
42             unique_id='tag:%s,%s:%s' % (self.site_url.replace('http://', ''),
43                                         item.date.date(), item.url),
44             description=item.content,
45             categories=item.tags if hasattr(item, 'tags') else None,
46             author_name=getattr(item, 'author', 'John Doe'),
47             pubdate=set_date_tzinfo(item.date,
48                 self.settings.get('TIMEZONE', None)))
49 
50     def write_feed(self, elements, context, filename=None, feed_type='atom'):
51         """Generate a feed with the list of articles provided
52 
53         Return the feed. If no output_path or filename is specified, just
54         return the feed object.
55 
56         :param elements: the articles to put on the feed.
57         :param context: the context to get the feed metadata.
58         :param filename: the filename to output.
59         :param feed_type: the feed type to use (atom or rss)
60         """
61         old_locale = locale.setlocale(locale.LC_ALL)
62         locale.setlocale(locale.LC_ALL, 'C')
63         try:
64             self.site_url = context.get('SITEURL', get_relative_path(filename))
65             self.feed_domain = context.get('FEED_DOMAIN')
66             self.feed_url = '%s/%s' % (self.feed_domain, filename)
67 
68             feed = self._create_new_feed(feed_type, context)
69 
70             max_items = len(elements)
71             if self.settings['FEED_MAX_ITEMS']:
72                 max_items = min(self.settings['FEED_MAX_ITEMS'], max_items)
73             for i in xrange(max_items):
74                 self._add_item_to_the_feed(feed, elements[i])
75 
76             if filename:
77                 complete_path = os.path.join(self.output_path, filename)
78                 try:
79                     os.makedirs(os.path.dirname(complete_path))
80                 except Exception:
81                     pass
82                 fp = open(complete_path, 'w')
83                 feed.write(fp, 'utf-8')
84                 logger.info('writing %s' % complete_path)
85 
86                 fp.close()
87             return feed
88         finally:
89             locale.setlocale(locale.LC_ALL, old_locale)
90 
91     def write_file(self, name, template, context, relative_urls=True,
92         paginated=None, **kwargs):
93         """Render the template and write the file.
94 
95         :param name: name of the file to output
96         :param template: template to use to generate the content
97         :param context: dict to pass to the templates.
98         :param relative_urls: use relative urls or absolutes ones
99         :param paginated: dict of article list to paginate - must have the
100             same length (same list in different orders)
101         :param **kwargs: additional variables to pass to the templates
102         """
103 
104         if name is False:
105             return
106         elif not name:
107             # other stuff, just return for now
108             return
109 
110         def _write_file(template, localcontext, output_path, name):
111             """Render the template write the file."""
112             old_locale = locale.setlocale(locale.LC_ALL)
113             locale.setlocale(locale.LC_ALL, 'C')
114             try:
115                 output = template.render(localcontext)
116             finally:
117                 locale.setlocale(locale.LC_ALL, old_locale)
118             filename = os.sep.join((output_path, name))
119             try:
120                 os.makedirs(os.path.dirname(filename))
121             except Exception:
122                 pass
123             with open(filename, 'w', encoding='utf-8') as f:
124                 f.write(output)
125             logger.info(u'writing %s' % filename)
126 
127         localcontext = context.copy()
128         if relative_urls:
129             localcontext['SITEURL'] = get_relative_path(name)
130 
131         localcontext.update(kwargs)
132         if relative_urls:
133             self.update_context_contents(name, localcontext)
134 
135         # check paginated
136         paginated = paginated or {}
137         if paginated:
138             # pagination needed, init paginators
139             paginators = {}
140             for key in paginated.iterkeys():
141                 object_list = paginated[key]
142 
143                 if self.settings.get('DEFAULT_PAGINATION'):
144                     paginators[key] = Paginator(object_list,
145                         self.settings.get('DEFAULT_PAGINATION'),
146                         self.settings.get('DEFAULT_ORPHANS'))
147                 else:
148                     paginators[key] = Paginator(object_list, len(object_list))
149 
150             # generated pages, and write
151             for page_num in range(paginators.values()[0].num_pages):
152                 paginated_localcontext = localcontext.copy()
153                 paginated_name = name
154                 for key in paginators.iterkeys():
155                     paginator = paginators[key]
156                     page = paginator.page(page_num + 1)
157                     paginated_localcontext.update(
158                             {'%s_paginator' % key: paginator,
159                              '%s_page' % key: page})
160                 if page_num > 0:
161                     ext = '.' + paginated_name.rsplit('.')[-1]
162                     paginated_name = paginated_name.replace(ext,
163                         '%s%s' % (page_num + 1, ext))
164 
165                 _write_file(template, paginated_localcontext, self.output_path,
166                     paginated_name)
167         else:
168             # no pagination
169             _write_file(template, localcontext, self.output_path, name)
170 
171     def update_context_contents(self, name, context):
172         """Recursively run the context to find elements (articles, pages, etc)
173         whose content getter needs to be modified in order to deal with
174         relative paths.
175 
176         :param name: name of the file to output.
177         :param context: dict that will be passed to the templates, which need
178                         to be updated.
179         """
180         def _update_content(name, input):
181             """Change all the relatives paths of the input content to relatives
182             paths suitable fot the ouput content
183 
184             :param name: path of the output.
185             :param input: input resource that will be passed to the templates.
186             """
187             content = input._content
188 
189             hrefs = re.compile(r"""
190                 (?P<markup><\s*[^\>]*  # match tag with src and href attr
191                     (?:href|src)\s*=\s*
192                 )
193                 (?P<quote>["\'])       # require value to be quoted
194                 (?![#?])               # don't match fragment or query URLs
195                 (?![a-z]+:)            # don't match protocol URLS
196                 (?P<path>.*?)          # the url value
197                 \2""", re.X)
198 
199             def replacer(m):
200                 relative_path = m.group('path')
201                 dest_path = os.path.normpath(
202                                 os.sep.join((get_relative_path(name), "static",
203                                 relative_path)))
204 
205                 return m.group('markup') + m.group('quote') + dest_path \
206                         + m.group('quote')
207 
208             return hrefs.sub(replacer, content)
209 
210         if context is None:
211             return
212         if hasattr(context, 'values'):
213             context = context.values()
214 
215         for item in context:
216             # run recursively on iterables
217             if hasattr(item, '__iter__'):
218                 self.update_context_contents(name, item)
219 
220             # if it is a content, patch it
221             elif hasattr(item, '_content'):
222                 relative_path = get_relative_path(name)
223 
224                 paths = self.reminder.setdefault(item, [])
225                 if relative_path not in paths:
226                     paths.append(relative_path)
227                     setattr(item, "_get_content",
228                         partial(_update_content, name, item))
229
```
--- 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/writers.py b/pelican/writers.py
--- a/pelican/writers.py
+++ b/pelican/writers.py
@@ -148,9 +148,9 @@
                     paginators[key] = Paginator(object_list, len(object_list))
 
             # generated pages, and write
+            name_root, ext = os.path.splitext(name)
             for page_num in range(paginators.values()[0].num_pages):
                 paginated_localcontext = localcontext.copy()
-                paginated_name = name
                 for key in paginators.iterkeys():
                     paginator = paginators[key]
                     page = paginator.page(page_num + 1)
@@ -158,9 +158,10 @@
                             {'%s_paginator' % key: paginator,
                              '%s_page' % key: page})
                 if page_num > 0:
-                    ext = '.' + paginated_name.rsplit('.')[-1]
-                    paginated_name = paginated_name.replace(ext,
-                        '%s%s' % (page_num + 1, ext))
+                    paginated_name = '%s%s%s' % (
+                        name_root, page_num + 1, ext)
+                else:
+                    paginated_name = name
 
                 _write_file(template, paginated_localcontext, self.output_path,
                     paginated_name)

{"golden_diff": "diff --git a/pelican/writers.py b/pelican/writers.py\n--- a/pelican/writers.py\n+++ b/pelican/writers.py\n@@ -148,9 +148,9 @@\n                     paginators[key] = Paginator(object_list, len(object_list))\n \n             # generated pages, and write\n+            name_root, ext = os.path.splitext(name)\n             for page_num in range(paginators.values()[0].num_pages):\n                 paginated_localcontext = localcontext.copy()\n-                paginated_name = name\n                 for key in paginators.iterkeys():\n                     paginator = paginators[key]\n                     page = paginator.page(page_num + 1)\n@@ -158,9 +158,10 @@\n                             {'%s_paginator' % key: paginator,\n                              '%s_page' % key: page})\n                 if page_num > 0:\n-                    ext = '.' + paginated_name.rsplit('.')[-1]\n-                    paginated_name = paginated_name.replace(ext,\n-                        '%s%s' % (page_num + 1, ext))\n+                    paginated_name = '%s%s%s' % (\n+                        name_root, page_num + 1, ext)\n+                else:\n+                    paginated_name = name\n \n                 _write_file(template, paginated_localcontext, self.output_path,\n                     paginated_name)\n", "issue": "Pagination fails when files don't have an extension\nThe pagination process assumes that files will have extensions (i.e. usually \".html\"). This fails if the URL scheme for the site uses extension-less names. My settings.py has:\n\n```\nARTICLE_URL = '{slug}'\nARTICLE_SAVE_AS = '{slug}'\nAUTHOR_URL = 'author/{name}.html'\nCATEGORY_URL = 'category/{name}'\nCATEGORY_SAVE_AS = 'category/{name}'\nTAG_URL = 'tag/{name}'\nTAG_SAVE_AS = 'tag/{name}'\n```\n\nThis means that, for example, the linux tag is listed at `http://example.com/tag/linux` -- note: no extension. Using commit  1580f7f (current master as of this writing), only the final page of tags is generated, because the same file is rewritten for each page because the name doesn't change.\n\nI have a patch for this and will submit a PR.\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nfrom __future__ import with_statement\n\nimport os\nimport re\nimport locale\nimport logging\n\nfrom codecs import open\nfrom functools import partial\nfrom feedgenerator import Atom1Feed, Rss201rev2Feed\nfrom jinja2 import Markup\nfrom pelican.paginator import Paginator\nfrom pelican.utils import get_relative_path, set_date_tzinfo\n\nlogger = logging.getLogger(__name__)\n\n\nclass Writer(object):\n\n    def __init__(self, output_path, settings=None):\n        self.output_path = output_path\n        self.reminder = dict()\n        self.settings = settings or {}\n\n    def _create_new_feed(self, feed_type, context):\n        feed_class = Rss201rev2Feed if feed_type == 'rss' else Atom1Feed\n        sitename = Markup(context['SITENAME']).striptags()\n        feed = feed_class(\n            title=sitename,\n            link=(self.site_url + '/'),\n            feed_url=self.feed_url,\n            description=context.get('SITESUBTITLE', ''))\n        return feed\n\n    def _add_item_to_the_feed(self, feed, item):\n\n        title = Markup(item.title).striptags()\n        feed.add_item(\n            title=title,\n            link='%s/%s' % (self.site_url, item.url),\n            unique_id='tag:%s,%s:%s' % (self.site_url.replace('http://', ''),\n                                        item.date.date(), item.url),\n            description=item.content,\n            categories=item.tags if hasattr(item, 'tags') else None,\n            author_name=getattr(item, 'author', 'John Doe'),\n            pubdate=set_date_tzinfo(item.date,\n                self.settings.get('TIMEZONE', None)))\n\n    def write_feed(self, elements, context, filename=None, feed_type='atom'):\n        \"\"\"Generate a feed with the list of articles provided\n\n        Return the feed. If no output_path or filename is specified, just\n        return the feed object.\n\n        :param elements: the articles to put on the feed.\n        :param context: the context to get the feed metadata.\n        :param filename: the filename to output.\n        :param feed_type: the feed type to use (atom or rss)\n        \"\"\"\n        old_locale = locale.setlocale(locale.LC_ALL)\n        locale.setlocale(locale.LC_ALL, 'C')\n        try:\n            self.site_url = context.get('SITEURL', get_relative_path(filename))\n            self.feed_domain = context.get('FEED_DOMAIN')\n            self.feed_url = '%s/%s' % (self.feed_domain, filename)\n\n            feed = self._create_new_feed(feed_type, context)\n\n            max_items = len(elements)\n            if self.settings['FEED_MAX_ITEMS']:\n                max_items = min(self.settings['FEED_MAX_ITEMS'], max_items)\n            for i in xrange(max_items):\n                self._add_item_to_the_feed(feed, elements[i])\n\n            if filename:\n                complete_path = os.path.join(self.output_path, filename)\n                try:\n                    os.makedirs(os.path.dirname(complete_path))\n                except Exception:\n                    pass\n                fp = open(complete_path, 'w')\n                feed.write(fp, 'utf-8')\n                logger.info('writing %s' % complete_path)\n\n                fp.close()\n            return feed\n        finally:\n            locale.setlocale(locale.LC_ALL, old_locale)\n\n    def write_file(self, name, template, context, relative_urls=True,\n        paginated=None, **kwargs):\n        \"\"\"Render the template and write the file.\n\n        :param name: name of the file to output\n        :param template: template to use to generate the content\n        :param context: dict to pass to the templates.\n        :param relative_urls: use relative urls or absolutes ones\n        :param paginated: dict of article list to paginate - must have the\n            same length (same list in different orders)\n        :param **kwargs: additional variables to pass to the templates\n        \"\"\"\n\n        if name is False:\n            return\n        elif not name:\n            # other stuff, just return for now\n            return\n\n        def _write_file(template, localcontext, output_path, name):\n            \"\"\"Render the template write the file.\"\"\"\n            old_locale = locale.setlocale(locale.LC_ALL)\n            locale.setlocale(locale.LC_ALL, 'C')\n            try:\n                output = template.render(localcontext)\n            finally:\n                locale.setlocale(locale.LC_ALL, old_locale)\n            filename = os.sep.join((output_path, name))\n            try:\n                os.makedirs(os.path.dirname(filename))\n            except Exception:\n                pass\n            with open(filename, 'w', encoding='utf-8') as f:\n                f.write(output)\n            logger.info(u'writing %s' % filename)\n\n        localcontext = context.copy()\n        if relative_urls:\n            localcontext['SITEURL'] = get_relative_path(name)\n\n        localcontext.update(kwargs)\n        if relative_urls:\n            self.update_context_contents(name, localcontext)\n\n        # check paginated\n        paginated = paginated or {}\n        if paginated:\n            # pagination needed, init paginators\n            paginators = {}\n            for key in paginated.iterkeys():\n                object_list = paginated[key]\n\n                if self.settings.get('DEFAULT_PAGINATION'):\n                    paginators[key] = Paginator(object_list,\n                        self.settings.get('DEFAULT_PAGINATION'),\n                        self.settings.get('DEFAULT_ORPHANS'))\n                else:\n                    paginators[key] = Paginator(object_list, len(object_list))\n\n            # generated pages, and write\n            for page_num in range(paginators.values()[0].num_pages):\n                paginated_localcontext = localcontext.copy()\n                paginated_name = name\n                for key in paginators.iterkeys():\n                    paginator = paginators[key]\n                    page = paginator.page(page_num + 1)\n                    paginated_localcontext.update(\n                            {'%s_paginator' % key: paginator,\n                             '%s_page' % key: page})\n                if page_num > 0:\n                    ext = '.' + paginated_name.rsplit('.')[-1]\n                    paginated_name = paginated_name.replace(ext,\n                        '%s%s' % (page_num + 1, ext))\n\n                _write_file(template, paginated_localcontext, self.output_path,\n                    paginated_name)\n        else:\n            # no pagination\n            _write_file(template, localcontext, self.output_path, name)\n\n    def update_context_contents(self, name, context):\n        \"\"\"Recursively run the context to find elements (articles, pages, etc)\n        whose content getter needs to be modified in order to deal with\n        relative paths.\n\n        :param name: name of the file to output.\n        :param context: dict that will be passed to the templates, which need\n                        to be updated.\n        \"\"\"\n        def _update_content(name, input):\n            \"\"\"Change all the relatives paths of the input content to relatives\n            paths suitable fot the ouput content\n\n            :param name: path of the output.\n            :param input: input resource that will be passed to the templates.\n            \"\"\"\n            content = input._content\n\n            hrefs = re.compile(r\"\"\"\n                (?P<markup><\\s*[^\\>]*  # match tag with src and href attr\n                    (?:href|src)\\s*=\\s*\n                )\n                (?P<quote>[\"\\'])       # require value to be quoted\n                (?![#?])               # don't match fragment or query URLs\n                (?![a-z]+:)            # don't match protocol URLS\n                (?P<path>.*?)          # the url value\n                \\2\"\"\", re.X)\n\n            def replacer(m):\n                relative_path = m.group('path')\n                dest_path = os.path.normpath(\n                                os.sep.join((get_relative_path(name), \"static\",\n                                relative_path)))\n\n                return m.group('markup') + m.group('quote') + dest_path \\\n                        + m.group('quote')\n\n            return hrefs.sub(replacer, content)\n\n        if context is None:\n            return\n        if hasattr(context, 'values'):\n            context = context.values()\n\n        for item in context:\n            # run recursively on iterables\n            if hasattr(item, '__iter__'):\n                self.update_context_contents(name, item)\n\n            # if it is a content, patch it\n            elif hasattr(item, '_content'):\n                relative_path = get_relative_path(name)\n\n                paths = self.reminder.setdefault(item, [])\n                if relative_path not in paths:\n                    paths.append(relative_path)\n                    setattr(item, \"_get_content\",\n                        partial(_update_content, name, item))\n", "path": "pelican/writers.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nfrom __future__ import with_statement\n\nimport os\nimport re\nimport locale\nimport logging\n\nfrom codecs import open\nfrom functools import partial\nfrom feedgenerator import Atom1Feed, Rss201rev2Feed\nfrom jinja2 import Markup\nfrom pelican.paginator import Paginator\nfrom pelican.utils import get_relative_path, set_date_tzinfo\n\nlogger = logging.getLogger(__name__)\n\n\nclass Writer(object):\n\n    def __init__(self, output_path, settings=None):\n        self.output_path = output_path\n        self.reminder = dict()\n        self.settings = settings or {}\n\n    def _create_new_feed(self, feed_type, context):\n        feed_class = Rss201rev2Feed if feed_type == 'rss' else Atom1Feed\n        sitename = Markup(context['SITENAME']).striptags()\n        feed = feed_class(\n            title=sitename,\n            link=(self.site_url + '/'),\n            feed_url=self.feed_url,\n            description=context.get('SITESUBTITLE', ''))\n        return feed\n\n    def _add_item_to_the_feed(self, feed, item):\n\n        title = Markup(item.title).striptags()\n        feed.add_item(\n            title=title,\n            link='%s/%s' % (self.site_url, item.url),\n            unique_id='tag:%s,%s:%s' % (self.site_url.replace('http://', ''),\n                                        item.date.date(), item.url),\n            description=item.content,\n            categories=item.tags if hasattr(item, 'tags') else None,\n            author_name=getattr(item, 'author', 'John Doe'),\n            pubdate=set_date_tzinfo(item.date,\n                self.settings.get('TIMEZONE', None)))\n\n    def write_feed(self, elements, context, filename=None, feed_type='atom'):\n        \"\"\"Generate a feed with the list of articles provided\n\n        Return the feed. If no output_path or filename is specified, just\n        return the feed object.\n\n        :param elements: the articles to put on the feed.\n        :param context: the context to get the feed metadata.\n        :param filename: the filename to output.\n        :param feed_type: the feed type to use (atom or rss)\n        \"\"\"\n        old_locale = locale.setlocale(locale.LC_ALL)\n        locale.setlocale(locale.LC_ALL, 'C')\n        try:\n            self.site_url = context.get('SITEURL', get_relative_path(filename))\n            self.feed_domain = context.get('FEED_DOMAIN')\n            self.feed_url = '%s/%s' % (self.feed_domain, filename)\n\n            feed = self._create_new_feed(feed_type, context)\n\n            max_items = len(elements)\n            if self.settings['FEED_MAX_ITEMS']:\n                max_items = min(self.settings['FEED_MAX_ITEMS'], max_items)\n            for i in xrange(max_items):\n                self._add_item_to_the_feed(feed, elements[i])\n\n            if filename:\n                complete_path = os.path.join(self.output_path, filename)\n                try:\n                    os.makedirs(os.path.dirname(complete_path))\n                except Exception:\n                    pass\n                fp = open(complete_path, 'w')\n                feed.write(fp, 'utf-8')\n                logger.info('writing %s' % complete_path)\n\n                fp.close()\n            return feed\n        finally:\n            locale.setlocale(locale.LC_ALL, old_locale)\n\n    def write_file(self, name, template, context, relative_urls=True,\n        paginated=None, **kwargs):\n        \"\"\"Render the template and write the file.\n\n        :param name: name of the file to output\n        :param template: template to use to generate the content\n        :param context: dict to pass to the templates.\n        :param relative_urls: use relative urls or absolutes ones\n        :param paginated: dict of article list to paginate - must have the\n            same length (same list in different orders)\n        :param **kwargs: additional variables to pass to the templates\n        \"\"\"\n\n        if name is False:\n            return\n        elif not name:\n            # other stuff, just return for now\n            return\n\n        def _write_file(template, localcontext, output_path, name):\n            \"\"\"Render the template write the file.\"\"\"\n            old_locale = locale.setlocale(locale.LC_ALL)\n            locale.setlocale(locale.LC_ALL, 'C')\n            try:\n                output = template.render(localcontext)\n            finally:\n                locale.setlocale(locale.LC_ALL, old_locale)\n            filename = os.sep.join((output_path, name))\n            try:\n                os.makedirs(os.path.dirname(filename))\n            except Exception:\n                pass\n            with open(filename, 'w', encoding='utf-8') as f:\n                f.write(output)\n            logger.info(u'writing %s' % filename)\n\n        localcontext = context.copy()\n        if relative_urls:\n            localcontext['SITEURL'] = get_relative_path(name)\n\n        localcontext.update(kwargs)\n        if relative_urls:\n            self.update_context_contents(name, localcontext)\n\n        # check paginated\n        paginated = paginated or {}\n        if paginated:\n            # pagination needed, init paginators\n            paginators = {}\n            for key in paginated.iterkeys():\n                object_list = paginated[key]\n\n                if self.settings.get('DEFAULT_PAGINATION'):\n                    paginators[key] = Paginator(object_list,\n                        self.settings.get('DEFAULT_PAGINATION'),\n                        self.settings.get('DEFAULT_ORPHANS'))\n                else:\n                    paginators[key] = Paginator(object_list, len(object_list))\n\n            # generated pages, and write\n            name_root, ext = os.path.splitext(name)\n            for page_num in range(paginators.values()[0].num_pages):\n                paginated_localcontext = localcontext.copy()\n                for key in paginators.iterkeys():\n                    paginator = paginators[key]\n                    page = paginator.page(page_num + 1)\n                    paginated_localcontext.update(\n                            {'%s_paginator' % key: paginator,\n                             '%s_page' % key: page})\n                if page_num > 0:\n                    paginated_name = '%s%s%s' % (\n                        name_root, page_num + 1, ext)\n                else:\n                    paginated_name = name\n\n                _write_file(template, paginated_localcontext, self.output_path,\n                    paginated_name)\n        else:\n            # no pagination\n            _write_file(template, localcontext, self.output_path, name)\n\n    def update_context_contents(self, name, context):\n        \"\"\"Recursively run the context to find elements (articles, pages, etc)\n        whose content getter needs to be modified in order to deal with\n        relative paths.\n\n        :param name: name of the file to output.\n        :param context: dict that will be passed to the templates, which need\n                        to be updated.\n        \"\"\"\n        def _update_content(name, input):\n            \"\"\"Change all the relatives paths of the input content to relatives\n            paths suitable fot the ouput content\n\n            :param name: path of the output.\n            :param input: input resource that will be passed to the templates.\n            \"\"\"\n            content = input._content\n\n            hrefs = re.compile(r\"\"\"\n                (?P<markup><\\s*[^\\>]*  # match tag with src and href attr\n                    (?:href|src)\\s*=\\s*\n                )\n                (?P<quote>[\"\\'])       # require value to be quoted\n                (?![#?])               # don't match fragment or query URLs\n                (?![a-z]+:)            # don't match protocol URLS\n                (?P<path>.*?)          # the url value\n                \\2\"\"\", re.X)\n\n            def replacer(m):\n                relative_path = m.group('path')\n                dest_path = os.path.normpath(\n                                os.sep.join((get_relative_path(name), \"static\",\n                                relative_path)))\n\n                return m.group('markup') + m.group('quote') + dest_path \\\n                        + m.group('quote')\n\n            return hrefs.sub(replacer, content)\n\n        if context is None:\n            return\n        if hasattr(context, 'values'):\n            context = context.values()\n\n        for item in context:\n            # run recursively on iterables\n            if hasattr(item, '__iter__'):\n                self.update_context_contents(name, item)\n\n            # if it is a content, patch it\n            elif hasattr(item, '_content'):\n                relative_path = get_relative_path(name)\n\n                paths = self.reminder.setdefault(item, [])\n                if relative_path not in paths:\n                    paths.append(relative_path)\n                    setattr(item, \"_get_content\",\n                        partial(_update_content, name, item))\n", "path": "pelican/writers.py"}]}