Skip to content

Commit

Permalink
Merge b71a818 into 9a09d5d
Browse files Browse the repository at this point in the history
  • Loading branch information
felixfontein committed Oct 26, 2016
2 parents 9a09d5d + b71a818 commit fde04c8
Show file tree
Hide file tree
Showing 17 changed files with 1,360 additions and 925 deletions.
3 changes: 3 additions & 0 deletions nikola/nikola.py
Expand Up @@ -73,6 +73,7 @@
SignalHandler,
ConfigPlugin,
PostScanner,
Taxonomy,
)

if DEBUG:
Expand Down Expand Up @@ -948,6 +949,7 @@ def init_plugins(self, commands_only=False, load_all=False):
"SignalHandler": SignalHandler,
"ConfigPlugin": ConfigPlugin,
"PostScanner": PostScanner,
"Taxonomy": Taxonomy,
})
self.plugin_manager.getPluginLocator().setPluginInfoExtension('plugin')
extra_plugins_dirs = self.config['EXTRA_PLUGINS_DIRS']
Expand Down Expand Up @@ -1019,6 +1021,7 @@ def plugin_position_in_places(plugin):

self.plugin_manager.loadPlugins()

self._activate_plugins_of_category("Taxonomy")
self._activate_plugins_of_category("SignalHandler")

# Emit signal for SignalHandlers which need to start running immediately.
Expand Down
219 changes: 219 additions & 0 deletions nikola/plugin_categories.py
Expand Up @@ -49,6 +49,7 @@
'SignalHandler',
'ConfigPlugin',
'PostScanner',
'Taxonomy',
)


Expand Down Expand Up @@ -451,3 +452,221 @@ def import_file(self):
def save_post(self):
"""Save a post to disk."""
raise NotImplementedError()


class Taxonomy(BasePlugin):
"""Taxonomy for posts.

A taxonomy plugin allows to classify posts (see #2107) by
classification strings.
"""

name = "dummy_taxonomy"

# Adjust the following values in your plugin!

# The classification name to be used for path handlers.
classification_name = "taxonomy"
# The classification name to be used when storing the classification
# in the metadata. If set to None, the classification won't be stored
# in the metadata.
metadata_name = "taxonomy"
# Variable for the overview page template which contains the list of
# classifications.
overview_page_variable_name = "taxonomy"
# If True, there can be more than one classification per post; in that case,
# the classification data in the metadata is stored as a list. If False,
# the classification data in the metadata is stored as a string, or None
# when no classification is given.
more_than_one_classifications_per_post = False
# Whether the classification has a hierarchy.
has_hierarchy = False
# If True, the list for a classification includes all posts with a
# sub-classification (in case has_hierarchy is True).
include_posts_from_subhierarchies = False
# If True, include_posts_from_subhierarchies == True will also insert
# posts into the list for the empty hierarchy [].
include_posts_into_hierarchy_root = False
# If not False, for every classification which has at least one
# subclassification, create a list of subcategories instead of a list/index
# of posts. This is only used when has_hierarchy = True. If not False, this
# must be the template name for the list; usually "list.tmpl".
# If this is set to a string, it is recommended to set
# include_posts_from_subhierarchies to True to get correct post counts.
show_list_as_subcategories_list = False
# Whether to show the posts for one classification as an index or
# as a post list.
show_list_as_index = False
# Whether to generate Atom feeds for post lists in case GENERATE_ATOM is set.
generate_atom_feeds_for_post_lists = False
# The template to use for the post list for one classification.
template_for_list_of_one_classification = "tagindex.tmpl"
# The template to use for the classification overview page.
# Set to None to avoid generating overviews.
template_for_classification_overview = "list.tmpl"
# Whether to always disable RSS feed generation
always_disable_rss = False
# Whether this classification applies to posts.
apply_to_posts = True
# Whether this classification applies to pages.
apply_to_pages = False
# The minimum number of posts a classification must have to be listed in
# the overview.
minimum_post_count_per_classification_in_overview = 1
# Whether post lists resp. indexes should be created for empty
# classifications.
omit_empty_classifications = False
# Whether to include all classifications for all languages in every
# language, or only the classifications for one language in its language's
# pages.
also_create_classifications_from_other_languages = True

def is_enabled(self, lang=None):
"""Return True if this taxonomy is enabled, or False otherwise.

If lang is None, this determins whether the classification is
made at all. If lang is not None, this determines whether the
overview page and the classification lists are created for this
language.
"""
return True

def get_implicit_classifications(self, lang):
"""Return a list of classification strings which should always appear in posts_per_classification."""
return []

def classify(self, post, lang):
"""Classify the given post for the given language.

Must return a list or tuple of strings.
"""
raise NotImplementedError()

