Browse Source

Merge pull request #120 from patacrep/test_compilation

[test] Test whole compilation
pull/134/merge
Louis 9 years ago
parent
commit
d211630cf9
  1. 10
      .travis.yml
  2. 2
      examples/example-crepbook.sb
  3. 2
      examples/example-layout.sb
  4. 2
      examples/example-songs.sb
  5. 18
      examples/example-subdir.sb
  6. 2
      examples/example.sb
  7. 2
      examples/example_encoding.sb
  8. BIN
      examples/img/datadir.png
  9. 19
      examples/root.ly
  10. BIN
      examples/root.png
  11. BIN
      examples/songs/subdir/relative.png
  12. 10
      examples/songs/subdir/root.sg
  13. 6
      examples/songs/subdir/root.sgc
  14. 6
      patacrep/content/song.py
  15. 0
      patacrep/data/img/treble_a.png
  16. 16
      patacrep/data/templates/default.tex
  17. 24
      patacrep/data/templates/patacrep.tex
  18. 42
      patacrep/data/templates/songs.tex
  19. 5
      patacrep/songbook/__main__.py
  20. 2
      setup.py
  21. 7
      songbook
  22. 25
      test/dynamic.py
  23. 39
      test/test_chordpro/test_parser.py
  24. 2
      test/test_compilation/.gitignore
  25. 0
      test/test_compilation/__init__.py
  26. 7
      test/test_compilation/subdir.sb
  27. 179
      test/test_compilation/subdir.tex.control
  28. BIN
      test/test_compilation/subdir_datadir/img/datadir.png
  29. 0
      test/test_compilation/subdir_datadir/scores/datadir.ly
  30. 0
      test/test_compilation/subdir_datadir/songs/datadir.sg
  31. 1
      test/test_compilation/subdir_datadir/songs/datadir.sgc
  32. 0
      test/test_compilation/subdir_datadir/songs/datadir2.sg
  33. 1
      test/test_compilation/subdir_datadir/songs/datadir2.sgc
  34. 0
      test/test_compilation/subdir_datadir/songs/relative.ly
  35. BIN
      test/test_compilation/subdir_datadir/songs/relative.png
  36. 0
      test/test_compilation/subdir_datadir/songs/relative.sg
  37. 1
      test/test_compilation/subdir_datadir/songs/relative.sgc
  38. 0
      test/test_compilation/subdir_datadir2/img/datadir2.png
  39. 0
      test/test_compilation/subdir_datadir2/scores/datadir2.ly
  40. 111
      test/test_compilation/test_compilation.py

10
.travis.yml

@ -7,3 +7,13 @@ install:
- pip install tox - pip install tox
script: script:
- tox - tox
sudo: false
addons:
apt:
packages:
- texlive-latex-base
- latex-xcolor
- texlive-latex-extra
- pgf
- lmodern
- lilypond

2
examples/example-crepbook.sb

@ -7,7 +7,7 @@
"pictures" "pictures"
], ],
"booktype" : "chorded", "booktype" : "chorded",
"lang" : "french", "lang" : "fr",
"authwords" : { "authwords" : {
"sep" : ["and", "et"] "sep" : ["and", "et"]
}, },

2
examples/example-layout.sb

@ -7,7 +7,7 @@
"pictures" "pictures"
], ],
"booktype" : "chorded", "booktype" : "chorded",
"lang" : "french", "lang" : "fr",
"authwords" : { "authwords" : {
"sep" : ["and", "et"] "sep" : ["and", "et"]
}, },

2
examples/example-songs.sb

@ -7,7 +7,7 @@
"pictures" "pictures"
], ],
"booktype" : "chorded", "booktype" : "chorded",
"lang" : "french", "lang" : "fr",
"authwords" : { "authwords" : {
"sep" : ["and", "et"] "sep" : ["and", "et"]
}, },

18
examples/example-subdir.sb

