Compare commits
13 Commits
f5f9e9193f
...
84f0a3a521
Author | SHA1 | Date | |
---|---|---|---|
84f0a3a521 | |||
1ce68931d6 | |||
16af6c15fc | |||
f0be577119 | |||
97468b9602 | |||
d66e1a0887 | |||
011ff6e7e5 | |||
d0741b254f | |||
1ba29c057b | |||
9d5c231c9c | |||
b40b114bb4 | |||
39785cb617 | |||
21d650101c |
14
.drone.yml
Normal file
14
.drone.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
kind: pipeline
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Publish
|
||||||
|
image: plugins/pypi
|
||||||
|
settings:
|
||||||
|
username:
|
||||||
|
from_secret: pypi_username
|
||||||
|
password:
|
||||||
|
from_secret: pypi_password
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- tag
|
@ -2,7 +2,8 @@
|
|||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
|
||||||
|
|
||||||
__version__ = "0.1"
|
#from .bopytex import subject_metadatas, crazy_feed, pdfjoin
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------
|
# -----------------------------
|
||||||
# Reglages pour 'vim'
|
# Reglages pour 'vim'
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# encoding: utf-8
|
|
||||||
|
|
||||||
|
|
||||||
from .bopytex import main
|
|
||||||
|
|
||||||
main()
|
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------
|
|
||||||
# Reglages pour 'vim'
|
|
||||||
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
|
|
||||||
# cursor: 16 del
|
|
@ -5,12 +5,11 @@
|
|||||||
Producing then compiling templates
|
Producing then compiling templates
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import csv
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import optparse
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from path import Path
|
from pathlib import Path
|
||||||
import pytex
|
import pytex
|
||||||
from mapytex import Expression, Integer, Decimal
|
from mapytex import Expression, Integer, Decimal
|
||||||
import bopytex.filters as filters
|
import bopytex.filters as filters
|
||||||
@ -46,18 +45,18 @@ def setup():
|
|||||||
|
|
||||||
def get_working_dir(options):
|
def get_working_dir(options):
|
||||||
""" Get the working directory """
|
""" Get the working directory """
|
||||||
if options.working_dir:
|
if options["working_dir"]:
|
||||||
working_dir = Path(options.working_dir)
|
working_dir = Path(options["working_dir"])
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
template = Path(options.template)
|
template = Path(options["template"])
|
||||||
except TypeError:
|
except TypeError:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Need to set the working directory \
|
"Need to set the working directory \
|
||||||
or to give a template"
|
or to give a template"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
working_dir = template.dirname()
|
working_dir = template.parent
|
||||||
logger.debug(f"The output directory will be {working_dir}")
|
logger.debug(f"The output directory will be {working_dir}")
|
||||||
return working_dir
|
return working_dir
|
||||||
|
|
||||||
@ -100,146 +99,138 @@ def pdfjoin(pdf_files, destname, working_dir=".", rm_pdfs=1):
|
|||||||
os.system(f"rm {pdf_files_str}")
|
os.system(f"rm {pdf_files_str}")
|
||||||
|
|
||||||
|
|
||||||
|
def extract_student_csv(csv_filename):
|
||||||
|
""" Extract student list from csv_filename """
|
||||||
|
with open(csv_filename, "r") as csvfile:
|
||||||
|
reader = csv.DictReader(csvfile)
|
||||||
|
return [r for r in reader]
|
||||||
|
|
||||||
|
|
||||||
|
def subject_metadatas(options):
|
||||||
|
""" Return metadata on subject to produce
|
||||||
|
|
||||||
|
if csv is given it will based on is
|
||||||
|
otherwise it will be based on quantity
|
||||||
|
|
||||||
|
:example:
|
||||||
|
>>> subject_metadata(10)
|
||||||
|
"""
|
||||||
|
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)
|
||||||
|
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")
|
||||||
|
|
||||||
|
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):
|
def produce_and_compile(options):
|
||||||
""" Produce and compile subjects
|
""" Produce and compile subjects
|
||||||
"""
|
"""
|
||||||
working_dir = get_working_dir(options)
|
|
||||||
|
|
||||||
if options.only_corr:
|
|
||||||
options.corr = True
|
|
||||||
tex_files = working_dir.files("[0-9]*_*.tex")
|
|
||||||
else:
|
|
||||||
template = Path(options.template).name
|
|
||||||
logger.debug(f"Template will be {template}")
|
|
||||||
|
|
||||||
list_infos = [{"num": f"{i+1:02d}"} for i in range(options.num_subj)]
|
|
||||||
|
|
||||||
tex_files = []
|
|
||||||
for infos in list_infos:
|
|
||||||
dest = working_dir / Path(template.replace("tpl", infos["num"]))
|
|
||||||
logger.debug(f"Feeding template toward {dest}")
|
|
||||||
tex_files.append(dest)
|
|
||||||
pytex.feed(working_dir / template, {"infos": infos}, output=dest, force=1)
|
|
||||||
logger.debug(f"{dest} fed")
|
|
||||||
|
|
||||||
if not options.no_compil:
|
|
||||||
pdf_files = []
|
|
||||||
for texfile in tex_files:
|
|
||||||
logger.debug(f"Start compiling {texfile}")
|
|
||||||
pytex.pdflatex(texfile)
|
|
||||||
logger.debug(f"End compiling {texfile}")
|
|
||||||
pdf_files.append(str(texfile[:-4] + ".pdf"))
|
|
||||||
logger.debug(f"Compiled files : {pdf_files}")
|
|
||||||
|
|
||||||
if not options.no_join and not options.no_compil:
|
|
||||||
pdfjoin(
|
|
||||||
pdf_files,
|
|
||||||
template.replace("tpl", "all").replace(".tex", ".pdf"),
|
|
||||||
working_dir,
|
|
||||||
rm_pdfs=1,
|
|
||||||
)
|
|
||||||
|
|
||||||
if options.corr:
|
|
||||||
pdf_files = []
|
|
||||||
for texfile in tex_files:
|
|
||||||
corr_fname = activate_printanswers(texfile)
|
|
||||||
if not options.no_compil:
|
|
||||||
logger.debug(f"Start compiling {texfile}")
|
|
||||||
pytex.pdflatex(corr_fname)
|
|
||||||
logger.debug(f"End compiling {texfile}")
|
|
||||||
pdf_files.append(str(corr_fname[:-4] + ".pdf"))
|
|
||||||
deactivate_printanswers(corr_fname)
|
|
||||||
|
|
||||||
if not options.no_join and not options.no_compil:
|
|
||||||
pdfjoin(
|
|
||||||
pdf_files,
|
|
||||||
template.replace("tpl", "corr").replace(".tex", ".pdf"),
|
|
||||||
working_dir,
|
|
||||||
rm_pdfs=1,
|
|
||||||
)
|
|
||||||
|
|
||||||
if not options.dirty:
|
|
||||||
pytex.clean(working_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
setup()
|
|
||||||
|
|
||||||
parser = optparse.OptionParser()
|
|
||||||
parser.add_option(
|
|
||||||
"-t",
|
|
||||||
"--template",
|
|
||||||
action="store",
|
|
||||||
type="string",
|
|
||||||
dest="template",
|
|
||||||
help="File with the template. The name should have the following form tpl_... .",
|
|
||||||
)
|
|
||||||
parser.add_option(
|
|
||||||
"-w",
|
|
||||||
"--working-dir",
|
|
||||||
action="store",
|
|
||||||
type="string",
|
|
||||||
dest="working_dir",
|
|
||||||
help="Where fed templates and compiled files will be placed",
|
|
||||||
)
|
|
||||||
parser.add_option(
|
|
||||||
"-N",
|
|
||||||
"--number_subjects",
|
|
||||||
action="store",
|
|
||||||
type="int",
|
|
||||||
dest="num_subj",
|
|
||||||
default=1,
|
|
||||||
help="The number of subjects to make",
|
|
||||||
)
|
|
||||||
parser.add_option(
|
|
||||||
"-d",
|
|
||||||
"--dirty",
|
|
||||||
action="store_true",
|
|
||||||
dest="dirty",
|
|
||||||
help="Do not clean after compilation",
|
|
||||||
)
|
|
||||||
parser.add_option(
|
|
||||||
"-n",
|
|
||||||
"--no-compile",
|
|
||||||
action="store_true",
|
|
||||||
dest="no_compil",
|
|
||||||
help="Do not compile source code",
|
|
||||||
)
|
|
||||||
parser.add_option(
|
|
||||||
"-j",
|
|
||||||
"--no-join",
|
|
||||||
action="store_true",
|
|
||||||
dest="no_join",
|
|
||||||
help="Do not join pdf and clean single pdf",
|
|
||||||
)
|
|
||||||
parser.add_option(
|
|
||||||
"-O",
|
|
||||||
"--only-corr",
|
|
||||||
action="store_true",
|
|
||||||
dest="only_corr",
|
|
||||||
help="Create and compile only correction from existing subjects",
|
|
||||||
)
|
|
||||||
parser.add_option(
|
|
||||||
"-c",
|
|
||||||
"--corr",
|
|
||||||
action="store_true",
|
|
||||||
dest="corr",
|
|
||||||
help="Create and compile correction while making subjects",
|
|
||||||
)
|
|
||||||
|
|
||||||
(options, _) = parser.parse_args()
|
|
||||||
|
|
||||||
logger.debug(f"CI parser gets {options}")
|
logger.debug(f"CI parser gets {options}")
|
||||||
|
|
||||||
if not options.template:
|
template = Path(options["template"]).name
|
||||||
print("I need a template!")
|
directory = Path(options["template"]).parent
|
||||||
sys.exit(0)
|
metadatas = subject_metadatas(options)
|
||||||
|
logger.debug(f"Metadata {metadatas}")
|
||||||
|
|
||||||
produce_and_compile(options)
|
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 __name__ == "__main__":
|
if not options["no_compile"]:
|
||||||
main()
|
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)
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------
|
# -----------------------------
|
||||||
|
163
bopytex/script.py
Normal file
163
bopytex/script.py
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
#!/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, setup, activate_printanswers
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
setup()
|
||||||
|
|
||||||
|
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
|
@ -1,18 +0,0 @@
|
|||||||
% vim:ft=tex:
|
|
||||||
%
|
|
||||||
\documentclass[12pt]{article}
|
|
||||||
|
|
||||||
\begin{document}
|
|
||||||
|
|
||||||
\section{Ajouts de fractions}
|
|
||||||
|
|
||||||
Adding two fractions
|
|
||||||
\[
|
|
||||||
A = \frac{- 2}{4} + \frac{7}{8}
|
|
||||||
\]
|
|
||||||
Solution
|
|
||||||
\[
|
|
||||||
\frac{- 2}{4} + \frac{7}{8}=\frac{- 2 \times 2}{4 \times 2} + \frac{7}{8}=\frac{- 4}{8} + \frac{7}{8}=\frac{- 4 + 7}{8}=\frac{3}{8}
|
|
||||||
\]
|
|
||||||
|
|
||||||
\end{document}
|
|
@ -1,18 +0,0 @@
|
|||||||
% vim:ft=tex:
|
|
||||||
%
|
|
||||||
\documentclass[12pt]{article}
|
|
||||||
|
|
||||||
\begin{document}
|
|
||||||
|
|
||||||
\section{Ajouts de fractions}
|
|
||||||
|
|
||||||
Adding two fractions
|
|
||||||
\[
|
|
||||||
A = \frac{8}{9} + \frac{3}{63}
|
|
||||||
\]
|
|
||||||
Solution
|
|
||||||
\[
|
|
||||||
\frac{8}{9} + \frac{3}{63}=\frac{8 \times 7}{9 \times 7} + \frac{3}{63}=\frac{56}{63} + \frac{3}{63}=\frac{56 + 3}{63}=\frac{59}{63}
|
|
||||||
\]
|
|
||||||
|
|
||||||
\end{document}
|
|
Binary file not shown.
@ -11,7 +11,6 @@ location==0.0.7
|
|||||||
MarkupSafe==1.0
|
MarkupSafe==1.0
|
||||||
mpmath==0.19
|
mpmath==0.19
|
||||||
packaging==16.8
|
packaging==16.8
|
||||||
path.py==10.1
|
|
||||||
pexpect==4.2.1
|
pexpect==4.2.1
|
||||||
pickleshare==0.7.4
|
pickleshare==0.7.4
|
||||||
prompt-toolkit==1.0.14
|
prompt-toolkit==1.0.14
|
||||||
|
5
setup.py
5
setup.py
@ -5,7 +5,7 @@ from setuptools import setup
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='Bopytex',
|
name='Bopytex',
|
||||||
version='0.1.1',
|
version='0.1.2',
|
||||||
description='Command line tool for compiling latex with python command embedded',
|
description='Command line tool for compiling latex with python command embedded',
|
||||||
author='Benjamin Bertrand',
|
author='Benjamin Bertrand',
|
||||||
author_email='programming@opytex.org',
|
author_email='programming@opytex.org',
|
||||||
@ -13,9 +13,10 @@ setup(
|
|||||||
install_requires=[
|
install_requires=[
|
||||||
'mapytex',
|
'mapytex',
|
||||||
'mypytex',
|
'mypytex',
|
||||||
|
'click',
|
||||||
],
|
],
|
||||||
entry_points={
|
entry_points={
|
||||||
"console_scripts": ['bopytex= bopytex.bopytex:main']
|
"console_scripts": ['bopytex=bopytex.script:new']
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,133 +0,0 @@
|
|||||||
% vim:ft=tex:
|
|
||||||
%
|
|
||||||
\documentclass[12pt]{article}
|
|
||||||
\usepackage[utf8x]{inputenc}
|
|
||||||
\usepackage[francais]{babel}
|
|
||||||
\usepackage[T1]{fontenc}
|
|
||||||
\usepackage{amssymb}
|
|
||||||
\usepackage{amsmath}
|
|
||||||
\usepackage{amsfonts}
|
|
||||||
|
|
||||||
|
|
||||||
\title{
|
|
||||||
Snippets pour Opytex \\
|
|
||||||
Fractions
|
|
||||||
}
|
|
||||||
\author{
|
|
||||||
Benjamin Bertrand
|
|
||||||
}
|
|
||||||
|
|
||||||
\begin{document}
|
|
||||||
\maketitle
|
|
||||||
|
|
||||||
\section{Simplifications de fractions}
|
|
||||||
\begin{itemize}
|
|
||||||
\item Trouver le numérateur quand le dénominateur augmente
|
|
||||||
%
|
|
||||||
\begin{align*}
|
|
||||||
\dfrac{2}{6} = \dfrac{\ldots}{48}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\dfrac{2}{6} = \dfrac{16}{48}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Trouver le numérateur quand le dénominateur diminue
|
|
||||||
%
|
|
||||||
\begin{align*}
|
|
||||||
\dfrac{12}{9} = \dfrac{\cdots}{3}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\dfrac{12}{9} = \dfrac{4}{3}
|
|
||||||
\end{align*}
|
|
||||||
Explications
|
|
||||||
|
|
||||||
\begin{align*}
|
|
||||||
\frac{ 12 }{ 9 }=\frac{ 4 \times 3 }{ 3 \times 3 }=\frac{ 4 }{ 3 }
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
|
|
||||||
\section{Ajouts de fractions}
|
|
||||||
|
|
||||||
\begin{itemize}
|
|
||||||
\item Fraction avec le même dénominateur
|
|
||||||
|
|
||||||
\begin{align*}
|
|
||||||
A = \frac{ 1 }{ 4 } + \frac{ 5 }{ 4 }
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\frac{ 1 }{ 4 } + \frac{ 5 }{ 4 }=\frac{ 1 + 5 }{ 4 }=\frac{ 6 }{ 4 }=\frac{ 3 \times 2 }{ 2 \times 2 }=\frac{ 3 }{ 2 }
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Fraction avec un denominateur multiple de l'autre
|
|
||||||
|
|
||||||
\begin{align*}
|
|
||||||
A = \frac{ 10 }{ 7 } + \frac{ 3 }{ 49 }
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\frac{ 10 }{ 7 } + \frac{ 3 }{ 49 }=\frac{ 10 \times 7 }{ 7 \times 7 } + \frac{ 3 \times 1 }{ 49 \times 1 }=\frac{ 70 }{ 49 } + \frac{ 3 }{ 49 }=\frac{ 70 + 3 }{ 49 }=\frac{ 73 }{ 49 }
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Fraction avec des dénominateurs premiers entre eux
|
|
||||||
|
|
||||||
\begin{align*}
|
|
||||||
A = \frac{ 10 }{ 3 } + \frac{ 4 }{ 2 }
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\frac{ 10 }{ 3 } + \frac{ 4 }{ 2 }=\frac{ 10 \times 2 }{ 3 \times 2 } + \frac{ 4 \times 3 }{ 2 \times 3 }=\frac{ 20 }{ 6 } + \frac{ 12 }{ 6 }=\frac{ 20 + 12 }{ 6 }=\frac{ 32 }{ 6 }=\frac{ 16 \times 2 }{ 3 \times 2 }=\frac{ 16 }{ 3 }
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Une fraction et un entier
|
|
||||||
|
|
||||||
\begin{align*}
|
|
||||||
A = \frac{ 6 }{ 8 } + 9
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\frac{ 6 }{ 8 } + 9=\frac{ 6 \times 1 }{ 8 \times 1 } + \frac{ 9 \times 8 }{ 1 \times 8 }=\frac{ 6 }{ 8 } + \frac{ 72 }{ 8 }=\frac{ 6 + 72 }{ 8 }=\frac{ 78 }{ 8 }=\frac{ 39 \times 2 }{ 4 \times 2 }=\frac{ 39 }{ 4 }
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Une fraction et un entier
|
|
||||||
|
|
||||||
\begin{align*}
|
|
||||||
A = 2 + \frac{ 8 }{ 2 }
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
2 + \frac{ 8 }{ 2 }=\frac{ 2 \times 2 }{ 1 \times 2 } + \frac{ 8 \times 1 }{ 2 \times 1 }=\frac{ 4 }{ 2 } + \frac{ 8 }{ 2 }=\frac{ 4 + 8 }{ 2 }=6
|
|
||||||
\end{align*}
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
|
|
||||||
\section{Multiplications de fractions}
|
|
||||||
\begin{itemize}
|
|
||||||
\item Une fraction et un entier
|
|
||||||
|
|
||||||
\begin{align*}
|
|
||||||
A = 5 \times \frac{ 7 }{ 8 }
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
5 \times \frac{ 7 }{ 8 }=\frac{ 7 }{ 8 } \times 5=\frac{ 7 \times 5 }{ 8 }=\frac{ 35 }{ 8 }
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Fraction avec des dénominateurs quelconques
|
|
||||||
|
|
||||||
\begin{align*}
|
|
||||||
A = \frac{ 5 }{ 10 } \times \frac{ 4 }{ 7 }
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\frac{ 5 }{ 10 } \times \frac{ 4 }{ 7 }=\frac{ 4 }{ 7 } \times \frac{ 5 }{ 10 }=\frac{ 2 \times 2 \times 5 }{ 7 \times 5 \times 2 }=\frac{ 4 \times 5 }{ 7 \times 10 }=\frac{ 20 }{ 70 }=\frac{ 2 \times 10 }{ 7 \times 10 }=\frac{ 2 }{ 7 }
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
|
|
||||||
\end{document}
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,96 +0,0 @@
|
|||||||
% vim:ft=tex:
|
|
||||||
%
|
|
||||||
\documentclass[12pt]{article}
|
|
||||||
\usepackage[utf8x]{inputenc}
|
|
||||||
\usepackage[francais]{babel}
|
|
||||||
\usepackage[T1]{fontenc}
|
|
||||||
\usepackage{amssymb}
|
|
||||||
\usepackage{amsmath}
|
|
||||||
\usepackage{amsfonts}
|
|
||||||
|
|
||||||
|
|
||||||
\title{
|
|
||||||
Snippets pour Opytex \\
|
|
||||||
Fonctions
|
|
||||||
}
|
|
||||||
\author{
|
|
||||||
Benjamin Bertrand
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
\begin{document}
|
|
||||||
\maketitle
|
|
||||||
|
|
||||||
\section{Calculer des images}
|
|
||||||
\begin{enumerate}
|
|
||||||
%-set f = Expression.random("{a}*x^2 + {b}*x + {c}")
|
|
||||||
\item $\forall x \in \mathbb{R} \qquad f(x) = \Var{f}$
|
|
||||||
|
|
||||||
Solution:
|
|
||||||
\begin{align*}
|
|
||||||
f(0) &= \Var{f(0).explain() | join('=')} \\
|
|
||||||
f(1) &= \Var{f(1).explain() | join('=')} \\
|
|
||||||
f(2) &= \Var{f(2).explain() | join('=')} \\
|
|
||||||
f({10}) &= \Var{f(10).explain() | join('=')} \\
|
|
||||||
f({100}) &= \Var{f(100).explain() | join('=')}
|
|
||||||
\end{align*}
|
|
||||||
\end{enumerate}
|
|
||||||
|
|
||||||
\section{Résolution d'équation du 2nd degré}
|
|
||||||
%- macro solveEquation(P)
|
|
||||||
|
|
||||||
On commence par calculer le discriminant de $P(x) = \Var{P}$.
|
|
||||||
\begin{eqnarray*}
|
|
||||||
\Delta & = & b^2-4ac \\
|
|
||||||
\Var{P.delta.explain()|calculus(name="\\Delta")}
|
|
||||||
\end{eqnarray*}
|
|
||||||
|
|
||||||
\Block{if P.delta > 0}
|
|
||||||
comme $\Delta = \Var{P.delta} > 0$ donc $P$ a deux racines
|
|
||||||
|
|
||||||
\begin{eqnarray*}
|
|
||||||
x_1 & = & \frac{-b - \sqrt{\Delta}}{2a} = \frac{\Var{-P.b} - \sqrt{\Var{P.delta}}}{2 \times \Var{P.a}} = \Var{P.roots[0] } \\
|
|
||||||
x_2 & = & \frac{-b + \sqrt{\Delta}}{2a} = \frac{\Var{-P.b} + \sqrt{\Var{P.delta}}}{2 \times \Var{P.a}} = \Var{P.roots[1] }
|
|
||||||
\end{eqnarray*}
|
|
||||||
|
|
||||||
Les solutions de l'équation $\Var{P} = 0$ sont donc $\mathcal{S} = \left\{ \Var{P.roots[0]}; \Var{P.roots[1]} \right\}$
|
|
||||||
|
|
||||||
\Block{elif P.delta == 0}
|
|
||||||
Comme $\Delta = 0$ donc $P$ a une racine
|
|
||||||
|
|
||||||
\begin{eqnarray*}
|
|
||||||
x_1 = \frac{-b}{2a} = \frac{-\Var{P.b}}{2\times \Var{P.a}} = \Var{P.roots[0]} \\
|
|
||||||
\end{eqnarray*}
|
|
||||||
|
|
||||||
La solution de $\Var{P} = 0$ est donc $\mathcal{S} = \left\{ \Var{P.roots[0]}\right\}$
|
|
||||||
|
|
||||||
\Block{else}
|
|
||||||
Alors $\Delta = \Var{P.delta} < 0$ donc $P$ n'a pas de racine donc l'équation $\Var{P} = 0$ n'a pas de solution.
|
|
||||||
|
|
||||||
\Block{endif}
|
|
||||||
%- endmacro
|
|
||||||
|
|
||||||
\begin{enumerate}
|
|
||||||
%-set P = Expression.random("{a}*x^2 + {b}*x + {c}", ["b**2-4*a*c>0"])
|
|
||||||
\item Étude du polynôme $P$, $\forall x \in \mathbb{R} \quad P(x) = \Var{P}$
|
|
||||||
|
|
||||||
Solution:
|
|
||||||
|
|
||||||
\Var{solveEquation(P)}
|
|
||||||
|
|
||||||
%-set P = Expression.random("{a}*x^2 + {b}*x + {c}", ["b**2-4*a*c==0"])
|
|
||||||
\item Étude du polynôme $P$, $\forall x \in \mathbb{R} \quad P(x) = \Var{P}$
|
|
||||||
|
|
||||||
Solution:
|
|
||||||
|
|
||||||
\Var{solveEquation(P)}
|
|
||||||
|
|
||||||
%-set P = Expression.random("{a}*x^2 + {b}*x + {c}", ["b**2-4*a*c<0"])
|
|
||||||
\item Étude du polynôme $P$, $\forall x \in \mathbb{R} \quad P(x) = \Var{P}$
|
|
||||||
|
|
||||||
Solution:
|
|
||||||
|
|
||||||
\Var{solveEquation(P)}
|
|
||||||
|
|
||||||
\end{enumerate}
|
|
||||||
\end{document}
|
|
@ -1,133 +0,0 @@
|
|||||||
% vim:ft=tex:
|
|
||||||
%
|
|
||||||
\documentclass[12pt]{article}
|
|
||||||
\usepackage[utf8x]{inputenc}
|
|
||||||
\usepackage[francais]{babel}
|
|
||||||
\usepackage[T1]{fontenc}
|
|
||||||
\usepackage{amssymb}
|
|
||||||
\usepackage{amsmath}
|
|
||||||
\usepackage{amsfonts}
|
|
||||||
|
|
||||||
|
|
||||||
\title{
|
|
||||||
Snippets pour Opytex \\
|
|
||||||
Fractions
|
|
||||||
}
|
|
||||||
\author{
|
|
||||||
Benjamin Bertrand
|
|
||||||
}
|
|
||||||
|
|
||||||
\begin{document}
|
|
||||||
\maketitle
|
|
||||||
|
|
||||||
\section{Simplifications de fractions}
|
|
||||||
\begin{itemize}
|
|
||||||
\item Trouver le numérateur quand le dénominateur augmente
|
|
||||||
\Block{set a,b,ans,c = random_str("{a},{b},{a*c},{b*c}", conditions = ["{a} != {b}"], val_min = 2, val_max = 10).split(',')}%
|
|
||||||
\begin{align*}
|
|
||||||
\dfrac{\Var{a}}{\Var{b}} = \dfrac{\ldots}{\Var{c}}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\dfrac{\Var{a}}{\Var{b}} = \dfrac{\Var{ans}}{\Var{c}}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Trouver le numérateur quand le dénominateur diminue
|
|
||||||
\Block{set a,b,ans,c = random_str("{a*c},{b*c},{a},{b}", conditions = ["{a} != {b}"], val_min = 2, val_max = 10).split(',')}%
|
|
||||||
\begin{align*}
|
|
||||||
\dfrac{\Var{a}}{\Var{b}} = \dfrac{\cdots}{\Var{c}}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\dfrac{\Var{a}}{\Var{b}} = \dfrac{\Var{ans}}{\Var{c}}
|
|
||||||
\end{align*}
|
|
||||||
Explications
|
|
||||||
\Block{set f = Expression(a + "/" +b)}
|
|
||||||
\begin{align*}
|
|
||||||
\Var{f.simplify().explain()|join('=')}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
|
|
||||||
\section{Ajouts de fractions}
|
|
||||||
|
|
||||||
\begin{itemize}
|
|
||||||
\item Fraction avec le même dénominateur
|
|
||||||
\Block{set e = Expression.random("{a} / {b} + {c} / {b}", ["{b} > 1"], val_min = 1)}
|
|
||||||
\begin{align*}
|
|
||||||
A = \Var{e}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\Var{e.simplify().explain() | join('=')}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Fraction avec un denominateur multiple de l'autre
|
|
||||||
\Block{set e = Expression.random("{a} / {b} + {c} / {b*d}", ["{b} > 1","{d} > 1"], val_min = 1)}
|
|
||||||
\begin{align*}
|
|
||||||
A = \Var{e}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\Var{e.simplify().explain() | join('=')}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Fraction avec des dénominateurs premiers entre eux
|
|
||||||
\Block{set e = Expression.random("{a} / {b} + {c} / {d}", ["{b} > 1","{d} > 1", "gcd({b},{d}) == 1"], val_min = 1)}
|
|
||||||
\begin{align*}
|
|
||||||
A = \Var{e}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\Var{e.simplify().explain() | join('=')}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Une fraction et un entier
|
|
||||||
\Block{set e = Expression.random("{a} / {b} + {c}", ["{b} > 1"], val_min = 1)}
|
|
||||||
\begin{align*}
|
|
||||||
A = \Var{e}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\Var{e.simplify().explain() | join('=')}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Une fraction et un entier
|
|
||||||
\Block{set e = Expression.random("{c} + {a} / {b}", ["{b} > 1"], val_min = 1)}
|
|
||||||
\begin{align*}
|
|
||||||
A = \Var{e}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\Var{e.simplify().explain() | join('=')}
|
|
||||||
\end{align*}
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
|
|
||||||
\section{Multiplications de fractions}
|
|
||||||
\begin{itemize}
|
|
||||||
\item Une fraction et un entier
|
|
||||||
\Block{set e = Expression.random("{c} * {a} / {b}", ["{b} > 1"], val_min = 1)}
|
|
||||||
\begin{align*}
|
|
||||||
A = \Var{e}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\Var{e.simplify().explain() | join('=')}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\item Fraction avec des dénominateurs quelconques
|
|
||||||
\Block{set e = Expression.random("{a} / {b} * {c} / {d}", ["{b} > 1","{d} > 1"], val_min = 1)}
|
|
||||||
\begin{align*}
|
|
||||||
A = \Var{e}
|
|
||||||
\end{align*}
|
|
||||||
Solution
|
|
||||||
\begin{align*}
|
|
||||||
\Var{e.simplify().explain() | join('=')}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
|
|
||||||
\end{document}
|
|
@ -1,87 +0,0 @@
|
|||||||
% vim:ft=tex:
|
|
||||||
%
|
|
||||||
\documentclass[12pt]{article}
|
|
||||||
\usepackage[utf8x]{inputenc}
|
|
||||||
\usepackage[francais]{babel}
|
|
||||||
\usepackage[T1]{fontenc}
|
|
||||||
\usepackage{amssymb}
|
|
||||||
\usepackage{amsmath}
|
|
||||||
\usepackage{amsfonts}
|
|
||||||
|
|
||||||
|
|
||||||
\title{
|
|
||||||
Snippets pour Opytex \\
|
|
||||||
Suites
|
|
||||||
}
|
|
||||||
\author{
|
|
||||||
Benjamin Bertrand
|
|
||||||
}
|
|
||||||
|
|
||||||
\begin{document}
|
|
||||||
\maketitle
|
|
||||||
|
|
||||||
\section{Calculs de termes}
|
|
||||||
\begin{enumerate}
|
|
||||||
\item Calculer les termes $u_0$, $u_1$, $u_2$, $u_{10}$ et $u_{100}$ pour les suites suivantes
|
|
||||||
\begin{enumerate}
|
|
||||||
%-set u = Expression.random("{a}*n+{b}")
|
|
||||||
\item $\forall n \in \mathbb{N} \qquad u_n = \Var{u}$
|
|
||||||
|
|
||||||
Solution:
|
|
||||||
\begin{align*}
|
|
||||||
u_0 &= \Var{u(0).explain() | join('=')} \\
|
|
||||||
u_1 &= \Var{u(1).explain() | join('=')} \\
|
|
||||||
u_2 &= \Var{u(2).explain() | join('=')} \\
|
|
||||||
u_{10} &= \Var{u(10).explain() | join('=')} \\
|
|
||||||
u_{100} &= \Var{u(100).explain() | join('=')}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
%-set v = Expression.random("({a}*n+{b})/{c}", ["c>1"])
|
|
||||||
\item $\forall n \in \mathbb{N} \qquad v_n = \Var{v|replace("frac","dfrac")}$
|
|
||||||
|
|
||||||
Solution:
|
|
||||||
\begin{align*}
|
|
||||||
v_0 &= \Var{v(0).explain() | join('=')} \\
|
|
||||||
v_1 &= \Var{v(1).explain() | join('=')} \\
|
|
||||||
v_2 &= \Var{v(2).explain() | join('=')} \\
|
|
||||||
v_{10} &= \Var{v(10).explain() | join('=')} \\
|
|
||||||
v_{100} &= \Var{v(100).explain() | join('=')}
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
%-set v = Expression.random("({a}*n+{b})/{c}", ["c>1"])
|
|
||||||
\item $\forall n \in \mathbb{N} \qquad v_n = \Var{v}$
|
|
||||||
|
|
||||||
Solution:
|
|
||||||
\begin{align*}
|
|
||||||
%- for j in [0, 1, 2, 10, 100]
|
|
||||||
v_{\Var{j}} &= \Var{v(j).explain() | join('=')} \\
|
|
||||||
%- endfor
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
%-set f = Expression.random("{a}*x")
|
|
||||||
%-set v0 = randint(0, 10)
|
|
||||||
\item $\forall n \in \mathbb{N} \qquad v_{n+1} = \Var{f("v_n")} \mbox{ et } v_0 = \Var{v0}$
|
|
||||||
|
|
||||||
Solution:
|
|
||||||
\begin{align*}
|
|
||||||
v_0 &= \Var{v0} \\
|
|
||||||
%-set v = f(v0)
|
|
||||||
v_1 &= \Var{v.explain() | join('=')} \\
|
|
||||||
%-set v = f(v)
|
|
||||||
v_2 &= \Var{v.explain() | join('=')} \\
|
|
||||||
\end{align*}
|
|
||||||
Pour le terme 10, il faut calculer tous les autres avant!
|
|
||||||
\begin{align*}
|
|
||||||
%#- Trick to move around scoping rules
|
|
||||||
%#- https://stackoverflow.com/a/49699589
|
|
||||||
%- set v = namespace(val = v)
|
|
||||||
%- for i in range(8)
|
|
||||||
%- set v.val = f(v.val)
|
|
||||||
v_{\Var{i+3}} &= \Var{v.val.explain() | join('=')} \\
|
|
||||||
%- endfor
|
|
||||||
\end{align*}
|
|
||||||
|
|
||||||
\end{enumerate}
|
|
||||||
|
|
||||||
\end{enumerate}
|
|
||||||
\end{document}
|
|
6
test/students.csv
Normal file
6
test/students.csv
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
nom,classe,elo
|
||||||
|
Bob,1ST,1000
|
||||||
|
Pipo,1ST,1300
|
||||||
|
Popi,1ST,100
|
||||||
|
Boule,1ST,4000
|
||||||
|
Bill,1ST,1300
|
|
22
test/templates/tpl_test.tex
Normal file
22
test/templates/tpl_test.tex
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
\documentclass[12pt]{article}
|
||||||
|
\usepackage[utf8x]{inputenc}
|
||||||
|
\usepackage[francais]{babel}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage{amssymb}
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{amsfonts}
|
||||||
|
|
||||||
|
|
||||||
|
\title{
|
||||||
|
Tests
|
||||||
|
}
|
||||||
|
\author{
|
||||||
|
Benjamin Bertrand
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\end{document}
|
212
test/test_bopytex.py
Normal file
212
test/test_bopytex.py
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from shutil import copyfile
|
||||||
|
from bopytex.bopytex import produce_and_compile, subject_metadatas
|
||||||
|
|
||||||
|
SNIPPETS_PATH = Path("snippets/")
|
||||||
|
TEST_PATH = Path("test")
|
||||||
|
TEST_TEMPLATE_PATH = TEST_PATH / "templates/"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def prepare_test_template(tmp_path):
|
||||||
|
""" Create a tmp directory, copy snippets inside
|
||||||
|
|
||||||
|
return tmp directory name
|
||||||
|
"""
|
||||||
|
tmp = tmp_path
|
||||||
|
snippets = TEST_TEMPLATE_PATH.glob("tpl_*.tex")
|
||||||
|
for s in snippets:
|
||||||
|
copyfile(s, tmp / s.name)
|
||||||
|
csvs = TEST_PATH.glob("*.csv")
|
||||||
|
for s in csvs:
|
||||||
|
copyfile(s, tmp / s.name)
|
||||||
|
|
||||||
|
prev_dir = Path.cwd()
|
||||||
|
os.chdir(tmp)
|
||||||
|
yield tmp
|
||||||
|
os.chdir(prev_dir)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def prepare_snippets(tmp_path):
|
||||||
|
""" Create a tmp directory, copy snippets inside
|
||||||
|
|
||||||
|
return tmp directory name
|
||||||
|
"""
|
||||||
|
tmp = tmp_path
|
||||||
|
snippets = SNIPPETS_PATH.glob("tpl_*.tex")
|
||||||
|
for s in snippets:
|
||||||
|
copyfile(s, tmp / s.name)
|
||||||
|
|
||||||
|
prev_dir = Path.cwd()
|
||||||
|
os.chdir(tmp)
|
||||||
|
yield tmp
|
||||||
|
os.chdir(prev_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def test_produce_and_compile_base(prepare_test_template):
|
||||||
|
test_tpl = list(Path(".").glob("tpl_*.tex"))
|
||||||
|
assert [tpl.name for tpl in test_tpl] == ["tpl_test.tex"]
|
||||||
|
for tpl in test_tpl:
|
||||||
|
produce_and_compile(
|
||||||
|
{
|
||||||
|
"template": tpl,
|
||||||
|
"working_dir": None,
|
||||||
|
"only_corr": False,
|
||||||
|
"students_csv": None,
|
||||||
|
"number_subjects": 1,
|
||||||
|
"dirty": False,
|
||||||
|
"no_compile": False,
|
||||||
|
"no_join": False,
|
||||||
|
"corr": False,
|
||||||
|
"crazy": False,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_produce_and_compile_csv(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,
|
||||||
|
}
|
||||||
|
# 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 = [
|
||||||
|
{
|
||||||
|
"num": "01",
|
||||||
|
"nom": "Bob",
|
||||||
|
"classe": "1ST",
|
||||||
|
"elo": "1000",
|
||||||
|
"texfile": "01_test.tex",
|
||||||
|
"template": "tpl_test.tex",
|
||||||
|
"directory": ".",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": "02",
|
||||||
|
"nom": "Pipo",
|
||||||
|
"classe": "1ST",
|
||||||
|
"elo": "1300",
|
||||||
|
"texfile": "02_test.tex",
|
||||||
|
"template": "tpl_test.tex",
|
||||||
|
"directory": ".",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": "03",
|
||||||
|
"nom": "Popi",
|
||||||
|
"classe": "1ST",
|
||||||
|
"elo": "100",
|
||||||
|
"texfile": "03_test.tex",
|
||||||
|
"template": "tpl_test.tex",
|
||||||
|
"directory": ".",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": "04",
|
||||||
|
"nom": "Boule",
|
||||||
|
"classe": "1ST",
|
||||||
|
"elo": "4000",
|
||||||
|
"texfile": "04_test.tex",
|
||||||
|
"template": "tpl_test.tex",
|
||||||
|
"directory": ".",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": "05",
|
||||||
|
"nom": "Bill",
|
||||||
|
"classe": "1ST",
|
||||||
|
"elo": "1300",
|
||||||
|
"texfile": "05_test.tex",
|
||||||
|
"template": "tpl_test.tex",
|
||||||
|
"directory": ".",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
assert metadatas == meta
|
||||||
|
|
||||||
|
|
||||||
|
def test_pdfjoin_current_directory(prepare_test_template):
|
||||||
|
wdir = prepare_test_template
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_pdfjoin_deep_directory():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_pdfjoin_dont_remove():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_subject_names():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_feed_texfiles():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_tex2pdf_current_directory():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_tex2pdf_deep_directory():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_activate_solution():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# def test_snippets(prepare_snippets):
|
||||||
|
# snippets = list(Path(".").glob("tpl_*.tex"))
|
||||||
|
# for tpl in snippets:
|
||||||
|
# produce_and_compile(
|
||||||
|
# {
|
||||||
|
# "template": tpl,
|
||||||
|
# "working_dir": None,
|
||||||
|
# "only_corr": False,
|
||||||
|
# "students_csv": None,
|
||||||
|
# "number_subjects": 1,
|
||||||
|
# "dirty": False,
|
||||||
|
# "no_compile": False,
|
||||||
|
# "no_join": False,
|
||||||
|
# "corr": False,
|
||||||
|
# "crazy": False,
|
||||||
|
# }
|
||||||
|
# )
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Reglages pour 'vim'
|
||||||
|
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
|
||||||
|
# cursor: 16 del
|
Loading…
Reference in New Issue
Block a user