@ -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"]] |
|||
|
|||
} |
Before Width: | Height: | Size: 645 B |
@ -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. |
|||
} |
|||
} |
Before Width: | Height: | Size: 513 B |
Before Width: | Height: | Size: 645 B |
@ -1,10 +0,0 @@ |
|||
\beginsong{Image included from root directory\\\LaTeX} |
|||
[cov={root}] |
|||
|
|||
\cover |
|||
|
|||
\lilypond{root.ly} |
|||
|
|||
\image{root} |
|||
|
|||
\endsong |
@ -1,6 +0,0 @@ |
|||
{title : Image included from root directory} |
|||
{subtitle: Chordpro} |
|||
{cover: root.png} |
|||
|
|||
{partition: root.ly} |
|||
{image: root.png} |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
@ -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. |
|||
# It is not part of the distributed software. |
|||
|
|||
"""Command line tool to compile songbooks using the songbook library.""" |
|||
|
|||
from patacrep.songbook import main |
|||
main() |
|||
python -m patacrep.songbook $* |
|||
|
@ -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() |
@ -0,0 +1,2 @@ |
|||
/*tex |
|||
.cache |
@ -0,0 +1,7 @@ |
|||
{ |
|||
"bookoptions" : [ |
|||
"pictures" |
|||
], |
|||
"datadir": ["subdir_datadir", "subdir_datadir2"], |
|||
"lang": "en" |
|||
} |
@ -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} |
After Width: | Height: | Size: 4.0 KiB |
@ -1,6 +1,7 @@ |
|||
{title : Image included from datadir} |
|||
{subtitle: Chordpro} |
|||
{cover: datadir.png} |
|||
{lang: en} |
|||
|
|||
{partition: datadir.ly} |
|||
{image: datadir.png} |
@ -1,6 +1,7 @@ |
|||
{title : Image included from a different datadir} |
|||
{subtitle: Chordpro} |
|||
{cover: datadir2.png} |
|||
{lang: en} |
|||
|
|||
{partition: datadir2.ly} |
|||
{image: datadir2.png} |
After Width: | Height: | Size: 3.9 KiB |
@ -1,6 +1,7 @@ |
|||
{title : Image included from song directory} |
|||
{subtitle: Chordpro} |
|||
{cover: relative.png} |
|||
{lang: en} |
|||
|
|||
{partition: relative.ly} |
|||
{image: relative.png} |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
@ -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 |