@ -1,18 +0,0 @@
{
"bookoptions" : [
"diagram",
"repeatchords",
"lilypond",
"pictures"
],
"datadir": ["datadir2"],
"booktype" : "chorded",
"template" : "patacrep.tex",
"lang" : "french",
"encoding": "utf8",
"authwords" : {
"sep" : ["and", "et"]
},
"content": [["sorted", "subdir/*.sg", "subdir/*.sgc"]]
}

2
examples/example.sb

@ -6,7 +6,7 @@
"pictures" "pictures"
], ],
"booktype" : "chorded", "booktype" : "chorded",
"lang" : "french", "lang" : "fr",
"authwords" : { "authwords" : {
"sep" : ["and", "et"] "sep" : ["and", "et"]
}, },

2
examples/example_encoding.sb

@ -6,7 +6,7 @@
"pictures" "pictures"
], ],
"booktype" : "chorded", "booktype" : "chorded",
"lang" : "french", "lang" : "fr",
"authwords" : { "authwords" : {
"sep" : ["and", "et", "À"], "sep" : ["and", "et", "À"],
"ignore" : ["À"], "ignore" : ["À"],

BIN
examples/img/datadir.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 645 B

19
examples/root.ly

@ -1,19 +0,0 @@
\include "_lilypond/header"
\paper{paper-height = 6.5\cm}
{
\key a \minor
\time 6/8
\partial 8 a'8
\relative c''{
c4 d8 e8. (f16) e8 d4 b8 g8. (a16) b8
c4 a8 a8. (gis16) a8 b4 gis8 e4 a8
c4 d8 e8. (f16 e8) d4 b8 g8. (a16) b8
c8. (b16) a8 gis8. (fis16) gis8 a4 a8 a4.
g'4. g8. (fis16) e8 d4 b8 g8. (a16) b8
c4 (a8) a8. (gis16) a8 b4 gis8 e4.
g'4. g8. (fis16) e8 d4 b8 g8. (a16) b8
c8. (b16) a8 gis8. (fis16) gis8 a4. a4.
}
}

BIN
examples/root.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

BIN
examples/songs/subdir/relative.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 645 B

10
examples/songs/subdir/root.sg

@ -1,10 +0,0 @@
\beginsong{Image included from root directory\\\LaTeX}
[cov={root}]
\cover
\lilypond{root.ly}
\image{root}
\endsong

6
examples/songs/subdir/root.sgc

@ -1,6 +0,0 @@
{title : Image included from root directory}
{subtitle: Chordpro}
{cover: root.png}
{partition: root.ly}
{image: root.png}

6
patacrep/content/song.py

@ -46,6 +46,10 @@ class SongRenderer(Content):
song=self.song.render(output=context['filename']), song=self.song.render(output=context['filename']),
) )
def __lt__(self, other):
"""Order by song path"""
return self.song.fullpath < other.song.fullpath
#pylint: disable=unused-argument #pylint: disable=unused-argument
def parse(keyword, argument, contentlist, config): def parse(keyword, argument, contentlist, config):
"""Parse data associated with keyword 'song'. """Parse data associated with keyword 'song'.
@ -102,7 +106,7 @@ def parse(keyword, argument, contentlist, config):
[item.fullpath for item in config['_songdir']], [item.fullpath for item in config['_songdir']],
message='Ignoring "{name}": did not match any file in {paths}.', message='Ignoring "{name}": did not match any file in {paths}.',
)) ))
return songlist return sorted(songlist)
CONTENT_PLUGINS = {'song': parse} CONTENT_PLUGINS = {'song': parse}

0
examples/img/treble_a.png → patacrep/data/img/treble_a.png

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

16
patacrep/data/templates/default.tex

