diff --git a/examples/datadir2/img/datadir2.ly b/examples/datadir2/scores/datadir2.ly
similarity index 100%
rename from examples/datadir2/img/datadir2.ly
rename to examples/datadir2/scores/datadir2.ly
diff --git a/examples/img/datadir.ly b/examples/scores/datadir.ly
similarity index 100%
rename from examples/img/datadir.ly
rename to examples/scores/datadir.ly
diff --git a/examples/songs/subdir/datadir.sg b/examples/songs/subdir/datadir.sg
index 18e92c3d..933e208b 100644
--- a/examples/songs/subdir/datadir.sg
+++ b/examples/songs/subdir/datadir.sg
@@ -1,10 +1,10 @@
\beginsong{Image included from datadir\\\LaTeX}
- [cov={datadir}]
+ [cov={img/datadir}]
\cover
- \lilypond{datadir.ly}
+ \lilypond{scores/datadir.ly}
- \image{datadir}
+ \image{img/datadir}
\endsong
diff --git a/examples/songs/subdir/datadir2.sg b/examples/songs/subdir/datadir2.sg
index f5bad860..6a805725 100644
--- a/examples/songs/subdir/datadir2.sg
+++ b/examples/songs/subdir/datadir2.sg
@@ -1,10 +1,10 @@
\beginsong{Image included from a different datadir\\\LaTeX}
- [cov={datadir2}]
+ [cov={img/datadir2}]
\cover
- \lilypond{datadir2.ly}
+ \lilypond{scores/datadir2.ly}
- \image{datadir2}
+ \image{img/datadir2}
\endsong
diff --git a/patacrep/build.py b/patacrep/build.py
index 44023e65..40ef74ff 100644
--- a/patacrep/build.py
+++ b/patacrep/build.py
@@ -110,8 +110,8 @@ class Songbook(object):
config['_song_plugins'] = files.load_plugins(
datadirs=config.get('datadir', []),
root_modules=['songs'],
- keyword='SONG_PARSERS',
- )
+ keyword='SONG_RENDERERS',
+ )['latex']
# Configuration set
config['render'] = content.render
diff --git a/patacrep/content/song.py b/patacrep/content/song.py
index c5455c92..480583fa 100755
--- a/patacrep/content/song.py
+++ b/patacrep/content/song.py
@@ -43,7 +43,7 @@ class SongRenderer(Content):
""").format(
separator="%"*80,
path=self.song.subpath,
- song=self.song.render(output=context['filename'], output_format="latex"),
+ song=self.song.render(output=context['filename']),
)
#pylint: disable=unused-argument
diff --git a/patacrep/data/templates/patacrep.tex b/patacrep/data/templates/patacrep.tex
index 96367078..50dacf5e 100644
--- a/patacrep/data/templates/patacrep.tex
+++ b/patacrep/data/templates/patacrep.tex
@@ -34,7 +34,7 @@
},
"picture": {"description": {"english": "Cover picture", "french": "Image de couverture"},
"type": "file",
- "default": {"default": "treble_a"}
+ "default": {"default": "img/treble_a"}
},
"picturecopyright": {"description": {"english": "Copyright for the cover picture", "french": "Copyright pour l'image de couverture"},
"default": {"default": "Dbolton \\url{http://commons.wikimedia.org/wiki/User:Dbolton}"}
diff --git a/patacrep/data/templates/songs.tex b/patacrep/data/templates/songs.tex
index 957e610e..741b5d39 100644
--- a/patacrep/data/templates/songs.tex
+++ b/patacrep/data/templates/songs.tex
@@ -89,7 +89,7 @@
\usepackage{graphicx}
\graphicspath{ %
(* for dir in datadir *)
- {(( path2posix(dir) ))/img/} %
+ {(( path2posix(dir) ))/} %
(* endfor *)
}
diff --git a/patacrep/files.py b/patacrep/files.py
index e77c3ab2..1116c8b0 100644
--- a/patacrep/files.py
+++ b/patacrep/files.py
@@ -8,6 +8,8 @@ import posixpath
import re
import sys
+from patacrep import utils
+
LOGGER = logging.getLogger(__name__)
def recursive_find(root_directory, extensions):
@@ -104,7 +106,7 @@ def load_plugins(datadirs, root_modules, keyword):
- keys are the keywords ;
- values are functions triggered when this keyword is met.
"""
- plugins = {}
+ plugins = utils.DictOfDict()
datadir_path = [
os.path.join(datadir, "python", *root_modules)
@@ -121,13 +123,5 @@ def load_plugins(datadirs, root_modules, keyword):
prefix="patacrep.{}.".format(".".join(root_modules))
):
if hasattr(module, keyword):
- for (key, value) in getattr(module, keyword).items():
- if key in plugins:
- LOGGER.warning(
- "File %s: Keyword '%s' is already used. Ignored.",
- module.__file__,
- key,
- )
- continue
- plugins[key] = value
+ plugins.update(getattr(module, keyword))
return plugins
diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py
index a9cef025..129c8045 100644
--- a/patacrep/songs/__init__.py
+++ b/patacrep/songs/__init__.py
@@ -168,16 +168,12 @@ class Song:
def __repr__(self):
return repr((self.titles, self.data, self.fullpath))
- def render(self, output_format, output=None, *args, **kwargs):
+ def render(self, output=None, *args, **kwargs):
"""Return the code rendering this song.
Arguments:
- - output_format: Format of the output file (latex, chordpro...)
- output: Name of the output file, or `None` if irrelevant.
"""
- method = "render_{}".format(output_format)
- if hasattr(self, method):
- return getattr(self, method)(output, *args, **kwargs)
raise NotImplementedError()
def _parse(self, config): # pylint: disable=no-self-use
@@ -204,15 +200,24 @@ class Song:
if os.path.isdir(fullpath):
yield fullpath
- def search_file(self, filename, extensions=None, directories=None):
+ def search_datadir_file(self, filename, extensions=None, directories=None):
"""Search for a file name.
:param str filename: The name, as provided in the chordpro file (with or without extension).
:param list extensions: Possible extensions (with '.'). Default is no extension.
:param iterator directories: Other directories where to search for the file
The directory where the Song file is stored is added to the list.
-
- Returns None if nothing found.
+ :return: A tuple `(datadir, filename, extension)` if file has been
+ found. It is guaranteed that `os.path.join(datadir,
+ filename+extension)` is a (relative or absolute) valid path to an
+ existing filename.
+ * `datadir` is the datadir in which the file has been found. Can be
+ the empty string.
+ * `filename` is the filename, relative to the datadir.
+ * `extension` is the extension that is to be appended to the
+ filename to get the real filename. Can be the empty string.
+
+ Raise `FileNotFoundError` if nothing found.
This function can also be used as a preprocessor for a renderer: for
instance, it can compile a file, place it in a temporary folder, and
@@ -224,27 +229,42 @@ class Song:
directories = self.config['datadir']
songdir = os.path.dirname(self.fullpath)
+ for extension in extensions:
+ if os.path.isfile(os.path.join(songdir, filename + extension)):
+ return "", os.path.join(songdir, filename), extension
- for directory in [songdir] + list(directories):
+ for directory in directories:
for extension in extensions:
- fullpath = os.path.join(directory, filename + extension)
- if os.path.isfile(fullpath):
- return os.path.abspath(fullpath)
- return None
+ if os.path.isfile(os.path.join(directory, filename + extension)):
+ return directory, filename, extension
+
+ raise FileNotFoundError(filename)
+
+ def search_file(self, filename, extensions=None, *, datadirs=None):
+ """Return the path to a file present in a datadir.
+
+ Implementation is specific to each renderer, as:
+ - some renderers can preprocess files;
+ - some renderers can return the absolute path, other can return something else;
+ - etc.
+ """
+ raise NotImplementedError()
- def search_image(self, filename, none_if_not_found=False):
+ def search_image(self, filename):
"""Search for an image file"""
- filepath = self.search_file(
+ return self.search_file(
filename,
['', '.jpg', '.png'],
- self.get_datadirs('img'),
+ datadirs=self.get_datadirs('img'),
)
- return filepath if none_if_not_found or filepath else filename
- def search_partition(self, filename, none_if_not_found=False):
+ def search_partition(self, filename):
"""Search for a lilypond file"""
- filepath = self.search_file(filename, ['', '.ly'])
- return filepath if none_if_not_found or filepath else filename
+ return self.search_file(
+ filename,
+ ['', '.ly'],
+ datadirs=self.get_datadirs('scores'),
+ )
def unprefixed_title(title, prefixes):
"""Remove the first prefix of the list in the beginning of title (if any).
diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py
index cc0807bb..c46a0880 100644
--- a/patacrep/songs/chordpro/__init__.py
+++ b/patacrep/songs/chordpro/__init__.py
@@ -1,9 +1,10 @@
"""Chordpro parser"""
-from jinja2 import Environment, FileSystemLoader, contextfunction
+from jinja2 import Environment, FileSystemLoader, contextfunction, ChoiceLoader
import jinja2
+import logging
import os
-import pkg_resources
+from pkg_resources import resource_filename
from patacrep import encoding, files
from patacrep.songs import Song
@@ -11,24 +12,13 @@ from patacrep.songs.chordpro.syntax import parse_song
from patacrep.templates import Renderer
from patacrep.latex import lang2babel
+LOGGER = logging.getLogger(__name__)
+
class ChordproSong(Song):
- """Chordpros song parser."""
+ """Chordpro song parser"""
+ # pylint: disable=abstract-method
- @staticmethod
- def iter_template_paths(templatedirs, output_format):
- """Iterate over paths in which templates are to be searched.
-
- :param iterator templatedirs: Iterators of additional directories (the
- default hard-coded template directory is returned last).
- :param str output_format: Song output format, which is appended to
- each directory.
- """
- for directory in templatedirs:
- yield os.path.join(directory, output_format)
- yield os.path.join(
- os.path.abspath(pkg_resources.resource_filename(__name__, 'data')),
- output_format,
- )
+ output_language = None
def _parse(self, config):
"""Parse content, and return the dictionary of song data."""
@@ -42,10 +32,7 @@ class ChordproSong(Song):
'song': song,
}
- def render(self, output_format, output=None, template="song", templatedirs=None): # pylint: disable=arguments-differ
- if templatedirs is None:
- templatedirs = []
-
+ def render(self, output=None, template="song"): # pylint: disable=arguments-differ
context = {
'lang': self.lang,
"titles": self.titles,
@@ -56,9 +43,14 @@ class ChordproSong(Song):
"content": self.cached['song'].content,
}
- jinjaenv = Environment(loader=FileSystemLoader(
- self.iter_template_paths(templatedirs, output_format)
- ))
+ jinjaenv = Environment(loader=ChoiceLoader([
+ FileSystemLoader(
+ self.get_datadirs(os.path.join("templates", self.output_language))
+ ),
+ FileSystemLoader(
+ os.path.join(resource_filename(__name__, 'data'), self.output_language)
+ ),
+ ]))
jinjaenv.filters['search_image'] = self.search_image
jinjaenv.filters['search_partition'] = self.search_partition
jinjaenv.filters['lang2babel'] = lang2babel
@@ -70,7 +62,7 @@ class ChordproSong(Song):
jinjaenv=jinjaenv,
).template.render(context)
except jinja2.exceptions.TemplateNotFound:
- raise NotImplementedError("Cannot convert to format '{}'.".format(output_format))
+ raise NotImplementedError("Cannot convert to format '{}'.".format(self.output_language))
@staticmethod
@contextfunction
@@ -79,6 +71,72 @@ class ChordproSong(Song):
context.vars['content'] = content
return context.environment.get_template(content.template()).render(context)
-SONG_PARSERS = {
- 'sgc': ChordproSong,
+class Chordpro2HtmlSong(ChordproSong):
+ """Render chordpro song to html code"""
+
+ output_language = "html"
+
+ def search_file(self, filename, extensions=None, *, datadirs=None):
+ try:
+ datadir, filename, extension = self.search_datadir_file(filename, extensions, datadirs)
+ return os.path.join(datadir, filename + extension)
+ except FileNotFoundError:
+ LOGGER.warning(
+ "Song '%s' (datadir '%s'): File '%s' not found.",
+ self.subpath, self.datadir, filename,
+ )
+ return None
+
+class Chordpro2LatexSong(ChordproSong):
+ """Render chordpro song to latex code"""
+
+ output_language = "latex"
+
+ def search_file(self, filename, extensions=None, *, datadirs=None):
+ _datadir, filename, _extension = self.search_datadir_file(
+ filename,
+ extensions,
+ datadirs,
+ )
+ return filename
+
+ def search_partition(self, filename):
+ try:
+ return os.path.join("scores", super().search_partition(filename))
+ except FileNotFoundError:
+ LOGGER.warning(
+ "Song '%s' (datadir '%s'): Score '%s' not found.",
+ self.subpath, self.datadir, filename,
+ )
+ return None
+
+ def search_image(self, filename):
+ try:
+ return os.path.join("img", super().search_image(filename))
+ except FileNotFoundError:
+ LOGGER.warning(
+ "Song '%s' (datadir '%s'): Image '%s' not found.",
+ self.subpath, self.datadir, filename,
+ )
+ return None
+
+class Chordpro2ChordproSong(ChordproSong):
+ """Render chordpro song to chordpro code"""
+
+ output_language = "chordpro"
+
+ def search_file(self, filename, extensions=None, *, datadirs=None):
+ # pylint: disable=unused-variable
+ return filename
+
+SONG_RENDERERS = {
+ "latex": {
+ 'sgc': Chordpro2LatexSong,
+ },
+ "html": {
+ 'sgc': Chordpro2HtmlSong,
+ },
+ "chordpro": {
+ 'sgc': Chordpro2ChordproSong,
+ },
}
diff --git a/patacrep/songs/chordpro/data/html/content_image b/patacrep/songs/chordpro/data/html/content_image
index 0da4bcfe..bf46a95f 100644
--- a/patacrep/songs/chordpro/data/html/content_image
+++ b/patacrep/songs/chordpro/data/html/content_image
@@ -1 +1,6 @@
+(* block image *)
+(* set image = content.argument|search_image *)
+(* if image *)
+(* endif *)
+(* endblock *)
diff --git a/patacrep/songs/chordpro/data/html/content_metadata_cover b/patacrep/songs/chordpro/data/html/content_metadata_cover
index 96fc7718..ef980a0a 100644
--- a/patacrep/songs/chordpro/data/html/content_metadata_cover
+++ b/patacrep/songs/chordpro/data/html/content_metadata_cover
@@ -1,3 +1,8 @@
+(* block cov *)
(* if 'cov' in metadata -*)
-
-(* endif *)
\ No newline at end of file
+ (* set cov = metadata['cov'].argument|search_image *)
+ (* if cov *)
+
+ (* endif *)
+(* endif *)
+(* endblock *)
diff --git a/patacrep/songs/chordpro/data/html/content_partition b/patacrep/songs/chordpro/data/html/content_partition
index 1075cced..b43318f8 100644
--- a/patacrep/songs/chordpro/data/html/content_partition
+++ b/patacrep/songs/chordpro/data/html/content_partition
@@ -1 +1,6 @@
-((content.argument))
+(* block partition *)
+(* set partition = content.argument|search_partition *)
+(* if partition *)
+((content.argument))
+(* endif *)
+(* endblock *)
diff --git a/patacrep/songs/chordpro/data/latex/content_image b/patacrep/songs/chordpro/data/latex/content_image
index e4c2befb..ac97404b 100644
--- a/patacrep/songs/chordpro/data/latex/content_image
+++ b/patacrep/songs/chordpro/data/latex/content_image
@@ -1 +1,6 @@
-\image{(( content.argument|search_image ))}
+(* block image *)
+(* set image = content.argument|search_image *)
+(* if image *)
+\image{(( image ))}
+(*- endif *)
+(*- endblock *)
diff --git a/patacrep/songs/chordpro/data/latex/content_partition b/patacrep/songs/chordpro/data/latex/content_partition
index 4ce134a1..a3c35a3e 100644
--- a/patacrep/songs/chordpro/data/latex/content_partition
+++ b/patacrep/songs/chordpro/data/latex/content_partition
@@ -1 +1,6 @@
+(* block partition *)
+(* set partition = content.argument|search_partition *)
+(* if partition *)
\lilypond{ ((- content.argument|search_partition -)) }
+(*- endif -*)
+(*- endblock -*)
diff --git a/patacrep/songs/chordpro/data/latex/song b/patacrep/songs/chordpro/data/latex/song
index d106c2e8..6f026c79 100644
--- a/patacrep/songs/chordpro/data/latex/song
+++ b/patacrep/songs/chordpro/data/latex/song
@@ -28,7 +28,12 @@
(* endif *)
(* endfor *)
(* if 'cov' in metadata *)
- cov={(( metadata["cov"].argument|search_image ))},
+ (* block cov *)
+ (* set cov = metadata["cov"].argument|search_image *)
+ (* if cov *)
+ cov={(( cov ))},
+ (* endif *)
+ (* endblock *)
(* endif *)
(* for key in metadata.morekeys *)
(( key.keyword ))={(( key.argument ))},
diff --git a/patacrep/songs/convert/__main__.py b/patacrep/songs/convert/__main__.py
index 51786875..6b40dca4 100644
--- a/patacrep/songs/convert/__main__.py
+++ b/patacrep/songs/convert/__main__.py
@@ -36,22 +36,29 @@ if __name__ == "__main__":
dest = sys.argv[2]
song_files = sys.argv[3:]
- song_parsers = files.load_plugins(
+ renderers = files.load_plugins(
datadirs=DEFAULT_CONFIG.get('datadir', []),
root_modules=['songs'],
- keyword='SONG_PARSERS',
+ keyword='SONG_RENDERERS',
)
- if source not in song_parsers:
+ if dest not in renderers:
LOGGER.error(
- "Unknown file format '%s'. Available ones are %s.",
+ "Unknown destination file format '%s'. Available ones are %s.",
source,
- ", ".join(["'{}'".format(key) for key in song_parsers.keys()])
+ ", ".join(["'{}'".format(key) for key in renderers.keys()])
+ )
+ sys.exit(1)
+ if source not in renderers[dest]:
+ LOGGER.error(
+ "Unknown source file format '%s'. Available ones are %s.",
+ source,
+ ", ".join(["'{}'".format(key) for key in renderers[dest].keys()])
)
sys.exit(1)
for file in song_files:
- song = song_parsers[source](file, DEFAULT_CONFIG)
+ song = renderers[dest][source](file, DEFAULT_CONFIG)
try:
destname = "{}.{}".format(".".join(file.split(".")[:-1]), dest)
if os.path.exists(destname):
diff --git a/patacrep/songs/latex/__init__.py b/patacrep/songs/latex/__init__.py
index 980fece2..8dd8d15b 100644
--- a/patacrep/songs/latex/__init__.py
+++ b/patacrep/songs/latex/__init__.py
@@ -11,8 +11,9 @@ from patacrep import files, encoding
from patacrep.latex import parse_song, BABEL_LANGUAGES
from patacrep.songs import Song
-class LatexSong(Song):
- """LaTeX song parser."""
+class Latex2LatexSong(Song):
+ """Song written in LaTeX, rendered in LaTeX"""
+ # pylint: disable=abstract-method
def _parse(self, __config):
"""Parse content, and return the dictionary of song data."""
@@ -28,8 +29,9 @@ class LatexSong(Song):
else:
self.authors = []
- def render_latex(self, output):
+ def render(self, output):
"""Return the code rendering the song."""
+ # pylint: disable=signature-differs
if output is None:
raise ValueError(output)
path = files.path2posix(files.relpath(
@@ -50,7 +52,10 @@ class LatexSong(Song):
BABEL_LANGUAGES[custom_lang] = language
self.lang = custom_lang
-SONG_PARSERS = {
- 'is': LatexSong,
- 'sg': LatexSong,
- }
+SONG_RENDERERS = {
+ "latex": {
+ 'is': Latex2LatexSong,
+ 'sg': Latex2LatexSong,
+ },
+}
+
diff --git a/patacrep/utils.py b/patacrep/utils.py
new file mode 100644
index 00000000..6d9eab4c
--- /dev/null
+++ b/patacrep/utils.py
@@ -0,0 +1,61 @@
+"""Some utility functions"""
+
+from collections import UserDict
+
+class DictOfDict(UserDict):
+ """Dictionary, with a recursive :meth:`update` method.
+
+ By "recursive", we mean: if `self.update(other)` is called, and for some
+ key both `self[key]` and `other[key]` are dictionary, then `self[key]` is
+ not replaced by `other[key]`, but instead is updated. This is done
+ recursively (that is, `self[foo][bar][baz]` is updated with
+ `other[foo][bar][baz]`, if the corresponding objects are dictionaries).
+
+ >>> ordinal = DictOfDict({
+ ... "francais": {
+ ... 1: "premier",
+ ... 2: "deuxieme",
+ ... },
+ ... "english": {
+ ... 1: "first",
+ ... },
+ ... })
+ >>> ordinal.update({
+ ... "francais": {
+ ... 2: "second",
+ ... 3: "troisieme",
+ ... },
+ ... "espanol": {
+ ... 1: "primero",
+ ... },
+ ... })
+ >>> ordinal == {
+ ... "francais": {
+ ... 1: "premier",
+ ... 2: "second",
+ ... 3: "troisieme",
+ ... },
+ ... "english": {
+ ... 1: "first",
+ ... },
+ ... "espanol": {
+ ... 1: "primero",
+ ... },
+ ... }
+ True
+ """
+
+ def update(self, other):
+ # pylint: disable=arguments-differ
+ self._update(self, other)
+
+ @staticmethod
+ def _update(left, right):
+ """Equivalent to `left.update(right)`, with recursive update."""
+ for key in right:
+ if key not in left:
+ left[key] = right[key]
+ elif isinstance(left[key], dict) and isinstance(right[key], dict):
+ DictOfDict._update(left[key], right[key])
+ else:
+ left[key] = right[key]
diff --git a/test/test_chordpro/datadir/img/traditionnel.png b/test/test_chordpro/datadir/img/traditionnel.png
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_chordpro/datadir/scores/greensleeves.ly b/test/test_chordpro/datadir/scores/greensleeves.ly
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_chordpro/greensleeves.tex b/test/test_chordpro/greensleeves.tex
index a0b602c0..f582b0c8 100644
--- a/test/test_chordpro/greensleeves.tex
+++ b/test/test_chordpro/greensleeves.tex
@@ -7,14 +7,14 @@ Un sous titre}[
by={
Traditionnel },
album={Angleterre},
- cov={traditionnel},
+ cov={img/traditionnel},
]
\cover
-\lilypond{greensleeves.ly}
+\lilypond{scores/greensleeves.ly}
diff --git a/test/test_chordpro/metadata.sgc b/test/test_chordpro/metadata.sgc
index d48ded77..559f3dd3 100644
--- a/test/test_chordpro/metadata.sgc
+++ b/test/test_chordpro/metadata.sgc
@@ -10,13 +10,13 @@
{artist: Author2}
{album: Album}
{copyright: Copyright}
-{cov: Cover}
+{cov: metadata_cover}
{key: foo: Foo}
{comment: Comment}
{guitar_comment: GuitarComment}
-{partition: Lilypond}
-{image: Image}
+{partition: metadata_lilypond}
+{image: metadata_image}
Foo
diff --git a/test/test_chordpro/metadata.source b/test/test_chordpro/metadata.source
index 02167238..7a623009 100644
--- a/test/test_chordpro/metadata.source
+++ b/test/test_chordpro/metadata.source
@@ -10,12 +10,12 @@
{artist: Author2}
{album: Album}
{copyright: Copyright}
-{cover: Cover}
+{cover: metadata_cover}
{capo: Capo}
{key: foo: Foo}
{comment: Comment}
{guitar_comment: GuitarComment}
-{partition: Lilypond}
-{image: Image}
+{partition: metadata_lilypond}
+{image: metadata_image}
Foo
diff --git a/test/test_chordpro/metadata.tex b/test/test_chordpro/metadata.tex
index fa29ec3c..a3a36676 100644
--- a/test/test_chordpro/metadata.tex
+++ b/test/test_chordpro/metadata.tex
@@ -11,7 +11,7 @@ Subtitle5}[
Author2 },
album={Album},
copyright={Copyright},
- cov={Cover},
+ cov={img/test/test_chordpro/metadata_cover},
foo={Foo},
]
@@ -19,8 +19,8 @@ Subtitle5}[
\textnote{Comment}
\musicnote{GuitarComment}
-\lilypond{Lilypond}
-\image{Image}
+\lilypond{scores/test/test_chordpro/metadata_lilypond}
+\image{img/test/test_chordpro/metadata_image}
diff --git a/test/test_chordpro/metadata_cover.png b/test/test_chordpro/metadata_cover.png
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_chordpro/metadata_image.png b/test/test_chordpro/metadata_image.png
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_chordpro/metadata_lilypond.ly b/test/test_chordpro/metadata_lilypond.ly
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_chordpro/test_parser.py b/test/test_chordpro/test_parser.py
index 20cafd38..6ce2a83a 100644
--- a/test/test_chordpro/test_parser.py
+++ b/test/test_chordpro/test_parser.py
@@ -5,9 +5,10 @@
import glob
import os
import unittest
+from pkg_resources import resource_filename
+from patacrep import files
from patacrep.build import DEFAULT_CONFIG
-from patacrep.songs.chordpro import ChordproSong
from .. import disable_logging
@@ -26,11 +27,22 @@ class FileTestMeta(type):
def __init__(cls, name, bases, nmspc):
super().__init__(name, bases, nmspc)
+ # Setting datadir
+ cls.config = DEFAULT_CONFIG
+ if 'datadir' not in cls.config:
+ cls.config['datadir'] = []
+ cls.config['datadir'].append(resource_filename(__name__, 'datadir'))
+
+ cls.song_plugins = files.load_plugins(
+ datadirs=cls.config['datadir'],
+ root_modules=['songs'],
+ keyword='SONG_RENDERERS',
+ )
for source in sorted(glob.glob(os.path.join(
os.path.dirname(__file__),
'*.source',
))):
- base = source[:-len(".source")]
+ base = os.path.relpath(source, os.getcwd())[:-len(".source")]
for dest in LANGUAGES:
destname = "{}.{}".format(base, dest)
if not os.path.exists(destname):
@@ -55,9 +67,8 @@ class FileTestMeta(type):
chordproname = "{}.source".format(base)
with disable_logging():
self.assertMultiLineEqual(
- ChordproSong(chordproname, DEFAULT_CONFIG).render(
+ self.song_plugins[LANGUAGES[dest]]['sgc'](chordproname, self.config).render(
output=chordproname,
- output_format=LANGUAGES[dest],
).strip(),
expectfile.read().strip(),
)