Browse Source

Merge pull request #20 from patacrep/next-steps

Ajout d'une option pour affiner la compilation
pull/22/head
Luthaf 11 years ago
parent
commit
7cc52074e7
  1. 43
      songbook
  2. 41
      songbook_core/build.py
  3. 28
      songbook_core/errors.py

43
songbook

@ -12,11 +12,26 @@ import os.path
import textwrap import textwrap
import sys import sys
from songbook_core.build import buildsongbook from songbook_core.build import buildsongbook, DEFAULT_STEPS
from songbook_core import __STR_VERSION__ from songbook_core import __STR_VERSION__
from songbook_core import errors from songbook_core import errors
# pylint: disable=too-few-public-methods
class ParseStepsAction(argparse.Action):
"""Argparse action to split a string into a list."""
def __call__(self, __parser, namespace, values, __option_string=None):
if not getattr(namespace, self.dest):
setattr(namespace, self.dest, [])
setattr(
namespace,
self.dest,
(
getattr(namespace, self.dest)
+ [value.strip() for value in values[0].split(',')]
),
)
def argument_parser(args): def argument_parser(args):
"""Parse argumnts""" """Parse argumnts"""
parser = argparse.ArgumentParser(description="A song book compiler") parser = argparse.ArgumentParser(description="A song book compiler")
@ -34,6 +49,23 @@ def argument_parser(args):
subdirectories are 'songs', 'img', 'latex', 'templates'. subdirectories are 'songs', 'img', 'latex', 'templates'.
""")) """))
parser.add_argument('--steps', '-s', nargs=1, type=str,
action=ParseStepsAction,
help=textwrap.dedent("""\
Steps to run. Default is "{steps}".
Available steps are:
"tex" produce .tex file from templates;
"pdf" compile .tex file;
"sbx" compile index files;
"clean" remove temporary files;
any string beginning with '%%' (in this case, it will be run
in a shell). Several steps (excepted the custom shell
command) can be combinend in one --steps argument, as a
comma separated string.
""".format(steps=','.join(DEFAULT_STEPS))),
default=None,
)
options = parser.parse_args(args) options = parser.parse_args(args)
return options return options
@ -71,8 +103,15 @@ def main():
) )
else: else:
songbook['datadir'] = os.path.dirname(songbook_path) songbook['datadir'] = os.path.dirname(songbook_path)
try: try:
buildsongbook(songbook, basename, interactive=True, logger=logger) buildsongbook(
songbook,
basename,
steps=options.steps,
interactive=True,
logger=logger,
)
except errors.SongbookError as error: except errors.SongbookError as error:
logger.error(error) logger.error(error)
sys.exit(1) sys.exit(1)

41
songbook_core/build.py