@ -20,23 +20,23 @@
(* variables *) (* variables *)
{ {
"classoptions": {"description": {"english": "LaTeX class options", "french": "Options de la classe LaTeX"}, "classoptions": {"description": {"en": "LaTeX class options", "fr": "Options de la classe LaTeX"},
"type": "flag", "type": "flag",
"join": ",", "join": ",",
"mandatory": true, "mandatory": true,
"default": {"default":[]} "default": {"default":[]}
}, },
"title": {"description": {"english": "Title", "french": "Titre"}, "title": {"description": {"en": "Title", "fr": "Titre"},
"default": {"english": "Guitar songbook", "french": "Recueil de chansons pour guitare"}, "default": {"en": "Guitar songbook", "fr": "Recueil de chansons pour guitare"},
"mandatory":true "mandatory":true
}, },
"author": {"description": {"english": "Author", "french": "Auteur"}, "author": {"description": {"en": "Author", "fr": "Auteur"},
"default": {"english": "The Patacrep Team", "french": "L'équipe Patacrep"}, "default": {"en": "The Patacrep Team", "fr": "L'équipe Patacrep"},
"mandatory":true "mandatory":true
}, },
"notenamesout": {"description": {"english": "Note names. Can be 'solfedge' (Do, Re, Mi...) or 'alphascale' (A, B, C...).", "notenamesout": {"description": {"en": "Note names. Can be 'solfedge' (Do, Re, Mi...) or 'alphascale' (A, B, C...).",
"french": "Nom des notes : 'solfedge' (Do, Ré, Mi...) ou 'alphascale' (A, B, C...)."}, "fr": "Nom des notes : 'solfedge' (Do, Ré, Mi...) ou 'alphascale' (A, B, C...)."},
"default": {"default": "alphascale", "french": "solfedge"} "default": {"default": "alphascale", "fr": "solfedge"}
} }
} }
(* endvariables -*) (* endvariables -*)

24
patacrep/data/templates/patacrep.tex

