From 5214248344ba75ec1e0ea804bcfcc25bc4b533e2 Mon Sep 17 00:00:00 2001 From: DJ Ramones <50655786+djramones@users.noreply.github.com> Date: Sun, 18 Jun 2023 11:07:39 +0800 Subject: [PATCH 1/5] Implement period_archives common context variable Also, set default patterns for time-period *_ARCHIVE_URL settings. --- docs/settings.rst | 25 +++--- docs/themes.rst | 61 ++++++++++++++ pelican/generators.py | 137 ++++++++++++++++++------------- pelican/settings.py | 6 +- pelican/tests/test_generators.py | 97 ++++++++++++++++++++++ 5 files changed, 256 insertions(+), 70 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index e51c6a120..259b53f5e 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -572,33 +572,36 @@ posts for the month at ``posts/2011/Aug/index.html``. This way a reader can remove a portion of your URL and automatically arrive at an appropriate archive of posts, without having to specify a page name. -.. data:: YEAR_ARCHIVE_URL = '' - - The URL to use for per-year archives of your posts. Used only if you have - the ``{url}`` placeholder in ``PAGINATION_PATTERNS``. - .. data:: YEAR_ARCHIVE_SAVE_AS = '' The location to save per-year archives of your posts. -.. data:: MONTH_ARCHIVE_URL = '' +.. data:: YEAR_ARCHIVE_URL = 'posts/{date:%Y}/' - The URL to use for per-month archives of your posts. Used only if you have - the ``{url}`` placeholder in ``PAGINATION_PATTERNS``. + The URL to use for per-year archives of your posts. This default value + matches a ``YEAR_ARCHIVE_SAVE_AS`` setting of + ``posts/{date:%Y}/index.html``. .. data:: MONTH_ARCHIVE_SAVE_AS = '' The location to save per-month archives of your posts. -.. data:: DAY_ARCHIVE_URL = '' +.. data:: MONTH_ARCHIVE_URL = 'posts/{date:%Y}/{date:%b}/' - The URL to use for per-day archives of your posts. Used only if you have the - ``{url}`` placeholder in ``PAGINATION_PATTERNS``. + The URL to use for per-month archives of your posts. This default value + matches a ``MONTH_ARCHIVE_SAVE_AS`` setting of + ``posts/{date:%Y}/{date:%b}/index.html``. .. data:: DAY_ARCHIVE_SAVE_AS = '' The location to save per-day archives of your posts. +.. data:: DAY_ARCHIVE_URL = 'posts/{date:%Y}/{date:%b}/{date:%d}/' + + The URL to use for per-day archives of your posts. This default value + matches a ``DAY_ARCHIVE_SAVE_AS`` setting of + ``posts/{date:%Y}/{date:%b}/{date:%d}/index.html``. + ``DIRECT_TEMPLATES`` work a bit differently than noted above. Only the ``_SAVE_AS`` settings are available, but it is available for any direct template. diff --git a/docs/themes.rst b/docs/themes.rst index fe6337d66..8e46b7160 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -71,6 +71,8 @@ All templates will receive the variables defined in your settings file, as long as they are in all-caps. You can access them directly. +.. _common_variables: + Common Variables ---------------- @@ -92,6 +94,10 @@ dates The same list of articles, but ordered by date, ascending. hidden_articles The list of hidden articles drafts The list of draft articles +period_archives A dictionary containing elements related to + time-period archives (if enabled). See the section + :ref:`Listing and Linking to Period Archives + ` for details. authors A list of (author, articles) tuples, containing all the authors and corresponding articles (values) categories A list of (category, articles) tuples, containing @@ -348,6 +354,61 @@ period_archives.html template `_. +.. _period_archives_variable: + +Listing and Linking to Period Archives +"""""""""""""""""""""""""""""""""""""" + +The ``period_archives`` variable can be used to generate a list of links to +the set of period archives that Pelican generates. As a :ref:`common variable +`, it is available for use in any template, so you +can implement such an index in a custom direct template, or in a sidebar +visible across different site pages. + +``period_archives`` is a dict that may contain ``year``, ``month``, and/or +``day`` keys, depending on which ``*_ARCHIVE_SAVE_AS`` settings are enabled. +The corresponding value is a list of dicts, where each dict in turn represents +a time period, with the following keys and values: + +=================== =================================================== +Key Value +=================== =================================================== +period The same tuple as described in + ``period_archives.html``, e.g. + ``(2023, 'June', 18)``. +period_num The same tuple as described in + ``period_archives.html``, e.g. ``(2023, 6, 18)``. +url The URL to the period archive page, e.g. + ``posts/2023/06/18/``. This is controlled by the + corresponding ``*_ARCHIVE_URL`` setting. +save_as The path to the save location of the period archive + page file, e.g. ``posts/2023/06/18/index.html``. + This is used internally by Pelican and is usually + not relevant to themes. +articles A list of :ref:`Article ` objects + that fall under the time period. +dates Same list as ``articles``, but ordered by date. +=================== =================================================== + +Here is an example of how ``period_archives`` can be used in a template: + +.. code-block:: html+jinja + + + +You can change ``period_archives.month`` in the ``for`` statement to +``period_archives.year`` or ``period_archives.day`` as appropriate, depending +on the time period granularity desired. + + Objects ======= diff --git a/pelican/generators.py b/pelican/generators.py index e18531bec..ad0f84c46 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -295,6 +295,7 @@ def __init__(self, *args, **kwargs): self.drafts = [] # only drafts in default language self.drafts_translations = [] self.dates = {} + self.period_archives = defaultdict(list) self.tags = defaultdict(list) self.categories = defaultdict(list) self.related_posts = [] @@ -483,64 +484,17 @@ def generate_period_archives(self, write): except PelicanTemplateNotFound: template = self.get_template('archives') - period_save_as = { - 'year': self.settings['YEAR_ARCHIVE_SAVE_AS'], - 'month': self.settings['MONTH_ARCHIVE_SAVE_AS'], - 'day': self.settings['DAY_ARCHIVE_SAVE_AS'], - } - - period_url = { - 'year': self.settings['YEAR_ARCHIVE_URL'], - 'month': self.settings['MONTH_ARCHIVE_URL'], - 'day': self.settings['DAY_ARCHIVE_URL'], - } - - period_date_key = { - 'year': attrgetter('date.year'), - 'month': attrgetter('date.year', 'date.month'), - 'day': attrgetter('date.year', 'date.month', 'date.day') - } - - def _generate_period_archives(dates, key, save_as_fmt, url_fmt): - """Generate period archives from `dates`, grouped by - `key` and written to `save_as`. - """ - # `dates` is already sorted by date - for _period, group in groupby(dates, key=key): - archive = list(group) - articles = [a for a in self.articles if a in archive] - # arbitrarily grab the first date so that the usual - # format string syntax can be used for specifying the - # period archive dates - date = archive[0].date - save_as = save_as_fmt.format(date=date) - url = url_fmt.format(date=date) + for granularity in list(self.period_archives.keys()): + for period in self.period_archives[granularity]: + context = self.context.copy() + context['period'] = period['period'] + context['period_num'] = period['period_num'] - if key == period_date_key['year']: - context["period"] = (_period,) - context["period_num"] = (_period,) - else: - month_name = calendar.month_name[_period[1]] - if key == period_date_key['month']: - context["period"] = (_period[0], - month_name) - else: - context["period"] = (_period[0], - month_name, - _period[2]) - context["period_num"] = tuple(_period) - - write(save_as, template, context, articles=articles, - dates=archive, template_name='period_archives', - blog=True, url=url, all_articles=self.articles) - - for period in 'year', 'month', 'day': - save_as = period_save_as[period] - url = period_url[period] - if save_as: - key = period_date_key[period] - _generate_period_archives(self.dates, key, save_as, url) + write(period['save_as'], template, context, + articles=period['articles'], dates=period['dates'], + template_name='period_archives', blog=True, + url=period['url'], all_articles=self.articles) def generate_direct_templates(self, write): """Generate direct templates pages""" @@ -680,6 +634,74 @@ def _process(arts): self.dates.sort(key=attrgetter('date'), reverse=self.context['NEWEST_FIRST_ARCHIVES']) + def _build_period_archives(sorted_articles): + period_archives = defaultdict(list) + + period_archives_settings = { + 'year': { + 'save_as': self.settings['YEAR_ARCHIVE_SAVE_AS'], + 'url': self.settings['YEAR_ARCHIVE_URL'], + }, + 'month': { + 'save_as': self.settings['MONTH_ARCHIVE_SAVE_AS'], + 'url': self.settings['MONTH_ARCHIVE_URL'], + }, + 'day': { + 'save_as': self.settings['DAY_ARCHIVE_SAVE_AS'], + 'url': self.settings['DAY_ARCHIVE_URL'], + }, + } + + granularity_key_func = { + 'year': attrgetter('date.year'), + 'month': attrgetter('date.year', 'date.month'), + 'day': attrgetter('date.year', 'date.month', 'date.day'), + } + + for granularity in 'year', 'month', 'day': + save_as_fmt = period_archives_settings[granularity]['save_as'] + url_fmt = period_archives_settings[granularity]['url'] + key_func = granularity_key_func[granularity] + + if not save_as_fmt: + # the archives for this period granularity are not needed + continue + + for period, group in groupby(sorted_articles, key=key_func): + period_archive = {} + + dates = list(group) + period_archive['dates'] = dates + period_archive['articles'] = [ + a for a in self.articles if a in dates + ] + + # use the first date to specify the period archive URL + # and save_as; the specific date used does not matter as + # they all belong to the same period + d = dates[0].date + period_archive['save_as'] = save_as_fmt.format(date=d) + period_archive['url'] = url_fmt.format(date=d) + + if granularity == 'year': + period_archive['period'] = (period,) + period_archive['period_num'] = (period,) + else: + month_name = calendar.month_name[period[1]] + if granularity == 'month': + period_archive['period'] = (period[0], month_name) + else: + period_archive['period'] = (period[0], + month_name, + period[2]) + period_archive['period_num'] = tuple(period) + + period_archives[granularity].append(period_archive) + + return period_archives + + self.period_archives = _build_period_archives(self.dates) + # and generate the output :) # order the categories per name @@ -694,6 +716,9 @@ def _process(arts): 'articles', 'drafts', 'hidden_articles', 'dates', 'tags', 'categories', 'authors', 'related_posts')) + # _update_context flattens dicts, which should not happen to + # period_archives, so we update the context directly for it: + self.context['period_archives'] = self.period_archives self.save_cache() self.readers.save_cache() signals.article_generator_finalized.send(self) diff --git a/pelican/settings.py b/pelican/settings.py index 5b495e863..2405902f2 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -90,11 +90,11 @@ def load_source(name, path): (1, '{name}{extension}', '{name}{extension}'), (2, '{name}{number}{extension}', '{name}{number}{extension}'), ], - 'YEAR_ARCHIVE_URL': '', + 'YEAR_ARCHIVE_URL': 'posts/{date:%Y}/', 'YEAR_ARCHIVE_SAVE_AS': '', - 'MONTH_ARCHIVE_URL': '', + 'MONTH_ARCHIVE_URL': 'posts/{date:%Y}/{date:%b}/', 'MONTH_ARCHIVE_SAVE_AS': '', - 'DAY_ARCHIVE_URL': '', + 'DAY_ARCHIVE_URL': 'posts/{date:%Y}/{date:%b}/{date:%d}/', 'DAY_ARCHIVE_SAVE_AS': '', 'RELATIVE_URLS': False, 'DEFAULT_LANG': 'en', diff --git a/pelican/tests/test_generators.py b/pelican/tests/test_generators.py index 1bc8aff0c..a6fe97317 100644 --- a/pelican/tests/test_generators.py +++ b/pelican/tests/test_generators.py @@ -405,6 +405,103 @@ def test_per_article_template(self): self.assertIn(custom_template, self.articles) self.assertIn(standard_template, self.articles) + def test_period_archives_context(self): + """Test correctness of the period_archives context values.""" + + old_locale = locale.setlocale(locale.LC_ALL) + locale.setlocale(locale.LC_ALL, 'C') + settings = get_settings() + settings['CACHE_PATH'] = self.temp_cache + + # No period archives enabled: + context = get_context(settings) + generator = ArticlesGenerator( + context=context, settings=settings, + path=CONTENT_DIR, theme=settings['THEME'], output_path=None) + generator.generate_context() + period_archives = generator.context['period_archives'] + self.assertEqual(len(period_archives.items()), 0) + + # Year archives enabled: + settings['YEAR_ARCHIVE_SAVE_AS'] = 'posts/{date:%Y}/index.html' + settings['YEAR_ARCHIVE_URL'] = 'posts/{date:%Y}/' + context = get_context(settings) + generator = ArticlesGenerator( + context=context, settings=settings, + path=CONTENT_DIR, theme=settings['THEME'], output_path=None) + generator.generate_context() + period_archives = generator.context['period_archives'] + self.assertEqual(len(period_archives.items()), 1) + self.assertIn('year', period_archives.keys()) + archive_years = [p['period'][0] for p in period_archives['year']] + self.assertIn(1970, archive_years) + self.assertIn(2014, archive_years) + + # Month archives enabled: + settings['MONTH_ARCHIVE_SAVE_AS'] = \ + 'posts/{date:%Y}/{date:%b}/index.html' + settings['MONTH_ARCHIVE_URL'] = \ + 'posts/{date:%Y}/{date:%b}/' + context = get_context(settings) + generator = ArticlesGenerator( + context=context, settings=settings, + path=CONTENT_DIR, theme=settings['THEME'], output_path=None) + generator.generate_context() + period_archives = generator.context['period_archives'] + self.assertEqual(len(period_archives.items()), 2) + self.assertIn('month', period_archives.keys()) + month_archives_tuples = [p['period'] for p in period_archives['month']] + self.assertIn((1970, 'January'), month_archives_tuples) + self.assertIn((2014, 'February'), month_archives_tuples) + + # Day archives enabled: + settings['DAY_ARCHIVE_SAVE_AS'] = \ + 'posts/{date:%Y}/{date:%b}/{date:%d}/index.html' + settings['DAY_ARCHIVE_URL'] = \ + 'posts/{date:%Y}/{date:%b}/{date:%d}/' + context = get_context(settings) + generator = ArticlesGenerator( + context=context, settings=settings, + path=CONTENT_DIR, theme=settings['THEME'], output_path=None) + generator.generate_context() + period_archives = generator.context['period_archives'] + self.assertEqual(len(period_archives.items()), 3) + self.assertIn('day', period_archives.keys()) + day_archives_tuples = [p['period'] for p in period_archives['day']] + self.assertIn((1970, 'January', 1), day_archives_tuples) + self.assertIn((2014, 'February', 9), day_archives_tuples) + + # Further item values tests + filtered_archives = [ + p for p in period_archives['day'] + if p['period'] == (2014, 'February', 9) + ] + self.assertEqual(len(filtered_archives), 1) + sample_archive = filtered_archives[0] + self.assertEqual(sample_archive['period_num'], (2014, 2, 9)) + self.assertEqual( + sample_archive['save_as'], 'posts/2014/Feb/09/index.html') + self.assertEqual( + sample_archive['url'], 'posts/2014/Feb/09/') + articles = [ + d for d in generator.articles if + d.date.year == 2014 and + d.date.month == 2 and + d.date.day == 9 + ] + self.assertEqual(len(sample_archive['articles']), len(articles)) + dates = [ + d for d in generator.dates if + d.date.year == 2014 and + d.date.month == 2 and + d.date.day == 9 + ] + self.assertEqual(len(sample_archive['dates']), len(dates)) + self.assertEqual(sample_archive['dates'][0].title, dates[0].title) + self.assertEqual(sample_archive['dates'][0].date, dates[0].date) + + locale.setlocale(locale.LC_ALL, old_locale) + def test_period_in_timeperiod_archive(self): """ Test that the context of a generated period_archive is passed From 6ba7a0926d506ae3c6ce8e085eb7a7a64c9946f2 Mon Sep 17 00:00:00 2001 From: DJ Ramones <50655786+djramones@users.noreply.github.com> Date: Mon, 19 Jun 2023 12:25:32 +0800 Subject: [PATCH 2/5] Clarify docs on ordering in period_archives var --- docs/themes.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/themes.rst b/docs/themes.rst index 8e46b7160..f68f50c0a 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -368,7 +368,8 @@ visible across different site pages. ``period_archives`` is a dict that may contain ``year``, ``month``, and/or ``day`` keys, depending on which ``*_ARCHIVE_SAVE_AS`` settings are enabled. The corresponding value is a list of dicts, where each dict in turn represents -a time period, with the following keys and values: +a time period (ordered according to the ``NEWEST_FIRST_ARCHIVES`` setting) +with the following keys and values: =================== =================================================== Key Value @@ -387,7 +388,8 @@ save_as The path to the save location of the period archive not relevant to themes. articles A list of :ref:`Article ` objects that fall under the time period. -dates Same list as ``articles``, but ordered by date. +dates Same list as ``articles``, but ordered according + to the ``NEWEST_FIRST_ARCHIVES`` setting. =================== =================================================== Here is an example of how ``period_archives`` can be used in a template: From 8a5f02ac6072e1fe7c406a7177a5745fc6e05112 Mon Sep 17 00:00:00 2001 From: DJ Ramones <50655786+djramones@users.noreply.github.com> Date: Thu, 17 Aug 2023 02:04:06 +0800 Subject: [PATCH 3/5] Move _build_period_archives out of generate_context So that we don't contribute to further clutter in generate_context. --- pelican/generators.py | 136 +++++++++++++++++++++--------------------- 1 file changed, 69 insertions(+), 67 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index ad0f84c46..7ab992638 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -634,73 +634,8 @@ def _process(arts): self.dates.sort(key=attrgetter('date'), reverse=self.context['NEWEST_FIRST_ARCHIVES']) - def _build_period_archives(sorted_articles): - period_archives = defaultdict(list) - - period_archives_settings = { - 'year': { - 'save_as': self.settings['YEAR_ARCHIVE_SAVE_AS'], - 'url': self.settings['YEAR_ARCHIVE_URL'], - }, - 'month': { - 'save_as': self.settings['MONTH_ARCHIVE_SAVE_AS'], - 'url': self.settings['MONTH_ARCHIVE_URL'], - }, - 'day': { - 'save_as': self.settings['DAY_ARCHIVE_SAVE_AS'], - 'url': self.settings['DAY_ARCHIVE_URL'], - }, - } - - granularity_key_func = { - 'year': attrgetter('date.year'), - 'month': attrgetter('date.year', 'date.month'), - 'day': attrgetter('date.year', 'date.month', 'date.day'), - } - - for granularity in 'year', 'month', 'day': - save_as_fmt = period_archives_settings[granularity]['save_as'] - url_fmt = period_archives_settings[granularity]['url'] - key_func = granularity_key_func[granularity] - - if not save_as_fmt: - # the archives for this period granularity are not needed - continue - - for period, group in groupby(sorted_articles, key=key_func): - period_archive = {} - - dates = list(group) - period_archive['dates'] = dates - period_archive['articles'] = [ - a for a in self.articles if a in dates - ] - - # use the first date to specify the period archive URL - # and save_as; the specific date used does not matter as - # they all belong to the same period - d = dates[0].date - period_archive['save_as'] = save_as_fmt.format(date=d) - period_archive['url'] = url_fmt.format(date=d) - - if granularity == 'year': - period_archive['period'] = (period,) - period_archive['period_num'] = (period,) - else: - month_name = calendar.month_name[period[1]] - if granularity == 'month': - period_archive['period'] = (period[0], month_name) - else: - period_archive['period'] = (period[0], - month_name, - period[2]) - period_archive['period_num'] = tuple(period) - - period_archives[granularity].append(period_archive) - - return period_archives - - self.period_archives = _build_period_archives(self.dates) + self.period_archives = self._build_period_archives( + self.dates, self.articles, self.settings) # and generate the output :) @@ -723,6 +658,73 @@ def _build_period_archives(sorted_articles): self.readers.save_cache() signals.article_generator_finalized.send(self) + def _build_period_archives(self, sorted_articles, articles, settings): + """ + Compute the groupings of articles, with related attributes, for + per-year, per-month, and per-day archives. + """ + + period_archives = defaultdict(list) + + period_archives_settings = { + 'year': { + 'save_as': settings['YEAR_ARCHIVE_SAVE_AS'], + 'url': settings['YEAR_ARCHIVE_URL'], + }, + 'month': { + 'save_as': settings['MONTH_ARCHIVE_SAVE_AS'], + 'url': settings['MONTH_ARCHIVE_URL'], + }, + 'day': { + 'save_as': settings['DAY_ARCHIVE_SAVE_AS'], + 'url': settings['DAY_ARCHIVE_URL'], + }, + } + + granularity_key_func = { + 'year': attrgetter('date.year'), + 'month': attrgetter('date.year', 'date.month'), + 'day': attrgetter('date.year', 'date.month', 'date.day'), + } + + for granularity in 'year', 'month', 'day': + save_as_fmt = period_archives_settings[granularity]['save_as'] + url_fmt = period_archives_settings[granularity]['url'] + key_func = granularity_key_func[granularity] + + if not save_as_fmt: + # the archives for this period granularity are not needed + continue + + for period, group in groupby(sorted_articles, key=key_func): + archive = {} + + dates = list(group) + archive['dates'] = dates + archive['articles'] = [a for a in articles if a in dates] + + # use the first date to specify the period archive URL + # and save_as; the specific date used does not matter as + # they all belong to the same period + d = dates[0].date + archive['save_as'] = save_as_fmt.format(date=d) + archive['url'] = url_fmt.format(date=d) + + if granularity == 'year': + archive['period'] = (period,) + archive['period_num'] = (period,) + else: + month_name = calendar.month_name[period[1]] + if granularity == 'month': + archive['period'] = (period[0], month_name) + else: + archive['period'] = (period[0], month_name, period[2]) + archive['period_num'] = tuple(period) + + period_archives[granularity].append(archive) + + return period_archives + def generate_output(self, writer): self.generate_feeds(writer) self.generate_pages(writer) From 30adfba1cafb046a77ee52463d430941bd75dc3e Mon Sep 17 00:00:00 2001 From: DJ Ramones <50655786+djramones@users.noreply.github.com> Date: Thu, 17 Aug 2023 02:35:39 +0800 Subject: [PATCH 4/5] Revert *_ARCHIVE_URL default settings to blank --- docs/settings.rst | 26 +++++++++++++------------- pelican/settings.py | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 259b53f5e..2950ea827 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -561,11 +561,14 @@ written over time. Example usage:: YEAR_ARCHIVE_SAVE_AS = 'posts/{date:%Y}/index.html' + YEAR_ARCHIVE_URL = 'posts/{date:%Y}/' MONTH_ARCHIVE_SAVE_AS = 'posts/{date:%Y}/{date:%b}/index.html' + MONTH_ARCHIVE_URL = 'posts/{date:%Y}/{date:%b}/' With these settings, Pelican will create an archive of all your posts for the year at (for instance) ``posts/2011/index.html`` and an archive of all your -posts for the month at ``posts/2011/Aug/index.html``. +posts for the month at ``posts/2011/Aug/index.html``. These can be accessed +through the URLs ``posts/2011/`` and ``posts/2011/Aug/``, respectively. .. note:: Period archives work best when the final path segment is ``index.html``. @@ -576,31 +579,28 @@ posts for the month at ``posts/2011/Aug/index.html``. The location to save per-year archives of your posts. -.. data:: YEAR_ARCHIVE_URL = 'posts/{date:%Y}/' +.. data:: YEAR_ARCHIVE_URL = '' - The URL to use for per-year archives of your posts. This default value - matches a ``YEAR_ARCHIVE_SAVE_AS`` setting of - ``posts/{date:%Y}/index.html``. + The URL to use for per-year archives of your posts. You should set this if + you enable per-year archives. .. data:: MONTH_ARCHIVE_SAVE_AS = '' The location to save per-month archives of your posts. -.. data:: MONTH_ARCHIVE_URL = 'posts/{date:%Y}/{date:%b}/' +.. data:: MONTH_ARCHIVE_URL = '' - The URL to use for per-month archives of your posts. This default value - matches a ``MONTH_ARCHIVE_SAVE_AS`` setting of - ``posts/{date:%Y}/{date:%b}/index.html``. + The URL to use for per-month archives of your posts. You should set this if + you enable per-month archives. .. data:: DAY_ARCHIVE_SAVE_AS = '' The location to save per-day archives of your posts. -.. data:: DAY_ARCHIVE_URL = 'posts/{date:%Y}/{date:%b}/{date:%d}/' +.. data:: DAY_ARCHIVE_URL = '' - The URL to use for per-day archives of your posts. This default value - matches a ``DAY_ARCHIVE_SAVE_AS`` setting of - ``posts/{date:%Y}/{date:%b}/{date:%d}/index.html``. + The URL to use for per-day archives of your posts. You should set this if + you enable per-day archives. ``DIRECT_TEMPLATES`` work a bit differently than noted above. Only the ``_SAVE_AS`` settings are available, but it is available for any direct diff --git a/pelican/settings.py b/pelican/settings.py index 2405902f2..5b495e863 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -90,11 +90,11 @@ def load_source(name, path): (1, '{name}{extension}', '{name}{extension}'), (2, '{name}{number}{extension}', '{name}{number}{extension}'), ], - 'YEAR_ARCHIVE_URL': 'posts/{date:%Y}/', + 'YEAR_ARCHIVE_URL': '', 'YEAR_ARCHIVE_SAVE_AS': '', - 'MONTH_ARCHIVE_URL': 'posts/{date:%Y}/{date:%b}/', + 'MONTH_ARCHIVE_URL': '', 'MONTH_ARCHIVE_SAVE_AS': '', - 'DAY_ARCHIVE_URL': 'posts/{date:%Y}/{date:%b}/{date:%d}/', + 'DAY_ARCHIVE_URL': '', 'DAY_ARCHIVE_SAVE_AS': '', 'RELATIVE_URLS': False, 'DEFAULT_LANG': 'en', From b8d5919cd24edc0aeb322f5c1eb036810ae6b38e Mon Sep 17 00:00:00 2001 From: Deniz Turgut Date: Sat, 28 Oct 2023 22:11:11 +0300 Subject: [PATCH 5/5] expand period tests to be more specific --- pelican/generators.py | 2 +- pelican/tests/test_generators.py | 62 ++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index 7ab992638..d874d97c3 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -484,7 +484,7 @@ def generate_period_archives(self, write): except PelicanTemplateNotFound: template = self.get_template('archives') - for granularity in list(self.period_archives.keys()): + for granularity in self.period_archives: for period in self.period_archives[granularity]: context = self.context.copy() diff --git a/pelican/tests/test_generators.py b/pelican/tests/test_generators.py index a6fe97317..ac271c1c5 100644 --- a/pelican/tests/test_generators.py +++ b/pelican/tests/test_generators.py @@ -431,11 +431,12 @@ def test_period_archives_context(self): path=CONTENT_DIR, theme=settings['THEME'], output_path=None) generator.generate_context() period_archives = generator.context['period_archives'] - self.assertEqual(len(period_archives.items()), 1) - self.assertIn('year', period_archives.keys()) - archive_years = [p['period'][0] for p in period_archives['year']] - self.assertIn(1970, archive_years) - self.assertIn(2014, archive_years) + abbreviated_archives = { + granularity: {period['period'] for period in periods} + for granularity, periods in period_archives.items() + } + expected = {'year': {(1970,), (2010,), (2012,), (2014,)}} + self.assertEqual(expected, abbreviated_archives) # Month archives enabled: settings['MONTH_ARCHIVE_SAVE_AS'] = \ @@ -448,11 +449,22 @@ def test_period_archives_context(self): path=CONTENT_DIR, theme=settings['THEME'], output_path=None) generator.generate_context() period_archives = generator.context['period_archives'] - self.assertEqual(len(period_archives.items()), 2) - self.assertIn('month', period_archives.keys()) - month_archives_tuples = [p['period'] for p in period_archives['month']] - self.assertIn((1970, 'January'), month_archives_tuples) - self.assertIn((2014, 'February'), month_archives_tuples) + abbreviated_archives = { + granularity: {period['period'] for period in periods} + for granularity, periods in period_archives.items() + } + expected = { + 'year': {(1970,), (2010,), (2012,), (2014,)}, + 'month': { + (1970, 'January'), + (2010, 'December'), + (2012, 'December'), + (2012, 'November'), + (2012, 'October'), + (2014, 'February'), + }, + } + self.assertEqual(expected, abbreviated_archives) # Day archives enabled: settings['DAY_ARCHIVE_SAVE_AS'] = \ @@ -465,11 +477,31 @@ def test_period_archives_context(self): path=CONTENT_DIR, theme=settings['THEME'], output_path=None) generator.generate_context() period_archives = generator.context['period_archives'] - self.assertEqual(len(period_archives.items()), 3) - self.assertIn('day', period_archives.keys()) - day_archives_tuples = [p['period'] for p in period_archives['day']] - self.assertIn((1970, 'January', 1), day_archives_tuples) - self.assertIn((2014, 'February', 9), day_archives_tuples) + abbreviated_archives = { + granularity: {period['period'] for period in periods} + for granularity, periods in period_archives.items() + } + expected = { + 'year': {(1970,), (2010,), (2012,), (2014,)}, + 'month': { + (1970, 'January'), + (2010, 'December'), + (2012, 'December'), + (2012, 'November'), + (2012, 'October'), + (2014, 'February'), + }, + 'day': { + (1970, 'January', 1), + (2010, 'December', 2), + (2012, 'December', 20), + (2012, 'November', 29), + (2012, 'October', 30), + (2012, 'October', 31), + (2014, 'February', 9), + }, + } + self.assertEqual(expected, abbreviated_archives) # Further item values tests filtered_archives = [