File: plugins.py

package info (click to toggle)
python-mkdocs 1.1.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,832 kB
  • sloc: python: 7,504; javascript: 2,299; perl: 142; sh: 66; makefile: 25; xml: 21
file content (100 lines) | stat: -rw-r--r-- 3,131 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""
Implements the plugin API for MkDocs.

"""


import pkg_resources
import logging
from collections import OrderedDict

from mkdocs.config.base import Config


log = logging.getLogger('mkdocs.plugins')


EVENTS = (
    'config', 'pre_build', 'files', 'nav', 'env', 'pre_template', 'template_context',
    'post_template', 'pre_page', 'page_read_source', 'page_markdown',
    'page_content', 'page_context', 'post_page', 'post_build', 'serve'
)


def get_plugins():
    """ Return a dict of all installed Plugins by name. """

    plugins = pkg_resources.iter_entry_points(group='mkdocs.plugins')

    return {plugin.name: plugin for plugin in plugins}


class BasePlugin:
    """
    Plugin base class.

    All plugins should subclass this class.
    """

    config_scheme = ()
    config = {}

    def load_config(self, options, config_file_path=None):
        """ Load config from a dict of options. Returns a tuple of (errors, warnings)."""

        self.config = Config(schema=self.config_scheme, config_file_path=config_file_path)
        self.config.load_dict(options)

        return self.config.validate()


class PluginCollection(OrderedDict):
    """
    A collection of plugins.

    In addition to being a dict of Plugin instances, each event method is registered
    upon being added. All registered methods for a given event can then be run in order
    by calling `run_event`.
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.events = {x: [] for x in EVENTS}

    def _register_event(self, event_name, method):
        """ Register a method for an event. """
        self.events[event_name].append(method)

    def __setitem__(self, key, value, **kwargs):
        if not isinstance(value, BasePlugin):
            raise TypeError(
                '{0}.{1} only accepts values which are instances of {2}.{3} '
                'sublcasses'.format(self.__module__, self.__name__,
                                    BasePlugin.__module__, BasePlugin.__name__))
        super().__setitem__(key, value, **kwargs)
        # Register all of the event methods defined for this Plugin.
        for event_name in (x for x in dir(value) if x.startswith('on_')):
            method = getattr(value, event_name)
            if callable(method):
                self._register_event(event_name[3:], method)

    def run_event(self, name, item=None, **kwargs):
        """
        Run all registered methods of an event.

        `item` is the object to be modified or replaced and returned by the event method.
        If it isn't given the event method creates a new object to be returned.
        All other keywords are variables for context, but would not generally
        be modified by the event method.
        """

        pass_item = item is not None
        for method in self.events[name]:
            if pass_item:
                result = method(item, **kwargs)
            else:
                result = method(**kwargs)
            # keep item if method returned `None`
            if result is not None:
                item = result
        return item