@ -20,42 +20,42 @@
(* variables *) (* variables *)
{ {
"subtitle": {"description": {"english": "Subtitle", "french": "Sous-titre"}, "subtitle": {"description": {"en": "Subtitle", "fr": "Sous-titre"},
"default": {"default": ""} "default": {"default": ""}
}, },
"version":{ "description": {"english": "Version", "french": "Version"}, "version":{ "description": {"en": "Version", "fr": "Version"},
"default": {"default": "undefined"} "default": {"default": "undefined"}
}, },
"web": {"description": {"english": "Website", "french": "Site web"}, "web": {"description": {"en": "Website", "fr": "Site web"},
"default": {"default": "http://www.patacrep.com"} "default": {"default": "http://www.patacrep.com"}
}, },
"mail": {"description": {"english": "Email", "french": "Adresse électronique"}, "mail": {"description": {"en": "Email", "fr": "Adresse électronique"},
"default": {"default": "crep@team-on-fire.com"} "default": {"default": "crep@team-on-fire.com"}
}, },
"picture": {"description": {"english": "Cover picture", "french": "Image de couverture"}, "picture": {"description": {"en": "Cover picture", "fr": "Image de couverture"},
"type": "file", "type": "file",
"default": {"default": "img/treble_a"} "default": {"default": "img/treble_a"}
}, },
"picturecopyright": {"description": {"english": "Copyright for the cover picture", "french": "Copyright pour l'image de couverture"}, "picturecopyright": {"description": {"en": "Copyright for the cover picture", "fr": "Copyright pour l'image de couverture"},
"default": {"default": "Dbolton \\url{http://commons.wikimedia.org/wiki/User:Dbolton}"} "default": {"default": "Dbolton \\url{http://commons.wikimedia.org/wiki/User:Dbolton}"}
}, },
"footer": {"description": {"english": "Footer", "french": "Pied de page"}, "footer": {"description": {"en": "Footer", "fr": "Pied de page"},
"default": {"default": "Generated using Songbook (\\url{http://www.patacrep.com})"} "default": {"default": "Generated using Songbook (\\url{http://www.patacrep.com})"}
}, },
"songnumberbgcolor": {"description": {"english": "Number Shade", "french": "Couleur des numéros"}, "songnumberbgcolor": {"description": {"en": "Number Shade", "fr": "Couleur des numéros"},
"type": "color", "type": "color",
"default": {"default": "D1E4AE"} "default": {"default": "D1E4AE"}
}, },
"notebgcolor": {"description": {"english": "Note Shade", "french": "Couleur des notes"}, "notebgcolor": {"description": {"en": "Note Shade", "fr": "Couleur des notes"},
"type": "color", "type": "color",
"default": {"default": "D1E4AE"} "default": {"default": "D1E4AE"}
}, },
"indexbgcolor": {"description": {"english": "Index Shade", "french": "Couleur d'index"}, "indexbgcolor": {"description": {"en": "Index Shade", "fr": "Couleur d'index"},
"type": "color", "type": "color",
"default": {"default": "D1E4AE"} "default": {"default": "D1E4AE"}
}, },
"titleprefixwords": {"description": {"english": "Ignore some words in the beginning of song titles", "titleprefixwords": {"description": {"en": "Ignore some words in the beginning of song titles",
"french": "Ignore des mots dans le classement des chansons"}, "fr": "Ignore des mots dans le classement des chansons"},
"default": {"default": ["The", "Le", "La", "L'", "A", "Au", "Ces", "De", "default": {"default": ["The", "Le", "La", "L'", "A", "Au", "Ces", "De",
"Des", "El", "Les", "Ma", "Mon", "Un"]} "Des", "El", "Les", "Ma", "Mon", "Un"]}
} }

42
patacrep/data/templates/songs.tex

@ -20,46 +20,46 @@
(* variables *) (* variables *)
{ {
"instruments": {"description": {"english": "Instruments", "french": "Instruments"}, "instruments": {"description": {"en": "Instruments", "fr": "Instruments"},
"type": "flag", "type": "flag",
"values": {"guitar": {"english": "Guitare", "french": "Guitare"}, "values": {"guitar": {"en": "Guitare", "fr": "Guitare"},
"ukulele": {"english": "Ukulele", "french": "Ukulele"} "ukulele": {"en": "Ukulele", "fr": "Ukulele"}
}, },
"join": ",", "join": ",",
"mandatory": true, "mandatory": true,
"default": {"default":["guitar"]} "default": {"default":["guitar"]}
}, },
"bookoptions": {"description": {"english": "Options", "french": "Options"}, "bookoptions": {"description": {"en": "Options", "fr": "Options"},
"type": "flag", "type": "flag",
"values": {"diagram": {"english": "Chords diagrams", "french": "Diagrammes d'accords"}, "values": {"diagram": {"en": "Chords diagrams", "fr": "Diagrammes d'accords"},
"importantdiagramonly": {"english": "Only importants diagrames", "french": "Diagrammes importants uniquement"}, "importantdiagramonly": {"en": "Only importants diagrames", "fr": "Diagrammes importants uniquement"},
"lilypond": {"english": "Lilypond music sheets", "french": "Partitions lilypond"}, "lilypond": {"en": "Lilypond music sheets", "fr": "Partitions lilypond"},
"pictures": {"english": "Cover pictures", "french": "Couvertures d'albums"}, "pictures": {"en": "Cover pictures", "fr": "Couvertures d'albums"},
"tabs": {"english": "Tablatures", "french": "Tablatures"}, "tabs": {"en": "Tablatures", "fr": "Tablatures"},
"repeatchords": {"english": "Repeat chords", "french": "Répéter les accords"}, "repeatchords": {"en": "Repeat chords", "fr": "Répéter les accords"},
"onesongperpage": {"english": "One song per page", "french": "Une chanson par page"} "onesongperpage": {"en": "One song per page", "fr": "Une chanson par page"}
}, },
"join": ",", "join": ",",
"mandatory": true, "mandatory": true,
"default": {"default":["diagram","pictures"]} "default": {"default":["diagram","pictures"]}
}, },
"booktype": {"description": {"english": "Type", "french": "Type"}, "booktype": {"description": {"en": "Type", "fr": "Type"},
"type": "enum", "type": "enum",
"values": {"chorded": {"english": "With guitar chords", "french": "Avec accords de guitare" }, "values": {"chorded": {"en": "With guitar chords", "fr": "Avec accords de guitare" },
"lyric": {"english": "Lyrics only", "french": "Paroles uniquement"} "lyric": {"en": "Lyrics only", "fr": "Paroles uniquement"}
}, },
"default": {"default":"chorded"}, "default": {"default":"chorded"},
"mandatory": true "mandatory": true
}, },
"lang": {"description": {"english": "Language", "french": "Langue"}, "lang": {"description": {"en": "Language", "fr": "Langue"},
"default": {"english": "en", "french": "fr"} "default": {"en": "en", "fr": "fr"}
}, },
"titleprefixwords": {"description": {"english": "Ignore some words in the beginning of song titles", "titleprefixwords": {"description": {"en": "Ignore some words in the beginning of song titles",
"french": "Ignore des mots dans le classement des chansons"}, "fr": "Ignore des mots dans le classement des chansons"},
"default": {"default": []} "default": {"default": []}
}, },
"authwords": {"description": {"english": "Set of options to process author string (LaTeX commands authsepword, authignoreword, authbyword)", "authwords": {"description": {"en": "Set of options to process author string (LaTeX commands authsepword, authignoreword, authbyword)",
"french": "Options pour traiter les noms d'auteurs (commandes LaTeX authsepword, authignoreword, authbyword)"}, "fr": "Options pour traiter les noms d'auteurs (commandes LaTeX authsepword, authignoreword, authbyword)"},
"default": {"default": {}} "default": {"default": {}}
} }
} }
@ -80,7 +80,7 @@
(* block songbookpreambule *) (* block songbookpreambule *)
(( super() )) (( super() ))
(* for lang in _langs -*) (* for lang in _langs|sort -*)
\PassOptionsToPackage{(( lang2babel(lang) ))}{babel} \PassOptionsToPackage{(( lang2babel(lang) ))}{babel}
(* endfor *) (* endfor *)
\usepackage[(( lang2babel(lang) ))]{babel} \usepackage[(( lang2babel(lang) ))]{babel}

5
patacrep/songbook.py → patacrep/songbook/__main__.py

@ -39,7 +39,10 @@ class VerboseAction(argparse.Action):
def argument_parser(args): def argument_parser(args):
"""Parse arguments""" """Parse arguments"""
parser = argparse.ArgumentParser(description="A song book compiler") parser = argparse.ArgumentParser(
prog="songbook",
description="A song book compiler",
)
parser.add_argument( parser.add_argument(
'--version', help='Show version', action='version', '--version', help='Show version', action='version',

2
setup.py

@ -24,7 +24,7 @@ setup(
include_package_data=True, include_package_data=True,
entry_points={ entry_points={
'console_scripts': [ 'console_scripts': [
"songbook = patacrep.songbook:main", "songbook = patacrep.songbook.__main__:main",
], ],
}, },
classifiers=[ classifiers=[

7
songbook

@ -1,9 +1,6 @@
#! /usr/bin/env python3 #! /bin/sh
# Do not edit this file. This file is just a helper file for development test. # Do not edit this file. This file is just a helper file for development test.
# It is not part of the distributed software. # It is not part of the distributed software.
"""Command line tool to compile songbooks using the songbook library.""" python -m patacrep.songbook $*
from patacrep.songbook import main
main()

25
test/dynamic.py

@ -0,0 +1,25 @@
"""Dynamic creation of test methods."""
class DynamicTest(type):
"""Metaclass that creates on-the-fly test methods.
Each class implementing this metaclass must define two class methods:
- `_iter_testmethods`, which iterate over `(methodname, args)`, where
`methodname` is the name of a test method to create, and `args` is a list
of arguments to pass to `_create_test`;
- `_create_test`, a method returning a test method.
"""
def __init__(cls, name, bases, nmspc):
super().__init__(name, bases, nmspc)
for methodname, args in cls._iter_testmethods():
setattr(cls, methodname, cls._create_test(*args))
def _iter_testmethods(cls):
"""Iterate over test methods."""
raise NotImplementedError()
def _create_test(cls, *args, **kwargs):
"""Create and return a test method."""
raise NotImplementedError()

39
test/test_chordpro/test_parser.py

@ -12,6 +12,7 @@ from patacrep.build import DEFAULT_CONFIG
from patacrep.encoding import open_read from patacrep.encoding import open_read
from .. import disable_logging from .. import disable_logging
from .. import dynamic # pylint: disable=unused-import
LANGUAGES = { LANGUAGES = {
'tex': 'latex', 'tex': 'latex',
@ -19,15 +20,22 @@ LANGUAGES = {
'html': 'html', 'html': 'html',
} }
class FileTestMeta(type): class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest):
"""Metaclass that creates on-the-fly test function according to files. """Test of chorpro parser, and several renderers.
For any given `foo.source`, it is parsed as a chordpro file, and should be
rendered as `foo.sgc` with the chordpro renderer, and `foo.tex` with the
latex renderer.
See the :class:`FileTest` documentation for more information. This class does nothing by itself, but its metaclass populates it with test
methods testing parser and renderers.
""" """
def __init__(cls, name, bases, nmspc): maxDiff = None
super().__init__(name, bases, nmspc)
@classmethod
def _iter_testmethods(cls):
"""Iterate over song files to test."""
# Setting datadir # Setting datadir
cls.config = DEFAULT_CONFIG cls.config = DEFAULT_CONFIG
if 'datadir' not in cls.config: if 'datadir' not in cls.config:
@ -48,14 +56,13 @@ class FileTestMeta(type):
destname = "{}.{}".format(base, dest) destname = "{}.{}".format(base, dest)
if not os.path.exists(destname): if not os.path.exists(destname):
continue continue
setattr( yield (
cls,
"test_{}_{}".format(os.path.basename(base), dest), "test_{}_{}".format(os.path.basename(base), dest),
cls._create_test(base, dest), [base, dest],
) )
@staticmethod @classmethod
def _create_test(base, dest): def _create_test(cls, base, dest):
"""Return a function testing that `base` compilation in `dest` format. """Return a function testing that `base` compilation in `dest` format.
""" """
@ -79,15 +86,3 @@ class FileTestMeta(type):
).format(base=os.path.basename(base), format=dest) ).format(base=os.path.basename(base), format=dest)
return test_parse_render return test_parse_render
class FileTest(unittest.TestCase, metaclass=FileTestMeta):
"""Test of chorpro parser, and several renderers.
For any given `foo.source`, it is parsed as a chordpro file, and should be
rendered as `foo.sgc` with the chordpro renderer, and `foo.tex` with the
latex renderer.
This class does nothing by itself, but its metaclass populates it with test
methods testing parser and renderers.
"""
maxDiff = None

2
test/test_compilation/.gitignore

@ -0,0 +1,2 @@
/*tex
.cache

0
test/test_compilation/__init__.py

7
test/test_compilation/subdir.sb

@ -0,0 +1,7 @@
{
"bookoptions" : [
"pictures"
],
"datadir": ["subdir_datadir", "subdir_datadir2"],
"lang": "en"
}

179
test/test_compilation/subdir.tex.control

@ -0,0 +1,179 @@
%% Automatically generated document.
%% You may edit this file but all changes will be overwritten.
%% If you want to change this document, have a look at
%% the templating system.
%%
%% Generated using Songbook <http://www.patacrep.com>
\makeatletter
\def\input@path{ %
{@TEST_FOLDER@/subdir_datadir/latex/} %
{@TEST_FOLDER@/subdir_datadir2/latex/} %
{@TEST_FOLDER@/latex/} %
{@DATA_FOLDER@/latex/} %
}
\makeatother
\documentclass[
]{article}
\usepackage[
chorded,
pictures,
guitar,
]{patacrep}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\PassOptionsToPackage{english}{babel}
\usepackage[english]{babel}
\lang{english}
\usepackage{graphicx}
\graphicspath{ %
{@TEST_FOLDER@/subdir_datadir/} %
{@TEST_FOLDER@/subdir_datadir2/} %
{@TEST_FOLDER@/} %
{@DATA_FOLDER@/} %
}
\makeatletter
\@ifpackageloaded{hyperref}{}{
\usepackage{url}
\newcommand{\phantomsection}{}
\newcommand{\hyperlink}[2]{#2}
\newcommand{\href}[2]{\expandafter\url\expandafter{#1}}
}
\makeatother
\usepackage{chords}
\title{Guitar songbook}
\author{The Patacrep Team}
\newindex{titleidx}{subdir_title}
\newauthorindex{authidx}{subdir_auth}
\notenamesout{A}{B}{C}{D}{E}{F}{G}
\begin{document}
\maketitle
\showindex{\songindexname}{titleidx}
\showindex{\authorindexname}{authidx}
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\fi
\phantomsection
\addcontentsline{toc}{section}{\songlistname}
\begin{songs}{titleidx,authidx}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./datadir.sg
\import{subdir_datadir/songs/}{datadir.sg}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./datadir.sgc
\selectlanguage{english}
\beginsong{Image included from datadir\\
Chordpro}[
by={
},
cov={img/datadir.png},
]
\cover
\lilypond{scores/datadir.ly}
\image{img/datadir.png}
\endsong
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./datadir2.sg
\import{subdir_datadir/songs/}{datadir2.sg}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./datadir2.sgc
\selectlanguage{english}
\beginsong{Image included from a different datadir\\
Chordpro}[
by={
},
cov={img/datadir2.png},
]
\cover
\lilypond{scores/datadir2.ly}
\image{img/datadir2.png}
\endsong
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./relative.sg
\import{subdir_datadir/songs/}{relative.sg}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./relative.sgc
\selectlanguage{english}
\beginsong{Image included from song directory\\
Chordpro}[
by={
},
cov={@TEST_FOLDER@/subdir_datadir/songs/./relative.png},
]
\cover
\lilypond{@TEST_FOLDER@/subdir_datadir/songs/./relative.ly}
\image{@TEST_FOLDER@/subdir_datadir/songs/./relative.png}
\endsong
\end{songs}
\end{document}

BIN
test/test_compilation/subdir_datadir/img/datadir.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

0
examples/scores/datadir.ly → test/test_compilation/subdir_datadir/scores/datadir.ly

0
examples/songs/subdir/datadir.sg → test/test_compilation/subdir_datadir/songs/datadir.sg

1
examples/songs/subdir/datadir.sgc → test/test_compilation/subdir_datadir/songs/datadir.sgc

@ -1,6 +1,7 @@
{title : Image included from datadir} {title : Image included from datadir}
{subtitle: Chordpro} {subtitle: Chordpro}
{cover: datadir.png} {cover: datadir.png}
{lang: en}
{partition: datadir.ly} {partition: datadir.ly}
{image: datadir.png} {image: datadir.png}

0
examples/songs/subdir/datadir2.sg → test/test_compilation/subdir_datadir/songs/datadir2.sg

1
examples/songs/subdir/datadir2.sgc → test/test_compilation/subdir_datadir/songs/datadir2.sgc

@ -1,6 +1,7 @@
{title : Image included from a different datadir} {title : Image included from a different datadir}
{subtitle: Chordpro} {subtitle: Chordpro}
{cover: datadir2.png} {cover: datadir2.png}
{lang: en}
{partition: datadir2.ly} {partition: datadir2.ly}
{image: datadir2.png} {image: datadir2.png}

0
examples/songs/subdir/relative.ly → test/test_compilation/subdir_datadir/songs/relative.ly

BIN
test/test_compilation/subdir_datadir/songs/relative.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

0
examples/songs/subdir/relative.sg → test/test_compilation/subdir_datadir/songs/relative.sg

1
examples/songs/subdir/relative.sgc → test/test_compilation/subdir_datadir/songs/relative.sgc

@ -1,6 +1,7 @@
{title : Image included from song directory} {title : Image included from song directory}
{subtitle: Chordpro} {subtitle: Chordpro}
{cover: relative.png} {cover: relative.png}
{lang: en}
{partition: relative.ly} {partition: relative.ly}
{image: relative.png} {image: relative.png}

0
examples/datadir2/img/datadir2.png → test/test_compilation/subdir_datadir2/img/datadir2.png

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

0
examples/datadir2/scores/datadir2.ly → test/test_compilation/subdir_datadir2/scores/datadir2.ly

111
test/test_compilation/test_compilation.py

@ -0,0 +1,111 @@
"""Tests for the chordpro parser."""
# pylint: disable=too-few-public-methods
import glob
import os
import subprocess
import unittest
import logging
from patacrep.encoding import open_read
from .. import dynamic # pylint: disable=unused-import
LOGGER = logging.getLogger(__name__)
class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest):
"""Test of songbook compilation.
For any given `foo.sb`, it performs several checks:
- the corresponding tex file is generated;
- the generated tex file matches the `foo.tex.control` control file;
- the compilation (tex, pdf, indexes) works without errors.
This class does nothing by itself, but its metaclass populates it with test
methods testing parser and renderers.
"""
maxDiff = None
@classmethod
def _iter_testmethods(cls):
"""Iterate over songbook files to test."""
for songbook in sorted(glob.glob(os.path.join(
os.path.dirname(__file__),
'*.sb',
))):
base = songbook[:-len(".sb")]
control = "{}.tex.control".format(base)
if not os.path.exists(control):
continue
yield (
"test_{}".format(os.path.basename(base)),
[base],
)
@classmethod
def _create_test(cls, base):
"""Return a function testing that `base` compiles."""
def test_compile(self):
"""Test that `base` is correctly compiled."""
if base is None:
return
songbook = "{}.sb".format(base)
# Check tex generation
self.assertEqual(0, self.compile_songbook(songbook, "tex"))
# Check generated tex
control = "{}.tex.control".format(base)
tex = "{}.tex".format(base)
with open_read(control) as expectfile:
with open_read(tex) as latexfile:
expected = expectfile.read().strip()
expected = expected.replace(
"@TEST_FOLDER@",
os.path.dirname(__file__),
)
expected = expected.replace(
"@DATA_FOLDER@",
subprocess.check_output(
["python", "-c", 'import patacrep, pkg_resources; print(pkg_resources.resource_filename(patacrep.__name__, "data"))'], # pylint: disable=line-too-long
universal_newlines=True,
cwd=os.path.dirname(songbook),
).strip(),
)
self.assertMultiLineEqual(
latexfile.read().strip(),
expected,
)
# Check compilation
self.assertEqual(0, self.compile_songbook(songbook))
test_compile.__doc__ = (
"Test that '{base}' is correctly compiled."
).format(base=os.path.basename(base))
return test_compile
@staticmethod
def compile_songbook(songbook, steps=None):
"""Compile songbook, and return the command return code."""
command = ['python', '-m', 'patacrep.songbook', songbook, '-v']
if steps:
command.extend(['--steps', steps])
try:
subprocess.check_output(
command,
stderr=subprocess.STDOUT,
universal_newlines=True,
cwd=os.path.dirname(songbook),
)
return 0
except subprocess.CalledProcessError as error:
LOGGER.warning(error.output)
return error.returncode
Loading…
Cancel
Save