Browse Source

Remplacement de buildsongbook par la classe SongbookBuilder (#21)

pull/25/head
Louis 10 years ago
parent
commit
c70fc1e7bc
  1. 14
      songbook
  2. 229
      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)

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