Browse Source

Merge branch 'master' into data

pull/156/head
Oliverpool 9 years ago
parent
commit
0704fc7de1
  1. 2
      patacrep/data/templates/songs/chordpro/latex/content_verse
  2. 23
      patacrep/songbook/__main__.py
  3. 4
      patacrep/songs/__init__.py
  4. 17
      patacrep/songs/convert/__main__.py
  5. 16
      patacrep/utils.py
  6. 2
      test/test_chordpro/nolyrics.tex
  7. 4
      test/test_compilation/syntax.sb
  8. 116
      test/test_compilation/syntax.tex.control
  9. 4
      test/test_compilation/syntax_datadir/songs/musicnote.sgc
  10. 17
      test/test_compilation/test_compilation.py

2
patacrep/data/templates/songs/chordpro/latex/content_verse

@ -6,7 +6,7 @@
\ifchorded \ifchorded
\begin{verse*} \begin{verse*}
(* for line in content.lines *) (* for line in content.lines *)
\musicnote {\nolyrics (( render(line) ))} \musicnote {\nolyrics (( render(line)|replace("#", "{\shrp}") ))}
(* endfor *) (* endfor *)
\end{verse*} \end{verse*}
\fi \fi

23
patacrep/songbook/__main__.py

@ -9,6 +9,7 @@ import textwrap
import sys import sys
from patacrep.build import SongbookBuilder, DEFAULT_STEPS from patacrep.build import SongbookBuilder, DEFAULT_STEPS
from patacrep.utils import yesno
from patacrep import __version__ from patacrep import __version__
from patacrep import errors from patacrep import errors
import patacrep.encoding import patacrep.encoding
@ -37,6 +38,16 @@ class VerboseAction(argparse.Action):
def __call__(self, *_args, **_kwargs): def __call__(self, *_args, **_kwargs):
LOGGER.setLevel(logging.DEBUG) LOGGER.setLevel(logging.DEBUG)
def yesno_type(string):
"""Interpret argument as a "yes" or a "no".
Raise `argparse.ArgumentTypeError` if string cannot be analysed.
"""
try:
return yesno(string)
except ValueError as error:
raise argparse.ArgumentTypeError(str(error))
def argument_parser(args): def argument_parser(args):
"""Parse arguments""" """Parse arguments"""
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
@ -68,6 +79,15 @@ def argument_parser(args):
""") """)
) )
parser.add_argument(
'--cache', '-c', nargs=1,
help=textwrap.dedent("""\
Enable song cache.
"""),
type=yesno_type,
default=[True],
)
parser.add_argument( parser.add_argument(
'--steps', '-s', nargs=1, type=str, '--steps', '-s', nargs=1, type=str,
action=ParseStepsAction, action=ParseStepsAction,
@ -107,7 +127,7 @@ def main():
options = argument_parser(sys.argv[1:]) options = argument_parser(sys.argv[1:])
songbook_path = options.book[0] songbook_path = options.book[-1]
if os.path.exists(songbook_path + ".sb") and not os.path.exists(songbook_path): if os.path.exists(songbook_path + ".sb") and not os.path.exists(songbook_path):
songbook_path += ".sb" songbook_path += ".sb"
@ -147,6 +167,7 @@ def main():
datadirs.append(os.path.dirname(os.path.abspath(songbook_path))) datadirs.append(os.path.dirname(os.path.abspath(songbook_path)))
songbook['datadir'] = datadirs songbook['datadir'] = datadirs
songbook['_cache'] = options.cache[0]
try: try:
sb_builder = SongbookBuilder(songbook, basename) sb_builder = SongbookBuilder(songbook, basename)

4
patacrep/songs/__init__.py

@ -104,7 +104,7 @@ class Song:
self.encoding = config["encoding"] self.encoding = config["encoding"]
self.config = config self.config = config
if datadir: if self.datadir and self.config['_cache']:
# Only songs in datadirs are cached # Only songs in datadirs are cached
self._filehash = hashlib.md5( self._filehash = hashlib.md5(
open(self.fullpath, 'rb').read() open(self.fullpath, 'rb').read()
@ -155,7 +155,7 @@ class Song:
def _write_cache(self): def _write_cache(self):
"""If relevant, write a dumbed down version of self to the cache.""" """If relevant, write a dumbed down version of self to the cache."""
if self.datadir: if self.datadir and self.config['_cache']:
cached = {} cached = {}
for attribute in self.cached_attributes: for attribute in self.cached_attributes:
cached[attribute] = getattr(self, attribute) cached[attribute] = getattr(self, attribute)

17
patacrep/songs/convert/__main__.py

@ -7,24 +7,21 @@ import os
import logging import logging
import sys import sys
from patacrep.build import DEFAULT_CONFIG
from patacrep import files from patacrep import files
from patacrep.build import DEFAULT_CONFIG
from patacrep.utils import yesno
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
def __usage(): def __usage():
return "python3 -m patacrep.songs.convert INPUTFORMAT OUTPUTFORMAT FILES" return "python3 -m patacrep.songs.convert INPUTFORMAT OUTPUTFORMAT FILES"
def yesno(prompt):
while True:
answer = input("{} [yn] ".format(prompt))
if answer.strip().lower() == "y":
return True
if answer.strip().lower() == "n":
return False
def confirm(destname): def confirm(destname):
return yesno("File '{}' already exist. Overwrite?".format(destname)) while True
try:
return yesno(input("File '{}' already exist. Overwrite? [yn] ".format(destname)))
except ValueError:
continue
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) < 4: if len(sys.argv) < 4:

16
patacrep/utils.py

@ -59,3 +59,19 @@ class DictOfDict(UserDict):
DictOfDict._update(left[key], right[key]) DictOfDict._update(left[key], right[key])
else: else:
left[key] = right[key] left[key] = right[key]
def yesno(string):
"""Interpret string argument as a boolean.
May raise `ValueError` if argument cannot be interpreted.
"""
yes_strings = ["y", "yes", "true", "1"]
no_strings = ["n", "no", "false", "0"]
if string.lower() in yes_strings:
return True
if string.lower() in no_strings:
return False
raise ValueError("'{}' is supposed to be one of {}.".format(
string,
", ".join(["'{}'".format(string) for string in yes_strings + no_strings]),
))

2
test/test_chordpro/nolyrics.tex

@ -14,7 +14,7 @@
\ifchorded \ifchorded
\begin{verse*} \begin{verse*}
\musicnote {\nolyrics \[A B#]} \musicnote {\nolyrics \[A B{\shrp}]}
\end{verse*} \end{verse*}
\fi \fi

4
test/test_compilation/syntax.sb

@ -0,0 +1,4 @@
{
"datadir": ["syntax_datadir"],
"lang": "en"
}

116
test/test_compilation/syntax.tex.control

@ -0,0 +1,116 @@
%% 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@/syntax_datadir/latex/} %
{@TEST_FOLDER@/latex/} %
{@DATA_FOLDER@/latex/} %
}
\makeatother
\documentclass[
]{article}
\usepackage[
chorded,
diagram,
pictures,
guitar,
]{patacrep}
\usepackage{lmodern}
\PassOptionsToPackage{english}{babel}
\usepackage[english]{babel}
\lang{english}
\usepackage{graphicx}
\graphicspath{ %
{@TEST_FOLDER@/syntax_datadir/} %
{@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}{syntax_title}
\newauthorindex{authidx}{syntax_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/./musicnote.sgc
\selectlanguage{english}
\beginsong{Song with Sharp in musicnote}[
by={
},
]
\ifchorded
\begin{verse*}
\musicnote {\nolyrics \[Am C{\shrp}m]}
\end{verse*}
\fi
\endsong
\end{songs}
\end{document}

4
test/test_compilation/syntax_datadir/songs/musicnote.sgc

@ -0,0 +1,4 @@
{title : Song with Sharp in musicnote}
{lang: en}
[Am C#m]

17
test/test_compilation/test_compilation.py

@ -9,7 +9,6 @@ import sys
import subprocess import subprocess
import unittest import unittest
from patacrep.encoding import open_read
from patacrep.files import path2posix from patacrep.files import path2posix
from .. import dynamic # pylint: disable=unused-import from .. import dynamic # pylint: disable=unused-import
@ -38,15 +37,12 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest):
'*.sb', '*.sb',
))): ))):
base = songbook[:-len(".sb")] base = songbook[:-len(".sb")]
control = "{}.tex.control".format(base)
if not os.path.exists(control):
continue
yield ( yield (
"test_generation_{}".format(os.path.basename(base)), "test_latex_generation_{}".format(os.path.basename(base)),
cls._create_generation_test(base), cls._create_generation_test(base),
) )
yield ( yield (
"test_compilation_{}".format(os.path.basename(base)), "test_pdf_compilation_{}".format(os.path.basename(base)),
cls._create_compilation_test(base), cls._create_compilation_test(base),
) )
@ -63,9 +59,12 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest):
# Check generated tex # Check generated tex
control = "{}.tex.control".format(base) control = "{}.tex.control".format(base)
if not os.path.exists(control):
raise unittest.SkipTest('No control file for {}'.format(songbook))
tex = "{}.tex".format(base) tex = "{}.tex".format(base)
with open_read(control) as expectfile: with open(control, mode="r", encoding="utf8") as expectfile:
with open_read(tex) as latexfile: with open(tex, mode="r", encoding="utf8") as latexfile:
expected = expectfile.read().strip() expected = expectfile.read().strip()
expected = expected.replace( expected = expected.replace(
"@TEST_FOLDER@", "@TEST_FOLDER@",
@ -112,7 +111,7 @@ class FileTest(unittest.TestCase, metaclass=dynamic.DynamicTest):
@staticmethod @staticmethod
def compile_songbook(songbook, steps=None): def compile_songbook(songbook, steps=None):
"""Compile songbook, and return the command return code.""" """Compile songbook, and return the command return code."""
command = [sys.executable, '-m', 'patacrep.songbook', songbook] command = [sys.executable, '-m', 'patacrep.songbook', '--cache=no', songbook, '-v']
if steps: if steps:
command.extend(['--steps', steps]) command.extend(['--steps', steps])

Loading…
Cancel
Save