Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a plugin_enabled Jinja test for themes #3235

Merged
merged 2 commits into from Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/themes.rst
Expand Up @@ -140,6 +140,23 @@ your date according to the locale given in your settings::
.. _datetime: https://docs.python.org/3/library/datetime.html#datetime-objects
.. _strftime: https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior

Checking Loaded Plugins
-----------------------

Pelican provides a ``plugin_enabled`` Jinja test for checking if a certain plugin
is enabled. This test accepts a plugin name as a string and will return a Boolean.
Namespace plugins can be specified by full name (``pelican.plugins.plugin_name``)
or short name (``plugin_name``). The following example uses the ``webassets`` plugin
to minify CSS if the plugin is enabled and otherwise falls back to regular CSS::

{% if "webassets" is plugin_enabled %}
{% assets filters="cssmin", output="css/style.min.css", "css/style.scss" %}
<link rel="stylesheet" href="{{SITEURL}}/{{ASSET_URL}}">
{% endassets %}
{% else %}
<link rel="stylesheet" href="{{SITEURL}}/css/style.css}">
{% endif %}


index.html
----------
Expand Down
4 changes: 4 additions & 0 deletions pelican/generators.py
Expand Up @@ -20,6 +20,7 @@
from pelican.cache import FileStampDataCacher
from pelican.contents import Article, Page, Static
from pelican.plugins import signals
from pelican.plugins._utils import plugin_enabled
from pelican.readers import Readers
from pelican.utils import (
DateFormatter,
Expand Down Expand Up @@ -102,6 +103,9 @@ def __init__(

# get custom Jinja tests from user settings
custom_tests = self.settings["JINJA_TESTS"]
self.env.tests["plugin_enabled"] = partial(
plugin_enabled, plugin_list=self.settings["PLUGINS"]
)
self.env.tests.update(custom_tests)

signals.generator_init.send(self)
Expand Down
16 changes: 16 additions & 0 deletions pelican/plugins/_utils.py
Expand Up @@ -40,6 +40,22 @@ def list_plugins(ns_pkg=None):
logger.info("No plugins are installed")


def plugin_enabled(name, plugin_list=None):
if plugin_list is None or not plugin_list:
# no plugins are loaded
return False

if name in plugin_list:
# search name as is
return True

if "pelican.plugins.{}".format(name) in plugin_list:
# check if short name is a namespace plugin
return True

return False


def load_legacy_plugin(plugin, plugin_paths):
if "." in plugin:
# it is in a package, try to resolve package first
Expand Down
25 changes: 25 additions & 0 deletions pelican/tests/test_generators.py
Expand Up @@ -1581,6 +1581,31 @@ def test_jinja2_filter(self):

self._test_jinja2_helper(settings, content, expected)

def test_jinja2_filter_plugin_enabled(self):
"""JINJA_FILTERS adds custom filters to Jinja2 environment"""
settings = {"PLUGINS": ["legacy_plugin", "pelican.plugins.ns_plugin"]}
jinja_template = (
"{plugin}: "
"{{% if '{plugin}' is plugin_enabled %}}yes"
"{{% else %}}no{{% endif %}}"
)
content = " / ".join(
(
jinja_template.format(plugin="ns_plugin"),
jinja_template.format(plugin="pelican.plugins.ns_plugin"),
jinja_template.format(plugin="legacy_plugin"),
jinja_template.format(plugin="unknown"),
)
)
expected = (
"ns_plugin: yes / "
"pelican.plugins.ns_plugin: yes / "
"legacy_plugin: yes / "
"unknown: no"
)

self._test_jinja2_helper(settings, content, expected)

def test_jinja2_test(self):
"""JINJA_TESTS adds custom tests to Jinja2 environment"""
content = "foo {{ foo is custom_test }}, bar {{ bar is custom_test }}"
Expand Down
82 changes: 81 additions & 1 deletion pelican/tests/test_plugins.py
Expand Up @@ -2,7 +2,12 @@
from contextlib import contextmanager

import pelican.tests.dummy_plugins.normal_plugin.normal_plugin as normal_plugin
from pelican.plugins._utils import get_namespace_plugins, get_plugin_name, load_plugins
from pelican.plugins._utils import (
get_namespace_plugins,
get_plugin_name,
load_plugins,
plugin_enabled,
)
from pelican.tests.support import unittest


Expand Down Expand Up @@ -183,3 +188,78 @@ def register(self):
get_plugin_name(NoopPlugin()),
"PluginTest.test_get_plugin_name.<locals>.NoopPlugin",
)

def test_plugin_enabled(self):
def get_plugin_names(plugins):
return [get_plugin_name(p) for p in plugins]

with tmp_namespace_path(self._NS_PLUGIN_FOLDER):
# with no `PLUGINS` setting, load namespace plugins
SETTINGS = {}
plugins = get_plugin_names(load_plugins(SETTINGS))
self.assertTrue(plugin_enabled("ns_plugin", plugins))
self.assertTrue(plugin_enabled("pelican.plugins.ns_plugin", plugins))
self.assertFalse(plugin_enabled("normal_plugin", plugins))
self.assertFalse(plugin_enabled("unknown", plugins))

# disable namespace plugins with `PLUGINS = []`
SETTINGS = {"PLUGINS": []}
plugins = get_plugin_names(load_plugins(SETTINGS))
self.assertFalse(plugin_enabled("ns_plugin", plugins))
self.assertFalse(plugin_enabled("pelican.plugins.ns_plugin", plugins))
self.assertFalse(plugin_enabled("normal_plugin", plugins))
self.assertFalse(plugin_enabled("unknown", plugins))

# with `PLUGINS`, load only specified plugins

# normal plugin
SETTINGS = {
"PLUGINS": ["normal_plugin"],
"PLUGIN_PATHS": [self._NORMAL_PLUGIN_FOLDER],
}
plugins = get_plugin_names(load_plugins(SETTINGS))
self.assertFalse(plugin_enabled("ns_plugin", plugins))
self.assertFalse(plugin_enabled("pelican.plugins.ns_plugin", plugins))
self.assertTrue(plugin_enabled("normal_plugin", plugins))
self.assertFalse(plugin_enabled("unknown", plugins))

# normal submodule/subpackage plugins
SETTINGS = {
"PLUGINS": [
"normal_submodule_plugin.subplugin",
"normal_submodule_plugin.subpackage.subpackage",
],
"PLUGIN_PATHS": [self._NORMAL_PLUGIN_FOLDER],
}
plugins = get_plugin_names(load_plugins(SETTINGS))
self.assertFalse(plugin_enabled("ns_plugin", plugins))
self.assertFalse(plugin_enabled("pelican.plugins.ns_plugin", plugins))
self.assertFalse(plugin_enabled("normal_plugin", plugins))
self.assertFalse(plugin_enabled("unknown", plugins))

# namespace plugin short
SETTINGS = {"PLUGINS": ["ns_plugin"]}
plugins = get_plugin_names(load_plugins(SETTINGS))
self.assertTrue(plugin_enabled("ns_plugin", plugins))
self.assertTrue(plugin_enabled("pelican.plugins.ns_plugin", plugins))
self.assertFalse(plugin_enabled("normal_plugin", plugins))
self.assertFalse(plugin_enabled("unknown", plugins))

# namespace plugin long
SETTINGS = {"PLUGINS": ["pelican.plugins.ns_plugin"]}
plugins = get_plugin_names(load_plugins(SETTINGS))
self.assertTrue(plugin_enabled("ns_plugin", plugins))
self.assertTrue(plugin_enabled("pelican.plugins.ns_plugin", plugins))
self.assertFalse(plugin_enabled("normal_plugin", plugins))
self.assertFalse(plugin_enabled("unknown", plugins))

# normal and namespace plugin
SETTINGS = {
"PLUGINS": ["normal_plugin", "ns_plugin"],
"PLUGIN_PATHS": [self._NORMAL_PLUGIN_FOLDER],
}
plugins = get_plugin_names(load_plugins(SETTINGS))
self.assertTrue(plugin_enabled("ns_plugin", plugins))
self.assertTrue(plugin_enabled("pelican.plugins.ns_plugin", plugins))
self.assertTrue(plugin_enabled("normal_plugin", plugins))
self.assertFalse(plugin_enabled("unknown", plugins))