Améliore l'export latex en utilisant pypandoc (suppose d'avoir installé pandoc sur la machine)

This commit is contained in:
Cléo Baras 2021-04-02 09:09:41 +02:00
parent e2f7c7da2f
commit cb81caf995
6 changed files with 323 additions and 80 deletions

View File

@ -1,46 +1,51 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ressources
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\nouvelleressource{R107}{Fondamentaux de la programmation}
\ajoutheures{41}{30}
%% Les compétences et les ACs
\ajoutcompetence{RT1-Administrer}{\niveauA}
\ajoutcompetence{RT2-Connecter}{\niveauA}
\ajoutcompetence{RT3-Programmer}{\niveauA}
% Les SAE
\ajoutsae{SAÉ15}{Traiter des données}
% Les pre-requis
% Le descriptif
\ajoutancrage{
Elle fournit les bases conceptuelles et pratiques pour concevoir et spécifier formellement un traitement automatisé de l'information. Ces bases pourront venir en appui de nombreuses compétences techniques (en informatique, en réseau, en télécommunication, ...) que le professionnel R\&T doit développer et sinscrivent dans de nombreuses situations professionnelles que rencontrent le professionnel R\&T, notamment le développement doutils informatiques à usage interne d'une équipe (compétence RT3-Programmer) ou lautomatisation du déploiement et de la maintenance des outils logiciels (compétence RT1-Administrer).
}
% Contenus
\ajoutcontenudetaille{
En utilisant un langage de programmation, comme par exemple Python, les contenus suivants seront traités : * Notions d'algorithmique :
En utilisant un langage de programmation, comme par exemple Python, les
contenus suivants seront traités : * Notions d'algorithmique :
\begin{verbatim}
* Variables, types de base (nombres, chaînes, listes/tableaux).
* Structures de contrôle : tests, répétitions.
* Fonctions et procédures.
* Portée des variables.
\end{verbatim}
\begin{itemize}
\item Variables, types de base (nombres, chaînes, listes/tableaux).
\item Structures de contrôle : tests, répétitions.
\item Fonctions et procédures.
\item Portée des variables.
\begin{itemize}
\item Tests et corrections dun programme. \item Prise en main dun environnement de programmation (éditeur, environnement de développement). \item Prise en main de bibliothèques, modules, d'objets existants (appels de méthodes), … \item Manipulation de fichiers texte. \item Interaction avec le système d'exploitation et la ligne de commande : arguments, lancement de commandes. \item Suivi de versions (git, svn, ...). Lutilisation de langlais est préconisée pour la documentation du code.
\end{itemize}
\tightlist
\item
Tests et corrections d'un programme.
\item
Prise en main d'un environnement de programmation (éditeur,
environnement de développement).
\item
Prise en main de bibliothèques, modules, d'objets existants (appels de
méthodes), \ldots{}
\item
Manipulation de fichiers texte.
\item
Interaction avec le système d'exploitation et la ligne de commande :
arguments, lancement de commandes.
\item
Suivi de versions (git, svn, \ldots). L'utilisation de l'anglais est
préconisée pour la documentation du code.
\end{itemize}
}
% Mots-clés
\ajoutmotscles{Algorithmes, langages de programmation, méthodologie de développement, suivi de versions}

View File

