|
|
@ -0,0 +1,391 @@
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
import glob
|
|
|
|
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
from . import constantes_csv as constantes
|
|
|
|
|
|
|
|
from pylatex import Document, Section, NoEscape, LongTable, Tabularx, Table
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def construction_nom_fichier(*args):
|
|
|
|
|
|
|
|
"""À partir de la liste, construit un nom de fichier valable : les arguments sont séparés par des sous-tirets
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
return '_'.join( [str(arg).lower() for arg in args ] )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def construction_ligne(*args,separator=';'):
|
|
|
|
|
|
|
|
"""À partir de la liste, construit une ligne csv valable : le séparateur par défaut est le point-virgule
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
return separator.join( [str(arg) for arg in args ] )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def arrondi(flottant,nb_chiffres=2):
|
|
|
|
|
|
|
|
"""Retourne un arrondi à deux chiffres après la virgule d'un flottant
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
return round(float(flottant),nb_chiffres)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def taille_donnee(string):
|
|
|
|
|
|
|
|
"""Retourne une valeur entière de la taille d'une chaîne de caractère, pour tenir compte des chaînes de caractères contenant du LaTeX
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
taille_0 = [r'$',"\\frac",'{','}','\\left[','\\right]','\\left(','\\right)','\\left{','\\right}'] # Quelques symboles maths
|
|
|
|
|
|
|
|
taille_1 = ['\\alpha','\\beta','\\epsilon','\\gamma','\\delta','\\eta','\\phi','\\psi','\\epsilon','\\neq','\\leq','\\geq',r"\textcolor{green}{\checkmark}",r"\textcolor{red}{\text{X}}"] #alphabet grec, quelques symboles maths, quelques commandes latex
|
|
|
|
|
|
|
|
taille_2 = ['\\sum','\\prod','\\oplus'] # symboles sommes, produits, somme directe
|
|
|
|
|
|
|
|
liste_taille = [taille_0,taille_1,taille_2]
|
|
|
|
|
|
|
|
a_remplacer = ''
|
|
|
|
|
|
|
|
for liste in liste_taille:
|
|
|
|
|
|
|
|
for element in liste:
|
|
|
|
|
|
|
|
string = string.replace(element,a_remplacer)
|
|
|
|
|
|
|
|
string = string.replace(element.capitalize(),a_remplacer) # Pour tenir compte des lettres majuscules
|
|
|
|
|
|
|
|
a_remplacer += ' '
|
|
|
|
|
|
|
|
return len(string)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def taille_colonnes(donnees):
|
|
|
|
|
|
|
|
"""Prend en argument la liste de liste des données d'un fichier csv pour extraire la taille maximale à affecter à chaque colonne. Les contraintes suivantes sont respectées :
|
|
|
|
|
|
|
|
- la somme des tailles fait 42em, la largeur maximale du pdf : on applique pour chaque maximum de chaque colonne la formule 42*max/(somme des max des colonnes).
|
|
|
|
|
|
|
|
- si la taille maximum d'une colonne est réalisée pour un seul mot, la largeur du mot est prise pour taille maximale (en gros, cette largeur étant donnée par len(string)/1.9) : la formule précédente est conservée uniquement sur les autres colonnes : la somme des tailles peut être alors plus petite ou plus grande que 42em. Si elle est plus grande on affiche un message d'erreur.
|
|
|
|
|
|
|
|
Retourne la liste des arguments à retourner à un environnement LaTeX de type Tabular
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
taille_max = constantes.taille_max #42em en LaTeX
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Taille expérimentale d'une chaîne de caractère
|
|
|
|
|
|
|
|
def largeur_string(taille_string):
|
|
|
|
|
|
|
|
return taille_string/constantes.rapport_caractere
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nombre_colonne = len(donnees[0])
|
|
|
|
|
|
|
|
liste_des_maximum = [max([ taille_donnee(ligne[i]) for ligne in donnees]) for i in range(nombre_colonne) ]#0 for _ in range(nombre_colonne) ]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Récupération de la liste des colonnes pour lesquelles le maximum est réalisée pour un mot unique
|
|
|
|
|
|
|
|
def unique_mot(string):
|
|
|
|
|
|
|
|
return len(string.split(' ')) <= 1 # True si moins d'un mot
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mot_unique = [ False for _ in range(nombre_colonne) ] # A priori les colonnes ont plus d'un mot
|
|
|
|
|
|
|
|
for i in range(nombre_colonne):
|
|
|
|
|
|
|
|
colonne_i = [ ligne[i] for ligne in donnees ]
|
|
|
|
|
|
|
|
for element in colonne_i: # On teste pour tous les max possibles si l'élément maximum n'a qu'un mot, cela évite les problèmes de doublons : dès qu'un max est réalisé pour un unique mot c'est cette contrainte que l'on choisi.
|
|
|
|
|
|
|
|
if taille_donnee(element) == liste_des_maximum[i]:
|
|
|
|
|
|
|
|
if unique_mot(element):
|
|
|
|
|
|
|
|
mot_unique[i] = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Remplissage de la liste des tailles
|
|
|
|
|
|
|
|
liste_taille = [ 0 for _ in range(nombre_colonne) ]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Liste des tailles de colonnes dont le max est réalisée pour un mot unique
|
|
|
|
|
|
|
|
for i in range(nombre_colonne):
|
|
|
|
|
|
|
|
if mot_unique[i]:
|
|
|
|
|
|
|
|
liste_taille[i] = arrondi(largeur_string(liste_des_maximum[i]),1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Liste des tailles des autres colonnes
|
|
|
|
|
|
|
|
caracteres_deja_pris = sum(liste_taille)
|
|
|
|
|
|
|
|
taille_cumulee = sum([liste_des_maximum[i] for i in range(nombre_colonne) if not(mot_unique[i]) ])
|
|
|
|
|
|
|
|
for i in range(nombre_colonne):
|
|
|
|
|
|
|
|
if not(mot_unique[i]):
|
|
|
|
|
|
|
|
#liste_taille[i] = arrondi(liste_des_maximum[i]*(taille_max-caracteres_deja_pris)/(taille_cumulee-caracteres_deja_pris),1)
|
|
|
|
|
|
|
|
liste_taille[i] = arrondi((taille_max-caracteres_deja_pris)*liste_des_maximum[i]/taille_cumulee,1)
|
|
|
|
|
|
|
|
if constantes.DEBUG:
|
|
|
|
|
|
|
|
print(liste_taille)
|
|
|
|
|
|
|
|
# Message d'erreur si jamais la somme des tailles est trop grande.
|
|
|
|
|
|
|
|
if sum(liste_taille) > taille_max:
|
|
|
|
|
|
|
|
print("Les colonnes sont trop grandes, le document risque d'être bien moche")
|
|
|
|
|
|
|
|
return ">{\\centering\\arraybackslash}"+">{\\centering\\arraybackslash}".join([ 'm'+'{'+str(element)+'em'+'}' for element in liste_taille ])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#'|'+'|'.join([ 'p'+'{'+str(element)+'em'+'}' for element in liste_taille ])+'|'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Fichier():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Classe de fichier, porte un nom et un emplacement de dossier (chemin absolu ?)
|
|
|
|
|
|
|
|
On peut :
|
|
|
|
|
|
|
|
- retourner le nom sans l'extension
|
|
|
|
|
|
|
|
- le créer physiquement sur la machine
|
|
|
|
|
|
|
|
- le copier
|
|
|
|
|
|
|
|
- l'imprimer tel quel
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self,nom,path):
|
|
|
|
|
|
|
|
"""Les attributs sont le nom et le chemin du dossier où se trouve le fichier """
|
|
|
|
|
|
|
|
self.nom = nom
|
|
|
|
|
|
|
|
self.path = path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def emplacement(self):
|
|
|
|
|
|
|
|
"""Chemin du fichier complet """
|
|
|
|
|
|
|
|
return os.path.join(self.path,self.nom)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def splitext(self):
|
|
|
|
|
|
|
|
"""Retourne le nom du fichier sans extension """
|
|
|
|
|
|
|
|
if self.nom[0]=='.': # Ne prend pas les fichiers cachés ?
|
|
|
|
|
|
|
|
return ''
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return os.path.splitext(self.nom)[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def exists(self):
|
|
|
|
|
|
|
|
"""Test d'existence du fichier """
|
|
|
|
|
|
|
|
return os.path.exists(self.emplacement())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def existserror(self):
|
|
|
|
|
|
|
|
"""Message d'erreur en cas de non existence du fichier : utilisée dans le décorateur suivant """
|
|
|
|
|
|
|
|
if not self.exists():
|
|
|
|
|
|
|
|
print('le fichier '+self.emplacement()+" n'existe pas")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def existswrap(func):
|
|
|
|
|
|
|
|
"""Décorateur pour s'assurer que l'on applique la fonction à un fichier qui existe """
|
|
|
|
|
|
|
|
def wrap(self,*args,**kwargs):
|
|
|
|
|
|
|
|
if self.exists():
|
|
|
|
|
|
|
|
return func(self,*args,**kwargs)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return self.existserror()
|
|
|
|
|
|
|
|
return wrap
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create(self):
|
|
|
|
|
|
|
|
"""Crée le fichier ainsi que tous les sous-dossiers nécessaires, si le fichier n'existe pas déjà """
|
|
|
|
|
|
|
|
if not self.exists():
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
os.makedirs(self.path)
|
|
|
|
|
|
|
|
with open(self.emplacement(),'w') as csvfile:
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
with open(self.emplacement(),'w') as csvfile:
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def returndir(func):
|
|
|
|
|
|
|
|
"""Décorateur pour effectuer une action dans un sous-dossier puis revenir """
|
|
|
|
|
|
|
|
def wrap(self,*args,**kwargs):
|
|
|
|
|
|
|
|
returnpath = os.getcwd()
|
|
|
|
|
|
|
|
f = func(self,*args,**kwargs)
|
|
|
|
|
|
|
|
os.chdir(returnpath)
|
|
|
|
|
|
|
|
return f
|
|
|
|
|
|
|
|
return wrap
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@existswrap
|
|
|
|
|
|
|
|
def ecrire(self,*args):
|
|
|
|
|
|
|
|
"""Écrit dans un fichier chaque élément de la liste des arguments, un par ligne """
|
|
|
|
|
|
|
|
with open(self.emplacement(),'a') as outfile:
|
|
|
|
|
|
|
|
for arg in args:
|
|
|
|
|
|
|
|
outfile.write(arg+'\n')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@existswrap
|
|
|
|
|
|
|
|
def lire(self):
|
|
|
|
|
|
|
|
"""Permet de lire le fichier en entier """
|
|
|
|
|
|
|
|
with open(self.emplacement(),'r') as csvfile:
|
|
|
|
|
|
|
|
data = csvfile.read()
|
|
|
|
|
|
|
|
return data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@existswrap
|
|
|
|
|
|
|
|
def copier(self,path):
|
|
|
|
|
|
|
|
"""Copie le fichier à l'endroit désigné """
|
|
|
|
|
|
|
|
data = self.lire()
|
|
|
|
|
|
|
|
copie = Fichier(self.nom,path)
|
|
|
|
|
|
|
|
copie.create()
|
|
|
|
|
|
|
|
copie.ecrire(data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@existswrap
|
|
|
|
|
|
|
|
def imprimer(self,*args):
|
|
|
|
|
|
|
|
"""Imprimer les fichier de la liste des arguments """
|
|
|
|
|
|
|
|
cmd = ['lpr']+[arg for arg in args]+[self.emplacement()]
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
subprocess.call(cmd)
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
print("Impossible d'imprimer le fichier")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@returndir
|
|
|
|
|
|
|
|
@existswrap
|
|
|
|
|
|
|
|
def tex_to_pdf(self,path_sources_tex):
|
|
|
|
|
|
|
|
"""Permet de compiler un fichier latex : on ne vérifie pas l'extension !
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
tex_path = self.path
|
|
|
|
|
|
|
|
fichiers_tex = sorted([fichier for fichier in glob.glob(os.path.join(path_sources_tex,'*.tex'))])
|
|
|
|
|
|
|
|
fichiers_sources_tex = [Fichier(fichier,path_sources_tex) for fichier in fichiers_tex]
|
|
|
|
|
|
|
|
if len(fichiers_sources_tex) == 0:
|
|
|
|
|
|
|
|
print("Le dossier des sources LaTeX n'existe pas ")
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
a_copier = ''
|
|
|
|
|
|
|
|
for fichier in fichiers_sources_tex:
|
|
|
|
|
|
|
|
if 'tailer.tex' not in fichier.nom:
|
|
|
|
|
|
|
|
a_copier +=r'\input{'+fichier.splitext()+'}'
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
tailer = r'\input{'+fichier.splitext()+'}'
|
|
|
|
|
|
|
|
data_tex = self.lire()
|
|
|
|
|
|
|
|
with open(self.emplacement(),'w') as texfile:
|
|
|
|
|
|
|
|
texfile.write(a_copier)
|
|
|
|
|
|
|
|
texfile.write('\n')
|
|
|
|
|
|
|
|
texfile.write(data_tex)
|
|
|
|
|
|
|
|
texfile.write('\n')
|
|
|
|
|
|
|
|
texfile.write(tailer)
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
os.chdir(self.path)
|
|
|
|
|
|
|
|
cmd = [constantes.compilateur_latex]+[self.nom]
|
|
|
|
|
|
|
|
outfile = os.path.join(self.splitext()+'.logtex')
|
|
|
|
|
|
|
|
with open(outfile,'w') as out:
|
|
|
|
|
|
|
|
subprocess.call(cmd,stdout = out)
|
|
|
|
|
|
|
|
return Fichier(self.splitext()+'.pdf',self.path)
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
print("Il y a eu une erreur durant la compilation (fichier csv non écrit en LaTeX ?), voir le fichier .logtex situé dans "+self.path)
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FichierCSV(Fichier):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Classe de fichier CSV héritant de la classe de fichier pour manipuler des fichiers csv.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Attributs :
|
|
|
|
|
|
|
|
- nom de fichier avec extension csv
|
|
|
|
|
|
|
|
- la liste des noms des colonnes, dans l'ordre (pourquoi ? Non implémenté pour le moment)
|
|
|
|
|
|
|
|
- emplacement du dossier parent
|
|
|
|
|
|
|
|
- séparateur
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### IMPORTANT ###
|
|
|
|
|
|
|
|
Le séparateur par défaut est un point-virgule.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Le fichier doit se terminer par une ligne commençant par le mot "terminer" pour pouvoir être utilisé par LaTeX (chelou et faux pour le moment !)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self,nom,path,separator=';'): # le séparateur par défaut est un point-virgule !
|
|
|
|
|
|
|
|
nomcsv = nom+'.csv'
|
|
|
|
|
|
|
|
self.nom = nomcsv
|
|
|
|
|
|
|
|
self.path = path
|
|
|
|
|
|
|
|
self.separator = separator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create(self,nom_des_colonnes):
|
|
|
|
|
|
|
|
"""Crée le fichier CSV ainsi que sa première ligne sur le même modèle que la méthode create sur les fichiers """
|
|
|
|
|
|
|
|
if not self.exists():
|
|
|
|
|
|
|
|
ligne = construction_ligne(*nom_des_colonnes,separator=self.separator)
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
os.makedirs(self.path)
|
|
|
|
|
|
|
|
with open(self.emplacement(),'w') as csvfile:
|
|
|
|
|
|
|
|
csvfile.write(ligne+'\n')
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
with open(self.emplacement(),'w') as csvfile:
|
|
|
|
|
|
|
|
csvfile.write(ligne+'\n')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Fichier.existswrap
|
|
|
|
|
|
|
|
def ecrire(self,*args):
|
|
|
|
|
|
|
|
"""Écrit dans le fichier CSV la ligne correspondant à la liste des arguments au format voulu """
|
|
|
|
|
|
|
|
ligne = construction_ligne(*args,separator=self.separator)
|
|
|
|
|
|
|
|
with open(self.emplacement(),'a') as csvfile:
|
|
|
|
|
|
|
|
csvfile.write(ligne+'\n')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Fichier.existswrap
|
|
|
|
|
|
|
|
def reinitialiser(self):
|
|
|
|
|
|
|
|
"""Écrase le fichier et le remet à 0
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
nom_des_colonnes = self.nom_colonnes()
|
|
|
|
|
|
|
|
ligne = construction_ligne(*nom_des_colonnes,separator=self.separator)
|
|
|
|
|
|
|
|
with open(self.emplacement(),'w') as csvfile:
|
|
|
|
|
|
|
|
csvfile.write(ligne+'\n')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Fichier.existswrap
|
|
|
|
|
|
|
|
def lire(self):
|
|
|
|
|
|
|
|
"""Récupère une liste de listes des données du fichier CSV. On ne prend évidemment pas la première ligne qui est la ligne des noms de colonnes """
|
|
|
|
|
|
|
|
with open(self.emplacement(),'r') as csvfile:
|
|
|
|
|
|
|
|
lines = csvfile.readlines()
|
|
|
|
|
|
|
|
return [line.rstrip('\n').split(self.separator) for line in lines][1:]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Fichier.existswrap
|
|
|
|
|
|
|
|
def nom_colonnes(self):
|
|
|
|
|
|
|
|
"""Récupère les noms des colonnes : c'est la première ligne """
|
|
|
|
|
|
|
|
with open(self.emplacement(),'r') as csvfile:
|
|
|
|
|
|
|
|
lines = csvfile.readlines()
|
|
|
|
|
|
|
|
return [line.rstrip('\n').split(self.separator) for line in lines][0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Fichier.existswrap
|
|
|
|
|
|
|
|
@Fichier.returndir
|
|
|
|
|
|
|
|
def csv_to_tex(self,titre='',commentaires='',conclusion=''):
|
|
|
|
|
|
|
|
"""Crée dans le dossier courant un dossier TEX ainsi qu'un sous-dossier du nom du fichier csv dans lequel on construit une version tex du fichier CSV. Ces fichier TeX brut est à insérer avec les en-têtes et tailer pour compilation
|
|
|
|
|
|
|
|
Contrainte : le fichier CSV doit être écrit en TeX car on a mis des NoEscape partout
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
infos = self.lire()
|
|
|
|
|
|
|
|
donnees = infos+[self.nom_colonnes()]
|
|
|
|
|
|
|
|
nom_des_colonnes = self.nom_colonnes()
|
|
|
|
|
|
|
|
path = self.path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Création du dossier TEX et du sous-dossier self.splitext()
|
|
|
|
|
|
|
|
tex_path = os.path.join(path,constantes.nom_dossier_latex)
|
|
|
|
|
|
|
|
fichier_tex_path = os.path.join(tex_path,self.splitext())
|
|
|
|
|
|
|
|
if not os.path.exists(tex_path):
|
|
|
|
|
|
|
|
os.makedirs(tex_path)
|
|
|
|
|
|
|
|
if not os.path.exists(fichier_tex_path):
|
|
|
|
|
|
|
|
os.makedirs(fichier_tex_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Génération du fichier TeX dans le sous-dossier TEX/self.splitext()
|
|
|
|
|
|
|
|
os.chdir(fichier_tex_path)
|
|
|
|
|
|
|
|
doc = Section(NoEscape(titre),numbering=False)
|
|
|
|
|
|
|
|
doc.append(NoEscape(r'\begin{center}'))
|
|
|
|
|
|
|
|
doc.append(NoEscape(commentaires))
|
|
|
|
|
|
|
|
doc.append(NoEscape(r'\end{center}'))
|
|
|
|
|
|
|
|
doc.append(NoEscape(r'\begin{center}'))
|
|
|
|
|
|
|
|
with doc.create(LongTable(table_spec=NoEscape(taille_colonnes(donnees)),pos=['H'])) as info:
|
|
|
|
|
|
|
|
#LongTable(table_spec=NoEscape(taille_colonnes(donnees)),pos=['H'])) as info:
|
|
|
|
|
|
|
|
info.add_hline()
|
|
|
|
|
|
|
|
info.add_row(*[NoEscape(element) for element in nom_des_colonnes])
|
|
|
|
|
|
|
|
info.add_hline()
|
|
|
|
|
|
|
|
for element in infos:
|
|
|
|
|
|
|
|
info.add_row(*[NoEscape(item) for item in element ])
|
|
|
|
|
|
|
|
info.add_hline()
|
|
|
|
|
|
|
|
doc.append(NoEscape(r'\end{center}'))
|
|
|
|
|
|
|
|
doc.append(NoEscape(r'\begin{center}'))
|
|
|
|
|
|
|
|
doc.append(NoEscape(conclusion))
|
|
|
|
|
|
|
|
doc.append(NoEscape(r'\end{center}'))
|
|
|
|
|
|
|
|
doc.generate_tex(self.splitext())
|
|
|
|
|
|
|
|
return Fichier(self.splitext()+'.tex',fichier_tex_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Fichier.existswrap
|
|
|
|
|
|
|
|
@Fichier.returndir
|
|
|
|
|
|
|
|
def csv_to_tex_to_pdf(self,path_sources_tex,titre='',commentaires='',conclusion=''):
|
|
|
|
|
|
|
|
"""Appelle la méthode csv_to_tex, ajoute les en-têtes et tailer de path_sources_tex au fichier TeX du dossier TEX/self.splitext() et compile le fichier tex.
|
|
|
|
|
|
|
|
Les sources doivent être ordonnées selon l'ordre lexicographique pour préfixer et suffixer le fichier self.nom.tex pour ensuite le compiler. Le fichier à utiliser pour suffixer doit s'appeller "tailer". Ne fonctionnera que si pdflatex est présent et accessible par subprocess.call
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
tex_fichier = self.csv_to_tex(titre=titre,commentaires=commentaires,conclusion=conclusion)
|
|
|
|
|
|
|
|
tex_path = tex_fichier.path
|
|
|
|
|
|
|
|
if tex_fichier.exists():
|
|
|
|
|
|
|
|
fichiers_tex = sorted([fichier for fichier in glob.glob(os.path.join(path_sources_tex,'*.tex'))])
|
|
|
|
|
|
|
|
fichiers_sources_tex = [Fichier(fichier,path_sources_tex) for fichier in fichiers_tex]
|
|
|
|
|
|
|
|
if len(fichiers_sources_tex) == 0:
|
|
|
|
|
|
|
|
print("Le dossier des sources LaTeX n'existe pas ")
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
a_copier = ''
|
|
|
|
|
|
|
|
for fichier in fichiers_sources_tex:
|
|
|
|
|
|
|
|
if 'tailer.tex' not in fichier.nom:
|
|
|
|
|
|
|
|
a_copier +=r'\input{'+fichier.splitext()+'}'
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
tailer = r'\input{'+fichier.splitext()+'}'
|
|
|
|
|
|
|
|
data_tex = tex_fichier.lire()
|
|
|
|
|
|
|
|
with open(tex_fichier.emplacement(),'w') as texfile:
|
|
|
|
|
|
|
|
texfile.write(a_copier)
|
|
|
|
|
|
|
|
texfile.write('\n')
|
|
|
|
|
|
|
|
texfile.write(data_tex)
|
|
|
|
|
|
|
|
texfile.write('\n')
|
|
|
|
|
|
|
|
texfile.write(tailer)
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
os.chdir(tex_fichier.path)
|
|
|
|
|
|
|
|
cmd = [constantes.compilateur_latex]+[tex_fichier.nom ]#emplacement()]
|
|
|
|
|
|
|
|
outfile = os.path.join(tex_fichier.splitext()+'.logtex')#tex_fichier.path,tex_fichier.splitext()+'.logtex')
|
|
|
|
|
|
|
|
with open(outfile,'w') as out:
|
|
|
|
|
|
|
|
subprocess.call(cmd,stdout = out)
|
|
|
|
|
|
|
|
return Fichier(tex_fichier.splitext()+'.pdf',tex_fichier.path)
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
|
|
|
print("Il y a eu une erreur durant la compilation (fichier csv non écrit en LaTeX ?), voir le fichier .logtex situé dans "+tex_fichier.path)
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
print('le fichier '+tex_fichier.emplacement()+" n'existe pas, et ça c'est chelou ! ")
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fichier(path_complet_du_fichier):
|
|
|
|
|
|
|
|
"""Construit un objet Fichier à partir de son nom complet
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
return Fichier(os.path.basename(path_complet_du_fichier),os.path.dirname(path_complet_du_fichier))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fichierCSV(nom_de_fichier,separator=';'):
|
|
|
|
|
|
|
|
"""Construit un objet FichierCSV à partir de son nom. Le fichier csv doit être un fichier valable (la première ligne doit être les noms de colonnes), ceci n'est pas testé.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
nom_fichier = os.path.splitext(os.path.basename(nom_de_fichier))[0]
|
|
|
|
|
|
|
|
path_fichier = os.path.dirname(nom_de_fichier)
|
|
|
|
|
|
|
|
return FichierCSV(nom_fichier,path_fichier,separator=separator)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Bareme(FichierCSV):
|
|
|
|
|
|
|
|
def __init__(self,type_ecrit,matiere,numero,detail=True,separator=';'):
|
|
|
|
|
|
|
|
"""Un barème se crée uniquement dans le dossier typeecrit_matiere_numero du dossier courant
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
self.nom = construction_nom_fichier('bareme',type_ecrit,matiere,numero)+'.csv'
|
|
|
|
|
|
|
|
self.type_ecrit = type_ecrit
|
|
|
|
|
|
|
|
self.matiere = matiere
|
|
|
|
|
|
|
|
self.numero = numero
|
|
|
|
|
|
|
|
self.path = os.path.join(os.getcwd(),construction_nom_fichier(type_ecrit,matiere,numero.strip('/'))) # dossier dans lequel se trouve le barème
|
|
|
|
|
|
|
|
self.detail = detail
|
|
|
|
|
|
|
|
self.separator = separator
|