diff --git a/patacrep/build.py b/patacrep/build.py index 3998244d..a66619d7 100644 --- a/patacrep/build.py +++ b/patacrep/build.py @@ -10,7 +10,7 @@ from subprocess import Popen, PIPE, call, check_call import yaml -from patacrep import authors, content, encoding, errors, files, pkg_datapath, utils +from patacrep import authors, content, encoding, errors, pkg_datapath, utils from patacrep.index import process_sxd from patacrep.templates import TexBookRenderer, iter_bookoptions @@ -79,18 +79,6 @@ class Songbook: copy.deepcopy(self._config['authors']) ) - # Loading custom plugins - self._config['_content_plugins'] = files.load_plugins( - datadirs=self._config['_datadir'], - root_modules=['content'], - keyword='CONTENT_PLUGINS', - ) - self._config['_song_plugins'] = files.load_plugins( - datadirs=self._config['_datadir'], - root_modules=['songs'], - keyword='SONG_RENDERERS', - )['tsg'] - # Configuration set self._config['render'] = content.render self._config['content'] = content.process_content( diff --git a/patacrep/content/__init__.py b/patacrep/content/__init__.py index 275f332a..5acc2aae 100755 --- a/patacrep/content/__init__.py +++ b/patacrep/content/__init__.py @@ -265,7 +265,7 @@ def process_content(content, config=None): included in the .tex file. """ contentlist = ContentList() - plugins = config.get('_content_plugins', {}) + plugins = files.load_content_plugins(config['_datadir']) if not content: content = [{'song': None}] elif isinstance(content, dict): diff --git a/patacrep/content/song.py b/patacrep/content/song.py index 4f81cc12..3063a700 100755 --- a/patacrep/content/song.py +++ b/patacrep/content/song.py @@ -87,7 +87,7 @@ def parse(keyword, argument, config): contentlist = argument if isinstance(contentlist, str): contentlist = [contentlist] - plugins = config['_song_plugins'] + plugins = files.load_renderer_plugins(config['_datadir'])['tsg'] if '_langs' not in config: config['_langs'] = set() songlist = ContentList() diff --git a/patacrep/files.py b/patacrep/files.py index bc51557d..1ad296d5 100644 --- a/patacrep/files.py +++ b/patacrep/files.py @@ -1,6 +1,7 @@ """File system utilities.""" from contextlib import contextmanager +from functools import lru_cache import logging import os import pkgutil @@ -93,6 +94,23 @@ def iter_modules(path, prefix): LOGGER.debug("[plugins] Could not load module {}: {}".format(name, str(error))) continue +def load_content_plugins(datadirs=()): + """Load the content plugins, and return a dictionary of those plugins.""" + return load_plugins( + datadirs=tuple(datadirs), + root_modules=('content',), + keyword='CONTENT_PLUGINS', + ) + +def load_renderer_plugins(datadirs=()): + """Load the song renderer plugins, and return a dictionary of those plugins.""" + return load_plugins( + datadirs=tuple(datadirs), + root_modules=('songs',), + keyword='SONG_RENDERERS', + ) + +@lru_cache() def load_plugins(datadirs, root_modules, keyword): """Load all plugins, and return a dictionary of those plugins. @@ -102,6 +120,7 @@ def load_plugins(datadirs, root_modules, keyword): Arguments: - datadirs: List of directories in which plugins are to be searched. + The plugins will also be searched in the patacrep modules. - root_modules: the submodule in which plugins are to be searched, as a list of modules (e.g. ["some", "deep", "module"] for "some.deep.module"). diff --git a/patacrep/tools/convert/__main__.py b/patacrep/tools/convert/__main__.py index 65b82d8b..3916b6ae 100644 --- a/patacrep/tools/convert/__main__.py +++ b/patacrep/tools/convert/__main__.py @@ -35,12 +35,7 @@ def main(args=None): dest = args[2] song_files = args[3:] - # todo : what is the datadir argument used for? - renderers = files.load_plugins( - datadirs=[], - root_modules=['songs'], - keyword='SONG_RENDERERS', - ) + renderers = files.load_renderer_plugins() if dest not in renderers: LOGGER.error( diff --git a/test/test_content/test_content.py b/test/test_content/test_content.py index dbf6926a..770d4e1a 100644 --- a/test/test_content/test_content.py +++ b/test/test_content/test_content.py @@ -107,16 +107,4 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): outputdir ) - # Load the plugins - config['_content_plugins'] = files.load_plugins( - datadirs=config['_datadir'], - root_modules=['content'], - keyword='CONTENT_PLUGINS', - ) - config['_song_plugins'] = files.load_plugins( - datadirs=config['_datadir'], - root_modules=['songs'], - keyword='SONG_RENDERERS', - )['tsg'] - return config diff --git a/test/test_song/test_parser.py b/test/test_song/test_parser.py index 39f4a05c..6123470a 100644 --- a/test/test_song/test_parser.py +++ b/test/test_song/test_parser.py @@ -60,7 +60,7 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): with self.chdir(): with open_read(destname) as expectfile: with logging_reduced(): - song = self.song_plugins[out_format][in_format](sourcename, self.config) + song = self.song_renderer[out_format][in_format](sourcename, self.config) expected = expectfile.read().strip().replace( "@TEST_FOLDER@", files.path2posix(resource_filename(__name__, "")), @@ -76,16 +76,10 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): # Setting datadir # Load the default songbook config cls.config = config_model('default')['en'] + cls.config['_datadir'] = ['datadir'] - if '_datadir' not in cls.config: - cls.config['_datadir'] = [] - cls.config['_datadir'].append('datadir') + cls.song_renderer = files.load_renderer_plugins() - cls.song_plugins = files.load_plugins( - datadirs=cls.config['_datadir'], - root_modules=['songs'], - keyword='SONG_RENDERERS', - ) with cls.chdir(): for source in sorted(glob.glob('*.*.source')): [*base, in_format, _] = source.split('.') @@ -128,7 +122,7 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest): """Test that `base` parsing fails.""" sourcename = "{}.{}.source".format(base, in_format) with self.chdir('errors'): - parser = self.song_plugins[out_format][in_format] + parser = self.song_renderer[out_format][in_format] self.assertRaises(errors.SongSyntaxError, parser, sourcename, self.config) test_parse_failure.__doc__ = (