Browse Source

Remplacement de buildsongbook par la classe SongbookBuilder (#21)

pull/25/head
Louis 11 years ago
parent
commit
c70fc1e7bc
  1. 14
      songbook
  2. 179
      songbook_core/build.py

14
songbook

@ -12,7 +12,7 @@ import os.path
import textwrap import textwrap
import sys import sys
from songbook_core.build import buildsongbook, DEFAULT_STEPS from songbook_core.build import SongbookBuilder, DEFAULT_STEPS
from songbook_core import __STR_VERSION__ from songbook_core import __STR_VERSION__
from songbook_core import errors from songbook_core import errors
@ -105,13 +105,11 @@ def main():
songbook['datadir'] = os.path.dirname(songbook_path) songbook['datadir'] = os.path.dirname(songbook_path)
try: try:
buildsongbook( sb_builder = SongbookBuilder(songbook, basename, logger=logger)
songbook, sb_builder.interactive = True
basename, sb_builder.unsafe = True
steps=options.steps,
interactive=True, sb_builder.build_steps(options.steps)
logger=logger,
)
except errors.SongbookError as error: except errors.SongbookError as error:
logger.error(error) logger.error(error)
sys.exit(1) sys.exit(1)

179
songbook_core/build.py

@ -24,6 +24,18 @@ DEFAULT_AUTHWORDS = {
"sep": ["and"], "sep": ["and"],
} }
DEFAULT_STEPS = ['tex', 'pdf', 'sbx', 'pdf', 'clean'] DEFAULT_STEPS = ['tex', 'pdf', 'sbx', 'pdf', 'clean']
GENERATED_EXTENSIONS = [
"_auth.sbx",
"_auth.sxd",
".aux",
".log",
".out",
".sxc",
".tex",
"_title.sbx",
"_title.sxd",
]
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods
@ -123,58 +135,39 @@ class Songbook(object):
renderer.render_tex(output, context) renderer.render_tex(output, context)
def clean(basename): class SongbookBuilder(object):
"""Clean (some) temporary files used during compilation. """Provide methods to compile a songbook."""
Depending of the LaTeX modules used in the template, there may be others
that are not deleted by this function."""
generated_extensions = [
"_auth.sbx",
"_auth.sxd",
".aux",
".log",
".out",
".sxc",
".tex",
"_title.sbx",
"_title.sxd",
]
for ext in generated_extensions: # Representation of the .sb songbook configuration file.
if os.path.isfile(basename + ext): songbook = {}
try: # Basename of the songbook to be built.
os.unlink(basename + ext) basename = None
except Exception as exception: # if False, do not expect anything from stdin.
raise errors.CleaningError(basename + ext, exception) interactive = False
# if True, allow unsafe option, like adding the --shell-escape to pdflatex
unsafe = False
# Options to add to pdflatex
_pdflatex_options = []
# Dictionary of functions that have been called by self._run_once(). Keys
# are function; values are return values of functions.
_called_functions = {}
def __init__(self, raw_songbook, basename, logger):
self.songbook = Songbook(raw_songbook, basename)
self.basename = basename
self.logger = logger
def buildsongbook( def _run_once(self, function, *args, **kwargs):
raw_songbook, """Run function if it has not been run yet.
basename,
steps=None,
interactive=False,
logger=logging.getLogger(),
):
"""Build a songbook
Arguments: If it as, return the previous return value.
- raw_songbook: Python representation of the .sb songbook configuration
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,
- any string beginning with a sharp sign (#): it is interpreted as a
command to run in a shell.
- basename: basename of the songbook to be built.
- interactive: in False, do not expect anything from stdin.
""" """
if function not in self._called_functions:
self._called_functions[function] = function(*args, **kwargs)
return self._called_functions[function]
if steps is None: def _set_latex(self):
steps = DEFAULT_STEPS """Set TEXINPUTS and LaTeX options."""
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(
@ -182,43 +175,85 @@ def buildsongbook(
'latex', 'latex',
) )
os.environ['TEXINPUTS'] += os.pathsep + os.path.join( os.environ['TEXINPUTS'] += os.pathsep + os.path.join(
songbook.config['datadir'], self.songbook.config['datadir'],
'latex', 'latex',
) )
# pdflatex options if self.unsafe:
pdflatex_options = [] self._pdflatex_options.append("--shell-escape")
pdflatex_options.append("--shell-escape") # Lilypond compilation if not self.interactive:
if not interactive: self._pdflatex_options.append("-halt-on-error")
pdflatex_options.append("-halt-on-error")
def build_steps(self, steps=None):
"""Perform steps on the songbook by calling relevant self.build_*()
Arguments:
- 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,
- any string beginning with a sharp sign (#): it is interpreted as a
command to run in a shell.
"""
if not steps:
steps = DEFAULT_STEPS
# Compilation
for step in steps: for step in steps:
if step == 'tex': if step == 'tex':
# Building .tex file from templates self.build_tex()
with codecs.open("{}.tex".format(basename), 'w', 'utf-8') as output:
songbook.write_tex(output)
elif step == 'pdf': elif step == 'pdf':
if subprocess.call(["pdflatex"] + pdflatex_options + [basename]): self.build_pdf()
raise errors.LatexCompilationError(basename)
elif step == 'sbx': elif step == 'sbx':
# Make index self.build_sbx()
sxd_files = glob.glob("%s_*.sxd" % basename) elif step == 'clean':
self.clean()
elif step.startswith("%"):
self.build_custom(step[1:])
else:
# Unknown step name
raise errors.UnknownStep(step)
def build_tex(self):
"""Build .tex file from templates"""
self._run_once(self._set_latex)
with codecs.open(
"{}.tex".format(self.basename), 'w', 'utf-8',
) as output:
self.songbook.write_tex(output)
def build_pdf(self):
"""Build .pdf file from .tex file"""
if subprocess.call(
["pdflatex"] + self._pdflatex_options + [self.basename]
):
raise errors.LatexCompilationError(self.basename)
def build_sbx(self):
"""Make index"""
sxd_files = glob.glob("%s_*.sxd" % self.basename)
for sxd_file in sxd_files: for sxd_file in sxd_files:
logger.info("processing " + sxd_file) self.logger.info("processing " + sxd_file)
idx = process_sxd(sxd_file) idx = process_sxd(sxd_file)
index_file = open(sxd_file[:-3] + "sbx", "w") with open(sxd_file[:-3] + "sbx", "w") as index_file:
index_file.write(idx.entries_to_str().encode('utf8')) index_file.write(idx.entries_to_str().encode('utf8'))
index_file.close()
elif step == 'clean': @staticmethod
# Cleaning def build_custom(command):
clean(basename) """Run a shell command"""
elif step.startswith("%"):
# Shell command
command = step[1:]
exit_code = subprocess.call(command, shell=True) exit_code = subprocess.call(command, shell=True)
if exit_code: if exit_code:
raise errors.StepCommandError(command, exit_code) raise errors.StepCommandError(command, exit_code)
else:
# Unknown step name def clean(self):
raise errors.UnknownStep(step) """Clean (some) temporary files used during compilation.
Depending of the LaTeX modules used in the template, there may be others
that are not deleted by this function."""
for ext in GENERATED_EXTENSIONS:
if os.path.isfile(self.basename + ext):
try:
os.unlink(self.basename + ext)
except Exception as exception:
raise errors.CleaningError(self.basename + ext, exception)

Loading…
Cancel
Save