def sort_posts(self, posts, classification, lang):
"""Sort the given list of posts.

The sort must happen in-place.
"""
pass

def sort_classifications(self, classifications, lang, level=None):
"""Sort the given list of classification strings.

For hierarchical taxonomies, the elements of the list are a single
path element of the path returned by `extract_hierarchy()`. The index
of the path element in the path will be provided in `level`.

The sort must happen in-place.
"""
pass

def get_classification_printable_name(self, classification, lang, only_last_component=False):
"""Extract a printable name from the classification.

For hierarchical taxonomies, the result of extract_hierarchy is provided
as `classification`. For non-hierarchical taxonomies, the classification
string itself is provided as `classification`.

The argument `only_last_component` is only relevant to hierarchical
taxonomies. If it is set, the printable name should only describe the
last component of `classification` if possible.
"""
raise NotImplementedError()

def get_list_path(self, lang, type='page'):
"""A path handler for the list of all classifications.

Must return one or two values (in this order):
* a list or tuple of strings: the path relative to OUTPUT_DIRECTORY;
* a string with values 'auto', 'always' or 'never', indicating whether
INDEX_FILE should be added or not.

Note that this function must always return a list or tuple of strings;
the other return value is optional with default value `'auto'`.

In case INDEX_FILE should potentially be added, the last element in the
returned path must have no extension, and the PRETTY_URLS config must
be ignored by this handler. The return value will be modified based on
the PRETTY_URLS and INDEX_FILE settings.

Type can be either 'page', 'feed' (for Atom feed) or 'rss'.
"""
raise NotImplementedError()

def get_path(self, classification, lang, type='page'):
"""A path handler for the given classification.

Must return one to three values (in this order):
* a list or tuple of strings: the path relative to OUTPUT_DIRECTORY;
* a string with values 'auto', 'always' or 'never', indicating whether
INDEX_FILE should be added or not;
* an integer if a specific page of the index is to be targeted (will be
ignored for post lists), or `None` if the most current page is targeted.

Note that this function must always return a list or tuple of strings;
the other two return values are optional with default values `'auto'` and
`None`.

In case INDEX_FILE should potentially be added, the last element in the
returned path must have no extension, and the PRETTY_URLS config must
be ignored by this handler. The return value will be modified based on
the PRETTY_URLS and INDEX_FILE settings.

Type can be either 'page', 'feed' (for Atom feed) or 'rss'.

For hierarchical taxonomies, the result of extract_hierarchy is provided
as `classification`. For non-hierarchical taxonomies, the classification
string itself is provided as `classification`.
"""
raise NotImplementedError()

def extract_hierarchy(self, classification):
"""Given a classification, return a list of parts in the hierarchy.

For non-hierarchical taxonomies, it usually suffices to return
`[classification]`.
"""
return [classification]

def recombine_classification_from_hierarchy(self, hierarchy):
"""Given a list of parts in the hierarchy, return the classification string.

For non-hierarchical taxonomies, it usually suffices to return hierarchy[0].
"""
return hierarchy[0]

def provide_list_context_and_uptodate(self, lang):
"""Provide data for the context and the uptodate list for the list of all classifiations.

Must return a tuple of two dicts. The first is merged into the page's context,
the second will be put into the uptodate list of all generated tasks.

Context must contain `title`.
"""
raise NotImplementedError()

def provide_context_and_uptodate(self, classification, lang):
"""Provide data for the context and the uptodate list for the list of the given classifiation.

Must return a tuple of two dicts. The first is merged into the page's context,
the second will be put into the uptodate list of all generated tasks.

Context must contain `title`, which should be something like 'Posts about <classification>'.
"""
raise NotImplementedError()

def should_generate_classification_list(self, classification, post_list, lang):
"""Only generates list of posts for classification if this function returns True."""
return True

def postprocess_posts_per_classification(self, posts_per_classification_per_language, flat_hierarchy_per_lang=None, hierarchy_lookup_per_lang=None):
"""Rearrange, modify or otherwise use the list of posts per classification and per language.

For compatibility reasons, the list could be stored somewhere else as well.

In case `has_hierarchy` is `True`, `flat_hierarchy_per_lang` is the flat
hierarchy consisting of `utils.TreeNode` elements, and `hierarchy_lookup_per_lang`
is the corresponding hierarchy lookup mapping classification strings to
`utils.TreeNode` objects.
"""
pass
12 changes: 12 additions & 0 deletions nikola/plugins/misc/taxonomies_classifier.plugin
@@ -0,0 +1,12 @@
[Core]
name = classify_taxonomies
module = taxonomies_classifier

[Documentation]
author = Roberto Alsina
version = 1.0
website = https://getnikola.com/
description = Classifies the timeline into taxonomies.

[Nikola]
plugincategory = SignalHandler

0 comments on commit fde04c8

Please sign in to comment.