@ -23,6 +23,7 @@ DEFAULT_AUTHWORDS = {
"ignore": ["unknown"], "ignore": ["unknown"],
"sep": ["and"], "sep": ["and"],
} }
DEFAULT_STEPS = ['tex', 'pdf', 'sbx', 'pdf', 'clean']
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods
@ -137,6 +138,7 @@ def clean(basename):
] ]
for ext in generated_extensions: for ext in generated_extensions:
if os.path.isfile(basename + ext):
try: try:
os.unlink(basename + ext) os.unlink(basename + ext)
except Exception as exception: except Exception as exception:
@ -146,22 +148,28 @@ def clean(basename):
def buildsongbook( def buildsongbook(
raw_songbook, raw_songbook,
basename, basename,
steps=None,
interactive=False, interactive=False,
logger=logging.getLogger() logger=logging.getLogger(),
): ):
"""Build a songbook """Build a songbook
Arguments: Arguments:
- raw_songbook: Python representation of the .sb songbook configuration - raw_songbook: Python representation of the .sb songbook configuration
file. file.
- steps: list of steps to perform to compile songbook. Available steps are:
- tex: build .tex file from templates;
- pdf: compile .tex using pdflatex;
- sbx: compile song and author indexes;
- clean: remove temporary files.
- basename: basename of the songbook to be built. - basename: basename of the songbook to be built.
- interactive: in False, do not expect anything from stdin. - interactive: in False, do not expect anything from stdin.
""" """
songbook = Songbook(raw_songbook, basename) if steps is None:
with codecs.open("{}.tex".format(basename), 'w', 'utf-8') as output: steps = DEFAULT_STEPS
songbook.write_tex(output)
songbook = Songbook(raw_songbook, basename)
if not 'TEXINPUTS' in os.environ.keys(): if not 'TEXINPUTS' in os.environ.keys():
os.environ['TEXINPUTS'] = '' os.environ['TEXINPUTS'] = ''
os.environ['TEXINPUTS'] += os.pathsep + os.path.join( os.environ['TEXINPUTS'] += os.pathsep + os.path.join(
@ -179,10 +187,16 @@ def buildsongbook(
if not interactive: if not interactive:
pdflatex_options.append("-halt-on-error") pdflatex_options.append("-halt-on-error")
# First pdflatex pass # Compilation
for step in steps:
if step == 'tex':
# Building .tex file from templates
with codecs.open("{}.tex".format(basename), 'w', 'utf-8') as output:
songbook.write_tex(output)
elif step == 'pdf':
if subprocess.call(["pdflatex"] + pdflatex_options + [basename]): if subprocess.call(["pdflatex"] + pdflatex_options + [basename]):
raise errors.LatexCompilationError(basename) raise errors.LatexCompilationError(basename)
elif step == 'sbx':
# Make index # Make index
sxd_files = glob.glob("%s_*.sxd" % basename) sxd_files = glob.glob("%s_*.sxd" % basename)
for sxd_file in sxd_files: for sxd_file in sxd_files:
@ -191,10 +205,15 @@ def buildsongbook(
index_file = open(sxd_file[:-3] + "sbx", "w") index_file = open(sxd_file[:-3] + "sbx", "w")
index_file.write(idx.entries_to_str().encode('utf8')) index_file.write(idx.entries_to_str().encode('utf8'))
index_file.close() index_file.close()
elif step == 'clean':
# Second pdflatex pass
if subprocess.call(["pdflatex"] + pdflatex_options + [basename]):
raise errors.LatexCompilationError(basename)
# Cleaning # Cleaning
clean(basename) clean(basename)
elif step.startswith("%"):
# Shell command
command = step[1:]
exit_code = subprocess.call(command, shell=True)
if exit_code:
raise errors.StepCommandError(command, exit_code)
else:
# Unknown step name
raise errors.UnknownStep(step)

28
songbook_core/errors.py

@ -32,11 +32,22 @@ class LatexCompilationError(SongbookError):
self.basename = basename self.basename = basename
def __str__(self): def __str__(self):
return ( return ("""Error while pdfLaTeX compilation of "{basename}.tex" """
"""Error while pdfLaTeX compilation of "{basename}.tex" """(see {basename}.log for more information)."""
(see {basename}.log for more information)."""
).format(basename=self.basename) ).format(basename=self.basename)
class StepCommandError(SongbookError):
"""Error during LaTeX compilation."""
def __init__(self, command, code):
super(StepCommandError, self).__init__()
self.command = command
self.code = code
def __str__(self):
return ("""Error while running custom command "{command}": got return"""
" code {code}.").format(command=self.command, code=self.code)
class CleaningError(SongbookError): class CleaningError(SongbookError):
"""Error during cleaning of LaTeX auxiliary files.""" """Error during cleaning of LaTeX auxiliary files."""
@ -50,3 +61,14 @@ class CleaningError(SongbookError):
filename=self.filename, filename=self.filename,
exception=str(self.exception) exception=str(self.exception)
) )
class UnknownStep(SongbookError):
"""Unknown compilation step."""
def __init__(self, step):
super(UnknownStep, self).__init__()
self.step = step
def __str__(self):
return """Compilation step "{step}" unknown.""".format(step=self.step)

Loading…
Cancel
Save