Conversions de syntaxes Wiki
←
→
Transcription du contenu de la page
Si votre navigateur ne rend pas la page correctement, lisez s'il vous plaît le contenu de la page ci-dessous
Conversion de syntaxes Wiki
lUNIVERSITE LILLE 3
Année 2008-2009
Travail d’Etudes et de Recherche
Conversions de syntaxes Wiki
MIASHS M1 : Informatique et Document
Version 1.0
Auteurs :
MANTEL Julien
Enseignant responsable:
TOMMASI Marc
UNIVERSITE CHARLES-DE-GAULLE - LILLE 3
Domaine universitaire du "Pont de Bois"
rue du Barreau - BP 60149
59653 Villeneuve d'Ascq Cedex
Mantel Page 1 sur 29Conversion de syntaxes Wiki
Remerciements
Je tiens à adresser mes sincères remerciements :
A Monsieur Marc TOMMASI, membre du Grappa, et enseignant-chercheur a
l’Université de Lille3, notamment dans la spécialité Informatique et Document, de la
mention MIASHS (mathématiques informatiques sciences humaines et sociales) du
master Sciences Humaines et Sociales, qui, m’a permis de réaliser ce travail et qui,
par ses nombreux conseils, m’a permis de le réaliser.
A Monsieur Jérémie Mary, membre du Grappa, enseignant-chercheur et
responsable du Master MIASHS spécialité Informatique et Document.
Enfin, je tenais à remercier ceux qui ont participé de prés ou de loin a ce
travail, notamment Johan Dufour, qui m’ont épaulé et ou participer a la relecture de
ce document.
Mantel Page 2 sur 29Conversion de syntaxes Wiki
Contrôle du document
Historique des versions
Date Version Auteurs Principales modifications
16 Juin 1.0 Mantel Création et rédaction du
document
Distribution
Aux auteurs
Au responsable enseignant
Etat
Travail Terminé Validé Archivage
Sécurité et confidentialité
Copyright aux auteurs.
A diffusion limitée : au responsable enseignant, aux auteurs
Responsabilité
Ne s’applique pas
Note sur cette édition
Aucun commentaire
Mantel Page 3 sur 29Conversion de syntaxes Wiki
Sommaire
Remerciements .......................................................................................................... 2
Introduction................................................................................................................. 5
I) Présentation de l’Inria et des syntaxes Wiki. ........................................................... 6
Présentation de l’Inria.......................................................................................... 6
reStructuredText.................................................................................................. 7
TWiki Markup ...................................................................................................... 9
L’initiative WikiCréole ........................................................................................ 10
Contexte et problèmatique........................................................................................ 11
II) Outils existants, et méthodes de conversions ...................................................... 11
Introduction........................................................................................................ 11
Docutils.............................................................................................................. 11
HtmlToTWiki Converter ..................................................................................... 11
Méthode par approche arborescente................................................................. 12
Technique ligne a ligne...................................................................................... 15
Les expressions régulières................................................................................ 16
III) Mise en œuvre .................................................................................................... 17
Introduction........................................................................................................ 17
Technique utilisée.............................................................................................. 17
Gestion des fichiers ........................................................................................... 17
Ouverture et lecture d’un fichier, et choix de conversion ................................... 18
Création du fichier final...................................................................................... 19
Fonction de conversion RST vers WikiCréole (parser)...................................... 20
Approches arborescente ................................................................................... 22
Conclusion................................................................................................................ 23
Mantel Page 4 sur 29Conversion de syntaxes Wiki
Introduction
Ce document est le rapport de synthèse du travail d’études et de recherches
(TER) de 6 semaines que j’ai effectué du 12 Mai au 23 Juin 2009, dans le cadre de
la première année du Master MIASHS Informatique et Document, à l’Université
Charles-De-Gaulle, Lille 3. Ce TER avait comme objectif de vérifier les
connaissances que j’ai acquis au cours de cette première année, ainsi que de me
préparer au monde du travail.
Ces 6 semaines ont eu pour but la compréhension des méthodes de
conversions de Wiki, ainsi que la réalisation d’un programme de conversion.
Le sujet consistait en une compréhension des différentes syntaxes de Wiki,
notamment Twiki et le ReStructured Text (RST), une étude des outils et des
méthodes de conversion existantes (Docutils, conversion en arborescence, ou ligne
par ligne), et en une mise en œuvre de ces techniques, à travers la programmation
d’une application de conversion, en Python.
Ce rapport montrera d’abord une présentation rapide de l’Inria, et une
présentation détaillée des syntaxes Wiki étudiées. Nous ferons ensuite une analyse
des techniques existantes, avant de présenter le travail de programmation effectué.
Différents aspects du travail seront aussi montrés, notamment, une réflexion
sur les techniques de conversion, et les problèmes rencontrés lors du
développement.
Mantel Page 5 sur 29Conversion de syntaxes Wiki
I) Présentation de l’Inria et des syntaxes Wiki.
Présentation de l’Inria
1) L’inria en bref
L'Institut national de recherche en informatique et en automatique (INRIA) est
un organisme public civil de recherche français créé le 3 janvier 1967 suite au
lancement du Plan Calcul.
L’Inria a pour vocation d'entreprendre des recherches fondamentales et
appliquées dans les domaines des sciences et technologies de l'information et de la
communication (STIC). L'institut assure également un fort transfert de technologie en
accordant une grande attention à la formation par la recherche, à la diffusion de
l'information scientifique et technique, au développement, à l'expertise et à la
participation à des programmes internationaux.
2) Quelques Chiffres :
Ressources budgétaires (janvier 2008) :
• Budget total : 186 Millions d’euros HT
• Ressources propres : 1/5
Ressources humaines (janvier 2008)
• 3 800 personnes, dont 2 100 rémunérées par l'INRIA répartis dans 8
centres de recherche.
• 2 800 scientifiques, dont 1 300 chercheurs et enseignants-
chercheurs, 1 000 doctorants, et 500 post doctorants et contractuels
Activités scientifiques (janvier 2008)
• 150 équipes-projets de recherche
• 4 000 publications scientifiques
• 24 conférences internationales organisées ou co-organisées par
l'INRIA ayant mobilisé 2 500 participants dont 1 700 étrangers
• 14 300 heures d'enseignement
Relations industrielles (janvier 2008)
• 790 contrats de recherche actifs
• 230 brevets actifs
• 80 logiciels déposés à l'Agence pour la Protection des Programmes
• 89 sociétés de technologie issues de l'INRIA, depuis Ilog, aujourd'hui
cotée au Nasdaq, jusqu'aux 9 dernières créées en 2007.
Mantel Page 6 sur 29Conversion de syntaxes Wiki
reStructuredText
1) Présentation
Le reStructuredText est un langage très léger d’écriture de Wiki. Son nom
signifie : "revised, reworked, and reinterpreted StructuredText", et est parfois abrégé
RST.
Le parser (analyseur syntaxique) est intégré dans la bibliothèque Docutils
(http://docutils.sourceforge.net/index.html), cette dernière étant écrite en langage
Python. A noter que d’autres parsers sont disponibles, et qu’ils sont disponibles pour
d’autres langages que Python.
Le reStructuredText est donc utilisé dans la création de documentations
techniques, cela donc peut être une documentation sous forme de Wiki.
Une documentation complète du RST est disponible sur le
site http://docutils.sourceforge.net/rst.html et une rapide introduction au langage est
disponible sur le site suivant : http://commandline.org.uk/python/introduction-
restructuredtext/
Nous pouvons déjà remarquer quelques exemples de syntaxes propres au
RST. Ces exemples se focalisent sur des exemples un peu plus complexes que les
simples « soulignement, mise en emphase… »
2) Quelques règles de formatages
• Formatage de caractères :
*texte en italique*
**texte en gras**
• Titres, sous-titres:
Titre
=====
Sous-titre
----------
Le nombre de caractères au dessus et au dessous du (sous-)titre doit être
égal au nombre de caractères de la chaîne à traiter.
• Des listes :
- Une liste a puce
- 2eme item
- Un sous item
1) Une liste numérotée
2) Second item
a) Sous item
i) Sous sous item
3) Troisième item
# Item auto-incrémenté
(L’indentation définit le niveau de l’item dans la liste)
Mantel Page 7 sur 29Conversion de syntaxes Wiki
• Des liens nommés :
A sentence with links to Wikipedia_ and the `Linux kernel archive`_.
.. _Wikipedia: http://www.wikipedia.org/
.. _Linux kernel archive: http://www.kernel.org/
(Ce sont les underscores qui définissent les mots sur lequel le lien sera
activé).
• Liens “anonymes” :
Another sentence with an `anonymous link to the Python website`__.
__ http://www.python.org/
• Le RST permet aussi d’afficher des « directives » semblables à d’autres
langages et qui permettent des fonctions un peu plus avancées, telles
que l’affichage d’images ou encore de code.
Exemples :
.. image:: \http://commandline.org.uk/images/whokilledtux.png
Permet d’afficher l’image fournie en URL.
.. sourcecode:: python
import os
for i in os.uname():
print i
Permet l’affichage de ce code dans un cadre type « code ».
Mantel Page 8 sur 29Conversion de syntaxes Wiki
TWiki Markup
1) Présentation
TWiki est un logiciel moteur de Wiki, développé en Perl, qui fourni une
plateforme de travail collaboratif. Il peut être utilisé comme un espace de
développement, système d'administration de documents ou de personnel.
Les développeurs peuvent ajouter des fonctionnalités grâce à des extensions et des
scripts TWiki. La communauté autour de ce projet Open Source est donc importante.
Il est à noter qu’il existe un markup pour TWiki, dont nous verrons quelques
syntaxes, mais il n’est pas indispensable de la connaître pour écrire du contenu : un
éditeur WYSIWYG est intégré au logiciel, ce qui favorisera son utilisation auprès des
néophytes.
Plus d’informations sont disponibles sur le site officiel (http://twiki.org/), et les règles
de formatage sont disponibles à l’adresse suivante : http://twiki.org/cgi-
bin/view/TWiki/TextFormattingRules
2) Quelques règles de formatage
• Formatages des caractères
_texte en italique_
*texte en gras*
• Titre, sous-titres
---++ Titre niveau 1
---+++ Titre niveau 2
• Listes
* Liste a puce
* Deuxième item
1. Liste numérotée
1. Deuxième item (sera numéroté 2, le 1. note l’appartenance à la liste)
1. Sous item
On notera qu’on peut aussi utiliser une incrémentation en lettres ou en chiffres
romains.
• Liens
[[Url du lien]]
[[Url du lien][libellé du lien]]
Mantel Page 9 sur 29Conversion de syntaxes Wiki
On peut déjà remarquer ici les différences entre la syntaxe RST et Twiki : il n’y
a pas beaucoup de syntaxes communes.
Cependant, dans un souci de rendre les syntaxes compatibles entres elles,
des initiatives d’universalisation des syntaxes Wiki sont apparues, et notamment
l’initiative WikiCréole.
L’initiative WikiCréole
1) Présentation
Le projet WikiCréole a été crée dans le but d’uniformiser les différents
langages des Wiki, ce qui permet une meilleure compréhension pour les novices.
Le projet Créole 1.0 a été achevé le 4 Juillet 2007, et officialise les premières
spécifications de l’initiative. http://www.wikicreole.org/wiki/Creole1.0
2) Quelques règles de formatage
• Formatages de caractères
//Texte en italique//
*Texte en gras*
• En-tête :
= Titre niveau 1 =
== Titre niveau 2 ==
=== Titre niveau 3 ===
• Listes :
* Liste a puce
** Niveau 2
* Niveau 1
# Liste auto incrémentée
## Sous item auto incrémentée
# Autre item niveau 1
• Liens :
[[link]]
[[MyBigPage|Go to my page]]
[[http://www.wikicreole.org/]]
[[http://www.wikicreole.org/|Visit the WikiCreole website]]
On remarquera donc quelques similitudes avec le TWiki, notamment pour les
syntaxes des listes à puces ou des liens.
Cependant, nombre des syntaxes sont très différentes les unes des autres, ce
qui nous amène à notre problématique.
Mantel Page 10 sur 29Conversion de syntaxes Wiki
Contexte et problématique
L’Inria souhaite migrer ses structures TWiki vers le reStructuredText, pour
pouvoir l’intégrer dans son système Plone.
Cependant, les deux syntaxes étant très différentes l’une de l’autre, concevoir
un programme pouvant convertir toutes ces syntaxes n’est pas forcément évident.
Existe-t-il donc des outils, ou des programmes capables de traiter une partie
du problème, et pouvant aussi donner des indications sur les méthodes de
conversion existantes ?
II) Outils existants, et méthodes de conversions
Introduction
Il existe des outils et des programmes permettant certaines conversions,
notamment des conversions vers l’HTML, XSLT ou autres. Cependant, nous allons
intéresser à 2 outils. Le premier étant le parser (convertisseur) présent dans la
bibliothèque Docutils, bibliothèque développée en python et contenant la syntaxe
reStructuredText. Le deuxième, étant le programme HtmlToTWiki Converter, écrit en
Perl, pour l’environnement TWiki, et qui, comme son nom l’indique, converti l’HTML
en syntaxe TWiki.
Ces 2 programmes seront étudiés afin de ressortir leurs méthodes de
conversion, et nous décrirons ces méthodes.
Docutils
Docutils est donc une bibliothèque développée en Python, permettant le
traitement de documents HTML, XML ou encore LaTeX. Docutils propose aussi
divers outils, et donc celui qui nous intéressera le plus, le parser permettant de
convertir le reStructuredText vers d’autres formats.
L’ensemble des outils est téléchargeable sur la page web de l’outil
http://docutils.sourceforge.net/ , le package docutils-0.5.tar.gz ainsi téléchargé
contient tous les fichiers des bibliothèques.
Il existe donc plusieurs programmes de conversion au sein de ce package,
notamment les programmes rst2html.py, rst2xml.py, rst2latex.py etc, convertissant
donc chacun, le RST vers un format choisi.
Cependant, ce ne sont pas ces fichiers qui font la conversion. Cette tache est
effectuée en 4 temps par différentes fonctions, et ces différentes étapes constituent
la conversion par approche arborescente. Nous allons détailler cette technique et les
différentes étapes la composant par la suite
HtmlToTWiki Converter
Ce programme est une petite application développée en Java, et existante
aussi en Perl, permettant de coller son document HTML dans une fenêtre et
retournant le résultat en syntaxe TWiki.
Le parser de la version en Perl, utilise une autre technique que celui de
Docutils. La technique employée est celle de la conversion ligne à ligne.
Mantel Page 11 sur 29Conversion de syntaxes Wiki
Méthode par approche arborescente
La méthode de conversion par arborescence se décompose en 4 étapes : la
lecture du document, l’analyse (parsing), la transformation, et enfin l’écriture du
document.
La finalité de cette méthode est bien sur d’obtenir une conversion complète et
valide. Il est important de noter que pendant l’analyse, un document intermédiaire, en
arbre donc, est crée.
On peut symboliser schématiquement cette représentation comme ci-dessous.
Document Document
initial Lecture Analyse Transformation Ecriture
final
Création d’un
document en
arbre
Schématisation de la methode arborescente
Lecture
Le programme (par défaut avec Docutils, il s’agit de
docutils/readers/standalone.py) récupère le document en entrée et le garde en
mémoire pour la suite du traitement.
Analyse
C’est ici que le parser intervient. Par défaut il se trouve dans
/docutils/parsers/__init__.py . C’est donc lors de cette étape qu’est crée un fichier
intermédiaire. On peut avoir un aperçu d’un tel fichier en utilisant la fonction du fichier
quicktest.py .
Avec un fichier « test.txt » écrit en RST comme ci-dessous :
My *favorite* language is Python_.
.. _Python: http://www.python.org/
On obtient en sortie, fichier comme celui-ci :
My
favorite
language is
Python
.
Mantel Page 12 sur 29Conversion de syntaxes Wiki
On remarque directement que cette structure arborescente, ressemble très
fortement à la structure d’un document XML, ce qui nous amènera à poser une petite
réflexion à ce sujet.
On notera par ailleurs que le parser, en l’état, permet de transformer certaines
syntaxes comme l’emphasis, ou les paragraphes simples.
Transformation
Cette étape va transformer les éléments qui ne l’ont pas été durant la phase
précédente. Cela consiste donc en une succession de traitements, que le système
effectuera lorsqu’il aura repéré une balise appropriée.
On pourra donc traiter les liens hypertextes, les tables de matières (donc les
listes, ou tableaux), les notes de références, etc etc.
Dans notre exemple ci dessus, on constate que l’élément « reference »
Python, n’a pas son adresse en attribut. L’étape de transformation va donc, entre
autres, traiter ce problème, après avoir identifié cette référence.
Le fichier arborescent obtenu peut être visualisé grâce à la fonction
« rst2pseudoxml.py », qui porte bien son nom. (A noter qu’on pourra obtenir du vrai
xml avec « rst2xml.py »
My
favorite
language is
Python
.
On remarque donc l’ajout de l’url en attribut de l’élément « reference ».
Ecriture
Cette dernière fonction va tout simplement transformer nos éléments pseudo
XML en éléments valides du langage de sortie choisi.
Par exemple, toujours avec notre fichier ci-dessus, la fonction de
transformation en HTML « rst2html.py » donnera en sortie le fichier suivant :
Mantel Page 13 sur 29Conversion de syntaxes Wiki
My favorite language is Python.
Avantages, inconvénients
La méthode en arborescence présente plusieurs avantages, dont le principal
est de pouvoir utiliser le document pseudo-XML, pour transformer le document.
En effet, il suffirait de transformer les « balises » éléments du fichier pseudo-XML
vers la syntaxe des éléments du format de sortie choisi, comme dans notre exemple
ci-dessus, avec une sortie en HTML.
Le parser (étape d’analyse) n’a donc, dans l’absolu, pas besoin d’être modifié.
Pour avoir un nouveau format de conversion, il faudrait donc ajouter une nouvelle
fonction d’écriture, contenant les transformations du format désiré.
Par contre, on notera que pour obtenir une transformation vers un format, il
faudra forcément passer par les 4 étapes et donc ceci peut engendrer du calcul
supplémentaire, pas forcément nécessaire lorsque la transformation désirée est
simple : imaginons une transformation XML vers XHTML en utilisant ce procédé, il
faudrait repasser l’XML vers un pseudo XML pour ensuite le repasser vers de
l’XTML…qui est très semblable a l’XML au final.
Réflexion sur l’aspect XML
Nous avons vu que cette méthode créé une représentation en pseudo-XML,
c'est-à-dire une représentation en arbre/élément. On peut donc en déduire que
l’XML, est une représentation de choix pour la représentation de tous les documents.
En effet, ce choix de prédilection montre aussi la facilité d’écriture et de
lecture de l’XML, et permet donc facilement la transformation des éléments vers de
nouvelles syntaxes et langages, tel que l’HTML, l’XSLT, LaTeX, etc etc.
Mantel Page 14 sur 29Conversion de syntaxes Wiki
Technique ligne a ligne
Contrairement à la technique par arborescence, cette deuxième technique
n’utilise pas de format intermédiaire.
Le programme « Html2TWiki » montre en effet que le fichier en entrée est lu
(les lignes des fichiers sont gardées en mémoires), et un traitement a base
d’expressions régulières, est appliqué sur chaque ligne. La transformation est
aussitôt faite sur la ligne grâce à cette méthode. On peut représenter un tel
algorithme par ce schéma :
Ouverture du fichier
Lecture du fichier
Lecture d’une ligne
Traitement des expressions
régulières
Si non EOF
Transformation de la ligne
Ecriture de la ligne
Fermeture fichier
Algorithme ligne à ligne
Avantages, inconvénients
Le principal inconvénient de cette technique, est qu’il faut évidemment coder
toutes les transformations par les expressions régulières pour une conversion
donnée. Un tel programme est donc difficile à faire évoluer.
Par ailleurs, travailler sur les expressions régulières est difficile et parfois
rebutant, les optimisations sont coûteuses.
Cependant, on notera que le temps de calcul pourra être réduit, car il n’y a
pas de fichier intermédiaire en pseudo-XML.
Mantel Page 15 sur 29Conversion de syntaxes Wiki
Les expressions régulières
Les expressions régulières sont des chaînes de caractères décrivant un motif,
motif pouvant être utilisé, repéré ou modifié dans d’autres chaînes de caractères :
tout traitement automatisé peut donc être effectué grâce au repérage du motif dans
une chaîne.
Le bon exemple pour montrer les principes de base des expressions
régulières, est la suite de mots : « ex-équo, ex-equo, ex-aequo et ex-æquo ».
Cette suite de mot peut-être représentée par le motif suivant : « ex-
(a?e|æ|é)quo ».
On remarquera que l’on peut grouper certains caractères (avec les
parenthèses), noter une quantification (« * » signifie « 0 ou plusieurs fois », « + »
signifie « au moins 1 fois », et « ? » signifie « 0 ou 1 fois »), l’alternative (avec « | »)
A noter que, dépendant du langage employé, des extensions sont possibles.
En Python, langage qui servira à coder notre application, on notera les
caractères :
« […] » : Spécifie des classes de caractères ou des intervalles.
« . » : Remplacement de n’importe quel caractères
« \t » : Tabulation
« ^ » : Signifie le début de la ligne
Par ailleurs, pour spécifier qu’un caractère doit être repéré, et n’est pas un
caractère spécial d’un motif, il faut utiliser le caractère « \ », comme c’est le cas pour
la tabulation.
Les expressions régulières en Python sont gérées et traitées grâce à la
bibliothèque « re » (pour « Regular Expressions »). Nous verrons dans notre mise en
œuvre, les fonctions de cette bibliothèque utilisées (notamment « re.match »,
« re.sub » et « re.compile »)
Mantel Page 16 sur 29Conversion de syntaxes Wiki
III) Mise en œuvre
Introduction
Comme précisé dans le contexte du TER, l’un des objectif de celui-ci était la
création d’une application pouvant convertir des syntaxes Wiki, et notamment le
passage de TWiki vers reStructuredText. La conversion inverse était elle aussi
envisagée.
Le choix du langage pour une telle application s’est donc porté vers Python. A
noter que certaines bibliothèques ont été utilisées, notamment donc, la bibliothèque
« re » (Regular Expressions), ainsi que la bibliothèque « os » pour la gestion des
fichiers.
Dans cette partie nous verrons donc plusieurs aspects techniques de la
réalisation de l’application, nommée Wiki2All.py, avec pour chaque aspect, les
problèmes rencontrés.
Technique utilisée
A l’origine, le développement s’est dirigé vers la méthode ligne par ligne en
utilisant les expressions régulières sur chacune des lignes des fichiers. La
conversion passerait directement de RST vers TWiki et inversement.
Cependant, après avoir étudié l’initiative d’universalisation WikiCréole, il
semblait intéressant de pouvoir gérer cette syntaxe aussi. L’idée d’utiliser la syntaxe
WikiCréole comme syntaxe intermédiaire est donc apparue, modifiant la technique
ligne à ligne en une technique « hybride » : une technique ligne à ligne mais avec
format intermédiaire (mais qui n’est pas apparentée a l’XML).
Gestion des fichiers
Explications
Cette partie a été très vite implémentée au tout début du développement et
n’a pas été modifiée par la suite. Elle consiste à lister les différents fichiers
compatibles dans le dossier courant du fichier Wiki2All.py. Ces fichiers portent les
extensions « .rst », « .cre », ou « .twi ». Ils ne correspondent à aucune extension
existante, ce sont simplement des fichiers textes dont l’extension est choisie en
fonction du langage utilisé.
La fonction « listdir » de la bibliothèque « os » a été utilisée pour lister les
fichiers. Quelques tests sont nécessaires afin de ne pas lister les dossiers et fichiers
cachés, ainsi que les fichiers dont le format n’est pas souhaité. Au final on obtient un
objet liste contenant les noms des fichiers compatibles.
from os import listdir
#Déclaration des extensions de fichiers valides pour la création de la liste de fichier
valides a l'ouverture
format1=".rst"
format2=".twi"
format3=".cre"
#Création de la liste de fichiers valides
def listedefichiervalides():
global listfichier
Mantel Page 17 sur 29Conversion de syntaxes Wiki
#on crée une premier liste pour obtenir les noms de fichiers du dossier courant
(meme les cachés et les temporaires)
listfichier = listdir(".")
i=0
#le While est utilisé, car lors d'une suppression il faut rester sur le meme indice
pour retester le nouveau nom. Ceci n'est pas possible avec un for.
while i < len(listfichier):
print listfichier[i]
#le gros test : on test les 4 derniers caracteres du fichier en cours. Si
il ne correspond pas a un format, on le supprime de la liste. Sinon on le passe.
if (listfichier[i][(len(listfichier[i])-4):(len(listfichier[i]))] !=
format1 and listfichier[i][(len(listfichier[i])-4):(len(listfichier[i]))] != format2 and
listfichier[i][(len(listfichier[i])-4):(len(listfichier[i]))] != format3):
listfichier.remove(listfichier[i])
else :
i+=1
print "Liste de fichier valides disponibles :", listfichier
Problèmes rencontrés
La fonction telle qu’elle ne vérifie pas si les fichiers « .rst », « .cre » ou « .twi »
sont correctement écrits et valides : durant tout le TER et le développement, on a
admis que les documents qui seraient traités sont valides, et n’ont pas besoin de
vérification syntaxiques.
Ouverture et lecture d’un fichier, et choix de conversion
Afin de gérer le choix du ficher et celui de la conversion, des simples boucles
de type « prompt » ont été développées. Ces boucles se contentent de demander le
nom de fichier à rentrer, et un numéro de choix de conversion.
Des messages d’erreurs sont renvoyés si le fichier n’est pas dans la liste des
fichiers valides, ou si le choix de conversion n’est pas possible, par exemple quand
on souhaite convertir un fichier « .rst » en fichier « .rst », ou lorsque la conversion n’a
pas été développée.
#Fonction : affiche un prompt qui demandera quel fichier a traiter.
def promptouvrirfichier():
#def de variables globales : lignesfic est la liste des lignes du fichiers, fic est
la variable de fichier, formatfic est le format du fichier ouvert.
global lignesfic
global fic
global formatfic
#un flag qui servira au test d'ouverture d'un fichier
flagfichierok=False
while flagfichierok == False :
prompt=raw_input("Entrez votre nom de fichier (valide) a ouvrir :")
#boucle : on test si le nom de fichier est dans la liste crée précédemment.
Si il est trouvé, on l'ouvre en lecture, on récupere les lignes, on passe le flag a True, et
l'on récupere le format du fichier.
for i in range(len(listfichier)):
if listfichier[i]==prompt :
fic=open(prompt,'r')
lignesfic=fic.readlines()
flagfichierok=True
formatfic=prompt[(len(prompt)-4):(len(prompt))]
break
if flagfichierok==False :
print "Fichier inexistant ou invalide."
Mantel Page 18 sur 29Conversion de syntaxes Wiki
#Nouveau prompt qui demande quelle conversion a faire (on suppose que l'utilisateur fait des
fichiers avec le contenu coincident a son extension.
def promptconversion():
flagconvertok=False
print "Attention : le fichier 'sortie.xxx' obtenu precedemment sera écrasé !"
while flagconvertok==False :
prompt=input("Entrez le numero de la conversion a faire : 1=RST (.rst),
2=Twiki (.twi), 3=Wiki Creole (.cre) : ")
print formatfic
if prompt==1 :
if formatfic==".rst" :
print "Le fichier est déja en extension RST."
else :
formatconvert=".rst"
flagconvertok=True
elif prompt==2 :
if formatfic==".twi" :
print "Le fichier est déja en extension Twiki."
else :
formatconvert=".twi"
flagconvertok=True
elif prompt==3 :
if formatfic==".cre" :
print "Le fichier est déja en extension Wiki Creole."
else :
formatconvert=".cre"
flagconvertok=True
return formatconvert
Le choix de conversion sera aussi utilisé afin de renommer le fichier de sortie
grâce à la variable « formatconvert ».
Très important, dans la première des 2 fonctions, le fichier entré si il existe
sera ouvert et ses lignes lues, et stockées en mémoire dans la variable globale
« lignesfic ».
Problèmes rencontrés
La aussi, le programme ne tiens pas compte des syntaxes même des fichiers,
puisque l’on admet les fichiers valides dans leur format. Les exceptions de validation
ne sont donc pas gérées.
Création du fichier final
Maintenant que l’on connaît le format de fichier, la conversion désirée, et que
le fichier en entrée est lu, la fonction suivante va créer un fichier de sortie vide avec
l’extension désirée.
Chaque ligne du fichier est envoyée à la fonction de conversion
correspondante.
Notons que seule la conversion RST vers WikiCréole avait été développée à
ce moment.
def creationfichierfinal(format):
global fileout
fileout=open("sortie"+format,'w')
for i in range(len(lignesfic)):
conversionligneRST2cre(lignesfic[i])
Mantel Page 19 sur 29Conversion de syntaxes Wiki
Fonction de conversion RST vers WikiCréole (parser)
La conversion se faisant ligne à ligne, à la base, une seule fonction par type
de conversion était présente (par exemple donc « conversionligneRST2cre »).
Chaque ligne du fichier est reçue afin que chaque expression régulière soit
testée sur cette ligne, grâce a la fonction « re.match ». Les transformations sont
effectuées cas échéant, par la fonction « re.sub ».
L’ensemble du code et des expressions régulières développé à ce moment du
développement est fourni en annexe.
Problèmes rencontrés
Divers problèmes ont été rencontrés dans cette phase de développement,
certainement la plus longue.
La première difficulté a été de déterminer quelles sont les règles de
formatages à transformer. Nous nous sommes limités donc a la conversion des
caractères en gras et italiques, la conversion des listes (énumérées ou non), des
titres niveau 1 et 2, des liens et si possible des tableaux.
Cependant, travailler sur les expressions régulières est laborieux, et les
optimisations fréquentes et/ou longues. Ce fut le cas de l’optimisation des titres
niveau 1 et 2. Les titres en RST demandent d’avoir un soulignement ou un
surlignement de caractères spéciaux de même taille que la chaîne à titrer, il était
nécessaire de devoir conserver au moins les 2 lignes précédentes afin de comparer
et d’opérer la transformation.
Ceci a été réglé par l’ajout de variables globales permettant de sauvegarder
les lignes précédentes.
global ligneante
global ligneprec
global headingspotted
global headingok
global heading2ok
lignesortie=ligne
if dicoRE['Heading'].match(ligne) :
if headingok or heading2ok:
headingspotted=False
else :
headingspotted=True
if len(ligne)==len(ligneprec) and ligne==ligneante :
headingok=True
lignesortie="== "+ligneprec
fileout.write(lignesortie)
elif len(ligne)==len(ligneprec) and ligne!=ligneprec :
heading2ok=True
lignesortie="=== "+ligneprec
fileout.write(lignesortie)
[…]
ligneante=ligneprec
ligneprec=ligne
Mantel Page 20 sur 29Conversion de syntaxes Wiki
A noter que cette fonction tiens compte d’une évolution que l’on évoquera par
la suite, visible par l’appel « dicoRE['Heading'] ».
Dans le programme principal :
ligneante = ""
ligneprec = ""
Les variables « headingok » et « headingok2 » servent à déterminer si notre
ligne en cours fait partie d’un titre niveau 1 ou 2, ce qui empêche la réécriture de
lignes inutiles.
Autre problème : la gestion des liens hypertextes. En effet, ceux-ci sont écrits
sur 2 lignes, la première indiquant le ou les mots à rendre hypertextes, et la
deuxième contenant ces mots en libellé et l’URL (voir syntaxe RST).
Pour régler ce problème, je n’ai pas trouvé de meilleure solution que de lire
une première fois le document afin de rechercher chaque ligne commençant par
« .. _ », afin d’ajouter le libellé et l’URL dans un dictionnaire.
def creationdicolinks():
global dicolinks
dicolinks={}
for i in range(len(lignesfic)):
if re.match("^\.\. .*: ", lignesfic[i]):
for j in range(len(lignesfic[i])):
if lignesfic[i][j]==":" :
pos2points = j
break
inddico = lignesfic[i][4:pos2points]
valdico =
lignesfic[i][pos2points+2:len(lignesfic[i])-1]
dicolinks[inddico]=valdico
Cependant, la manipulation de ce dictionnaire dans le parser entraîne des
problèmes de repérages, qui n’ont pas été résolus : tout semble indiquer que la
construction d’une chaîne est correcte cependant, le test de repérage reste non
concluant.
La majeure partie des problèmes restant est restée du domaine des
expressions régulières, délicates à écrire et tester avec précision.
Ainsi, les listes à puces, les listes numérotées, les caractères en gras ou
italiques ont été traités.
Cependant, les expressions s’ajoutant, très vite il devient difficile de lire le
code. Sous les conseils de mon tuteur Mr. Tommasi, j’ai donc utilisé la fonction
« re.compile », pour « aérer » l’affichage de mes expressions régulières.
Cette fonction se charge de stocker en mémoire grâce à un dictionnaire, une
expression régulière sous un nom donné, pour pouvoir réutiliser juste ce nom.
Mantel Page 21 sur 29Conversion de syntaxes Wiki
Exemple d’application :
def prepareRERST():
dicoRE={}
dicoRE['Heading'] = re.compile("[-,=,:,~,^,_,*,+,#,]{2,}")
dicoRE['Gras']= re.compile(".*\*\*.*\*\*.*")
dicoRE['Italique']= re.compile(".*\*.*\*.*")
dicoRE['Puce']= re.compile("^[-\+] ")
dicoRE['ListeNum']= re.compile("^\t*([0-9#]+\.)* ")
return dicoRE
Un appel se fait de la façon suivante :
dicoRE['Heading'].match(ligne)
Le code devient ainsi plus clair, et il suffit d’ajouter de nouvelles entrées dans
le dictionnaire, et les appeler dans les divers programmes de conversion.
Cependant, par manque de temps, les autres conversions n’ont pas été
implémentées. Je me suis donc penché, pendant le temps restant sur la méthode
arborescente, afin de déterminer s’il était techniquement possible de la réaliser sur
mon application.
Approches arborescente
La technique en arborescence n’est pas évidente à approcher. Il faut tout
d’abord comprendre ses mécanismes de base, c'est-à-dire les 4 phases décrites
précédemment.
Malheureusement, le temps manquant, je ne me suis contenté que de tester
ces phases, sans pouvoir en comprendre les algorithmes ou de le reproduire sur
mon application.
Mes tests se sont basés sur les fichiers et scripts de tests fournis dans le
package Docutils et présentés précédemment, ce qui m’a permis de comprendre les
fonctions.
Mantel Page 22 sur 29Conversion de syntaxes Wiki
Conclusion
D’un point de vue technique, ce TER m’a permis de travailler sur un aspect
intéressant des technologies d’aujourd’hui, à savoir les syntaxes Wiki ainsi que les
méthodes de conversions.
J’ai donc pu revoir des notions vues en cours, notamment le développement
Python, ainsi que le développement d’expressions régulières.
D’un point de vue personnel, ce stage m’a permis de travailler en totale
autonomie, comme lors de mon précédent TER l’an passé, ou j’ai du développer un
produit Zope/Plone.
Enfin, j’ajouterai que ce TER, m’aura évidemment permis d’acquérir de
nouvelles connaissances, et d’approfondir certains aspects notamment sur les
expressions régulières, et les syntaxes.
Mantel Page 23 sur 29Conversion de syntaxes Wiki
Annexes
Mantel Page 24 sur 29Conversion de syntaxes Wiki
Code source de Wiki2All.py
#!/usr/bin/python
# -*- coding: utf8 -*-
from os import listdir
import re
#Déclaration des extensions de fichiers valides pour la création de la
liste de fichier valides a l'ouverture
format1=".rst"
format2=".twi"
format3=".cre"
#Création de la liste de fichiers valides
def listedefichiervalides():
global listfichier
#on crée une premier liste pour obtenir les noms de fichiers du
dossier courant (meme les cachés et les temporaires)
listfichier = listdir(".")
i=0
#le While est utilisé, car lors d'une suppression il faut rester
sur le meme indice pour retester le nouveau nom. Ceci n'est pas possible
avec un for.
while i < len(listfichier):
print listfichier[i]
#le gros test : on test les 4 derniers caracteres du fichier
en cours. Si il ne correspond pas a un format, on le supprime de la liste.
Sinon on le passe.
if (listfichier[i][(len(listfichier[i])-
4):(len(listfichier[i]))] != format1 and
listfichier[i][(len(listfichier[i])-4):(len(listfichier[i]))] != format2
and listfichier[i][(len(listfichier[i])-4):(len(listfichier[i]))] !=
format3):
listfichier.remove(listfichier[i])
else :
i+=1
print "Liste de fichier valides disponibles :", listfichier
#Fonction : affiche un prompt qui demandera quel fichier a traiter.
def promptouvrirfichier():
#def de variables globales : lignesfic est la liste des lignes du
fichiers, fic est la variable de fichier, formatfic est le format du
fichier ouvert.
global lignesfic
global fic
global formatfic
#un flag qui servira au test d'ouverture d'un fichier
flagfichierok=False
while flagfichierok == False :
prompt=raw_input("Entrez votre nom de fichier (valide) a
ouvrir :")
#boucle : on test si le nom de fichier est dans la liste
crée précédemment. Si il est trouvé, on l'ouvre en lecture, on récupere les
lignes, on passe le flag a True, et l'on récupere le format du fichier.
for i in range(len(listfichier)):
Mantel Page 25 sur 29Conversion de syntaxes Wiki
if listfichier[i]==prompt :
fic=open(prompt,'r')
lignesfic=fic.readlines()
flagfichierok=True
formatfic=prompt[(len(prompt)-
4):(len(prompt))]
break
if flagfichierok==False :
print "Fichier inexistant ou invalide."
#Nouveau prompt qui demande quelle conversion a faire (on suppose que
l'utilisateur fait des fichiers avec le contenu coincident a son extension.
def promptconversion():
flagconvertok=False
print "Attention : le fichier 'sortie.xxx' obtenu precedemment sera
écrasé !"
while flagconvertok==False :
prompt=input("Entrez le numero de la conversion a faire :
1=RST (.rst), 2=Twiki (.twi), 3=Wiki Creole (.cre) : ")
print formatfic
if prompt==1 :
if formatfic==".rst" :
print "Le fichier est déja en extension RST."
else :
formatconvert=".rst"
flagconvertok=True
elif prompt==2 :
if formatfic==".twi" :
print "Le fichier est déja en extension
Twiki."
else :
formatconvert=".twi"
flagconvertok=True
elif prompt==3 :
if formatfic==".cre" :
print "Le fichier est déja en extension Wiki
Creole."
else :
formatconvert=".cre"
flagconvertok=True
return formatconvert
def prepareRE():
dicoRE={}
dicoRE['Heading'] = re.compile("[-,=,:,~,^,_,*,+,#,]{2,}")
dicoRE['Gras']= re.compile(".*\*\*.*\*\*.*")
dicoRE['Italique']= re.compile(".*\*.*\*.*")
dicoRE['Puce']= re.compile("^[-\+] ")
dicoRE['ListeNum']= re.compile("^\t*([0-9#]+\.)* ")
return dicoRE
def conversionligneRST2cre(ligne):
global ligneante
global ligneprec
global headingspotted
global headingok
global heading2ok
global dicoliens
Mantel Page 26 sur 29Conversion de syntaxes Wiki
lignesortie=ligne
#heading
if dicoRE['Heading'].match(ligne) :
if headingok or heading2ok:
headingspotted=False
else :
headingspotted=True
if len(ligne)==len(ligneprec) and ligne==ligneante :
headingok=True
lignesortie="== "+ligneprec
fileout.write(lignesortie)
elif len(ligne)==len(ligneprec) and ligne!=ligneprec :
heading2ok=True
lignesortie="=== "+ligneprec
fileout.write(lignesortie)
if dicoRE['Italique'].re.match(ligne):
#Probleme pour le caractere d'echappement \ suivi de *
#if re.match("\\//", lignesortie):
# lignesortie=re.sub("\\//","/*",lignesortie)
#else :
lignesortie=re.sub("\*", "//", ligne)
#petite exception : a améliorer si possible. explications :
lorsque l'on change * par //, les strong emphasis du RST passent de ** a
////. Comment matcher * et pas ** en meme temps ? En attendant, je met un
match sur //// pour le changer en *.
if re.match(".*////.*////.*", lignesortie) :
lignesortie=re.sub("////", "*", lignesortie)
if dicoRE['Gras'].re.match(ligne):
lignesortie=re.sub("\*\*", "*", ligne)
#------------------
#Les puces :
if re.match("^- ", ligne) :
lignesortie= re.sub("^- ", "* ", ligne)
if re.match("^\+ ", ligne) :
lignesortie= re.sub("^\+ ", "* ", ligne)
#Listes numérotées :
if dicoRE['ListeNum'].re.match(ligne):
counttab=0
for j in range(len(ligne)):
if ligne[j]=="\t" :
Mantel Page 27 sur 29Conversion de syntaxes Wiki
counttab+=1
lignesortie = re.sub("^(\t)*([0-9#]+\.)*",
"#"*(counttab+1), ligne)
if re.match(".*_.*", ligne):
for clef in dicolinks:
print "Ligne : " + ligne
print "dico", dicolinks
print "match", re.match(str(clef),ligne)
matching = clef+"_"
print "match", re.match(matching,ligne)
print clef+"_"
if re.match(clef+"_",ligne):
print "SPOTTED !"
lignesortie=re.sub(clef+"_",
"[["+dicolinks[clef]+"|"+clef+"]]",ligne)
if headingspotted == False :
if heading2ok == False :
fileout.write(lignesortie)
else :
heading2ok= False
ligneante=ligneprec
ligneprec=ligne
def creationdicolinks():
global dicolinks
dicolinks={}
for i in range(len(lignesfic)):
if re.match("^\.\. .*: ", lignesfic[i]):
for j in range(len(lignesfic[i])):
if lignesfic[i][j]==":" :
pos2points = j
break
inddico = lignesfic[i][4:pos2points]
valdico =
lignesfic[i][pos2points+2:len(lignesfic[i])-1]
print inddico
print valdico
dicolinks[inddico]=valdico
print dicolinks
def creationfichierfinal(format):
global fileout
fileout=open("sortie"+format,'w')
creationdicolinks()
for i in range(len(lignesfic)):
conversionligneRST2cre(lignesfic[i])
ligneante = ""
ligneprec = ""
headingok=False
heading2ok=False
Mantel Page 28 sur 29Conversion de syntaxes Wiki listedefichiervalides() promptouvrirfichier() formatconvert=promptconversion() creationfichierfinal(formatconvert) Mantel Page 29 sur 29
Vous pouvez aussi lire