@ -1,41 +1,50 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ressources
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\nouvelleressource{R108}{Bases des systèmes d'exploitation}
\ajoutheures{27}{21}
%% Les compétences et les ACs
\ajoutcompetence{RT1-Administrer}{\niveauA}
\ajoutac{RT1}{Maîtriser les lois fondamentales de l'électricité afin d'intervenir sur des équipements de réseaux et télécommunications}
\ajoutac{RT1}{Maîtriser les rôles et les principes fondamentaux des systèmes d'exploitation afin d'interagir avec ceux-ci pour la configuration et administration des réseaux et services fournis}
\ajoutac{RT1}{Installer un poste client}
\ajoutcompetence{RT2-Connecter}{\niveauA}
\ajoutcompetence{RT3-Programmer}{\niveauA}
% Les SAE
\ajoutsae{SAÉ15}{Traiter des données}
% Les pre-requis
% Le descriptif
\ajoutancrage{
Cette ressource traite des bases de lutilisation dun poste client et de son système dexploitation. Elle est essentielle pour la prise en main pratique dun système informatique en abordant notamment la gestion des données dans un espace de stockage (organisation, recherche, droits) et la maîtrise dun environnement numérique, deux thèmes attendus par le référentiel PIX (https://pix.fr/competences). Cette ressource introduit également un usage avancé du système dexploitation nécessaire au besoin dun professionnel R\&T. Elle vise la maîtrise de commandes en ligne pour gérer larborescence de fichiers, les programmes et les processus du système dexploitation, par exemple pour exécuter un programme ou configurer les éléments dun site Web (compétence RT3-Programmer). Elle vise également lemploi des principales commandes réseau, dans des scripts simples. Ces commandes sont les bases dappui pour administrer - par la suite - un réseau et de ses services (compétence RT1-Administrer). Elle contribue donc aux apprentissages critiques mentionnés précédemment.
Cette ressource traite des bases de lutilisation dun poste client et de son système dexploitation.
Elle est essentielle pour la prise en main pratique dun système informatique en abordant notamment la gestion des données dans un espace de stockage (organisation, recherche, droits) et la maîtrise dun environnement numérique, deux thèmes attendus par le référentiel PIX (https://pix.fr/competences). Cette ressource introduit également un usage avancé du système dexploitation nécessaire au besoin dun professionnel R\&T. Elle vise la maîtrise de commandes en ligne pour gérer larborescence de fichiers, les programmes et les processus du système dexploitation, par exemple pour exécuter un programme ou configurer les éléments dun site Web (compétence RT3-Programmer). Elle vise également lemploi des principales commandes réseau, dans des scripts simples. Ces commandes sont les bases dappui pour administrer - par la suite - un réseau et de ses services (compétence RT1-Administrer). Elle contribue donc aux apprentissages critiques mentionnés précédemment.
}
% Contenus
\ajoutcontenudetaille{
\begin{itemize}
\item Systèmes d'exploitations Windows/Linux, InterfaceHommeMachine et ligne de commande \item Arborescence des répertoires, déplacement, consultation, chemins \item Manipulation de fichiers avec un éditeur texte \item Permissions, droits \item Gestion des processus et flux (redirection, pipe…) \item Se documenter sur le détail des commandes en français/anglais (commande man) \item Consulter et modifier les variables denvironnement \item Commandes réseau (wget, curl, ping, traceroute, netstat, nmap…) \item Initiation aux scripts pour lautomatisation de séquences de commandes, aux structures de contrôle
\tightlist
\item
Systèmes d'exploitations Windows/Linux, Interface-Homme-Machine et
ligne de commande
\item
Arborescence des répertoires, déplacement, consultation, chemins
\item
Manipulation de fichiers avec un éditeur texte
\item
Permissions, droits
\item
Gestion des processus et flux (redirection, pipe\ldots)
\item
Se documenter sur le détail des commandes en français/anglais
(commande man)
\item
Consulter et modifier les variables d'environnement
\item
Commandes réseau (wget, curl, ping, traceroute, netstat, nmap\ldots)
\item
Initiation aux scripts pour l'automatisation de séquences de
commandes, aux structures de contrôle
\end{itemize}
}
% Mots-clés
\ajoutmotscles{Programmation, arborescence, processus, scripts, variables denvironnement, PIX.}

View File

@ -6,7 +6,7 @@ import logging
__LOGGER = logging.getLogger(__name__)
REPERTOIRE = "import"
DOCUMENT = "000 compilation-ressources 2021-03-29T23_14_27.262Z"
DOCUMENT = "ressources_v0"
# Ouverture du document
docu = docx2python.docx2python(REPERTOIRE + "/" + DOCUMENT + ".docx")
@ -131,6 +131,7 @@ ressources = {"S1" : [], "S2": []}
for r in liste_ressources:
# Nettoie titre
nettoie_titre(r)
# Nettoie le champ heures_encadrees

View File

@ -0,0 +1,199 @@
import docx2python
from ressource import *
import logging
__LOGGER = logging.getLogger(__name__)
REPERTOIRE = "import"
DOCUMENT = "000 compilation-saes 2021-03-29T11_10_11.377Z"
# Ouverture du document
docu = docx2python.docx2python(REPERTOIRE + "/" + DOCUMENT + ".docx")
docu = docu.body
docu[0] # Titre général
docu[1] # Tableau de synthèse des ressources
nbre_ressources = 0
ENTETES_CHAPEAU = ["Titre", "Code", "Semestre", "Heures de formation", "dont heures de TP", "Heures \"projet",
"Description des objectifs",
"Liste des ressources", "Type de livrable", "Mots clefs"]
ENTETES_EXEMPLES = ["Titre", "Compétence", "Description des objectifs", "Types"]
def get_indice(champ):
"""Récupère l'indice d'une entête"""
for (i, entete) in enumerate(ENTETES):
if entete in champ:
return i
return None
def get_indice_sans_accent_ni_espace(champ):
"""Récupère l'indice d'une entête en se débarrassant des majuscules/caractères spéciaux/espace"""
champ_purge = supprime_accent_espace(champ)
for (i, entete) in enumerate(ENTETES):
entete_purge = supprime_accent_espace(entete)
if entete_purge in champ_purge:
return i
return None
"""
Format du parsing issu de docx2python
[ # document
[ # table A
[ # table A row
[ # table A cell 1 <-- structure des tableaux
"""
liste_ressources = [] # la liste des ressources telle qu'extrait du docx
print("*Etape 1* : Parsing")
for i in range(2, len(docu)): # A priori un tableau
est_ressource = False
try:
if "Nom de la ressource" in docu[i][0][0][0]: # [03][00][0][0]
est_ressource = True
nbre_ressources += 1
except:
pass
if est_ressource == True:
res = docu[i] # la ressource
nom_ressource = res[0][1][0]
# Création de la ressource
r = RessourceDocx(nom_ressource, res)
liste_ressources.append(r)
# if len(res) != 15:
# __LOGGER.warning(f"Champs en trop ou manquants dans \"{nom_ressource}\"")
# Parsing des données brute de la ressource
data = [None for i in range(len(ENTETES))] # les données attendues Nom, Code, ..., Mots clés
apprentissages = [None for i in range(3)] # les apprentissages des 3 compétences
non_interprete = []
for j in range(len(res)): # parcours des entêtes du tableau décrivant la ressource
ligne = res[j]
if len(ligne) == 2: # ligne de données classique champ => valeur
champ = ligne[0][0] # le nom du champ
i = get_indice_sans_accent_ni_espace(champ) # l'indice de l'entete dans ENTETES
if i != None:
data[i] = "\n".join(res[j][1])
if champ == "Prérequis" and not data[i]:
data[i] = "aucun"
print(f"Dans {nom_ressource}, complète les prérequis à \"aucun\"")
else:
non_interprete.append((champ, ligne[1][0]))
else: # ligne de données soit chapeau (ex Compétences ciblées) soit détail par compétence
champ = ligne[0][0]
if "Apprentissages" in champ: # les compétences ciblées sont déduites de la présence d'apprentissage critiques
# j+1 = les ACs par compétences
acs = res[j+2]
for k in range(len(acs)):
apprentissages[k] = "\n".join(acs[k]) # fusionne les ACS (généralement sur plusieurs lignes)
if non_interprete: # souvent Heures de formation (incluant les TP)
try:
indice_champ = [chp[0] for chp in non_interprete].index("Heures de formation (incluant les TP)")
except:
indice_champ = -1
if indice_champ >= 0: # si le champ "Heures de formation (incluant les TP)" est trouvé
# tente de réinjecter les heures dans Heures encadrées si elles n'on pas déjà été renseignées
indice_heure = get_indice("formation encadrée")
if not data[indice_heure]:
print(f"Dans \"{nom_ressource}\", réinjection de \"Heures de formation (incluant les TP)\" dans \"formation encadrée\"")
data[indice_heure] = champ[1]
non_interprete = non_interprete[:indice_champ] + non_interprete[indice_champ+1:] # supprime le champ
if non_interprete:
__LOGGER.warning(f"Dans \"{nom_ressource}\", champs en trop non interprétés : " + ",".join(
[chp[0] for chp in non_interprete]))
# Analyse des champs manquants
champ_manquants = []
for (j, champ) in enumerate(ENTETES):
if not data[j]:
champ_manquants += [champ]
if champ_manquants:
__LOGGER.warning(f"Dans \"{nom_ressource}\", champs manquants : " + ",".join(champ_manquants))
# Sauvegarde des champs de la ressource
info = tuple(data[1:])
r.charge_informations(*info)
r.charge_ac(apprentissages)
# fin du parsing
print(f"{nbre_ressources} ressources")
# ************************************************************************
# Post traitement des ressources => gestion des heures/des acs/ + tri par semestre
ressources = {"S1" : [], "S2": []}
for r in liste_ressources:
# Nettoie titre
nettoie_titre(r)
# Nettoie le champ heures_encadrees
nettoie_heure(r)
# Nettoie les codes
nettoie_code(r)
# Nettoie les semestres
nettoie_semestre(r)
# Remet en forme les ACs
nettoie_acs(r)
# Remet en forme les saé
nettoie_sae(r)
# Remet en forme les pré-requis
nettoie_prerequis(r)
# Remet en forme le descriptif
split_description(r)
nettoie_contenus(r)
# Remet en forme les mots-clés
# Tri dans le bon semestre
ressources[r.semestre] += [r]
# complète les codes d'après les numéros
for sem in ressources:
for (i, r) in enumerate(ressources[sem]):
if not r.code:
if i == 0:
r.code = "R" + sem[1] + "01"
elif ressources[sem][i-1].code:
r.code = "R" + sem[1] + "{:02d}".format(int(ressources[sem][i-1].code[-2:])+1)
# ************************************************************************
# Affichages divers
# Le tableau des heures ressources
for sem in ressources: # parcours des semestres
# print(f"Semestre {sem}")
chaine = affiche_bilan_heures(ressources, sem)
# Matrice ACS/ressources
matrices = {}
les_codes_acs = [code for comp in DATA_ACS for code in DATA_ACS[comp]]
nbre_acs = len(les_codes_acs)
for sem in ressources:
# print("Matrice du semestre " + sem)
(matrices[sem], chaine) = get_matrices_ac_ressource(ressources, sem)
# Export yaml
WITH_EXPORT = True
for sem in ressources:
for r in ressources[sem]:
output = r.to_yaml()
if WITH_EXPORT and r.code:
fichier = "export/{}.yml".format(r.code)
with open(fichier, "w", encoding="utf8") as fid:
fid.write(output)

View File

@ -18,9 +18,24 @@ for file in fichiers:
sem = "S" + str(r.ressource["semestre"])
ressources[sem].append(r)
r1 = ressources["S1"][0]
r2 = ressources["S1"][1]
temp1 = r1.ressource["contenu"]
temp2 = r2.ressource["contenu"]
output1 = pypandoc.convert_text(temp1, 'tex', format='md',
extra_args=['--atx-headers'])
output2 = pypandoc.convert_text(temp2, 'tex', format='md',
extra_args=['--atx-headers'])
print("ici")
# Export latex
for sem in ressources:
for r in ressources[sem]:
if r.ressource["nom"] == "R112":
print("ici")
fichierlatex = REPERTOIRE_LATEX + "/" + "{}.tex".format(r.ressource["code"])
contenu = r.str_to_latex()
with open(fichierlatex, "w", encoding="utf8") as fid:

View File

@ -4,6 +4,7 @@ from modeles import *
from officiel import supprime_accent_espace, get_code_from_nom
import ruamel.yaml
from ruamel.yaml.scalarstring import FoldedScalarString as folded
import pypandoc
__LOGGER = logging.getLogger(__name__)
@ -51,8 +52,8 @@ class RessourceDocx():
"acs": self.apprentissages,
"sae": self.sae,
"prerequis": self.prerequis,
"contexte": folded(self.contexte).replace("\n\n", "\n"),
"contenu": folded(self.contenu).replace("\n\n", "\n"),
"contexte": folded(self.contexte),
"contenu": folded(self.contenu),
"motscles": self.mots if self.mots else ""
}
# output = yaml.dump(dico, #Dumper=yaml.Dumper,
@ -60,7 +61,7 @@ class RessourceDocx():
output = ruamel.yaml.dump(dico, Dumper=ruamel.yaml.RoundTripDumper,
allow_unicode=True,
width=200)
width=100)
output = output.replace("\n\n", "\n")
return output
@ -157,6 +158,8 @@ def nettoie_acs(r):
# donnees = donnees.replace("\t", "").replace("-", "") # supprime les tabulations
acs_avec_code = devine_acs_by_code(donnees)
acs_avec_nom = devine_code_by_nom_from_dict(donnees, DATA_ACS)
if acs_avec_code and set(acs_avec_nom).intersection(set(acs_avec_code)) != set(acs_avec_nom):
__LOGGER.warning(f"Dans {r.nom}, revoir les ACS : {acs_avec_code} vs {acs_avec_nom}")
acs_finaux = acs_avec_code + acs_avec_nom
acs_finaux = [ac.replace(" ", "") for ac in acs_finaux]
acs_finaux = sorted(list(set(acs_finaux)))
@ -196,7 +199,10 @@ def devine_acs_by_code(champ):
codes3 = re.findall(r"(AC[0-9][0-9][0-9]\D)", champ) # de code à 3 chiffres
codes4 = re.findall(r"(AC0[0-9][0-9][0-9])", champ)
codes4 += [ "AC0" + c[-4:] for c in codes3] # ajoute les 0 manquants des acs (codage AC0111)
codes3 = [c.rstrip() for c in codes3]
codes4 = [c.rstrip() for c in codes4]
codes4 += [ "AC0" + c[-3:] for c in codes3] # ajoute les 0 manquants des acs (codage AC0111)
return sorted(list(set(codes4)))
def devine_ressources_by_code(champ):
@ -269,14 +275,16 @@ def remove_ligne_vide(contenus):
def get_marqueur_numerique(contenu):
"""Revoie la liste des marqueurs numériques"""
m = re.findall(r"(\d/|\d\s\)|\d\s/)", contenu)
m = re.findall(r"(\d/|\d\s/)", contenu)
m += re.findall(r"(\d\s\)|\d\))", contenu) # les marqueurs de la forme 1)
m += re.findall(r"(--\s|--\t)", contenu)
return m
def get_marqueurs(contenus):
"""Renvoie la liste des marqueurs partant d'une liste de ligne"""
"""Renvoie la liste des marqueurs (à 1 caractère) partant d'une liste de ligne"""
marqueurs = []
for ligne in contenus:
m = re.search(r"(\t)*", ligne) # dès \t ?
m = re.search(r"(\t)*", ligne) # des \t ?
if m.group() != "":
ajout = m.group()
else:
@ -299,29 +307,30 @@ def get_marqueur(ligne, marqueurs):
def nettoie_contenus(r):
# suppression des \t
contenu = r.contenu.replace(" / ", "/")
contenu = r.contenu.replace(" / ", "/").replace(u'\xa0', ' ') # supprime les nbsp
if r.code == "R102":
print("ici")
marqueurs_numeriques = get_marqueur_numerique(contenu)
for m in marqueurs_numeriques: # remplace les marqueurs numériques
contenu = contenu.replace(m, ">")
contenus = [ligne.rstrip().replace("--", "-") for ligne in contenu.split("\n")] # les contenus
contenus = [ligne.rstrip() for ligne in contenu.split("\n")] # les contenus
contenus = remove_ligne_vide(contenus) # supprime les lignes vides
marqueurs_finaux = get_marqueurs(contenus)
contenus_fin = contenus[:] # copie des ligne
for (i, ligne) in enumerate(contenus):
m = get_marqueur(ligne, marqueurs_finaux)
if m:
pos = marqueurs_finaux.index(m)
contenus_fin[i] = "\t" * pos + "* " + ligne.replace(m, "").replace("\t", "").rstrip()
contenus_fin[i] = "\t" * (pos) + "* " + ligne.replace(m, "").replace("\t", "").rstrip()
contenu = "\n".join(contenus_fin)
contenu = contenu.replace("\n\n", "\n")
contenu = "\n\n".join(contenus_fin)
# contenu = contenu.replace("\n\n", "\n")
r.contenu = contenu
@ -347,8 +356,10 @@ class Ressource():
compRT = []
for accomp in self.ressource["acs"]:
comps = []
for no_ac in range(len(self.ressource["acs"][accomp])): # les ac de la comp
comps.append( ajoutac % (accomp, DATA_ACS[accomp][self.ressource["acs"][accomp][no_ac]]) )
code_ac = self.ressource["acs"][accomp][no_ac]
comps.append( ajoutac % (accomp, DATA_ACS[accomp][code_ac]) )
compRT.append("\n".join(comps))
# Préparation des sae
@ -376,34 +387,37 @@ class Ressource():
# print("ici")
contenu = self.ressource["contenu"] #supprime les passages à la ligne
marqueurs = ["*", "\t*"] # les marqueurs de Markdown
# marqueurs = ["*", "\t*"] # les marqueurs de Markdown
#
# for marq in marqueurs[::-1]:
# premier_marqueur = False
# contenu_balise = contenu.split("\n")
# contenu_latex = []
#
# for (i, ligne) in enumerate(contenu_balise): # pour le contenu latex actuel
# un_marqueur = get_marqueur(ligne, [marq])
# if un_marqueur: # le marqueur est trouvé
# if premier_marqueur == False:
# contenu_latex.append("\\begin{itemize}")
# premier_marqueur = True
# contenu_latex.append( ligne.replace(marq, "\\item"))
# elif premier_marqueur == True: # le marqueur n'est plus trouvé
# contenu_latex.append( ligne.replace(marq, "\\item"))
# contenu_latex.append("\\end{itemize}")
# premier_marqueur = False
# else:
# contenu_latex.append(ligne) # la ligne d'origine
# if i == len(contenu_balise) -1 and premier_marqueur == True:
# contenu_latex.append("\\end{itemize}")
# premier_marqueur = True # ferme la dernière balise
#
# # contenu_balise = contenu_latex[:]
# contenu = "\n".join(contenu_latex) # stocke le contenu
#
# contenu = "\n".join(contenu_latex)
for marq in marqueurs[::-1]:
premier_marqueur = False
contenu_balise = contenu.split("\n")
contenu_latex = []
for (i, ligne) in enumerate(contenu_balise): # pour le contenu latex actuel
un_marqueur = get_marqueur(ligne, [marq])
if un_marqueur: # le marqueur est trouvé
if premier_marqueur == False:
contenu_latex.append("\\begin{itemize}")
premier_marqueur = True
contenu_latex.append( ligne.replace(marq, "\\item"))
elif premier_marqueur == True: # le marqueur n'est plus trouvé
contenu_latex.append( ligne.replace(marq, "\\item"))
contenu_latex.append("\\end{itemize}")
premier_marqueur = False
else:
contenu_latex.append(ligne) # la ligne d'origine
if i == len(contenu_balise) -1 and premier_marqueur == True:
contenu_latex.append("\\end{itemize}")
premier_marqueur = True # ferme la dernière balise
# contenu_balise = contenu_latex[:]
contenu = "\n".join(contenu_latex) # stocke le contenu
contenu = "\n".join(contenu_latex)
output = pypandoc.convert_text(contenu, 'tex', format='md',
extra_args=['--atx-headers'])
chaine = ""
chaine = TemplateLatex(modlatex).substitute(code=self.ressource["code"],
@ -417,9 +431,9 @@ class Ressource():
motscles=self.ressource["motscles"],
prerequis=prerequis,
contexte=contexte,
contenu=contenu
contenu=output.replace("\r\n", "\n").replace("\n\n", "\n")
)
chaine = chaine.replace("&", "\&")
chaine = chaine.replace("&", "\&").replace("\n\n", "\n")
return chaine