From 36c1e1a12f00c2e8a184d8f5f1bef21bb438c3d8 Mon Sep 17 00:00:00 2001 From: Frederik Ring Date: Sun, 3 Jan 2021 11:29:42 +0100 Subject: [PATCH] fix: stringify plugin definitions so they can be pickled during caching --- pelican/__init__.py | 3 ++- pelican/settings.py | 12 ++++++++++++ pelican/tests/support.py | 5 +++++ pelican/tests/test_settings.py | 13 +++++++++++-- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/pelican/__init__.py b/pelican/__init__.py index 0d723220..b5ba46af 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -23,7 +23,7 @@ from pelican.plugins import signals from pelican.plugins._utils import load_plugins from pelican.readers import Readers from pelican.server import ComplexHTTPRequestHandler, RootedHTTPServer -from pelican.settings import coerce_overrides, read_settings +from pelican.settings import coerce_overrides, read_settings, stringify_plugins from pelican.utils import (FileSystemWatcher, clean_output_dir, maybe_pluralize) from pelican.writers import Writer @@ -73,6 +73,7 @@ class Pelican: except Exception as e: logger.error('Cannot register plugin `%s`\n%s', plugin.__name__, e) + stringify_plugins(self.settings) def run(self): """Run the generators and return""" diff --git a/pelican/settings.py b/pelican/settings.py index ea3ee8eb..1762b400 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -681,3 +681,15 @@ def coerce_overrides(overrides): 'load as json', k, v) coerced[k] = json.loads(v) return coerced + + +def stringify_plugins(settings): + """ + Plugins can be passed as module objects, however this breaks caching as + module objects cannot be pickled. To work around this, we stringify all + plugin definitions post-initialization. + """ + if 'PLUGINS' in settings and settings['PLUGINS'] is not None: + settings['PLUGINS'] = [str(p) for p in settings['PLUGINS']] + + return settings diff --git a/pelican/tests/support.py b/pelican/tests/support.py index 55ddf625..43029575 100644 --- a/pelican/tests/support.py +++ b/pelican/tests/support.py @@ -193,6 +193,11 @@ def get_context(settings=None, **kwargs): return context +class NoopPlugin: + def register(self): + pass + + class LogCountHandler(BufferingHandler): """Capturing and counting logged messages.""" diff --git a/pelican/tests/test_settings.py b/pelican/tests/test_settings.py index 83203ae5..69d47bf5 100644 --- a/pelican/tests/test_settings.py +++ b/pelican/tests/test_settings.py @@ -8,8 +8,9 @@ from sys import platform from pelican.settings import (DEFAULT_CONFIG, DEFAULT_THEME, _printf_s_to_format_field, coerce_overrides, configure_settings, - handle_deprecated_settings, read_settings) -from pelican.tests.support import unittest + handle_deprecated_settings, read_settings, + stringify_plugins) +from pelican.tests.support import NoopPlugin, unittest class TestSettingsConfiguration(unittest.TestCase): @@ -319,3 +320,11 @@ class TestSettingsConfiguration(unittest.TestCase): 'THEME_STATIC_DIR': 'theme', } self.assertDictEqual(overrides, expected) + + def test_stringify_plugins(self): + settings = { + 'PLUGINS': ['string_plugin', NoopPlugin] + } + stringify_plugins(settings) + # Plugins are converted to string references + self.assertTrue(all(str(p) == p for p in settings['PLUGINS']))