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

Use callback to set plugin module path for template location #3702

Merged
merged 1 commit into from
Jul 22, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions nikola/nikola.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,19 @@ def _enclosure(post, lang):
return url, length, mime


def _plugin_load_callback(plugin_info):
"""Set the plugin's module path.
So we can find its template path later.
"""
try:
plugin_info.plugin_object.set_module_path(plugin_info.path)
except AttributeError:
# this is just for safety in case plugin_object somehow
# isn't set
pass


class Nikola(object):
"""Class that handles site generation.
Expand Down Expand Up @@ -1103,7 +1116,7 @@ def init_plugins(self, commands_only=False, load_all=False):
self.plugin_manager._candidates = list(set(self.plugin_manager._candidates) - bad_candidates)

self.plugin_manager._candidates = self._filter_duplicate_plugins(self.plugin_manager._candidates)
self.plugin_manager.loadPlugins()
self.plugin_manager.loadPlugins(callback_after=_plugin_load_callback)

# Search for compiler plugins which we disabled but shouldn't have
self._activate_plugins_of_category("PostScanner")
Expand Down Expand Up @@ -1134,7 +1147,7 @@ def init_plugins(self, commands_only=False, load_all=False):
utils.LOGGER.debug('Not loading compiler extension {}', p[-1].name)
if to_add:
self.plugin_manager._candidates = self._filter_duplicate_plugins(to_add)
self.plugin_manager.loadPlugins()
self.plugin_manager.loadPlugins(callback_after=_plugin_load_callback)

# Jupyter theme configuration. If a website has ipynb enabled in post_pages
# we should enable the Jupyter CSS (leaving that up to the theme itself).
Expand Down
39 changes: 8 additions & 31 deletions nikola/plugin_categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import io
import logging
import os
import sys
import typing

import doit
Expand Down Expand Up @@ -72,46 +71,24 @@ def set_site(self, site):
if not site.debug:
self.logger.level = logging.INFO

def set_module_path(self, module_path):
"""Set the plugin's module path."""
self.module_path = module_path

def inject_templates(self):
"""Inject 'templates/<engine>' (if exists) very early in the theme chain."""
try:
mod_candidate = None
# since https://github.com/tibonihoo/yapsy/pull/11 ,
# yapsy only adds each imported plugin to sys.modules
# under its modified, "unique" name (see early in
# PluginManager.loadPlugins), so we recreate the
# modified name here to find it. we fudge the serial
# number here, assuming that if a plugin is loaded
# under the same name multiple times, the location
# will also be the same, so we can just use 0.
possible_names = (
self.__class__.__module__,
"yapsy_loaded_plugin_" + self.__class__.__module__ + "_0",
"yapsy_loaded_plugin_" + self.name + "_0",
)
for possible_name in possible_names:
mod_candidate = sys.modules.get(possible_name)
if mod_candidate:
break
if not mod_candidate:
# well, we tried. we wind up here for the dummy
# plugins; honestly I'm not sure exactly why/how,
# but they don't have templates, so it's okay
return
# Sorry, found no other way to get this
mod_path = mod_candidate.__file__
mod_dir = os.path.dirname(mod_path)
mod_dir = os.path.dirname(self.module_path)
tmpl_dir = os.path.join(
mod_dir, 'templates', self.site.template_system.name
)
if os.path.isdir(tmpl_dir):
# Inject tmpl_dir low in the theme chain
self.site.template_system.inject_directory(tmpl_dir)
except AttributeError:
# In some cases, __builtin__ becomes the module of a plugin.
# We couldn’t reproduce that, and really find the reason for this,
# so let’s just ignore it and be done with it.
pass
# This would likely mean we don't have module_path set.
# this should not usually happen, so log a warning
LOGGER.warning("Could not find template path for module {0}".format(self.name))

def inject_dependency(self, target, dependency):
"""Add 'dependency' to the target task's task_deps."""
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mako>=1.0.0
Markdown>=3.0.0
unidecode>=0.04.16
lxml>=3.3.5
Yapsy>=1.11.223
Yapsy>=1.12.0
PyRSS2Gen>=1.1
blinker>=1.3
setuptools>=24.2.0
Expand Down