pytex/pytex/pytex.py

131 lines
3.8 KiB
Python
Raw Normal View History

2017-04-16 13:11:47 +00:00
#!/usr/bin/env python
# encoding: utf-8
"""
Feeding latex templates and compiling it
"""
import logging
import math as m
import subprocess
import random as rd
2019-12-22 16:30:23 +00:00
from pathlib import Path
import os
from .texenv import *
2018-05-20 08:59:10 +00:00
from .latex_error_parser import generic_sink, filter_errors
formatter = logging.Formatter('%(name)s :: %(levelname)s :: %(message)s')
steam_handler = logging.StreamHandler()
steam_handler.setLevel(logging.DEBUG)
steam_handler.setFormatter(formatter)
# création de l'objet logger qui va nous servir à écrire dans les logs
# on met le niveau du logger à DEBUG, comme ça il écrit tout
2017-04-16 13:11:47 +00:00
logger = logging.getLogger(__name__)
2018-12-07 07:49:50 +00:00
logger.setLevel(logging.ERROR)
2018-05-20 08:59:10 +00:00
logger.addHandler(steam_handler)
2017-04-16 13:11:47 +00:00
EXPORT_DICT = {}
EXPORT_DICT.update(m.__dict__)
EXPORT_DICT.update(rd.__dict__)
EXPORT_DICT.update(__builtins__)
2017-04-16 13:13:14 +00:00
2017-04-16 13:11:47 +00:00
def update_export_dict(new_dict):
"""Update global variable with new_dict
2017-08-15 06:56:29 +00:00
It allows to import new functions (or modules) inside templates.
2017-04-16 13:11:47 +00:00
:param new_dict: needed tools across all template renders
"""
EXPORT_DICT.update(new_dict)
2017-04-16 13:13:14 +00:00
2017-04-16 13:58:36 +00:00
def feed(template, data, output="", force=0):
2017-04-16 13:11:47 +00:00
""" Feed template with data to output
2017-04-17 07:42:26 +00:00
:param template: jinja2 template with texenv environment
2017-04-16 13:11:47 +00:00
:param data: Data dictionnary
:param output: name of the output file
2017-04-16 13:58:36 +00:00
(by default: tpl is replaced by a 2 digits number)
:param force: Override is the output already exists
2018-05-19 08:08:29 +00:00
:return: name of fed template
2017-04-16 13:11:47 +00:00
"""
logger.info(f"Getting template {template}")
2017-04-16 15:47:24 +00:00
tpl = texenv.get_template(str(template))
2017-04-16 13:11:47 +00:00
2017-04-16 13:58:36 +00:00
if not output:
num = 1
2017-04-16 14:16:46 +00:00
output_p = Path(template.replace('tpl', f'{num:02d}'))
while output_p.exists() and not force:
2017-04-16 13:58:36 +00:00
logger.debug(f"{output_p} exists. Try next one")
num += 1
2017-04-16 14:16:46 +00:00
output_p = Path(template.replace('tpl', f'{num:02d}'))
else:
output_p = Path(output)
if not force and output_p.exists():
logger.error(f"{output} exists. Use force=1 do override it")
raise ValueError(f"{output} exists. Use force=1 do override it")
2017-04-16 13:58:36 +00:00
2019-12-22 16:30:23 +00:00
output_dir = output_p.parent
2017-04-16 14:16:46 +00:00
if output_dir and not output_dir.exists():
2018-05-19 08:08:29 +00:00
logger.debug(f"Creating output dir {output_dir}")
output_dir.mkdir(exist_ok=True)
2017-04-16 13:11:47 +00:00
2017-04-16 14:16:46 +00:00
with open(output_p, "w") as output_f:
2017-04-16 13:11:47 +00:00
output_f.write(tpl.render(**EXPORT_DICT, **data))
logger.info(f"{template} has been rendered to {output}.")
2018-05-19 08:08:29 +00:00
return output_p
2017-04-16 13:11:47 +00:00
2017-04-16 13:13:14 +00:00
def pdflatex(latex_file, output_dir=""):
2018-05-19 08:08:29 +00:00
""" Compile a latex file with pdflatex
2017-04-16 13:11:47 +00:00
If output_dir is not set, it produce it next to the latex file.
"""
if not output_dir:
2019-12-22 16:30:23 +00:00
output_dir = Path(latex_file).parent.resolve()
2018-05-19 08:08:29 +00:00
logger.debug(f"output_dir for pdflatex is {output_dir}")
2017-04-16 13:11:47 +00:00
2019-12-22 16:30:23 +00:00
prev_cwd = Path.cwd()
os.chdir(output_dir)
2017-04-16 13:11:47 +00:00
compilation = subprocess.Popen(
[
"pdflatex",
2018-05-20 08:59:10 +00:00
f"-output-directory={output_dir}",
# "-halt-on-error",
"-interaction=nonstopmode",
2017-04-25 09:07:19 +00:00
"-shell-escape",
str(Path(latex_file).name),
2017-04-16 13:11:47 +00:00
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
# shell=True
)
2018-05-20 08:59:10 +00:00
latex_error_logger = filter_errors(generic_sink(logger.error))
for line in compilation.stdout:
2018-12-07 07:49:50 +00:00
latex_error_logger.send(line.decode("latin-1").rstrip('\r\n'))
2019-12-22 16:30:23 +00:00
compilation_status = compilation.wait()
2018-05-20 08:59:10 +00:00
logger.debug(f"{latex_file.name} has been compiled in {output_dir}")
2019-12-22 16:30:23 +00:00
os.chdir(prev_cwd)
2017-04-16 13:11:47 +00:00
2017-04-16 13:13:14 +00:00
2018-05-19 08:08:29 +00:00
def clean(dirname="", garbages=["*.aux", "*.log"]):
2017-04-16 13:11:47 +00:00
""" Clean the directory from aux and log latex files """
2017-04-17 05:26:32 +00:00
if not dirname:
dirname = Path("./")
for g in garbages:
2019-12-22 16:30:23 +00:00
g_files = Path(dirname).glob(g)
2017-04-17 05:26:32 +00:00
logger.debug(f"Remove {g_files}")
for g_file in g_files:
2019-12-22 16:30:23 +00:00
g_file.unlink()
2017-04-16 13:11:47 +00:00
# -----------------------------
# Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
# cursor: 16 del