diff --git a/bopytex/__init__.py b/bopytex/__init__.py index 15567b7..1306988 100644 --- a/bopytex/__init__.py +++ b/bopytex/__init__.py @@ -2,7 +2,7 @@ # encoding: utf-8 -from .bopytex import produce_and_compile +#from .bopytex import subject_metadatas, crazy_feed, pdfjoin # ----------------------------- diff --git a/bopytex/__main__.py b/bopytex/__main__.py deleted file mode 100644 index 26d8085..0000000 --- a/bopytex/__main__.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -import click -import logging -from .bopytex import produce_and_compile - -formatter = logging.Formatter("%(name)s :: %(levelname)s :: %(message)s") -steam_handler = logging.StreamHandler() -steam_handler.setLevel(logging.DEBUG) -steam_handler.setFormatter(formatter) -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) -logger.addHandler(steam_handler) - - -@click.command() -@click.argument( - "template", - type=click.Path(exists=True), - nargs=1, - #help="File with the template. The name should have the following form tpl_... .", -) -@click.option( - "-w", - "--working-dir", - type=click.Path(exists=True), - help="Where fed templates and compiled files will be placed", -) -@click.option( - "-s", - "--students-csv", - type=str, - default='', - help="CSV containing list of students names", -) -@click.option( - "-d", - "--dirty", - is_flag=True, - default=False, - help="Do not clean after compilation", -) -@click.option( - "-n", - "--no-compile", - is_flag=True, - default=False, - help="Do not compile source code", -) -@click.option( - "-N", - "--number_subjects", - type=int, - default=1, - help="The number of subjects to make", -) -@click.option( - "-j", - "--no-join", - is_flag=True, - default=False, - help="Do not join pdfs to a single pdf and remove individuals", -) -@click.option( - "-O", - "--only-corr", - is_flag=True, - default=False, - help="Create and compile only correction from existing subjects", -) -@click.option( - "-c", - "--corr", - is_flag=True, - default=False, - help="Create and compile correction while making subjects", -) -@click.option( - "-C", - "--crazy", - is_flag=True, - default=False, - help="Crazy mode. Tries and tries again until template feeding success!", -) -def cli(**options): - """ Bopytex - - Feed the template (tpl_...) and then compile it with latex. - - """ - logger.debug(f"CI parser gets {options}") - produce_and_compile(options) - - -if __name__ == "__main__": - cli() - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/bopytex/bopytex.py b/bopytex/bopytex.py index 645f6a4..6be6037 100755 --- a/bopytex/bopytex.py +++ b/bopytex/bopytex.py @@ -106,7 +106,7 @@ def extract_student_csv(csv_filename): return [r for r in reader] -def subject_metadata(quantity=0, metacsv=None): +def subject_metadatas(options): """ Return metadata on subject to produce if csv is given it will based on is @@ -115,18 +115,55 @@ def subject_metadata(quantity=0, metacsv=None): :example: >>> subject_metadata(10) """ - if metacsv: - metadata = [] - for (i, s) in enumerate(extract_student_csv(metacsv)): + if options["students_csv"]: + metadatas = [] + for (i, s) in enumerate(extract_student_csv(options["students_csv"])): d = {"num": f"{i+1:02d}"} d.update(s) - metadata.append(d) - elif quantity > 0: - metadata = [{"num": f"{i+1:02d}"} for i in range(quantity)] + metadatas.append(d) + elif options["number_subjects"] > 0: + metadatas = [{"num": f"{i+1:02d}"} for i in range(options["number_subjects"])] else: raise ValueError("Need metacsv or quantity to build subject metadata") - return metadata + for meta in metadatas: + meta.update( + { + "template": str(Path(options["template"]).name), + "texfile": str(Path(options["template"]).name).replace( + "tpl", meta["num"] + ), + "directory": str(Path(options["template"]).parent), + } + ) + + return metadatas + + +def feed(*args, **kwrds): + """ Nice and smooth pytex feed """ + pytex.feed(*args, **kwrds) + + +def crazy_feed(*args, **kwrds): + """ Crazy mod for pytex feed """ + while True: + try: + pytex.feed(*args, **kwrds) + except: + logger.debug(f"Crazy feed is working hard...! {args} {kwrds}") + else: + break + + +def clean(directory): + pytex.clean(directory) + + +def texcompile(filename): + logger.debug(f"Start compiling {filename}") + pytex.pdflatex(Path(filename)) + logger.debug(f"End compiling") def produce_and_compile(options): @@ -141,9 +178,7 @@ def produce_and_compile(options): template = Path(options["template"]).name logger.debug(f"Template will be {template}") - list_infos = subject_metadata( - options["number_subjects"], options["students_csv"] - ) + list_infos = subject_metadatas(options) logger.debug(f"Metadata {list_infos}") diff --git a/bopytex/script.py b/bopytex/script.py new file mode 100644 index 0000000..d5e1918 --- /dev/null +++ b/bopytex/script.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +# encoding: utf-8 + + +import click +import logging +from pathlib import Path +from .bopytex import subject_metadatas, crazy_feed, pdfjoin, feed, clean, texcompile + +formatter = logging.Formatter("%(name)s :: %(levelname)s :: %(message)s") +steam_handler = logging.StreamHandler() +steam_handler.setLevel(logging.DEBUG) +steam_handler.setFormatter(formatter) +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) +logger.addHandler(steam_handler) + + +@click.command() +@click.argument( + "template", + type=click.Path(exists=True), + nargs=1, + # help="File with the template. The name should have the following form tpl_... .", +) +@click.option( + "-w", + "--working-dir", + type=click.Path(exists=True), + help="Where fed templates and compiled files will be placed", +) +@click.option( + "-s", + "--students-csv", + type=str, + default="", + help="CSV containing list of students names", +) +@click.option( + "-d", "--dirty", is_flag=True, default=False, help="Do not clean after compilation", +) +@click.option( + "-n", + "--no-compile", + is_flag=True, + default=False, + help="Do not compile source code", +) +@click.option( + "-N", + "--number_subjects", + type=int, + default=1, + help="The number of subjects to make", +) +@click.option( + "-j", + "--no-join", + is_flag=True, + default=False, + help="Do not join pdfs to a single pdf and remove individuals", +) +@click.option( + "-O", + "--only-corr", + is_flag=True, + default=False, + help="Create and compile only correction from existing subjects", +) +@click.option( + "-c", + "--corr", + is_flag=True, + default=False, + help="Create and compile correction while making subjects", +) +@click.option( + "-C", + "--crazy", + is_flag=True, + default=False, + help="Crazy mode. Tries and tries again until template feeding success!", +) +def new(**options): + """ Bopytex + + Feed the template (tpl_...) and then compile it with latex. + + """ + logger.debug(f"CI parser gets {options}") + + template = Path(options["template"]).name + directory = Path(options["template"]).parent + metadatas = subject_metadatas(options) + logger.debug(f"Metadata {metadatas}") + + for meta in metadatas: + logger.debug(f"Feeding template toward {meta['texfile']}") + if options["crazy"]: + crazy_feed( + template=Path(meta["directory"]) / meta["template"], + data=meta, + output=meta["texfile"], + force=1, + ) + else: + feed( + template=Path(meta["directory"]) / meta["template"], + data=meta, + output=meta["texfile"], + force=1, + ) + assert(Path(meta["texfile"]).exists()) + logger.debug(f"{meta['texfile']} fed") + + if options["corr"]: + logger.debug(f"Building correction for {meta['texfile']}") + meta.update({ + "corr_texfile": activate_printanswers(meta["texfile"]), + }) + + if not options["no_compile"]: + for prefix in ["", "corr_"]: + key = prefix + "texfile" + try: + meta[key] + except KeyError: + pass + else: + texcompile(meta[key]) + meta.update({ + prefix+'pdffile': meta[key].replace('tex', 'pdf') + }) + + if not options["no_join"]: + for prefix in ["", "corr_"]: + key = prefix + "pdffile" + try: + pdfs = [m[key] for m in metadatas] + except KeyError: + pass + else: + pdfjoin( + pdfs, + template.replace("tpl", prefix+"all").replace(".tex", ".pdf"), + directory, + rm_pdfs=1, + ) + + if not options["dirty"]: + clean(directory) + + # produce_and_compile(options) + + +if __name__ == "__main__": + new() + +# ----------------------------- +# Reglages pour 'vim' +# vim:set autoindent expandtab tabstop=4 shiftwidth=4: +# cursor: 16 del diff --git a/setup.py b/setup.py index 1338f69..b8bc0fc 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ setup( 'mypytex', ], entry_points={ - "console_scripts": ['bopytex= bopytex.bopytex:main'] + "console_scripts": ['bopytex=bopytex.script:new'] }, ) diff --git a/test/test_bopytex.py b/test/test_bopytex.py index 3857a47..5ecf335 100644 --- a/test/test_bopytex.py +++ b/test/test_bopytex.py @@ -6,7 +6,7 @@ import pytest import os from pathlib import Path from shutil import copyfile -from bopytex import produce_and_compile +from bopytex.bopytex import produce_and_compile, subject_metadatas SNIPPETS_PATH = Path("snippets/") TEST_PATH = Path("test") @@ -71,23 +71,83 @@ def test_produce_and_compile_base(prepare_test_template): def test_produce_and_compile_csv(prepare_test_template): - test_tpl = list(Path(".").glob("tpl_*.tex")) - assert [tpl.name for tpl in test_tpl] == ["tpl_test.tex"] + test_tpl = Path(".").glob("tpl_*.tex") for tpl in test_tpl: - produce_and_compile( + options = { + "template": tpl, + "working_dir": None, + "only_corr": False, + "students_csv": "students.csv", + "number_subjects": 1, + "dirty": False, + "no_compile": False, + "no_join": False, + "corr": False, + "crazy": False, + } + # produce_and_compile(options) + + +def test_metadatas(prepare_test_template): + test_tpl = Path(".").glob("tpl_*.tex") + for tpl in test_tpl: + options = { + "template": tpl, + "working_dir": None, + "only_corr": False, + "students_csv": "students.csv", + "number_subjects": 1, + "dirty": False, + "no_compile": False, + "no_join": False, + "corr": False, + "crazy": False, + } + metadatas = subject_metadatas(options) + meta = [ { - "template": tpl, - "working_dir": None, - "only_corr": False, - "students_csv": "students.csv", - "number_subjects": 1, - "dirty": False, - "no_compile": False, - "no_join": False, - "corr": False, - "crazy": False, - } - ) + "num": "01", + "nom": "Bob", + "classe": "1ST", + "elo": "1000", + "texfile": "01_test.tex", + "directory": ".", + }, + { + "num": "02", + "nom": "Pipo", + "classe": "1ST", + "elo": "1300", + "texfile": "02_test.tex", + "directory": ".", + }, + { + "num": "03", + "nom": "Popi", + "classe": "1ST", + "elo": "100", + "texfile": "03_test.tex", + "directory": ".", + }, + { + "num": "04", + "nom": "Boule", + "classe": "1ST", + "elo": "4000", + "texfile": "04_test.tex", + "directory": ".", + }, + { + "num": "05", + "nom": "Bill", + "classe": "1ST", + "elo": "1300", + "texfile": "05_test.tex", + "directory": ".", + }, + ] + assert metadatas == meta + def test_pdfjoin_current_directory(prepare_test_template): wdir = prepare_test_template @@ -122,7 +182,7 @@ def test_activate_solution(): pass -#def test_snippets(prepare_snippets): +# def test_snippets(prepare_snippets): # snippets = list(Path(".").glob("tpl_*.tex")) # for tpl in snippets: # produce_and_compile(