Advertisement
t_animal

Untitled

Oct 17th, 2016
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.70 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2.  
  3. # Copyright © 2012-2016 Roberto Alsina and others.
  4.  
  5. # Permission is hereby granted, free of charge, to any
  6. # person obtaining a copy of this software and associated
  7. # documentation files (the "Software"), to deal in the
  8. # Software without restriction, including without limitation
  9. # the rights to use, copy, modify, merge, publish,
  10. # distribute, sublicense, and/or sell copies of the
  11. # Software, and to permit persons to whom the Software is
  12. # furnished to do so, subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice
  15. # shall be included in all copies or substantial portions of
  16. # the Software.
  17. #
  18. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
  19. # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  20. # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  21. # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
  22. # OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23. # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  24. # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  25. # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26.  
  27. """Render one post archive per section."""
  28.  
  29. import copy
  30. import os
  31.  
  32. # for tearDown with _reload we cannot use 'import from' to access LocaleBorg
  33. import nikola.utils
  34. import datetime
  35. from nikola.plugin_categories import Task
  36. from nikola.utils import config_changed, adjust_name_for_index_path, adjust_name_for_index_link
  37.  
  38.  
  39. class SectionArchive(Task):
  40.     """Render the post archives."""
  41.  
  42.     name = "render_section_archive"
  43.  
  44.     def set_site(self, site):
  45.         """Set Nikola site."""
  46.         site.register_path_handler('section_archive', self.section_archive_path)
  47.         site.register_path_handler('section_archive_atom', self.archive_atom_path)
  48.         return super(SectionArchive, self).set_site(site)
  49.  
  50.     def _prepare_task(self, kw, name, lang, posts, items, template_name,
  51.                       title, deps_translatable=None):
  52.         """Prepare an archive task."""
  53.         # name: used to build permalink and destination
  54.         # posts, items: posts or items; only one of them should be used,
  55.         #               the other should be None
  56.         # template_name: name of the template to use
  57.         # title: the (translated) title for the generated page
  58.         # deps_translatable: dependencies (None if not added)
  59.         assert posts is not None or items is not None
  60.         task_cfg = [copy.copy(kw)]
  61.         context = {}
  62.         context["lang"] = lang
  63.         context["title"] = title
  64.         context["permalink"] = self.site.link("section_archive", name, lang)
  65.         context["pagekind"] = ["list", "archive_page"]
  66.         if posts is not None:
  67.             context["posts"] = posts
  68.             # Depend on all post metadata because it can be used in templates (Issue #1931)
  69.             task_cfg.append([repr(p) for p in posts])
  70.         else:
  71.             # Depend on the content of items, to rebuild if links change (Issue #1931)
  72.             context["items"] = items
  73.             task_cfg.append(items)
  74.         task = self.site.generic_post_list_renderer(
  75.             lang,
  76.             [],
  77.             os.path.join(kw['output_folder'], self.site.path("section_archive", name, lang)),
  78.             template_name,
  79.             kw['filters'],
  80.             context,
  81.         )
  82.  
  83.         task_cfg = {i: x for i, x in enumerate(task_cfg)}
  84.         if deps_translatable is not None:
  85.             task_cfg[3] = deps_translatable
  86.         task['uptodate'] = task['uptodate'] + [config_changed(task_cfg, 'nikola.plugins.task.archive')]
  87.         task['basename'] = self.name
  88.         return task
  89.  
  90.     def _generate_posts_task(self, kw, name, lang, posts, section, title, deps_translatable=None):
  91.         """Genereate a task for an archive with posts."""
  92.         posts = filter(lambda p: p.section_slug() == section, posts)
  93.         posts = sorted(posts, key=lambda a: a.date)
  94.         posts.reverse()
  95.         if kw['archives_are_indexes']:
  96.             def page_link(i, displayed_i, num_pages, force_addition, extension=None):
  97.                 feed = "_atom" if extension == ".atom" else ""
  98.                 return adjust_name_for_index_link(self.site.link("section_archive" + feed, (section, name), lang), i, displayed_i,
  99.                                                   lang, self.site, force_addition, extension)
  100.  
  101.             def page_path(i, displayed_i, num_pages, force_addition, extension=None):
  102.                 feed = "_atom" if extension == ".atom" else ""
  103.                 return adjust_name_for_index_path(self.site.path("section_archive" + feed, (section, name), lang), i, displayed_i,
  104.                                                   lang, self.site, force_addition, extension)
  105.  
  106.             uptodate = []
  107.             if deps_translatable is not None:
  108.                 uptodate += [config_changed(deps_translatable, 'nikola.plugins.task.archive')]
  109.             context = {"archive_name": name,
  110.                        "is_feed_stale": kw["is_feed_stale"],
  111.                        "pagekind": ["index", "archive_page"]}
  112.             yield self.site.generic_index_renderer(
  113.                 lang,
  114.                 posts,
  115.                 title,
  116.                 "archiveindex.tmpl",
  117.                 context,
  118.                 kw,
  119.                 str(self.name),
  120.                 page_link,
  121.                 page_path,
  122.                 uptodate)
  123.         else:
  124.             yield self._prepare_task(kw, (section, name), lang, posts, None, "list_post.tmpl", title, deps_translatable)
  125.  
  126.     def gen_tasks(self):
  127.         """Generate archive tasks."""
  128.         kw = {
  129.             "messages": self.site.MESSAGES,
  130.             "translations": self.site.config['TRANSLATIONS'],
  131.             "output_folder": self.site.config['OUTPUT_FOLDER'],
  132.             "filters": self.site.config['FILTERS'],
  133.             "archives_are_indexes": self.site.config['ARCHIVES_ARE_INDEXES'],
  134.             "create_monthly_archive": self.site.config['CREATE_MONTHLY_ARCHIVE'],
  135.             "create_single_archive": self.site.config['CREATE_SINGLE_ARCHIVE'],
  136.             "show_untranslated_posts": self.site.config['SHOW_UNTRANSLATED_POSTS'],
  137.             "create_full_archives": self.site.config['CREATE_FULL_ARCHIVES'],
  138.             "create_daily_archive": self.site.config['CREATE_DAILY_ARCHIVE'],
  139.             "pretty_urls": self.site.config['PRETTY_URLS'],
  140.             "strip_indexes": self.site.config['STRIP_INDEXES'],
  141.             "index_file": self.site.config['INDEX_FILE'],
  142.             "generate_atom": self.site.config["GENERATE_ATOM"],
  143.         }
  144.         self.site.scan_posts()
  145.         yield self.group_task()
  146.         # TODO add next/prev links for years
  147.         if (kw['create_monthly_archive'] and kw['create_single_archive']) and not kw['create_full_archives']:
  148.             raise Exception('Cannot create monthly and single archives at the same time.')
  149.  
  150.         availableSections = list(set([post.section_slug() for post in self.site.all_posts]))
  151.  
  152.         for lang in kw["translations"]:
  153.             if kw['create_single_archive'] and not kw['create_full_archives']:
  154.                 # if we are creating one single archive
  155.                 archdata = {}
  156.             else:
  157.                 # if we are not creating one single archive, start with all years
  158.                 archdata = self.site.posts_per_year.copy()
  159.             if kw['create_single_archive'] or kw['create_full_archives']:
  160.                 # if we are creating one single archive, or full archives
  161.                 archdata[None] = self.site.posts  # for create_single_archive
  162.  
  163.             for year, posts in archdata.items():
  164.                 # Filter untranslated posts (Issue #1360)
  165.                 if not kw["show_untranslated_posts"]:
  166.                     posts = [p for p in posts if lang in p.translated_to]
  167.  
  168.                 # Add archive per year or total archive
  169.                 if year:
  170.                     title = kw["messages"][lang]["Posts for year %s"] % year
  171.                     kw["is_feed_stale"] = (datetime.datetime.utcnow().strftime("%Y") != year)
  172.                 else:
  173.                     title = kw["messages"][lang]["Archive"]
  174.                     kw["is_feed_stale"] = False
  175.                 deps_translatable = {}
  176.                 for k in self.site._GLOBAL_CONTEXT_TRANSLATABLE:
  177.                     deps_translatable[k] = self.site.GLOBAL_CONTEXT[k](lang)
  178.                 if not kw["create_monthly_archive"] or kw["create_full_archives"]:
  179.                     for section in availableSections:
  180.                         yield self._generate_posts_task(kw, year, lang, posts, section, title, deps_translatable)
  181.                 else:
  182.                     #create a list of available archives
  183.                     for section in availableSections:
  184.                         months = set([(m.split('/')[1],
  185.                                        self.site.link("section_archive", (section, m), lang),
  186.                                        len([p for p in self.site.posts_per_month[m] if p.section_slug() == section])) for m in self.site.posts_per_month.keys() if m.startswith(str(year))])
  187.                         months = sorted(list(months))
  188.                         months.reverse()
  189.                         items = [[nikola.utils.LocaleBorg().get_month_name(int(month), lang), link, count] for month, link, count in months]
  190.                         yield self._prepare_task(kw, (section, year), lang, None, items, "list.tmpl", title, deps_translatable)
  191.  
  192.             if not kw["create_monthly_archive"] and not kw["create_full_archives"] and not kw["create_daily_archive"]:
  193.                 continue  # Just to avoid nesting the other loop in this if
  194.             for yearmonth, posts in self.site.posts_per_month.items():
  195.                 # Add archive per month
  196.                 year, month = yearmonth.split('/')
  197.  
  198.                 kw["is_feed_stale"] = (datetime.datetime.utcnow().strftime("%Y/%m") != yearmonth)
  199.  
  200.                 # Filter untranslated posts (via Issue #1360)
  201.                 if not kw["show_untranslated_posts"]:
  202.                     posts = [p for p in posts if lang in p.translated_to]
  203.  
  204.                 if kw["create_monthly_archive"] or kw["create_full_archives"]:
  205.                     title = kw["messages"][lang]["Posts for {month} {year}"].format(
  206.                         year=year, month=nikola.utils.LocaleBorg().get_month_name(int(month), lang))
  207.                     for section in availableSections:
  208.                         yield self._generate_posts_task(kw, yearmonth, lang, posts, section, title)
  209.  
  210.                 if not kw["create_full_archives"] and not kw["create_daily_archive"]:
  211.                     continue  # Just to avoid nesting the other loop in this if
  212.                 # Add archive per day
  213.                 days = dict()
  214.                 for p in posts:
  215.                     if p.date.day not in days:
  216.                         days[p.date.day] = list()
  217.                     days[p.date.day].append(p)
  218.                 for day, posts in days.items():
  219.                     title = kw["messages"][lang]["Posts for {month} {day}, {year}"].format(
  220.                         year=year, month=nikola.utils.LocaleBorg().get_month_name(int(month), lang), day=day)
  221.                     for section in availableSections:
  222.                         yield self._generate_posts_task(kw, yearmonth + '/{0:02d}'.format(day), lang, posts, section, title)
  223.  
  224.         if not kw['create_single_archive'] and not kw['create_full_archives']:
  225.             # And an "all your years" page for yearly and monthly archives
  226.             if "is_feed_stale" in kw:
  227.                 del kw["is_feed_stale"]
  228.             years = list(self.site.posts_per_year.keys())
  229.             years.sort(reverse=True)
  230.             kw['years'] = years
  231.             for lang in kw["translations"]:
  232.                 for section in availableSections:
  233.                     items = [(y, self.site.link("section_archive", (section, y), lang), len([p for p in self.site.posts_per_year[y] if p.section_slug() == section])) for y in years]
  234.                     yield self._prepare_task(kw, section, lang, None, items, "list.tmpl", kw["messages"][lang]["Archive"])
  235.  
  236.     def section_archive_path(self, name, lang, is_feed=False):
  237.         """Link to archive path, name is the section and year, seperated by a forward slash
  238.           Or (for internal use) if name is a tuple it is a tuple of (section, year)
  239.  
  240.        Example:
  241.  
  242.        link://archive/section/2013 => /section/archives/2013/index.html
  243.        """
  244.         if type(name) is str:
  245.             if '/' in name:
  246.                 section, year = name.split("/", 1)
  247.             else:
  248.                 section = name
  249.                 year = None
  250.         else:
  251.             section, year = name
  252.  
  253.         if is_feed:
  254.             extension = ".atom"
  255.             archive_file = os.path.splitext(self.site.config['ARCHIVE_FILENAME'])[0] + extension
  256.             index_file = os.path.splitext(self.site.config['INDEX_FILE'])[0] + extension
  257.         else:
  258.             archive_file = self.site.config['ARCHIVE_FILENAME']
  259.             index_file = self.site.config['INDEX_FILE']
  260.         if year:
  261.             return [_f for _f in [self.site.config['TRANSLATIONS'][lang], section,
  262.                                   self.site.config['ARCHIVE_PATH'], year,
  263.                                   index_file] if _f]
  264.         else:
  265.             return [_f for _f in [self.site.config['TRANSLATIONS'][lang], section,
  266.                                   self.site.config['ARCHIVE_PATH'],
  267.                                   archive_file] if _f]
  268.  
  269.     def archive_atom_path(self, name, lang):
  270.         """Link to atom archive path, name is the year.
  271.  
  272.        Example:
  273.  
  274.        link://archive_atom/2013 => /archives/2013/index.atom
  275.        """
  276.         return self.section_archive_path(name, lang, is_feed=True)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement